Files
ImageCompressor/Compressor/ImgsProcess.cs
2026-02-02 21:56:45 +08:00

240 lines
7.3 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//#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();
}
}
}