Added Compression statistics report in every run
QqAdded support for reading PPM PixelMap image files.
This commit is contained in:
+222
-14
@@ -25,6 +25,10 @@ using org.omg.PortableInterceptor;
|
||||
using org.apache.pdfbox.util.@operator;
|
||||
using java.nio;
|
||||
using ImageMagick;
|
||||
using javax.xml.transform;
|
||||
using System.Collections.Concurrent;
|
||||
using iText.Barcodes.Dmcode;
|
||||
using ZstdSharp;
|
||||
|
||||
namespace ComicCompressor
|
||||
{
|
||||
@@ -32,6 +36,7 @@ namespace ComicCompressor
|
||||
{
|
||||
public static int Main(string[] args) => CommandLineApplication.Execute<Program>(args);
|
||||
|
||||
#region INPUT_FLAGS
|
||||
[FileOrDirectoryExists]
|
||||
[Option("-i|--input <FOLDER/FIlE>", Description = "The file or folder to convert")]
|
||||
[Required]
|
||||
@@ -63,15 +68,50 @@ namespace ComicCompressor
|
||||
|
||||
[Option("-j|--image", Description = "process images only")]
|
||||
public bool DoImage { get; } = false;
|
||||
#endregion
|
||||
|
||||
#region STATISTICS
|
||||
|
||||
public class file_stat
|
||||
{
|
||||
public string Filename { get; set; }
|
||||
public file_stat(string filename) {
|
||||
Filename = filename;
|
||||
}
|
||||
public long Uncompressed_file_len { get; set; }
|
||||
public long Compressed_file_len { get; set; }
|
||||
|
||||
|
||||
}
|
||||
|
||||
static Dictionary <string, file_stat> file_statistics = new Dictionary<string, file_stat>();
|
||||
public static Dictionary<string, file_stat> File_statistics { get => file_statistics; set => file_statistics = value; }
|
||||
|
||||
#endregion
|
||||
|
||||
private Logger Logger { get; set; }
|
||||
|
||||
SimpleEncoder encoder = new SimpleEncoder();
|
||||
private List<Stream> imageStreams = null;
|
||||
public ZipArchive output = null;
|
||||
|
||||
static Random randomGen = new Random();
|
||||
static KnownColor[] names = (KnownColor[])Enum.GetValues(typeof(KnownColor));
|
||||
// static KnownColor randomColorName = names[randomGen.Next(names.Length)];
|
||||
// static Color randomColor = Color.FromKnownColor(randomColorName);
|
||||
|
||||
public Color[] myColors = null;
|
||||
private void OnExecute()
|
||||
{
|
||||
|
||||
File_statistics.Clear();
|
||||
|
||||
myColors = new Color[names.Count()];
|
||||
for(int i = 0; i< myColors.Length; i++)
|
||||
{
|
||||
KnownColor randomColorName = names[randomGen.Next(names.Length)];
|
||||
myColors[i] = Color.FromKnownColor(randomColorName);
|
||||
}
|
||||
//ImageExtractor7.MainBox();
|
||||
|
||||
Stopwatch sw = Stopwatch.StartNew();
|
||||
@@ -99,6 +139,7 @@ namespace ComicCompressor
|
||||
|
||||
foreach (var file in files)
|
||||
{
|
||||
File_statistics.Add(file, new file_stat(file));
|
||||
if(file.Length > filename_len)
|
||||
filename_len = file.Length;
|
||||
}
|
||||
@@ -115,6 +156,25 @@ namespace ComicCompressor
|
||||
n++;
|
||||
}
|
||||
|
||||
long tot_uncomp = 0;
|
||||
long tot_comp = 0;
|
||||
|
||||
foreach (var file in file_statistics)
|
||||
{
|
||||
long uncomp = file.Value.Uncompressed_file_len;
|
||||
long comp = file.Value.Compressed_file_len;
|
||||
if (uncomp != 0 && comp != 0)
|
||||
{
|
||||
Logger.Log($"{file.Value.Filename} U[{uncomp}] C[{comp}]", LogLevel.Verbose, true, Color.Pink);
|
||||
tot_uncomp += uncomp;
|
||||
tot_comp += comp;
|
||||
}
|
||||
}
|
||||
if (tot_uncomp != 0)
|
||||
{
|
||||
double save = 100 * (double)tot_comp / (double)tot_uncomp;
|
||||
Logger.Log($"TU[{tot_uncomp}] TC[{tot_comp}] R%[{save,5:##.00}] S[{(tot_uncomp-tot_comp)/1024.0/1024.0,5:##.00} MB]", LogLevel.Verbose, true, Color.Pink);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -122,37 +182,107 @@ namespace ComicCompressor
|
||||
{
|
||||
MaxDegreeOfParallelism = (NumOfCpu > Environment.ProcessorCount) ? Environment.ProcessorCount : NumOfCpu
|
||||
};
|
||||
#if true
|
||||
ParallelQuery<string> source = Partitioner.Create(files)
|
||||
.AsParallel()
|
||||
.AsOrdered();
|
||||
|
||||
Parallel.ForEach(files, options, file => CompressTask(compressor, file, filename_len, true));
|
||||
Parallel.ForEach(source, options, (file, state, index) => CompressTask(compressor, file, filename_len, true, state, index, files.Count));
|
||||
#else
|
||||
Parallel.ForEach(files, options, (file, state, index) => CompressTask(compressor, file, filename_len, true, state, index+1, files.Count));
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
foreach (var file in file_statistics)
|
||||
{
|
||||
Logger.Log($"{file.Value.Filename} U[{file.Value.Uncompressed_file_len}] C[{file.Value.Compressed_file_len}]", LogLevel.Verbose, true, Color.Pink);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void CompressTask(Compressor compressor, string filename, int max_name_len = -1, Boolean isPar = false)
|
||||
private void CompressTask(Compressor compressor, string filename, int max_name_len = -1, Boolean isPar = false, ParallelLoopState state = null, long index = 0, long total = 0)
|
||||
{
|
||||
var relativePath = Path.GetRelativePath(Input, filename);
|
||||
var outputPath = Path.Join(OutputFolder, Path.ChangeExtension(relativePath, "cbz"));
|
||||
var outputPath_webp = Path.Join(OutputFolder, Path.ChangeExtension(relativePath, "webp"));
|
||||
int digits = 1+(int)Math.Floor(Math.Log((Double)total) / Math.Log(10.0));
|
||||
|
||||
string print_line_header = "";
|
||||
switch (digits)
|
||||
{
|
||||
case 1:
|
||||
print_line_header = $"{index,1}/{total,1} - ";
|
||||
break;
|
||||
case 2:
|
||||
print_line_header = $"{index,2}/{total,2} - ";
|
||||
break;
|
||||
case 3:
|
||||
print_line_header = $"{index,3}/{total,3} - ";
|
||||
break;
|
||||
case 4:
|
||||
print_line_header = $"{index,4}/{total,4} - ";
|
||||
break;
|
||||
case 5:
|
||||
print_line_header = $"{index,5}/{total,5} - ";
|
||||
break;
|
||||
}
|
||||
|
||||
if (File.Exists(outputPath) && Skip)
|
||||
{
|
||||
long lengthin = new System.IO.FileInfo(filename).Length;
|
||||
long lengthout = new System.IO.FileInfo(outputPath).Length;
|
||||
Program.file_stat fs = null;
|
||||
Program.File_statistics.TryGetValue(filename, out fs);
|
||||
if (fs != null)
|
||||
{
|
||||
fs.Uncompressed_file_len = lengthin;
|
||||
fs.Compressed_file_len = lengthout;
|
||||
Program.File_statistics.TryAdd(filename, fs);
|
||||
}
|
||||
|
||||
|
||||
Logger.Log(outputPath, LogLevel.Verbose, true, Color.Yellow);
|
||||
return;
|
||||
}
|
||||
if (DoImage && Skip && File.Exists(outputPath_webp))
|
||||
{
|
||||
long lengthin = new System.IO.FileInfo(filename).Length;
|
||||
long lengthout = new System.IO.FileInfo(outputPath).Length;
|
||||
Program.file_stat fs = null;
|
||||
Program.File_statistics.TryGetValue(filename, out fs);
|
||||
if (fs != null)
|
||||
{
|
||||
fs.Uncompressed_file_len = lengthin;
|
||||
fs.Compressed_file_len = lengthout;
|
||||
Program.File_statistics.TryAdd(filename, fs);
|
||||
}
|
||||
|
||||
Logger.Log(outputPath_webp, LogLevel.Verbose, true, Color.Yellow);
|
||||
return;
|
||||
}
|
||||
|
||||
if (DoPdf && filename.ToLower().EndsWith(".pdf"))
|
||||
{
|
||||
ExtractImageFromPDF(filename, outputPath);
|
||||
|
||||
ExtractImageFromPDF(compressor,filename, outputPath);
|
||||
|
||||
long lengthin = new System.IO.FileInfo(filename).Length;
|
||||
long lengthout = new System.IO.FileInfo(outputPath).Length;
|
||||
Program.file_stat fs = null;
|
||||
Program.File_statistics.TryGetValue(filename, out fs);
|
||||
if (fs != null)
|
||||
{
|
||||
fs.Uncompressed_file_len = lengthin;
|
||||
fs.Compressed_file_len = lengthout;
|
||||
Program.File_statistics.TryAdd(filename, fs);
|
||||
}
|
||||
//compressor.CompressPdf(filename, outputPath);
|
||||
return;
|
||||
}
|
||||
|
||||
if (DoPdf)
|
||||
return;
|
||||
//if (DoPdf)
|
||||
// return;
|
||||
|
||||
if (DoImage &&
|
||||
filename.ToLower().EndsWith("jpg") ||
|
||||
@@ -161,7 +291,18 @@ namespace ComicCompressor
|
||||
filename.ToLower().EndsWith("png"))
|
||||
{
|
||||
outputPath = Path.Join(OutputFolder, Path.ChangeExtension(relativePath, "webp"));
|
||||
CompressImage(filename, outputPath, max_name_len,isPar);
|
||||
CompressImage(filename, outputPath, max_name_len,isPar, print_line_header);
|
||||
|
||||
long lengthin = new System.IO.FileInfo(filename).Length;
|
||||
long lengthout = new System.IO.FileInfo(outputPath).Length;
|
||||
Program.file_stat fs = null;
|
||||
Program.File_statistics.TryGetValue(filename, out fs);
|
||||
if (fs != null)
|
||||
{
|
||||
fs.Uncompressed_file_len = lengthin;
|
||||
fs.Compressed_file_len = lengthout;
|
||||
Program.File_statistics.TryAdd(filename, fs);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -288,7 +429,7 @@ namespace ComicCompressor
|
||||
}
|
||||
return "";
|
||||
}
|
||||
#else
|
||||
#elif false
|
||||
public int GetPlace(int value, int place)
|
||||
{
|
||||
return ((value % (place * 10)) - (value % place)) / place;
|
||||
@@ -437,18 +578,64 @@ namespace ComicCompressor
|
||||
|
||||
//Logger.Log(sw.ElapsedMilliseconds.ToString(), LogLevel.Verbose);
|
||||
}
|
||||
#else
|
||||
public void ExtractImageFromPDF(Compressor compressor, string sourcePdf, string outputFolder)
|
||||
{
|
||||
|
||||
//pdfimages.exe -j "Dragon Ball Full Color [Volume 1].pdf" "Dragon Ball Full Color [Volume 1]\img"
|
||||
//7za a -r -mx0 -tzip "Dragon Ball Full Color [Volume 1]" "Dragon Ball Full Color [Volume 1]\*"
|
||||
|
||||
|
||||
string subfolder = Path.GetFileNameWithoutExtension(sourcePdf);
|
||||
string folder = Path.GetDirectoryName(sourcePdf);
|
||||
string tempfolder = folder + "\\" + subfolder;
|
||||
Directory.CreateDirectory(tempfolder);
|
||||
|
||||
Logger.Log(sourcePdf, LogLevel.Verbose, true, Color.Green);
|
||||
|
||||
ProcessStartInfo startInfo_pdfimages = new ProcessStartInfo("pdfimages.exe");
|
||||
startInfo_pdfimages.Arguments = $@" -j ""{sourcePdf}"" ""{tempfolder}\img""";
|
||||
startInfo_pdfimages.UseShellExecute = false;
|
||||
Process pdfimages = System.Diagnostics.Process.Start(startInfo_pdfimages);
|
||||
pdfimages.WaitForExit();
|
||||
|
||||
string zipFile = tempfolder + ".zip";
|
||||
ProcessStartInfo startInfo_7za = new ProcessStartInfo("7za.exe");
|
||||
startInfo_7za.Arguments = $@" a -r -mx0 -tzip -sdel ""{zipFile}"" ""{tempfolder}\*"" > $null 2>&1";
|
||||
startInfo_7za.UseShellExecute = false;
|
||||
startInfo_7za.RedirectStandardOutput = true;
|
||||
Process zip7za = System.Diagnostics.Process.Start(startInfo_7za);
|
||||
zip7za.WaitForExit();
|
||||
Directory.Delete(tempfolder);
|
||||
|
||||
if (File.Exists(outputFolder) && Skip)
|
||||
{
|
||||
Logger.Log(outputFolder, LogLevel.Verbose, true, Color.Yellow);
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
compressor.Compress(zipFile, outputFolder);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Log("Error processing file: " + zipFile, LogLevel.Error, Color.Red);
|
||||
Logger.LogDebug(e, LogLevel.Error, col: Color.Red);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region COMPRESS_IMAGE
|
||||
public void CompressImage(string imagefile, string outputFolder, int max_name_len = -1, Boolean isPar = false)
|
||||
public void CompressImage(string imagefile, string outputFolder, int max_name_len = -1, Boolean isPar = false, string print_line_header = "")
|
||||
{
|
||||
string name_print = imagefile;
|
||||
if(max_name_len > 0)
|
||||
name_print = imagefile.PadRight(max_name_len);
|
||||
if(!isPar)
|
||||
Logger.Log(name_print, LogLevel.Verbose, false, col:Color.LightBlue);
|
||||
Logger.Log(print_line_header+name_print, LogLevel.Verbose, false, col:Color.LightBlue);
|
||||
|
||||
try
|
||||
{
|
||||
@@ -482,13 +669,34 @@ namespace ComicCompressor
|
||||
FileInfo finfo = new FileInfo(outputFolder);
|
||||
long length_out = finfo.Length;
|
||||
if (isPar)
|
||||
Logger.Log($"{name_print} - IN[{length_in,10}] OUT[{length_out,10}] %[{(100.0 * length_out / (double)length_in),5:##.00}]", LogLevel.Verbose, true,col:Color.Green);
|
||||
{
|
||||
#if false
|
||||
Logger.Log($"{print_line_header}[{Environment.CurrentManagedThreadId}]{name_print} - IN[{length_in,10}] OUT[{length_out,10}] %[{(100.0 * length_out / (double)length_in),5:##.00}]", LogLevel.Verbose, true, col: Color.Green);
|
||||
#else
|
||||
lock (Logger)
|
||||
{
|
||||
Logger.Log($"{print_line_header}[{Environment.CurrentManagedThreadId,2}] ", LogLevel.Verbose, false, col: myColors[Environment.CurrentManagedThreadId]);
|
||||
Logger.Log($"{name_print} - IN[{length_in,10}] OUT[{length_out,10}] %[{(100.0 * length_out / (double)length_in),5:##.00}]", LogLevel.Verbose, true, col: Color.Green);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
Logger.Log($" - IN[{length_in,10}] OUT[{length_out,10}] %[{(100.0 * length_out/(double)length_in),5:##.00}]", LogLevel.Verbose, true, col:Color.LightBlue);
|
||||
Logger.Log($" - IN[{length_in,10}] OUT[{length_out,10}] %[{(100.0 * length_out / (double)length_in),5:##.00}]", LogLevel.Verbose, true, col: Color.LightBlue);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
Logger.LogError(e, col: Color.Red);
|
||||
lock (Logger)
|
||||
{
|
||||
if (isPar)
|
||||
{
|
||||
Logger.Log($"{print_line_header}[{Environment.CurrentManagedThreadId}]{name_print} ERROR", LogLevel.Verbose, true, col: Color.Red);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Log($" ERROR", LogLevel.Verbose, true, col: Color.Red);
|
||||
}
|
||||
Logger.LogError(e, col: Color.Red);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -548,6 +756,6 @@ namespace ComicCompressor
|
||||
}
|
||||
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user