diff --git a/ComicCompress.csproj b/ComicCompress.csproj index 8d860f2..bb552af 100644 --- a/ComicCompress.csproj +++ b/ComicCompress.csproj @@ -8,20 +8,28 @@ True + + + + + + + + - + - + - - + + @@ -30,5 +38,9 @@ + + + + diff --git a/ComicCompress.csproj.user b/ComicCompress.csproj.user index e2ee5ae..9adce7d 100644 --- a/ComicCompress.csproj.user +++ b/ComicCompress.csproj.user @@ -5,6 +5,7 @@ DEV_HOME + <_LastSelectedProfileId>E:\_COMIX\_TOOLS_\comic-compress-new\Properties\PublishProfiles\FolderProfile.pubxml ProjectDebugger diff --git a/ComicCompress.sln b/ComicCompress.sln index 7b2586c..a8d0cf7 100644 --- a/ComicCompress.sln +++ b/ComicCompress.sln @@ -5,6 +5,10 @@ VisualStudioVersion = 17.5.33530.505 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ComicCompress", "ComicCompress.csproj", "{2625C71D-E4EC-4768-BF04-87AAB364916A}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "iMGcompress", "..\iMGcompress\iMGcompress.csproj", "{7330E00C-6C24-44B3-9768-1604802532FB}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "iMGcompress-core", "..\iMGcompress-core\iMGcompress-core.csproj", "{990E9DC1-B842-4E0E-AD7F-00CB2EF24AF4}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -15,6 +19,14 @@ Global {2625C71D-E4EC-4768-BF04-87AAB364916A}.Debug|Any CPU.Build.0 = Debug|Any CPU {2625C71D-E4EC-4768-BF04-87AAB364916A}.Release|Any CPU.ActiveCfg = Release|Any CPU {2625C71D-E4EC-4768-BF04-87AAB364916A}.Release|Any CPU.Build.0 = Release|Any CPU + {7330E00C-6C24-44B3-9768-1604802532FB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7330E00C-6C24-44B3-9768-1604802532FB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7330E00C-6C24-44B3-9768-1604802532FB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7330E00C-6C24-44B3-9768-1604802532FB}.Release|Any CPU.Build.0 = Release|Any CPU + {990E9DC1-B842-4E0E-AD7F-00CB2EF24AF4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {990E9DC1-B842-4E0E-AD7F-00CB2EF24AF4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {990E9DC1-B842-4E0E-AD7F-00CB2EF24AF4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {990E9DC1-B842-4E0E-AD7F-00CB2EF24AF4}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Compressor.cs b/Compressor.cs index f11f16d..02cc503 100644 --- a/Compressor.cs +++ b/Compressor.cs @@ -14,6 +14,7 @@ using javax.swing.plaf; using SharpCompress.Readers; using SharpCompress.Writers; using SharpCompress.Compressors.Xz; +using iMGcompress_core; //using SixLabors.ImageSharp; //using SixLabors.ImageSharp; //using SixLabors.ImageSharp.Processing; @@ -213,7 +214,8 @@ namespace ComicCompressor Directory.CreateDirectory(Path.GetDirectoryName(outputPath)); - output.SaveTo(outputPath, CompressionType.Deflate); +// output.SaveTo(outputPath, CompressionType.Deflate); + output.SaveTo(outputPath, CompressionType.None); //output.SaveTo(outputPath, CompressionType.None); diff --git a/FileParser.cs b/FileParser.cs deleted file mode 100644 index 2dec604..0000000 --- a/FileParser.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System.Collections.Generic; -using System.IO; - -namespace ComicCompressor -{ - public class FileParser - { - public IList ListAllFiles(string input, bool recursive) - { - Queue unexplored; - IList files = new List(); - - if (Directory.Exists(input)) - { - unexplored = new Queue(Directory.GetFileSystemEntries(input)); - } - else - { - // No directory but must exist so it is a file - unexplored = new Queue(); - unexplored.Enqueue(input); - } - - while(unexplored.Count > 0) - { - var file = unexplored.Dequeue(); - - if (File.Exists(file)) - { - files.Add(file); - } - else if (recursive) - { - foreach (var f in Directory.GetFileSystemEntries(file)) - { - unexplored.Enqueue(f); - } - } - } - - return files; - - } - } - -} \ No newline at end of file diff --git a/ImageExtractor.cs b/ImageExtractor.cs deleted file mode 100644 index 8ce5c8e..0000000 --- a/ImageExtractor.cs +++ /dev/null @@ -1,205 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Drawing; -using System.IO; -using System.Runtime.ConstrainedExecution; -using ikvm.extensions; -using Imazen.WebP; - -using iTextSharp.text.pdf; -using iTextSharp.text.pdf.parser; - -using SharpCompress.Archives; -using SharpCompress.Archives.Zip; -using SharpCompress.Common; - -using Path = System.IO.Path; - -namespace ComicCompressor -{ - /// - /// Helper lass to dump all images from a PDF into separate files - /// - public class ImageExtractor : IRenderListener - { - int _currentPage = 1; - int _imageCount = 0; - readonly string _outputFilePrefix = ""; - //readonly string _outputFolder; - //readonly bool _overwriteExistingFiles; - private bool Cover = true; - private Logger Logger { get; set; } - SimpleEncoder encoder = new SimpleEncoder(); - public int Quality { get; set; } = 75; - private List imageStreams = null; - public ZipArchive output = null; - - public ImageExtractor(Logger logger) - { - Logger = logger; - //_outputFilePrefix = outputFilePrefix; - //_outputFolder = outputFolder; - //_overwriteExistingFiles = overwriteExistingFiles; - } - public int GetPlace(int value, int place) - { - return ((value % (place * 10)) - (value % place)) / place; - } - /// - /// Extract all images from a PDF file - /// - /// Full path and file name of PDF file - /// Basic name of exported files. If null then uses same name as PDF file. - /// Where to save images. If null or empty then uses same folder as PDF file. - /// True to overwrite existing image files, false to skip past them - /// Count of number of images extracted. - public int ExtractImagesFromFile(string pdfPath, string outputFolder, int quality = 75) - { - // Handle setting of any default values - //outputFilePrefix = outputFilePrefix ?? Path.GetFileNameWithoutExtension(pdfPath); - //outputFolder = String.IsNullOrEmpty(outputFolder) ? Path.GetDirectoryName(pdfPath) : outputFolder; - - quality = quality; - - Stopwatch sw = Stopwatch.StartNew(); - using (var pdfReader = new PdfReader(pdfPath)) - { - Logger.Log($"Processing[{pdfReader.NumberOfPages}]: " + pdfPath, LogLevel.Verbose); - - if (pdfReader.IsEncrypted()) - throw new ApplicationException(pdfPath + " is encrypted."); - - var pdfParser = new PdfReaderContentParser(pdfReader); - - output = ZipArchive.Create(); - { - imageStreams = new List(); - int count = 0; - Cover = true; - while (_currentPage <= pdfReader.NumberOfPages) - { - pdfParser.ProcessContent(_currentPage, this); - - _currentPage++; - count++; - if (count % 10 == 0) - { - string digit = GetPlace(count, 10).ToString(); - Logger.Log(digit, LogLevel.Verbose, false); - } - } - - - Directory.CreateDirectory(Path.GetDirectoryName(outputFolder)); - - output.SaveTo(outputFolder, CompressionType.Deflate); - - //output.SaveTo(outputPath, CompressionType.None); - - imageStreams.ForEach(i => i.Dispose()); - } - output.Dispose(); - int nop = pdfReader.NumberOfPages; - if (nop == 0) nop = 1; - long elapsed = sw.ElapsedMilliseconds; - //Logger.Log($"\r\nFinished({save.ToString("0.##")}): " + pdfPath, LogLevel.Verbose); - Logger.Log($"\r\nFinished({0.ToString("0.##")} [{elapsed}][{elapsed / nop}]): " + pdfPath, LogLevel.Verbose); - - } - - return _imageCount; - } - private Bitmap ChangePixelFormat(Bitmap orig, System.Drawing.Imaging.PixelFormat format = System.Drawing.Imaging.PixelFormat.Format24bppRgb) - { - Bitmap clone = new Bitmap(orig.Width, orig.Height, format); - - using (Graphics gr = Graphics.FromImage(clone)) - { - gr.DrawImage(orig, new Rectangle(0, 0, clone.Width, clone.Height)); - } - - return clone; - - } - - #region Implementation of IRenderListener - - public void BeginTextBlock() - { - } - - public void EndTextBlock() - { - } - - public void RenderText(TextRenderInfo renderInfo) - { - var text = renderInfo.GetText(); - } - - public void RenderImage(ImageRenderInfo renderInfo) - { - try - { - var type = renderInfo.GetType(); - var str = renderInfo.toString(); - //var ftype = renderInfo.GetFileType(); - var imageObject = renderInfo.GetImage(); - - //var imageFileName = String.Format("{0}_{1}_{2}.{3}", _outputFilePrefix, _currentPage, _imageCount, - // imageObject.GetFileType()); - var imageFileName = String.Format($"{_imageCount.ToString("0000")}"); - //var imagePath = Path.Combine(_outputFolder, imageFileName); - - //if (_overwriteExistingFiles || !File.Exists(imagePath)) - { - var imageRawBytes = imageObject.GetImageAsBytes(); - var image = imageObject.GetDrawingImage(); - - //File.WriteAllBytes(imagePath, imageRawBytes); - if (image.Width < 512 || image.Height < 512) - return; - - if (image.PixelFormat != System.Drawing.Imaging.PixelFormat.Format24bppRgb) - { - var newBits = ChangePixelFormat((Bitmap)image); - image.Dispose(); - image = newBits; - } - - var ms = new MemoryStream(); - encoder.Encode((Bitmap)image, ms, Quality); - if (!Cover && ms.Length < imageRawBytes.Length) - { - imageStreams.Add(ms); - output.AddEntry(imageFileName + ".webp", ms); - Logger.Log(".", LogLevel.Verbose, false); - } - else - { - var mso = new MemoryStream(); - mso.Write(imageRawBytes); - output.AddEntry(imageFileName + imageObject.GetFileType(), mso); - Logger.Log(Cover ? "C" : "=", LogLevel.Verbose, false); - Cover = false; - } - } - - // Subtle: Always increment even if file is not written. This ensures consistency should only some - // of a PDF file's images actually exist. - _imageCount++; - } - catch (Exception e) - { - Console.WriteLine(e); - throw; - } - - } - - #endregion // Implementation of IRenderListener - - } -} - diff --git a/ImageExtractor7.cs b/ImageExtractor7.cs deleted file mode 100644 index ed1f147..0000000 --- a/ImageExtractor7.cs +++ /dev/null @@ -1,89 +0,0 @@ -using System; -using System.IO; -using System.Linq; - -using iText.Kernel.Geom; -using iText.Kernel.Pdf; -using iText.Kernel.Pdf.Xobject; -using iText.Layout; -using iText.Layout.Element; - -using java.util; -using org.apache.pdfbox.pdmodel.graphics.xobject; -using org.apache.pdfbox.pdmodel; - -namespace ComicCompressor -{ - public class ImageExtractor7 - { - public static readonly String DEST = "K:\\_COMIX\\_TOOLS_\\comic-compress-master\\bin\\Debug\\net6.0\\_NEW_PDF_\\Fan SUP 18.cbz"; - - public static readonly String SRC = "K:\\_COMIX\\_TOOLS_\\comic-compress-master\\bin\\Debug\\net6.0\\_PDF_\\Fan SUP 18.pdf"; - - public static void Main7() - { - FileInfo file = new FileInfo(DEST); - file.Directory.Create(); - - new ImageExtractor7().ManipulatePdf(DEST); - } - - protected void ManipulatePdf(String dest) - { - PdfDocument resultDoc = new PdfDocument(new PdfWriter(dest)); - PdfDocument srcDoc = new PdfDocument(new PdfReader(SRC)); - - // Assume that there is a single XObject in the source document - // and this single object is an image. - PdfDictionary pageDict = srcDoc.GetFirstPage().GetPdfObject(); - PdfDictionary pageResources = pageDict.GetAsDictionary(PdfName.Resources); - PdfDictionary pageXObjects = pageResources.GetAsDictionary(PdfName.XObject); - var ks = pageXObjects.KeySet(); - PdfName imgRef = pageXObjects.KeySet().First(); - PdfStream imgStream = pageXObjects.GetAsStream(imgRef); - PdfImageXObject imgObject = new PdfImageXObject((PdfStream)imgStream.CopyTo(resultDoc)); - Image image = new Image(imgObject); - image.ScaleToFit(14400, 14400); - image.SetFixedPosition(0, 0); - - - srcDoc.Close(); - - PageSize pageSize = new PageSize(image.GetImageScaledWidth(), image.GetImageScaledHeight()); - Document doc = new Document(resultDoc, pageSize); - doc.Add(image); - - doc.Close(); - } - - - public static void MainBox() - { - new ImageExtractor7().ManipulatePdf(DEST); - } - - protected void ManipulatePdfBox(String dest) - { - PDDocument document = null; - document = PDDocument.load(SRC); - java.util.List pages = document.getDocumentCatalog().getAllPages(); - Iterator iter = pages.iterator(); - while (iter.hasNext()) - { - PDPage page = (PDPage)iter.next(); - PDResources resources = page.getResources(); - Map pageImages = resources.getImages(); - if (pageImages != null) - { - Iterator imageIter = pageImages.keySet().iterator(); - while (imageIter.hasNext()) - { - String key = (String)imageIter.next(); - PDXObjectImage image = (PDXObjectImage)pageImages.get(key); - //image.write2OutputStream(/* some output stream */); - } - } - } - } - } -} diff --git a/Logger.cs b/Logger.cs deleted file mode 100644 index 6a025bb..0000000 --- a/Logger.cs +++ /dev/null @@ -1,93 +0,0 @@ -using System; -using System.Drawing; -using System.IO; -using System.Runtime.CompilerServices; - -using Pastel; - -namespace ComicCompressor -{ - public class Logger - { - public LogLevel LoggingLevel { get; set; } = LogLevel.Warning; - public bool Debug = false; - - // Set to null for stdout - public string LogFile { get; set; } = null; - - public void Log(object message, LogLevel logLevel, Color? col = null) - { - Log(message.ToString(), logLevel, col:col); - } - - public void Log(string message, LogLevel logLevel,bool newLine = true, Color? col = null) - { - if (logLevel > LoggingLevel) return; - - if (LogFile == null) - { - if(newLine) - Console.WriteLine(message.Pastel(col ?? Color.FromArgb(0,204,204,204))); - else - Console.Write(message.Pastel(col ?? Color.FromArgb(0, 204, 204, 204))); - return; - } - - WriteToFile(message); - } - - public void LogError(string message, Color? col = null) - { - Log(message, LogLevel.Error, col:col); - } - - public void LogError(object message, Color? col = null) - { - Log(message, LogLevel.Error, col:col); - } - - public void LogDebug(string message, LogLevel logLevel, Color? col = null) - { - if (!Debug) return; - Log(message, logLevel,col:col); - } - - public void LogDebug(object message, LogLevel logLevel, Color? col = null) - { - LogDebug(message.ToString(), logLevel, col:col); - } - - [MethodImpl(MethodImplOptions.Synchronized)] - private void WriteToFile(string message) - { - if (LogFile == null) return; - - if (!Path.IsPathRooted(LogFile) && !LogFile.StartsWith(".")) - { - LogFile = Path.Join(".", LogFile); - } - - try - { - Directory.CreateDirectory(Path.GetDirectoryName(LogFile)); - File.AppendAllText(Path.GetFullPath(LogFile), message + "\n"); - } - catch (UnauthorizedAccessException) - { - Console.WriteLine("Error: User does not have permissions for log file: " + LogFile); - return; - } - catch (Exception) - { - Console.WriteLine("Error: could not write to log file: " + LogFile); - return; - } - } - - } - - public enum LogLevel - { - Error = 2, Warning = 3, Info = 4, Verbose = 5 - } -} diff --git a/PixelMap.cs b/PixelMap.cs deleted file mode 100644 index f8d2432..0000000 --- a/PixelMap.cs +++ /dev/null @@ -1,631 +0,0 @@ -using System; -using System.Buffers; -using System.Collections.Generic; -using System.Drawing; -using System.Drawing.Imaging; -using System.IO; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; - -using System.Threading; - - -//using Microsoft.Xna.Framework; -//using Microsoft.Xna.Framework.Graphics; - -//using XnaColor = Microsoft.Xna.Framework.Graphics.Color; -//using XnaRectangle = Microsoft.Xna.Framework.Rectangle; -using SysColor = System.Drawing.Color; -using SysRectangle = System.Drawing.Rectangle; - -namespace ComicCompressor -{ - /// - /// This class provides a managed C# abstraction for Portable Bit Map (.pbm), Portable Grey Map (.pgm) and - /// Portable Pixel Map (.ppm)images. The class is able to handle P1 (ASCII .pbm), P2 (ASCII .pgm) P3 (ASCII .ppm), - /// P5 (binary .pgm), and P6 (binary .ppm) files and streams. P4 (binary .pbm) is not supported. The class can - /// process normal images, which have widths that are multiples of 4 pixels wide, and can also handle "off-size" - /// images using a less efficient algorithm. It presents .pbm and .pgm images using the 8bppIndexed pixel format, - /// and presents .ppm images using the 24bppRGB pixel format. It can convert these images into a visually pleasing - /// greyscale bitmap image (in a less efficient 24bppRGB pixel format), which is accessible using the GreyMap - /// property. - /// - /// To use this class: - /// 1. Copy the PixelMap.cs file into your own project. - /// 2. Change the namespace of the class (above this summary) from "PixelMap" to the namespace of your project. - /// 3. Compile. - /// - /// This class is used by the PixelMapViewer application. - /// - public class PixelMap - { - private PixelMapHeader header; - /// - /// The header portion of the PixelMap. - /// - public PixelMapHeader Header - { - get { return header; } - set { header = value; } - } - - private byte[] imageData; - /// - /// The data portion of the PixelMap. - /// - public byte[] ImageData - { - get { return imageData; } - set { imageData = value; } - } - - private PixelFormat pixelFormat; - /// - /// The pixel format used by the BitMap generated by this PixelMap. - /// - public PixelFormat PixelFormat - { - get { return pixelFormat; } - } - - private int bytesPerPixel; - /// - /// The number of bytes per pixel. - /// - public int BytesPerPixel - { - get { return bytesPerPixel; } - } - - private int stride; - /// - /// The stride of the scan across the image. Typically this is width * bytesPerPixel, and is a multiple of 4. - /// - public int Stride - { - get { return stride; } - set { stride = value; } - } - - private Bitmap bitmap; - /// - /// The Bitmap created from the PixelMap. - /// - public Bitmap BitMap - { - get { return bitmap; } - } - - /// - /// A 24bpp Grey map (really only 8bpp of information, since R,G,B bytes are identical) created from the PixelMap. - /// - public Bitmap GreyMap - { - get { return CreateGreyMap(); } - } - - /// - /// File-based constructor. - /// - /// The name of the .pbm, .pbm, or .ppm file. - public PixelMap(string filename) - { - if (File.Exists(filename)) - { - FileStream stream = new FileStream(filename, FileMode.Open); - this.FromStream(stream); - stream.Close(); - } - else - { - throw new FileNotFoundException("The file " + filename + " does not exist", filename); - } - } - - /// - /// Stream-based constructor. Typically, the stream will be a FileStream, but it may also be a MemoryStream - /// or other object derived from the Stream class. - /// - /// A stream containing the header and data portions of the .pbm, .pgm, or .ppm image. - public PixelMap(Stream stream) - { - this.FromStream(stream); - } - - private void FromStream(Stream stream) - { - int index; - this.header = new PixelMapHeader(); - int headerItemCount = 0; - stream.Position = 0; - BinaryReader binReader = new BinaryReader(stream, Encoding.ASCII); - try - { - //1. Read the Header. - while (headerItemCount < 4) - { - char nextChar = (char)binReader.PeekChar(); - if (nextChar == '#') // comment - { - while (binReader.ReadChar() != '\n') ; // ignore the rest of the line. - } - else if (Char.IsWhiteSpace(nextChar)) // whitespace - { - binReader.ReadChar(); // ignore whitespace - } - else - { - switch (headerItemCount) - { - case 0: // next item is Magic Number - // Read the first 2 characters and determine the type of pixelmap. - char[] chars = binReader.ReadChars(2); - this.header.MagicNumber = chars[0].ToString() + chars[1].ToString(); - headerItemCount++; - break; - case 1: // next item is the width. - this.header.Width = ReadValue(binReader); - headerItemCount++; - break; - case 2: // next item is the height. - this.header.Height = ReadValue(binReader); - headerItemCount++; - break; - case 3: // next item is the depth. - if (this.header.MagicNumber == "P1" | this.header.MagicNumber == "P4") - { - // no depth value for PBM type. - headerItemCount++; - } - else - { - this.header.Depth = ReadValue(binReader); - headerItemCount++; - } - break; - default: - throw new Exception("Error parsing the file header."); - } - } - } - - // 2. Read the image data. - // 2.1 Size the imageData array to hold the image bytes. - switch (this.header.MagicNumber) - { - case "P1": // 1 byte per pixel - this.pixelFormat = PixelFormat.Format8bppIndexed; - this.bytesPerPixel = 1; - break; - case "P2": // 1 byte per pixel - this.pixelFormat = PixelFormat.Format8bppIndexed; - this.bytesPerPixel = 1; - break; - case "P3": // 3 bytes per pixel - this.pixelFormat = PixelFormat.Format24bppRgb; - this.bytesPerPixel = 3; - break; - case "P4": - this.pixelFormat = PixelFormat.Format8bppIndexed; - this.bytesPerPixel = 1; - //throw new Exception("Binary .pbm (Magic Number P4) is not supported at this time."); - break; - case "P5": // 1 byte per pixel - this.pixelFormat = PixelFormat.Format8bppIndexed; - this.bytesPerPixel = 1; - break; - case "P6": // 3 bytes per pixel - this.pixelFormat = PixelFormat.Format24bppRgb; - this.bytesPerPixel = 3; - break; - default: - throw new Exception("Unknown Magic Number: " + this.header.MagicNumber); - } - this.imageData = new byte[this.header.Width * this.header.Height * this.bytesPerPixel]; - this.stride = this.header.Width * this.bytesPerPixel; - //while ((this.stride % 4) != 0) - //{ - // this.stride++; - //} - if (this.header.MagicNumber == "P1" | this.header.MagicNumber == "P2" | this.header.MagicNumber == "P3") // ASCII Encoding - { - int charsLeft = (int)(binReader.BaseStream.Length - binReader.BaseStream.Position); - char[] charData = binReader.ReadChars(charsLeft); // read all the data into an array in one go, for efficiency. - string valueString = string.Empty; - index = 0; - for (int i = 0; i < charData.Length; i++) - { - if (Char.IsWhiteSpace(charData[i])) // value is ignored if empty, or converted to byte and added to array otherwise. - { - if (valueString != string.Empty) - { - this.imageData[index] = (byte)int.Parse(valueString); - valueString = string.Empty; - index++; - } - } - else // add the character to the end of the valueString. - { - valueString += charData[i]; - } - } - } - else if(this.header.MagicNumber == "P4") - { - byte[] pixels = ReadP4(this.Header.Width, this.Header.Height, binReader); - this.imageData = pixels; - } - else // binary encoding. - { - int bytesLeft = (int)(binReader.BaseStream.Length - binReader.BaseStream.Position); - this.imageData = binReader.ReadBytes(bytesLeft); - } - - // 3. We need to change the byte order of this.imageData from BGR to RGB. - ReorderBGRtoRGB(); - - // 4. Create the BitMap - if (this.stride % 4 == 0) - { - this.bitmap = CreateBitMap(); - } - else - { - this.bitmap = CreateBitmapOffSize(); - } - - // 5. Rotate the BitMap by 180 degrees so it is in the same orientation as the original image. - this.bitmap.RotateFlip(RotateFlipType.Rotate180FlipNone); - } - - // If the end of the stream is reached before reading all of the expected values raise an exception. - catch (EndOfStreamException e) - { - Console.WriteLine(e.Message); - throw new Exception("Error reading the stream! ", e); - } - catch (Exception ex) - { - Console.WriteLine(ex.Message); - throw new Exception("Error reading the stream! ", ex); - } - finally - { - binReader.Close(); - } - } - - private static byte[] ReadP4(int Width, int Height, BinaryReader binReader) - { - - (int imageWidth, int imageHeight) = (Width, Height); - int srcStride = (imageWidth + (8 - 1)) / 8; // Ceiling - int srcSize = imageHeight * srcStride; - var pixels = new byte[Height * Width * 1+8]; - //byte[] buffer = ArrayPool.Shared.Rent(srcSize); - try - { - int charsLeft = (int)(binReader.BaseStream.Length - binReader.BaseStream.Position); - byte[] buffer = binReader.ReadBytes(charsLeft); // read all the data into an array in one go, for efficiency. - string valueString = string.Empty; - //index = 0; - - //int readSize = await stream.ReadAsync(buffer.AsMemory(0, srcSize), cancellationToken); - //if (readSize != srcSize) - // throw new NotImplementedException($"Unable to read the intended size. Expected={srcSize}, Actual={readSize}"); - - unsafe - { - fixed (byte* destHeadPtr = pixels) - fixed (byte* srcHeadPtr = buffer) - { - byte* srcTailPtr = srcHeadPtr + (srcStride * imageHeight); - byte* dest = destHeadPtr; - (int srcWidthMax, int remainder) = Math.DivRem(imageWidth, 8); - - for (byte* srcRowPtr = srcHeadPtr; srcRowPtr < srcTailPtr; srcRowPtr += srcStride) - { - byte* srcRowTailPtr = srcRowPtr + srcWidthMax; - for (byte* p = srcRowPtr; p < srcRowTailPtr; p++) - { - //Console.Write($" {(*p).ToString("X2")}"); - - //*((ulong*)dest) = - // (((*p & 0x80) is 0) ? 0UL : 0x0000_0000_0000_0001) - // | (((*p & 0x40) is 0) ? 0UL : 0x0000_0000_0000_0100) - // | (((*p & 0x20) is 0) ? 0UL : 0x0000_0000_0001_0000) - // | (((*p & 0x10) is 0) ? 0UL : 0x0000_0000_0100_0000) - // | (((*p & 0x08) is 0) ? 0UL : 0x0000_0001_0000_0000) - // | (((*p & 0x04) is 0) ? 0UL : 0x0000_0100_0000_0000) - // | (((*p & 0x02) is 0) ? 0UL : 0x0001_0000_0000_0000) - // | (((*p & 0x01) is 0) ? 0UL : 0x0100_0000_0000_0000); - *((ulong*)dest) = - (((*p & 0x80) is 0) ? 0UL : 0x0000_0000_0000_00ff) - | (((*p & 0x40) is 0) ? 0UL : 0x0000_0000_0000_ff00) - | (((*p & 0x20) is 0) ? 0UL : 0x0000_0000_00ff_0000) - | (((*p & 0x10) is 0) ? 0UL : 0x0000_0000_ff00_0000) - | (((*p & 0x08) is 0) ? 0UL : 0x0000_00ff_0000_0000) - | (((*p & 0x04) is 0) ? 0UL : 0x0000_ff00_0000_0000) - | (((*p & 0x02) is 0) ? 0UL : 0x00ff_0000_0000_0000) - | (((*p & 0x01) is 0) ? 0UL : 0xff00_0000_0000_0000); - - dest += sizeof(ulong); - - } - - if (remainder > 0) - { - const byte start = 0x80; - byte end = (byte)(start >> remainder); - - for (int mask = start; mask > end; mask >>= 1) - *(dest++) = ((*srcRowTailPtr & mask) is 0) ? (byte)0 : (byte)1; - } - } - } - } - return pixels; - } - catch(Exception ex) - { - Console.WriteLine(ex.Message + " - " + ex.StackTrace); - } - finally - { - } - return pixels; - } - - - /// - /// As it stands, the native byte order in .pbm, .pgm, and .ppm images is BGR. We need to reverse the order - /// into RGB as this is what is needed for 24bppRGB bitmap pixel format on Windows. - /// - private void ReorderBGRtoRGB() - { - byte[] tempData = new byte[this.imageData.Length]; - for (int i = 0; i < this.imageData.Length; i++) - { - tempData[i] = this.imageData[this.imageData.Length - 1 - i]; - } - this.imageData = tempData; - } - - private int ReadValue(BinaryReader binReader) - { - string value = string.Empty; - while (!Char.IsWhiteSpace((char)binReader.PeekChar())) - { - value += binReader.ReadChar().ToString(); - } - binReader.ReadByte(); // get rid of the whitespace. - return int.Parse(value); - } - - private Bitmap CreateBitMap() - { - IntPtr pImageData = Marshal.AllocHGlobal(this.imageData.Length); - Marshal.Copy(this.imageData, 0, pImageData, this.imageData.Length); - Bitmap bitmap = new Bitmap(this.header.Width, this.header.Height, this.stride, this.pixelFormat, pImageData); - return bitmap; - } - - private Bitmap CreateGreyMap() - { - byte[] greyData = new byte[this.header.Width * this.header.Height * 3]; - int stride = this.header.Width * 3; - //while (stride % 4 != 0) - //{ - // stride++; - //} - if (stride % 4 != 0) - { - return CreateGreyMapOffSize(greyData); - } - byte grey; - switch (this.pixelFormat) - { - case PixelFormat.Format24bppRgb: - int red, green, blue; - for (int i = 0; i < this.imageData.Length; i = i + 3) - { - red = (int)this.imageData[i]; - green = (int)this.imageData[i + 1]; - blue = (int)this.imageData[i + 2]; - grey = (byte)((red + green + blue) / 3); - greyData[i] = grey; - greyData[i + 1] = grey; - greyData[i + 2] = grey; - } - break; - case PixelFormat.Format8bppIndexed: - int index = 0; - for (int i = 0; i < this.imageData.Length; i++) - { - index = 3 * i; - grey = this.imageData[i]; - if (this.header.MagicNumber == "P1") - { - if ((int)grey == 1) - { - grey = (byte)255; - } - } - greyData[index] = grey; - greyData[index + 1] = grey; - greyData[index + 2] = grey; - } - break; - default: - throw new Exception("Unsupported Pixel Format: " + this.pixelFormat.ToString()); - } - IntPtr pGreyData = Marshal.AllocHGlobal(greyData.Length); - Marshal.Copy(greyData, 0, pGreyData, greyData.Length); - Bitmap bitmap = new Bitmap(this.header.Width, this.header.Height, stride, PixelFormat.Format24bppRgb, pGreyData); - bitmap.RotateFlip(RotateFlipType.Rotate180FlipNone); - return bitmap; - } - - /// - /// This method is able to handle the process of creating Bitmaps that are not sized in widths that are multiples - /// of 4 pixels (which is needed for the rapid drawing using the Marshal class.) Unfortunately, this is a very slow - /// method, since it uses SetPixel(). - /// - /// - private Bitmap CreateBitmapOffSize() - { - Bitmap bitmap = new Bitmap(this.header.Width, this.header.Height, PixelFormat.Format24bppRgb); - SysColor sysColor = new SysColor(); - int red, green, blue, grey; - int index; - - for (int x = 0; x < this.header.Width; x++) - { - for (int y = 0; y < this.header.Height; y++) - { - index = x + y * this.header.Width; - - switch (this.header.MagicNumber) - { - case "P1": - grey = (int)this.imageData[index]; - if (grey == 1) - { - grey = 255; - } - sysColor = SysColor.FromArgb(grey, grey, grey); - break; - case "P2": - grey = (int)this.imageData[index]; - sysColor = SysColor.FromArgb(grey, grey, grey); - break; - case "P3": - index = 3 * index; - blue = (int)this.imageData[index]; - green = (int)this.imageData[index + 1]; - red = (int)this.imageData[index + 2]; - sysColor = SysColor.FromArgb(red, green, blue); - break; - case "P4": - break; - case "P5": - grey = (int)this.imageData[index]; - sysColor = SysColor.FromArgb(grey, grey, grey); - break; - case "P6": - index = 3 * index; - blue = (int)this.imageData[index]; - green = (int)this.imageData[index + 1]; - red = (int)this.imageData[index + 2]; - sysColor = SysColor.FromArgb(red, green, blue); - break; - default: - break; - } - bitmap.SetPixel(x, y, sysColor); - } - } - return bitmap; - } - - private Bitmap CreateGreyMapOffSize(byte[] greyData) - { - Bitmap bitmap = new Bitmap(this.header.Width, this.header.Height, PixelFormat.Format24bppRgb); - SysColor sysColor = new SysColor(); - int index = 0; - int x = 0; - int y = -1; - switch (this.pixelFormat) - { - case PixelFormat.Format24bppRgb: - int red, green, blue, grey; - for (int i = 0; i < this.imageData.Length; i = i + 3) - { - index = i / 3; // the current pixel - if (index%this.header.Width == 0) y++; // the current row = y; - x = index - y * this.header.Width; // the current column = x; - red = (int)this.imageData[i]; - green = (int)this.imageData[i + 1]; - blue = (int)this.imageData[i + 2]; - grey = (byte)((red + green + blue) / 3); - sysColor = SysColor.FromArgb(grey, grey, grey); - bitmap.SetPixel(x, y, sysColor); - } - break; - case PixelFormat.Format8bppIndexed: - for (int i = 0; i < this.imageData.Length; i++) - { - index = i; // the current pixel - if (index % this.header.Width == 0) y++; // the current row = y; - x = index - y * this.header.Width; // the current column = x; - - grey = this.imageData[i]; - if (this.header.MagicNumber == "P1") - { - if ((int)grey == 1) - { - grey = (byte)255; - } - } - sysColor = SysColor.FromArgb(grey, grey, grey); - bitmap.SetPixel(x, y, sysColor); - } - break; - default: - throw new Exception("Unsupported Pixel Format: " + this.pixelFormat.ToString()); - } - bitmap.RotateFlip(RotateFlipType.Rotate180FlipNone); - return bitmap; - } - - /// - /// This struct contains the objects that are found in the header of .pbm, .pgm, and .ppm files. - /// - [Serializable] - public struct PixelMapHeader - { - private string magicNumber; - /// - /// The "Magic Number" that identifies the type of Pixelmap. P1 = PBM (ASCII); P2 = PGM (ASCII); P3 = PPM (ASCII); P4 is not used; - /// P5 = PGM (Binary); P6 = PPM (Binary). - /// - public string MagicNumber - { - get { return magicNumber; } - set { magicNumber = value; } - } - - private int width; - /// - /// The width of the image. - /// - public int Width - { - get { return width; } - set { width = value; } - } - - private int height; - /// - /// The height of the image. - /// - public int Height - { - get { return height; } - set { height = value; } - } - - private int depth; - /// - /// The depth (maximum color value in each channel) of the image. This allows the format to represent - /// more than a single byte (0-255) for each color channel. - /// - public int Depth - { - get { return depth; } - set { depth = value; } - } - } - } -} diff --git a/Program.cs b/Program.cs index e65235f..d5e9e5f 100644 --- a/Program.cs +++ b/Program.cs @@ -35,6 +35,10 @@ using Xabe.FFmpeg.Downloader; using System.Reflection; using Microsoft.VisualBasic; using BinaryKits.Zpl.Viewer; +using iMGcompress_core; + + + namespace ComicCompressor { @@ -125,8 +129,27 @@ namespace ComicCompressor // static Color randomColor = Color.FromKnownColor(randomColorName); public Color[] myColors = null; + + + + //static void TestPar2() + //{ + // var items = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; + + // // Create a SingleItemPartitioner from the collection + // var partitioner = new Partitioner(items); + + // // Use Parallel.ForEach to process items in parallel + // Parallel.ForEach(partitioner, item => + // { + // Console.WriteLine($"Processing item: {item}"); + // }); + //} + private void OnExecute() { + + File_statistics.Clear(); @@ -141,7 +164,7 @@ namespace ComicCompressor Stopwatch sw = Stopwatch.StartNew(); Logger = new Logger(); - Logger.Debug = true; + Logger.DebugOn = true; Logger.LoggingLevel = LogLevel.Verbose; Logger.Log(progVersion, LogLevel.Verbose, true); diff --git a/Properties/PublishProfiles/FolderProfile.pubxml b/Properties/PublishProfiles/FolderProfile.pubxml new file mode 100644 index 0000000..10f1155 --- /dev/null +++ b/Properties/PublishProfiles/FolderProfile.pubxml @@ -0,0 +1,11 @@ + + + + + Release + Any CPU + bin\Release\net8.0\publish\ + FileSystem + <_TargetId>Folder + + \ No newline at end of file diff --git a/Properties/PublishProfiles/FolderProfile.pubxml.user b/Properties/PublishProfiles/FolderProfile.pubxml.user new file mode 100644 index 0000000..4144f92 --- /dev/null +++ b/Properties/PublishProfiles/FolderProfile.pubxml.user @@ -0,0 +1,8 @@ + + + + + True|2025-03-12T20:02:41.5913059Z||; + + + \ No newline at end of file diff --git a/pdfimages.exe b/pdfimages.exe new file mode 100644 index 0000000..08a87cd Binary files /dev/null and b/pdfimages.exe differ