diff --git a/src/ImageSharp/Formats/Png/Filters/AverageFilter.cs b/src/ImageSharp/Formats/Png/Filters/AverageFilter.cs index 7a94ee32b..de494d42d 100644 --- a/src/ImageSharp/Formats/Png/Filters/AverageFilter.cs +++ b/src/ImageSharp/Formats/Png/Filters/AverageFilter.cs @@ -19,14 +19,15 @@ namespace ImageSharp.Formats /// /// The scanline to decode /// The previous scanline. + /// The number of bytes per scanline /// The bytes per pixel. - public static void Decode(byte[] scanline, byte[] previousScanline, int bytesPerPixel) + public static void Decode(byte[] scanline, byte[] previousScanline, int bytesPerScanline, int bytesPerPixel) { // Average(x) + floor((Raw(x-bpp)+Prior(x))/2) fixed (byte* scan = scanline) fixed (byte* prev = previousScanline) { - for (int x = 1; x < scanline.Length; x++) + for (int x = 1; x < bytesPerScanline; x++) { byte left = (x - bytesPerPixel < 1) ? (byte)0 : scan[x - bytesPerPixel]; byte above = prev[x]; diff --git a/src/ImageSharp/Formats/Png/Filters/PaethFilter.cs b/src/ImageSharp/Formats/Png/Filters/PaethFilter.cs index f257641e9..323611fbc 100644 --- a/src/ImageSharp/Formats/Png/Filters/PaethFilter.cs +++ b/src/ImageSharp/Formats/Png/Filters/PaethFilter.cs @@ -20,14 +20,15 @@ namespace ImageSharp.Formats /// /// The scanline to decode /// The previous scanline. + /// The number of bytes per scanline /// The bytes per pixel. - public static void Decode(byte[] scanline, byte[] previousScanline, int bytesPerPixel) + public static void Decode(byte[] scanline, byte[] previousScanline, int bytesPerScanline, int bytesPerPixel) { // Paeth(x) + PaethPredictor(Raw(x-bpp), Prior(x), Prior(x-bpp)) fixed (byte* scan = scanline) fixed (byte* prev = previousScanline) { - for (int x = 1; x < scanline.Length; x++) + for (int x = 1; x < bytesPerScanline; x++) { byte left = (x - bytesPerPixel < 1) ? (byte)0 : scan[x - bytesPerPixel]; byte above = prev[x]; diff --git a/src/ImageSharp/Formats/Png/Filters/SubFilter.cs b/src/ImageSharp/Formats/Png/Filters/SubFilter.cs index a098a242c..65e86f4f1 100644 --- a/src/ImageSharp/Formats/Png/Filters/SubFilter.cs +++ b/src/ImageSharp/Formats/Png/Filters/SubFilter.cs @@ -16,13 +16,14 @@ namespace ImageSharp.Formats /// Decodes the scanline /// /// The scanline to decode + /// The number of bytes per scanline /// The bytes per pixel. - public static void Decode(byte[] scanline, int bytesPerPixel) + public static void Decode(byte[] scanline, int bytesPerScanline, int bytesPerPixel) { // Sub(x) + Raw(x-bpp) fixed (byte* scan = scanline) { - for (int x = 1; x < scanline.Length; x++) + for (int x = 1; x < bytesPerScanline; x++) { byte priorRawByte = (x - bytesPerPixel < 1) ? (byte)0 : scan[x - bytesPerPixel]; scan[x] = (byte)((scan[x] + priorRawByte) % 256); diff --git a/src/ImageSharp/Formats/Png/Filters/UpFilter.cs b/src/ImageSharp/Formats/Png/Filters/UpFilter.cs index 9b8d78e81..036862ddc 100644 --- a/src/ImageSharp/Formats/Png/Filters/UpFilter.cs +++ b/src/ImageSharp/Formats/Png/Filters/UpFilter.cs @@ -17,13 +17,14 @@ namespace ImageSharp.Formats /// /// The scanline to decode /// The previous scanline. - public static void Decode(byte[] scanline, byte[] previousScanline) + /// The number of bytes per scanline + public static void Decode(byte[] scanline, byte[] previousScanline, int bytesPerScanline) { // Up(x) + Prior(x) fixed (byte* scan = scanline) fixed (byte* prev = previousScanline) { - for (int x = 1; x < scanline.Length; x++) + for (int x = 1; x < bytesPerScanline; x++) { byte above = prev[x]; diff --git a/src/ImageSharp/Formats/Png/PngDecoderCore.cs b/src/ImageSharp/Formats/Png/PngDecoderCore.cs index 07761ae90..91578aede 100644 --- a/src/ImageSharp/Formats/Png/PngDecoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngDecoderCore.cs @@ -197,11 +197,12 @@ namespace ImageSharp.Formats /// by a the specified number of bits. /// /// The bytes to convert from. Cannot be null. + /// The number of bytes per scanline /// 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) + private static byte[] ToArrayByBitsLength(byte[] source, int bytesPerScanline, int bits) { Guard.NotNull(source, nameof(source)); Guard.MustBeGreaterThan(bits, 0, nameof(bits)); @@ -210,12 +211,12 @@ namespace ImageSharp.Formats if (bits < 8) { - result = new byte[source.Length * 8 / bits]; + result = new byte[bytesPerScanline * 8 / bits]; int mask = 0xFF >> (8 - bits); int resultOffset = 0; // ReSharper disable once ForCanBeConvertedToForeach - for (int i = 0; i < source.Length; i++) + for (int i = 0; i < bytesPerScanline; i++) { byte b = source[i]; for (int shift = 0; shift < 8; shift += bits) @@ -338,6 +339,9 @@ namespace ImageSharp.Formats byte[] previousScanline = ArrayPool.Shared.Rent(this.bytesPerScanline); byte[] scanline = ArrayPool.Shared.Rent(this.bytesPerScanline); + // Zero out the previousScanline, because the bytes that are rented from the arraypool may not be zero. + Array.Clear(previousScanline, 0, this.bytesPerScanline); + try { for (int y = 0; y < this.header.Height; y++) @@ -356,25 +360,25 @@ namespace ImageSharp.Formats case FilterType.Sub: - SubFilter.Decode(scanline, this.bytesPerPixel); + SubFilter.Decode(scanline, this.bytesPerScanline, this.bytesPerPixel); break; case FilterType.Up: - UpFilter.Decode(scanline, previousScanline); + UpFilter.Decode(scanline, previousScanline, this.bytesPerScanline); break; case FilterType.Average: - AverageFilter.Decode(scanline, previousScanline, this.bytesPerPixel); + AverageFilter.Decode(scanline, previousScanline, this.bytesPerScanline, this.bytesPerPixel); break; case FilterType.Paeth: - PaethFilter.Decode(scanline, previousScanline, this.bytesPerPixel); + PaethFilter.Decode(scanline, previousScanline, this.bytesPerScanline, this.bytesPerPixel); break; @@ -411,7 +415,7 @@ namespace ImageSharp.Formats { case PngColorType.Grayscale: int factor = 255 / ((int)Math.Pow(2, this.header.BitDepth) - 1); - byte[] newScanline1 = ToArrayByBitsLength(defilteredScanline, this.header.BitDepth); + byte[] newScanline1 = ToArrayByBitsLength(defilteredScanline, this.bytesPerScanline, this.header.BitDepth); for (int x = 0; x < this.header.Width; x++) { int offset = 1 + ((x + 1) * this.bytesPerPixel); @@ -439,7 +443,7 @@ namespace ImageSharp.Formats case PngColorType.Palette: - byte[] newScanline = ToArrayByBitsLength(defilteredScanline, this.header.BitDepth); + byte[] newScanline = ToArrayByBitsLength(defilteredScanline, this.bytesPerScanline, this.header.BitDepth); if (this.paletteAlpha != null && this.paletteAlpha.Length > 0) {