Skip to content

Commit

Permalink
Fix combine for black & white
Browse files Browse the repository at this point in the history
  • Loading branch information
cyanfish committed Aug 5, 2024
1 parent ff0d9e9 commit 5cd0079
Show file tree
Hide file tree
Showing 9 changed files with 89 additions and 2 deletions.
1 change: 1 addition & 0 deletions NAPS2.Images/Bitwise/BitwisePrimitives.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ public static unsafe void Fill(BitwiseImageData data, byte value, int partStart
{
if (partStart == -1) partStart = 0;
if (partEnd == -1) partEnd = data.h;
if (data.invertColorSpace) value = (byte) ~value;

var longCount = data.stride / 8;
var remainingStart = longCount * 8;
Expand Down
11 changes: 9 additions & 2 deletions NAPS2.Images/Bitwise/CopyBitwiseImageOp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,14 @@ protected override void ValidateCore(BitwiseImageData src, BitwiseImageData dst)
protected override void PerformCore(BitwiseImageData src, BitwiseImageData dst, int partStart, int partEnd)
{
if (src.BitLayout == dst.BitLayout &&
(src.bytesPerPixel > 0 || (SourceXOffset % 8 == 0 && DestXOffset % 8 == 0)) &&
DestChannel == ColorChannel.All)
DestChannel == ColorChannel.All &&
(src.bytesPerPixel > 0 ||
// For Black & White images, to use the fast copy path, we must have that:
// 1. The offsets are to whole bytes
// 2a. Either we copy whole bytes, or
// 2b. We end at the far-right side of the destination (so any excess bits copied will be ignored)
(SourceXOffset % 8 == 0 && DestXOffset % 8 == 0 &&
(src.w % 8 == 0 || src.w + DestXOffset == dst.w))))
{
FastCopy(src, dst, partStart, partEnd);
}
Expand Down Expand Up @@ -254,6 +260,7 @@ private unsafe void UnalignedBitCopy(BitwiseImageData src, BitwiseImageData dst,
var dstPixelIndex = j + DestXOffset;
var dstPtr = dstRow + dstPixelIndex / 8;
var dstByte = *dstPtr;
dstByte &= (byte) ~(1 << (7 - dstPixelIndex % 8));
dstByte |= (byte) (bit << (7 - dstPixelIndex % 8));
*dstPtr = dstByte;
}
Expand Down
14 changes: 14 additions & 0 deletions NAPS2.Images/Bitwise/FillColorImageOp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,20 @@ public FillColorImageOp(byte r, byte g, byte b, byte a)
_a = a;
}

protected override void ValidateCore(BitwiseImageData data)
{
}

protected override void PerformCore(BitwiseImageData data, int partStart, int partEnd)
{
if (data.bytesPerPixel is 1 or 3 or 4)
{
PerformRgba(data, partStart, partEnd);
}
else if (data.bitsPerPixel == 1 && (_r, _g, _b, _a) is (0, 0, 0, 255) or (255, 255, 255, 255))
{
PerformBw(data, partStart, partEnd);
}
else
{
throw new InvalidOperationException("Unsupported pixel format");
Expand Down Expand Up @@ -54,4 +62,10 @@ private unsafe void PerformRgba(BitwiseImageData data, int partStart, int partEn
}
}
}

private void PerformBw(BitwiseImageData data, int partStart, int partEnd)
{
byte fill = (byte) (_r == 255 ? 0xFF : 0x00);
BitwisePrimitives.Fill(data, fill, partStart, partEnd);
}
}
30 changes: 30 additions & 0 deletions NAPS2.Sdk.Tests/ImageResources.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions NAPS2.Sdk.Tests/ImageResources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,9 @@
<data name="skewed_bw" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>Resources\skewed_bw.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="cat" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>Resources\cat.jpg;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="stock_cat" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>Resources\stock-cat.jpeg;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
Expand Down Expand Up @@ -304,4 +307,10 @@
<data name="dog_exif" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>Resources\dog_exif.jpg;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="dog_cat_combined" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>Resources\dog_cat_combined.jpg;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="dog_cat_combined_bw" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>Resources\dog_cat_combined_bw.jpg;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
</root>
26 changes: 26 additions & 0 deletions NAPS2.Sdk.Tests/Images/TransformTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,32 @@ public void Thumbnail()
AssertOwnership(original, transformed);
}

[Fact]
public void Combine()
{
var first = LoadImage(ImageResources.dog);
var second = LoadImage(ImageResources.cat);
var expected = LoadImage(ImageResources.dog_cat_combined);

var transformed = MoreImageTransforms.Combine(first, second, CombineOrientation.Vertical);
Assert.Equal(ImagePixelFormat.RGB24, transformed.PixelFormat);

ImageAsserts.Similar(expected, transformed, ImageAsserts.GENERAL_RMSE_THRESHOLD);
}

[Fact]
public void CombineBlackAndWhite()
{
var first = LoadImage(ImageResources.dog).PerformTransform(new BlackWhiteTransform());
var second = LoadImage(ImageResources.cat).PerformTransform(new BlackWhiteTransform());
var expected = LoadImage(ImageResources.dog_cat_combined_bw).PerformTransform(new BlackWhiteTransform());

var transformed = MoreImageTransforms.Combine(first, second, CombineOrientation.Vertical);
Assert.Equal(ImagePixelFormat.BW1, transformed.UpdateLogicalPixelFormat());

ImageAsserts.Similar(expected, transformed, ImageAsserts.XPLAT_RMSE_THRESHOLD);
}

private void AssertOwnership(IMemoryImage original, IMemoryImage transformed)
{
// The contract for a transform is that either it returns the original image or it disposes the original and
Expand Down
Binary file added NAPS2.Sdk.Tests/Resources/cat.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added NAPS2.Sdk.Tests/Resources/dog_cat_combined.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 5cd0079

Please sign in to comment.