240 lines
7.3 KiB
C#
240 lines
7.3 KiB
C#
//#define NoOutput
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.Drawing.Imaging;
|
||
using System.Drawing;
|
||
using System.IO;
|
||
using System.Linq;
|
||
using System.Text;
|
||
using System.Threading;
|
||
using System.Threading.Tasks;
|
||
using System.Diagnostics;
|
||
using System.Dynamic;
|
||
|
||
namespace ImageCompressor
|
||
{
|
||
|
||
/// <summary>
|
||
/// 一个单独的线程,来批量压缩图片
|
||
/// </summary>
|
||
class ImgsProcess
|
||
{
|
||
|
||
/// <summary>
|
||
/// 这个压缩进程内的所有压缩图片的路径
|
||
/// </summary>
|
||
ImgPaths[] ImgPaths { get; set; }
|
||
|
||
/// <summary>
|
||
/// 计数当前线程编号,用于Debug
|
||
/// </summary>
|
||
public int threadIndex=-1;
|
||
|
||
/// <summary>
|
||
/// 引用的进度总控
|
||
/// </summary>
|
||
readonly CountProgress progress;
|
||
|
||
int currentIndex = 0;
|
||
|
||
/// <summary>
|
||
/// 设定是否要在过程中停止计算,标记为停止后,等待计算停止
|
||
/// </summary>
|
||
public bool ToStop { get; set; } = false;
|
||
|
||
/// <summary>
|
||
/// 判断是否所有计算已经停止
|
||
/// </summary>
|
||
public bool Stoped { get; private set; } = false;
|
||
/// <summary>
|
||
/// 该线程处理的所有图片数量
|
||
/// </summary>
|
||
public int AllCount { get; private set; }
|
||
|
||
public ImgsProcess(int index, List<ImgPaths> imgPaths, CountProgress countProgress)
|
||
{
|
||
threadIndex = index;
|
||
ImgPaths = imgPaths.ToArray();
|
||
AllCount = ImgPaths.Length;
|
||
this.progress = countProgress;
|
||
}
|
||
/// <summary>
|
||
/// 开始时设定所有的压缩参数
|
||
/// </summary>
|
||
/// <param name="compressLevel"></param>
|
||
/// <param name="maxWidth"></param>
|
||
/// <param name="maxHeight"></param>
|
||
public void SetCompressLevel(int compressLevel,int maxWidth, int maxHeight)
|
||
{
|
||
this.compressLevel = compressLevel;
|
||
this.maxWidth = maxWidth;
|
||
this.maxHeight = maxHeight;
|
||
}
|
||
|
||
int compressLevel;
|
||
int maxWidth;
|
||
int maxHeight;
|
||
|
||
/// <summary>
|
||
/// 用来传递每个Img压缩时候的数据
|
||
/// </summary>
|
||
class DataPack
|
||
{
|
||
public DataPack(ImgPaths paths, JPGCompressor compressor)
|
||
{
|
||
this.compressor = compressor;
|
||
this.imgPaths = paths;
|
||
}
|
||
public JPGCompressor compressor;
|
||
public ImgPaths imgPaths;
|
||
public byte[] readBytes = null;
|
||
public byte[] saveBytes = null;
|
||
}
|
||
#if DEBUG
|
||
|
||
double Tick => Math.Round(DateTime.Now.TimeOfDay.TotalSeconds % 1000, 3);
|
||
#endif
|
||
public void Start()
|
||
{
|
||
Stoped = false;
|
||
ToStop = false;
|
||
ResetCountData();
|
||
while (currentIndex < AllCount)
|
||
{
|
||
#if DEBUG
|
||
long t1 = progress.stopwatch.ElapsedMilliseconds;
|
||
#endif
|
||
DataPack dataPack = new DataPack(ImgPaths[currentIndex],new JPGCompressor(compressLevel,maxWidth,maxHeight));
|
||
ReadOneImage(dataPack);
|
||
CompressCurrent(dataPack);
|
||
WriteOneImage(dataPack);
|
||
#if DEBUG
|
||
long t2 = progress.stopwatch.ElapsedMilliseconds;
|
||
#endif
|
||
progress.RWLock.AcquireWriterLock(-1);
|
||
UpdateCountProgress();
|
||
ResetCountData();
|
||
Thread.Sleep(25);
|
||
progress.RWLock.ReleaseWriterLock();
|
||
#if DEBUG
|
||
|
||
Debug.WriteLine($"thread {threadIndex} count {currentIndex}, from {t1}, used {t2 - t1}");
|
||
#endif
|
||
currentIndex++;
|
||
if (ToStop)
|
||
{
|
||
Stoped = true;
|
||
return;
|
||
}
|
||
}
|
||
Stoped = true;
|
||
}
|
||
|
||
//当前线程运行的结果变量
|
||
int successCount = 0;
|
||
int failedCount = 0;
|
||
List<string> failedPaths = new List<string>();
|
||
int skipCount = 0;
|
||
long preSizeKB = 0;
|
||
long saveSizeKB = 0;
|
||
|
||
/// <summary>
|
||
/// 重置当前线程运行的结果变量
|
||
/// </summary>
|
||
void ResetCountData()
|
||
{
|
||
successCount = 0;
|
||
failedCount = 0;
|
||
failedPaths.Clear();
|
||
skipCount = 0;
|
||
preSizeKB = 0;
|
||
saveSizeKB = 0;
|
||
}
|
||
/// <summary>
|
||
/// 读照片到DataPack
|
||
/// </summary>
|
||
/// <param name="dataPack"></param>
|
||
void ReadOneImage(DataPack dataPack)
|
||
{
|
||
ImgPaths imgPaths = dataPack.imgPaths;
|
||
if(!imgPaths.OriginalFileInfo.Exists)
|
||
{
|
||
failedCount++;
|
||
failedPaths.Add(Localize.Get("Read file missing") + imgPaths.OriginalFileInfo.FullName);
|
||
return;
|
||
}
|
||
preSizeKB += imgPaths.OriginalFileInfo.Length / 1024;
|
||
if (FilesManager.IsSkip(imgPaths.OriginalFileInfo))
|
||
{
|
||
skipCount++;
|
||
return;
|
||
}
|
||
dataPack.readBytes = dataPack.compressor.ReadFileToBytes(imgPaths.OriginalFileInfo, out string error);
|
||
if (dataPack.readBytes == null)
|
||
{
|
||
failedCount++;
|
||
failedPaths.Add(error + imgPaths.OriginalFileInfo.FullName);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 压缩得到文件的Bytes
|
||
/// </summary>
|
||
/// <param name="dataPack"></param>
|
||
void CompressCurrent(DataPack dataPack)
|
||
{
|
||
if (dataPack.readBytes != null)
|
||
{
|
||
dataPack.saveBytes = dataPack.compressor.CompressBytes(dataPack.readBytes,out string error);
|
||
if(dataPack.saveBytes == null)
|
||
{
|
||
failedCount++;
|
||
failedPaths.Add(error + dataPack.imgPaths.OriginalFileInfo.FullName);
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 写Bytes到文件
|
||
/// </summary>
|
||
/// <param name="dataPack"></param>
|
||
void WriteOneImage(DataPack dataPack)
|
||
{
|
||
if (dataPack.saveBytes != null)
|
||
{
|
||
bool keepOriginal = dataPack.imgPaths.KeepOriginal;
|
||
FileInfo saveFile = keepOriginal ? dataPack.imgPaths.DuplicatedFileInfo : dataPack.imgPaths.OriginalFileInfo;
|
||
|
||
bool re = dataPack.compressor.SaveCompressBytes(dataPack.saveBytes, saveFile, out string error);
|
||
if (re)
|
||
{
|
||
saveSizeKB += dataPack.saveBytes.LongLength / 1024;
|
||
successCount++;
|
||
}
|
||
else
|
||
{
|
||
failedCount++;
|
||
failedPaths.Add(error + dataPack.imgPaths.DuplicatedFileInfo.FullName);
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 将本线程结果更新到progress的结果
|
||
/// </summary>
|
||
void UpdateCountProgress()
|
||
{
|
||
if (progress.Finished) return;
|
||
progress.SuccessCount += successCount;
|
||
progress.FailedCount+= failedCount;
|
||
progress.SkipCount += skipCount;
|
||
progress.FailedInfos.AddRange(failedPaths);
|
||
progress.PreSizeKBSum+= preSizeKB;
|
||
progress.PostSizeKBSum += saveSizeKB;
|
||
progress.Update();
|
||
}
|
||
|
||
|
||
}
|
||
}
|