pixelmap/compressor - added support for pbm P4
moved to .net 8.0
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
<RootNamespace>ComicCompressor</RootNamespace>
|
<RootNamespace>ComicCompressor</RootNamespace>
|
||||||
<OutputName>ComicCompress</OutputName>
|
<OutputName>ComicCompress</OutputName>
|
||||||
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
|
||||||
|
|||||||
+35
-21
@@ -14,6 +14,9 @@ using javax.swing.plaf;
|
|||||||
using SharpCompress.Readers;
|
using SharpCompress.Readers;
|
||||||
using SharpCompress.Writers;
|
using SharpCompress.Writers;
|
||||||
using SharpCompress.Compressors.Xz;
|
using SharpCompress.Compressors.Xz;
|
||||||
|
//using SixLabors.ImageSharp;
|
||||||
|
//using SixLabors.ImageSharp;
|
||||||
|
//using SixLabors.ImageSharp.Processing;
|
||||||
|
|
||||||
namespace ComicCompressor
|
namespace ComicCompressor
|
||||||
{
|
{
|
||||||
@@ -72,18 +75,18 @@ namespace ComicCompressor
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Logger.Log($"Processing[{archive.Entries.Count()}]: " + filename, LogLevel.Verbose);
|
//Logger.Log($"Processing[{archive.Entries.Count()}]: " + filename, LogLevel.Verbose);
|
||||||
Logger.Log($"Processing[{archive.Entries.Count()}]: ", LogLevel.Verbose,false);
|
Logger.Log($"Processing[{archive.Entries.Count()}]: ", LogLevel.Verbose, false);
|
||||||
Logger.Log( filename, LogLevel.Verbose,col:Color.Green);
|
Logger.Log(filename, LogLevel.Verbose, col: Color.Green);
|
||||||
|
|
||||||
double save = 0;
|
double save = 0;
|
||||||
int num_pages =0;
|
int num_pages = 0;
|
||||||
if (isSolid)
|
if (isSolid)
|
||||||
{
|
{
|
||||||
using (Stream stream = File.OpenRead(filename))
|
using (Stream stream = File.OpenRead(filename))
|
||||||
{
|
{
|
||||||
using (var reader = ReaderFactory.Open(stream))
|
using (var reader = ReaderFactory.Open(stream))
|
||||||
{
|
{
|
||||||
(save, num_pages) = ProcessReader(archive,reader, outputFile);
|
(save, num_pages) = ProcessReader(archive, reader, outputFile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -91,7 +94,7 @@ namespace ComicCompressor
|
|||||||
(save, num_pages) = ProcessArchive(archive, outputFile, filename);
|
(save, num_pages) = ProcessArchive(archive, outputFile, filename);
|
||||||
if (num_pages == 0) num_pages = 1;
|
if (num_pages == 0) num_pages = 1;
|
||||||
long elapsed = sw.ElapsedMilliseconds;
|
long elapsed = sw.ElapsedMilliseconds;
|
||||||
Logger.Log($"\r\nFinished({save.ToString("0.##")}%) [{elapsed}][{elapsed/num_pages}]: " + filename, LogLevel.Verbose, col: Color.Green);
|
Logger.Log($"\r\nFinished({save.ToString("0.##")}%) [{elapsed}][{elapsed / num_pages}]: " + filename, LogLevel.Verbose, col: Color.Green);
|
||||||
}
|
}
|
||||||
|
|
||||||
private (double, int) ProcessReader(IArchive archive, IReader reader, string outputPath)
|
private (double, int) ProcessReader(IArchive archive, IReader reader, string outputPath)
|
||||||
@@ -125,6 +128,7 @@ namespace ComicCompressor
|
|||||||
!entry_key_lower.EndsWith(".png") &&
|
!entry_key_lower.EndsWith(".png") &&
|
||||||
!entry_key_lower.EndsWith(".bmp") &&
|
!entry_key_lower.EndsWith(".bmp") &&
|
||||||
!entry_key_lower.EndsWith(".ppm") &&
|
!entry_key_lower.EndsWith(".ppm") &&
|
||||||
|
!entry_key_lower.EndsWith(".pbm") &&
|
||||||
!entry_key_lower.EndsWith(".gif") &&
|
!entry_key_lower.EndsWith(".gif") &&
|
||||||
!entry_key_lower.EndsWith(".jpeg"))
|
!entry_key_lower.EndsWith(".jpeg"))
|
||||||
{
|
{
|
||||||
@@ -169,7 +173,7 @@ namespace ComicCompressor
|
|||||||
|
|
||||||
save = 100 * (double)output_length / (double)archive.TotalSize;
|
save = 100 * (double)output_length / (double)archive.TotalSize;
|
||||||
|
|
||||||
return (save,nop);
|
return (save, nop);
|
||||||
}
|
}
|
||||||
public int GetPlace(int value, int place)
|
public int GetPlace(int value, int place)
|
||||||
{
|
{
|
||||||
@@ -223,8 +227,8 @@ namespace ComicCompressor
|
|||||||
save = 100 * (double)output_length / (double)archive.TotalSize;
|
save = 100 * (double)output_length / (double)archive.TotalSize;
|
||||||
|
|
||||||
Program.file_stat fs = null;
|
Program.file_stat fs = null;
|
||||||
Program.File_statistics.TryGetValue(inputPath,out fs);
|
Program.File_statistics.TryGetValue(inputPath, out fs);
|
||||||
if(fs != null)
|
if (fs != null)
|
||||||
{
|
{
|
||||||
fs.Uncompressed_file_len = archive.TotalSize;
|
fs.Uncompressed_file_len = archive.TotalSize;
|
||||||
fs.Compressed_file_len = output_length;
|
fs.Compressed_file_len = output_length;
|
||||||
@@ -244,7 +248,7 @@ namespace ComicCompressor
|
|||||||
if (entry.IsEncrypted)
|
if (entry.IsEncrypted)
|
||||||
{
|
{
|
||||||
Logger.Log("X", LogLevel.Verbose, false, col: Color.Yellow);
|
Logger.Log("X", LogLevel.Verbose, false, col: Color.Yellow);
|
||||||
return (false,true);
|
return (false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -253,15 +257,17 @@ namespace ComicCompressor
|
|||||||
|
|
||||||
if (entry.Key.StartsWith("__MACOSX"))
|
if (entry.Key.StartsWith("__MACOSX"))
|
||||||
{
|
{
|
||||||
return (false,true);
|
return (false, true);
|
||||||
}
|
}
|
||||||
string entry_key_lower = entry.Key.ToLower();
|
string entry_key_lower = entry.Key.ToLower();
|
||||||
bool isPPM = entry_key_lower.EndsWith(".ppm");
|
bool isPPM = entry_key_lower.EndsWith(".ppm");
|
||||||
|
bool isPBM = entry_key_lower.EndsWith(".pbm");
|
||||||
|
|
||||||
if (!entry_key_lower.EndsWith(".jpg") &&
|
if (!entry_key_lower.EndsWith(".jpg") &&
|
||||||
!entry_key_lower.EndsWith(".png") &&
|
!entry_key_lower.EndsWith(".png") &&
|
||||||
!entry_key_lower.EndsWith(".bmp") &&
|
!entry_key_lower.EndsWith(".bmp") &&
|
||||||
!entry_key_lower.EndsWith(".ppm") &&
|
!entry_key_lower.EndsWith(".ppm") &&
|
||||||
|
!entry_key_lower.EndsWith(".pbm") &&
|
||||||
!entry_key_lower.EndsWith(".gif") &&
|
!entry_key_lower.EndsWith(".gif") &&
|
||||||
!entry_key_lower.EndsWith(".jpeg"))
|
!entry_key_lower.EndsWith(".jpeg"))
|
||||||
{
|
{
|
||||||
@@ -273,13 +279,13 @@ namespace ComicCompressor
|
|||||||
return (false, true);
|
return (false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cover && !isPPM)
|
if (cover && !isPPM && !isPBM)
|
||||||
{
|
{
|
||||||
var ms = new MemoryStream();
|
var ms = new MemoryStream();
|
||||||
imageStreams.Add(ms);
|
imageStreams.Add(ms);
|
||||||
stream.CopyTo(ms);
|
stream.CopyTo(ms);
|
||||||
output.AddEntry(entry.Key, ms);
|
output.AddEntry(entry.Key, ms);
|
||||||
Logger.Log("C", LogLevel.Verbose, false,col:Color.Green);
|
Logger.Log("C", LogLevel.Verbose, false, col: Color.Green);
|
||||||
return (true, false);
|
return (true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -289,7 +295,7 @@ namespace ComicCompressor
|
|||||||
stream.CopyTo(raw_ms);
|
stream.CopyTo(raw_ms);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if(isPPM)
|
if (isPPM)
|
||||||
{
|
{
|
||||||
Logger.Log("P", LogLevel.Verbose, false, col: Color.PaleGreen);
|
Logger.Log("P", LogLevel.Verbose, false, col: Color.PaleGreen);
|
||||||
PixelMap ppm = new PixelMap(raw_ms);
|
PixelMap ppm = new PixelMap(raw_ms);
|
||||||
@@ -297,6 +303,14 @@ namespace ComicCompressor
|
|||||||
bits = ppm.BitMap;
|
bits = ppm.BitMap;
|
||||||
Logger.Log("\b", LogLevel.Verbose, false, col: Color.PaleGreen);
|
Logger.Log("\b", LogLevel.Verbose, false, col: Color.PaleGreen);
|
||||||
}
|
}
|
||||||
|
else if (isPBM)
|
||||||
|
{
|
||||||
|
Logger.Log("B", LogLevel.Verbose, false, col: Color.PaleGreen);
|
||||||
|
PixelMap pbm = new PixelMap(raw_ms);
|
||||||
|
bits = pbm.BitMap;
|
||||||
|
Logger.Log("\b", LogLevel.Verbose, false, col: Color.PaleGreen);
|
||||||
|
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bits = new Bitmap(raw_ms);
|
bits = new Bitmap(raw_ms);
|
||||||
@@ -305,7 +319,7 @@ namespace ComicCompressor
|
|||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Logger.LogError("Error parsing bitmap: " + entry.Key, col: Color.Red);
|
Logger.LogError("Error parsing bitmap: " + entry.Key, col: Color.Red);
|
||||||
Logger.LogDebug(e, LogLevel.Error, col:Color.Red);
|
Logger.LogDebug(e, LogLevel.Error, col: Color.Red);
|
||||||
return (false, true);
|
return (false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -320,7 +334,7 @@ namespace ComicCompressor
|
|||||||
{
|
{
|
||||||
var ms = new MemoryStream();
|
var ms = new MemoryStream();
|
||||||
encoder.Encode(bits, ms, Quality);
|
encoder.Encode(bits, ms, Quality);
|
||||||
if (ms.Length < entry.Size)
|
if (ms.Length < entry.Size || isPBM)
|
||||||
{
|
{
|
||||||
imageStreams.Add(ms);
|
imageStreams.Add(ms);
|
||||||
output.AddEntry(entry.Key + ".webp", ms);
|
output.AddEntry(entry.Key + ".webp", ms);
|
||||||
@@ -364,15 +378,15 @@ namespace ComicCompressor
|
|||||||
Process proc = Process.GetCurrentProcess();
|
Process proc = Process.GetCurrentProcess();
|
||||||
//Logger.LogDebug($"M {proc.PrivateMemorySize64} - D {proc.PrivateMemorySize64 - last_mem}", LogLevel.Verbose);
|
//Logger.LogDebug($"M {proc.PrivateMemorySize64} - D {proc.PrivateMemorySize64 - last_mem}", LogLevel.Verbose);
|
||||||
//last_mem = proc.PrivateMemorySize64;
|
//last_mem = proc.PrivateMemorySize64;
|
||||||
return (false,false);
|
return (false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ProcessReaderEntry(IReader reader,EntryStream entry, IList<Stream> imageStreams, ZipArchive output, SimpleEncoder encoder)
|
private void ProcessReaderEntry(IReader reader, EntryStream entry, IList<Stream> imageStreams, ZipArchive output, SimpleEncoder encoder)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var stream = entry;
|
var stream = entry;
|
||||||
// using (var stream = entry.OpenEntryStream())
|
// using (var stream = entry.OpenEntryStream())
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
@@ -389,7 +403,7 @@ namespace ComicCompressor
|
|||||||
{
|
{
|
||||||
Logger.LogError("Error parsing bitmap: " + reader.Entry.Key, col: Color.Red);
|
Logger.LogError("Error parsing bitmap: " + reader.Entry.Key, col: Color.Red);
|
||||||
Logger.LogDebug(e, LogLevel.Error, col: Color.Red);
|
Logger.LogDebug(e, LogLevel.Error, col: Color.Red);
|
||||||
return ;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bits.PixelFormat != System.Drawing.Imaging.PixelFormat.Format24bppRgb)
|
if (bits.PixelFormat != System.Drawing.Imaging.PixelFormat.Format24bppRgb)
|
||||||
@@ -435,7 +449,7 @@ namespace ComicCompressor
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Bitmap ChangePixelFormat(Bitmap orig, System.Drawing.Imaging.PixelFormat format = System.Drawing.Imaging.PixelFormat.Format24bppRgb)
|
private Bitmap ChangePixelFormat(Bitmap orig, System.Drawing.Imaging.PixelFormat format = System.Drawing.Imaging.PixelFormat.Format24bppRgb)
|
||||||
|
|||||||
+96
-1
@@ -1,10 +1,15 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Buffers;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Drawing.Imaging;
|
using System.Drawing.Imaging;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
|
||||||
//using Microsoft.Xna.Framework;
|
//using Microsoft.Xna.Framework;
|
||||||
//using Microsoft.Xna.Framework.Graphics;
|
//using Microsoft.Xna.Framework.Graphics;
|
||||||
@@ -202,7 +207,10 @@ namespace ComicCompressor
|
|||||||
this.bytesPerPixel = 3;
|
this.bytesPerPixel = 3;
|
||||||
break;
|
break;
|
||||||
case "P4":
|
case "P4":
|
||||||
throw new Exception("Binary .pbm (Magic Number P4) is not supported at this time.");
|
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
|
case "P5": // 1 byte per pixel
|
||||||
this.pixelFormat = PixelFormat.Format8bppIndexed;
|
this.pixelFormat = PixelFormat.Format8bppIndexed;
|
||||||
this.bytesPerPixel = 1;
|
this.bytesPerPixel = 1;
|
||||||
@@ -243,6 +251,11 @@ namespace ComicCompressor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if(this.header.MagicNumber == "P4")
|
||||||
|
{
|
||||||
|
byte[] pixels = ReadP4(this.Header.Width, this.Header.Height, binReader);
|
||||||
|
this.imageData = pixels;
|
||||||
|
}
|
||||||
else // binary encoding.
|
else // binary encoding.
|
||||||
{
|
{
|
||||||
int bytesLeft = (int)(binReader.BaseStream.Length - binReader.BaseStream.Position);
|
int bytesLeft = (int)(binReader.BaseStream.Length - binReader.BaseStream.Position);
|
||||||
@@ -283,6 +296,88 @@ namespace ComicCompressor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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<byte>.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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// As it stands, the native byte order in .pbm, .pgm, and .ppm images is BGR. We need to reverse the order
|
/// 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.
|
/// into RGB as this is what is needed for 24bppRGB bitmap pixel format on Windows.
|
||||||
|
|||||||
Reference in New Issue
Block a user