naps2/NAPS2.Images/Bitwise/LogicalPixelFormatOp.cs
2024-04-07 17:09:22 -07:00

98 lines
3.1 KiB
C#

namespace NAPS2.Images.Bitwise;
internal class LogicalPixelFormatOp : UnaryBitwiseImageOp
{
public ImagePixelFormat LogicalPixelFormat { get; private set; }
protected override LockMode LockMode => LockMode.ReadOnly;
protected override void ValidateCore(BitwiseImageData data)
{
}
protected override unsafe void PerformCore(BitwiseImageData data, int partStart, int partEnd)
{
lock (this)
{
if (data.bitsPerPixel == 1)
{
LogicalPixelFormat = ImagePixelFormat.BW1;
return;
}
}
bool readGray = data.bytesPerPixel == 1;
bool isBinary = true;
bool isGray = true;
bool isOpaque = true;
bool checkBinary = data.bytesPerPixel >= 1;
bool checkGray = data.bytesPerPixel >= 3;
bool checkOpacity = data.hasAlpha;
for (int i = partStart; i < partEnd; i++)
{
byte* row = data.ptr + data.stride * i;
for (int j = 0; j < data.w; j++)
{
byte* pixel = row + data.bytesPerPixel * j;
if (readGray)
{
if (checkBinary)
{
byte val = *pixel;
if (val != 0 && val != 255)
{
isBinary = false;
break;
}
}
}
else
{
var r = *(pixel + data.rOff);
var g = *(pixel + data.gOff);
var b = *(pixel + data.bOff);
if (checkOpacity)
{
var a = *(pixel + data.aOff);
if (a != 255)
{
isOpaque = false;
checkOpacity = false;
break;
}
}
if (checkGray)
{
if (r != g || g != b)
{
isGray = false;
isBinary = false;
checkGray = false;
checkBinary = false;
if (!checkOpacity) break;
}
}
if (checkBinary)
{
if ((r != 0 && r != 255) || (g != 0 && g != 255) || (b != 0 && b != 255))
{
isBinary = false;
checkBinary = false;
}
}
}
}
}
var pixelFormat = isBinary && isOpaque ? ImagePixelFormat.BW1 :
isGray && isOpaque ? ImagePixelFormat.Gray8 :
isOpaque ? ImagePixelFormat.RGB24 : ImagePixelFormat.ARGB32;
lock (this)
{
if (pixelFormat > LogicalPixelFormat)
{
LogicalPixelFormat = pixelFormat;
}
}
}
}