diff --git a/Comic_Compressor/AvifCompressor.cs b/Comic_Compressor/AvifCompressor.cs index 32b4f70..d268d78 100644 --- a/Comic_Compressor/AvifCompressor.cs +++ b/Comic_Compressor/AvifCompressor.cs @@ -5,12 +5,11 @@ namespace Comic_Compressor { internal class AvifCompressor : Utils { - internal static void CompressImages(string sourceImagePath, string targetStoragePath, int threadCount) + internal static void CompressImages(string sourceImagePath, string targetStoragePath, int threadCount, bool usePresetQuality, int Quality) { - //config MagickFormat targetFormat = MagickFormat.Avif; string targetExtension = ".avif"; - int targetQuality = 80; + int targetQuality = usePresetQuality ? 80 : Quality; List subdirectories = new(Directory.GetDirectories(sourceImagePath, "*", SearchOption.AllDirectories)); diff --git a/Comic_Compressor/JxlCompressor.cs b/Comic_Compressor/JxlCompressor.cs index a0c7f70..b34d716 100644 --- a/Comic_Compressor/JxlCompressor.cs +++ b/Comic_Compressor/JxlCompressor.cs @@ -5,12 +5,11 @@ namespace Comic_Compressor { internal class JxlCompressor : Utils { - internal static void CompressImages(string sourceImagePath, string targetStoragePath, int threadCount) + internal static void CompressImages(string sourceImagePath, string targetStoragePath, int threadCount, bool usePresetQuality, int Quality) { - //config MagickFormat targetFormat = MagickFormat.Jxl; string targetExtension = ".jxl"; - int targetQuality = 90; + int targetQuality = usePresetQuality ? 90 : Quality; List subdirectories = new(Directory.GetDirectories(sourceImagePath, "*", SearchOption.AllDirectories)); diff --git a/Comic_Compressor/LegacyFormatCompressor.cs b/Comic_Compressor/LegacyFormatCompressor.cs index 0eee6e6..4560139 100644 --- a/Comic_Compressor/LegacyFormatCompressor.cs +++ b/Comic_Compressor/LegacyFormatCompressor.cs @@ -5,14 +5,25 @@ namespace Comic_Compressor //Process images in legacy format(JPG,PNG) internal class LegacyFormatCompressor : Utils { - internal static void CompressImages(string sourceImagePath, string targetStoragePath, int threadCount, int format) + internal static void CompressImages(string sourceImagePath, string targetStoragePath, int threadCount, bool usePresetQuality, int Quality, int format) { - //check format - throw new NotImplementedException(); - //config - MagickFormat targetFormat = MagickFormat.Jxl; - string targetExtension = ".jxl"; - int targetQuality = 90; + MagickFormat targetFormat = format switch + { + 3 => MagickFormat.Jpeg, + 4 => MagickFormat.Png, + 5 => MagickFormat.Bmp, + _ => throw new Exception(), + }; + + string targetExtension = format switch + { + 3 => ".jpg", + 4 => ".png", + 5 => ".bmp", + _ => throw new Exception(), + }; + + int targetQuality = usePresetQuality ? 90 : Quality; List subdirectories = new(Directory.GetDirectories(sourceImagePath, "*", SearchOption.AllDirectories)); diff --git a/Comic_Compressor/MixProcessor.cs b/Comic_Compressor/MixProcessor.cs index 825fe09..a141d4d 100644 --- a/Comic_Compressor/MixProcessor.cs +++ b/Comic_Compressor/MixProcessor.cs @@ -1,17 +1,11 @@ -using ImageMagick; -using ShellProgressBar; +using ShellProgressBar; namespace Comic_Compressor { internal class MixProcessor : Utils { - internal static void CompressImages(string sourceImagePath, string targetStoragePath, int threadCount, int format) + internal static void CompressImages(string sourceImagePath, string targetStoragePath, int threadCount, bool usePresetQuality, int Quality) { - //detect mu-config - throw new NotImplementedException(); - //config - MagickFormat targetFormat = MagickFormat.Jxl; - string targetExtension = ".jxl"; - int targetQuality = 90; + int targetQuality = usePresetQuality ? 90 : Quality; List subdirectories = new(Directory.GetDirectories(sourceImagePath, "*", SearchOption.AllDirectories)); @@ -29,7 +23,7 @@ namespace Comic_Compressor foreach (string subdirectory in subdirectories) { - ProcessDirectory(subdirectory, sourceImagePath, targetStoragePath, progressBar, threadCount, targetExtension, targetFormat, targetQuality); + ProcessDirectory(subdirectory, sourceImagePath, targetStoragePath, progressBar, threadCount, targetQuality); } Console.WriteLine("All directories processed successfully."); diff --git a/Comic_Compressor/Program.cs b/Comic_Compressor/Program.cs index af02604..acf93ae 100644 --- a/Comic_Compressor/Program.cs +++ b/Comic_Compressor/Program.cs @@ -1,6 +1,4 @@ -using ImageMagick; -using System.Text; -using System.Windows.Forms; +using System.Text; namespace Comic_Compressor { internal class Program @@ -29,9 +27,34 @@ namespace Comic_Compressor Console.WriteLine("处理线程数:"); int threadCount = int.Parse(Console.ReadLine() ?? "2"); - Console.WriteLine($"处理线程数设定:{threadCount}"); + if (threadCount < 1) + { + Console.WriteLine("无效线程数"); + return; + } - Console.WriteLine("目标格式:0 - webp, 1 - avif, 2 - JXL(JPEG-XL), 3 - JPG, 4 - PNG, 5 - BMP, 6 - 保留原格式(best effort)"); + Console.WriteLine("使用预设质量(默认使用)?(y/n)"); + string? input = Console.ReadLine()?.Trim().ToLower(); + bool usePresetQuality = input == null || input == "" || input == "y" || input == "yes"; + int targetQuality = -1; + if (!usePresetQuality) + { + Console.WriteLine("Quality (0-100 INT):"); + string? targetQualityStr = Console.ReadLine(); + if (targetQualityStr == null) + { + Console.WriteLine("无效输入"); + return; + } + targetQuality = int.Parse(targetQualityStr); + if (targetQuality < 0 || targetQuality > 100) + { + Console.WriteLine("invalid image quality"); + return; + } + } + + Console.WriteLine("目标格式:0 - webp, 1 - avif, 2 - JXL(JPEG-XL), 3 - JPG, 4 - PNG, 5 - BMP, 6 - 保留原格式"); string? modeInput = Console.ReadLine(); if (modeInput == null) { @@ -42,29 +65,27 @@ namespace Comic_Compressor switch (modeInput) { case "0": - WebpCompressor.CompressImages(sourceImagePath, targetStoragePath, threadCount); - Utils.GetCompressorResult(sourceImagePath, targetStoragePath); + WebpCompressor.CompressImages(sourceImagePath, targetStoragePath, threadCount, usePresetQuality, targetQuality); break; case "1": - AvifCompressor.CompressImages(sourceImagePath, targetStoragePath, threadCount); - Utils.GetCompressorResult(sourceImagePath, targetStoragePath); + AvifCompressor.CompressImages(sourceImagePath, targetStoragePath, threadCount, usePresetQuality, targetQuality); break; case "2": - JxlCompressor.CompressImages(sourceImagePath, targetStoragePath, threadCount); - Utils.GetCompressorResult(sourceImagePath, targetStoragePath); + JxlCompressor.CompressImages(sourceImagePath, targetStoragePath, threadCount, usePresetQuality, targetQuality); break; case "3": case "4": case "5": - LegacyFormatCompressor.CompressImages(sourceImagePath, targetStoragePath, threadCount,int.Parse(modeInput)); - Utils.GetCompressorResult(sourceImagePath, targetStoragePath); + LegacyFormatCompressor.CompressImages(sourceImagePath, targetStoragePath, threadCount, usePresetQuality, targetQuality, int.Parse(modeInput)); break; case "6": - throw new NotImplementedException(); + MixProcessor.CompressImages(sourceImagePath, targetStoragePath, threadCount, usePresetQuality, targetQuality); + break; default: Console.WriteLine("不支持的格式"); - break; + return; } + Utils.GetCompressorResult(sourceImagePath, targetStoragePath); } } } diff --git a/Comic_Compressor/Utils.cs b/Comic_Compressor/Utils.cs index 331ef26..16195cc 100644 --- a/Comic_Compressor/Utils.cs +++ b/Comic_Compressor/Utils.cs @@ -28,7 +28,7 @@ namespace Comic_Compressor // Get all image files in a directory with supported extensions public static string[] GetImageFiles(string directoryPath) { - string[] supportedExtensions = ["*.jpg", "*.jpeg", "*.png", "*.bmp", "*.gif", "*.tiff", "*.jxl", "*.avif", "*.webp"]; + string[] supportedExtensions = ["*.jpg", "*.jpeg", "*.png", "*.bmp", "*.gif", "*.tiff", "*.tif", "*.jxl", "*.avif", "*.webp"]; ConcurrentBag allFiles = []; foreach (string extension in supportedExtensions) @@ -76,6 +76,56 @@ namespace Comic_Compressor }); } + //Process all image files in a directory, save as origin format + public static void ProcessDirectory(string subdirectory, string sourceImagePath, string targetStoragePath, ShellProgressBar.ProgressBar progressBar, int threadCount, int quality) + { + string relativePath = Path.GetRelativePath(sourceImagePath, subdirectory); + + string targetSubdirectory = Path.Combine(targetStoragePath, relativePath); + Directory.CreateDirectory(targetSubdirectory); + + string[] imageFiles = GetImageFiles(subdirectory); + + ParallelOptions options = new() + { + MaxDegreeOfParallelism = threadCount // Adjust this value to set the number of concurrent threads + }; + + Parallel.ForEach(imageFiles, options, imageFile => + { + string targetFilePath = Path.Combine(targetSubdirectory, Path.GetFileName(imageFile)); + //detect file format + //supportedExtensions = ["*.jpg", "*.jpeg", "*.png", "*.bmp", "*.gif", "*.tiff", "*.jxl", "*.avif", "*.webp"]; + string extension = Path.GetExtension(targetFilePath).ToLower(); + + MagickFormat mFormat = extension switch + { + ".jpg" or ".jpeg" => MagickFormat.Jpeg, + ".png" => MagickFormat.Png, + ".bmp" => MagickFormat.Bmp, + ".gif" => MagickFormat.Gif, + ".tiff" or ".tif" => MagickFormat.Tiff, + ".jxl" => MagickFormat.Jxl, + ".avif" => MagickFormat.Avif, + ".webp" => MagickFormat.WebP, + _ => throw new Exception()//这个位置怎么还会有意外情况 + }; + if (!File.Exists(targetFilePath)) + { + CompressImage(imageFile, targetFilePath, mFormat, quality); + + lock (progressBar) + { + progressBar.Tick($"Processed {Path.GetFileName(imageFile)}"); + } + } + else + { + lock (progressBar) { progressBar.Tick($"Skipped {Path.GetFileName(imageFile)}"); } + } + }); + } + // Display the compression result public static void GetCompressorResult(string source, string target) { diff --git a/Comic_Compressor/WebpCompressor.cs b/Comic_Compressor/WebpCompressor.cs index ecbdd5f..43cb1fd 100644 --- a/Comic_Compressor/WebpCompressor.cs +++ b/Comic_Compressor/WebpCompressor.cs @@ -5,12 +5,11 @@ namespace Comic_Compressor { internal class WebpCompressor : Utils { - internal static void CompressImages(string sourceImagePath, string targetStoragePath, int threadCount) + internal static void CompressImages(string sourceImagePath, string targetStoragePath, int threadCount, bool usePresetQuality, int Quality) { - //config MagickFormat targetFormat = MagickFormat.WebP; string targetExtension = ".webp"; - int targetQuality = 90; + int targetQuality = usePresetQuality ? 90 : Quality; List subdirectories = new(Directory.GetDirectories(sourceImagePath, "*", SearchOption.AllDirectories));