pixelmap/compressor - added support for pbm P4

moved to .net 8.0
This commit is contained in:
Marco Giuntoni
2024-05-11 10:31:24 +02:00
parent 035652d292
commit c6954071c8
3 changed files with 144 additions and 35 deletions
+96 -1
View File
@@ -1,10 +1,15 @@
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;
@@ -202,7 +207,10 @@ namespace ComicCompressor
this.bytesPerPixel = 3;
break;
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
this.pixelFormat = PixelFormat.Format8bppIndexed;
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.
{
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>
/// 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.