From 329ea7ad0c331d09d628616e08c58f466a6a2969 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Fri, 18 Nov 2016 00:45:02 +1100 Subject: [PATCH] Fix decoding grayscale png --- .../Common/Extensions/ByteExtensions.cs | 44 --------------- src/ImageSharp/Formats/Png/PngDecoderCore.cs | 54 +++++++++++++++++-- 2 files changed, 49 insertions(+), 49 deletions(-) diff --git a/src/ImageSharp/Common/Extensions/ByteExtensions.cs b/src/ImageSharp/Common/Extensions/ByteExtensions.cs index cca014073..350777387 100644 --- a/src/ImageSharp/Common/Extensions/ByteExtensions.cs +++ b/src/ImageSharp/Common/Extensions/ByteExtensions.cs @@ -12,50 +12,6 @@ namespace ImageSharp /// internal static class ByteExtensions { - /// - /// Converts a byte array to a new array where each value in the original array is represented - /// by a the specified number of bits. - /// - /// The bytes to convert from. Cannot be null. - /// The number of bits per value. - /// The resulting array. Is never null. - /// is null. - /// is less than or equals than zero. - public static byte[] ToArrayByBitsLength(this byte[] source, int bits) - { - Guard.NotNull(source, nameof(source)); - Guard.MustBeGreaterThan(bits, 0, nameof(bits)); - - byte[] result; - - if (bits < 8) - { - result = new byte[source.Length * 8 / bits]; - int mask = 0xFF >> (8 - bits); - int resultOffset = 0; - - // ReSharper disable once ForCanBeConvertedToForeach - for (int i = 0; i < source.Length; i++) - { - byte b = source[i]; - for (int shift = 0; shift < 8; shift += bits) - { - int colorIndex = (b >> (8 - bits - shift)) & mask; - - result[resultOffset] = (byte)colorIndex; - - resultOffset++; - } - } - } - else - { - result = source; - } - - return result; - } - /// /// Optimized reversal algorithm. /// diff --git a/src/ImageSharp/Formats/Png/PngDecoderCore.cs b/src/ImageSharp/Formats/Png/PngDecoderCore.cs index 4d581b2b6..07761ae90 100644 --- a/src/ImageSharp/Formats/Png/PngDecoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngDecoderCore.cs @@ -192,6 +192,50 @@ namespace ImageSharp.Formats } } + /// + /// Converts a byte array to a new array where each value in the original array is represented + /// by a the specified number of bits. + /// + /// The bytes to convert from. Cannot be null. + /// The number of bits per value. + /// The resulting array. Is never null. + /// is null. + /// is less than or equals than zero. + private static byte[] ToArrayByBitsLength(byte[] source, int bits) + { + Guard.NotNull(source, nameof(source)); + Guard.MustBeGreaterThan(bits, 0, nameof(bits)); + + byte[] result; + + if (bits < 8) + { + result = new byte[source.Length * 8 / bits]; + int mask = 0xFF >> (8 - bits); + int resultOffset = 0; + + // ReSharper disable once ForCanBeConvertedToForeach + for (int i = 0; i < source.Length; i++) + { + byte b = source[i]; + for (int shift = 0; shift < 8; shift += bits) + { + int colorIndex = (b >> (8 - bits - shift)) & mask; + + result[resultOffset] = (byte)colorIndex; + + resultOffset++; + } + } + } + else + { + result = source; + } + + return result; + } + /// /// Reads the data chunk containing physical dimension data. /// @@ -366,12 +410,12 @@ namespace ImageSharp.Formats switch (this.PngColorType) { case PngColorType.Grayscale: - + int factor = 255 / ((int)Math.Pow(2, this.header.BitDepth) - 1); + byte[] newScanline1 = ToArrayByBitsLength(defilteredScanline, this.header.BitDepth); for (int x = 0; x < this.header.Width; x++) { - int offset = 1 + (x * this.bytesPerPixel); - - byte intensity = defilteredScanline[offset]; + int offset = 1 + ((x + 1) * this.bytesPerPixel); + byte intensity = (byte)(newScanline1[offset] * factor); color.PackFromBytes(intensity, intensity, intensity, 255); pixels[x, row] = color; } @@ -395,7 +439,7 @@ namespace ImageSharp.Formats case PngColorType.Palette: - byte[] newScanline = defilteredScanline.ToArrayByBitsLength(this.header.BitDepth); + byte[] newScanline = ToArrayByBitsLength(defilteredScanline, this.header.BitDepth); if (this.paletteAlpha != null && this.paletteAlpha.Length > 0) {