//#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 { /// /// 一个单独的线程,来批量压缩图片 /// class ImgsProcess { /// /// 这个压缩进程内的所有压缩图片的路径 /// ImgPaths[] ImgPaths { get; set; } /// /// 计数当前线程编号,用于Debug /// public int threadIndex=-1; /// /// 引用的进度总控 /// readonly CountProgress progress; int currentIndex = 0; /// /// 设定是否要在过程中停止计算,标记为停止后,等待计算停止 /// public bool ToStop { get; set; } = false; /// /// 判断是否所有计算已经停止 /// public bool Stoped { get; private set; } = false; /// /// 该线程处理的所有图片数量 /// public int AllCount { get; private set; } public ImgsProcess(int index, List imgPaths, CountProgress countProgress) { threadIndex = index; ImgPaths = imgPaths.ToArray(); AllCount = ImgPaths.Length; this.progress = countProgress; } /// /// 开始时设定所有的压缩参数 /// /// /// /// public void SetCompressLevel(int compressLevel,int maxWidth, int maxHeight) { this.compressLevel = compressLevel; this.maxWidth = maxWidth; this.maxHeight = maxHeight; } int compressLevel; int maxWidth; int maxHeight; /// /// 用来传递每个Img压缩时候的数据 /// 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 failedPaths = new List(); int skipCount = 0; long preSizeKB = 0; long saveSizeKB = 0; /// /// 重置当前线程运行的结果变量 /// void ResetCountData() { successCount = 0; failedCount = 0; failedPaths.Clear(); skipCount = 0; preSizeKB = 0; saveSizeKB = 0; } /// /// 读照片到DataPack /// /// 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); } } /// /// 压缩得到文件的Bytes /// /// 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); } } } /// /// 写Bytes到文件 /// /// 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); } } } /// /// 将本线程结果更新到progress的结果 /// 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(); } } }