From d43e82f8368651657579ddadbf0c2c6687e4bf90 Mon Sep 17 00:00:00 2001 From: Brian Popow Date: Mon, 4 Feb 2019 21:55:44 +0100 Subject: [PATCH] Fix Decoding 8-Bit grayscale png's with alpha --- .../Formats/Png/PngScanlineProcessor.cs | 3 +- .../Formats/Png/PngDecoderTests.cs | 30 ++++++++++++++++++ tests/ImageSharp.Tests/TestImages.cs | 1 + tests/Images/Input/Png/rollsroyce.png | Bin 0 -> 25400 bytes 4 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 tests/Images/Input/Png/rollsroyce.png diff --git a/src/ImageSharp/Formats/Png/PngScanlineProcessor.cs b/src/ImageSharp/Formats/Png/PngScanlineProcessor.cs index 4242b2d554..40c2841176 100644 --- a/src/ImageSharp/Formats/Png/PngScanlineProcessor.cs +++ b/src/ImageSharp/Formats/Png/PngScanlineProcessor.cs @@ -240,9 +240,9 @@ public static void ProcessInterlacedGrayscaleWithAlphaScanline( else { Rgba32 rgba32 = default; + int offset = 0; for (int x = pixelOffset; x < header.Width; x += increment) { - int offset = x * bytesPerPixel; byte luminance = Unsafe.Add(ref scanlineSpanRef, offset); byte alpha = Unsafe.Add(ref scanlineSpanRef, offset + bytesPerSample); rgba32.R = luminance; @@ -252,6 +252,7 @@ public static void ProcessInterlacedGrayscaleWithAlphaScanline( pixel.FromRgba32(rgba32); Unsafe.Add(ref rowSpanRef, x) = pixel; + offset += bytesPerPixel; } } } diff --git a/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs index f51f9b6c5c..1452f233b6 100644 --- a/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs @@ -67,6 +67,12 @@ public partial class PngDecoderTests TestImages.Png.GrayTrns16BitInterlaced }; + public static readonly string[] TestImagesGrayAlpha8Bit = + { + TestImages.Png.GrayAlpha8Bit, + TestImages.Png.GrayAlpha8Bit2 + }; + public static readonly TheoryData RatioFiles = new TheoryData { @@ -123,6 +129,18 @@ public void Decode_64Bpp(TestImageProvider provider) } } + [Theory] + [WithFileCollection(nameof(TestImagesGrayAlpha8Bit), PixelTypes.Rgba32)] + public void Decoder_Gray8bitWithAlpha(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage(new PngDecoder())) + { + image.DebugSave(provider); + image.CompareToOriginal(provider, ImageComparer.Exact); + } + } + [Theory] [WithFileCollection(nameof(TestImagesGray16Bit), PixelTypes.Rgb48)] public void Decode_Gray16Bit(TestImageProvider provider) @@ -159,6 +177,18 @@ public void Decoder_IsNotBoundToSinglePixelType(TestImageProvider(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage(new PngDecoder())) + { + image.DebugSave(provider); + image.CompareToOriginal(provider, ImageComparer.Exact); + } + } + [Fact] public void Decode_IgnoreMetadataIsFalse_TextChunckIsRead() { diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs index d83fe4907d..92773df7e4 100644 --- a/tests/ImageSharp.Tests/TestImages.cs +++ b/tests/ImageSharp.Tests/TestImages.cs @@ -29,6 +29,7 @@ public static class Png public const string Gray4Bpp = "Png/gray_4bpp.png"; public const string Gray16Bit = "Png/gray-16.png"; public const string GrayAlpha8Bit = "Png/gray-alpha-8.png"; + public const string GrayAlpha8Bit2 = "Png/rollsroyce.png"; public const string GrayAlpha16Bit = "Png/gray-alpha-16.png"; public const string GrayTrns16BitInterlaced = "Png/gray-16-tRNS-interlaced.png"; public const string Rgb24BppTrans = "Png/rgb-8-tRNS.png"; diff --git a/tests/Images/Input/Png/rollsroyce.png b/tests/Images/Input/Png/rollsroyce.png new file mode 100644 index 0000000000000000000000000000000000000000..7067372a2c247d4dd78d021e5f34d7a51af22a78 GIT binary patch literal 25400 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⪙6N+Jhf@*qv_Y#mrlPc<@jWQ_@LMoP5 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 literal 0 HcmV?d00001