diff --git a/src/ImageSharp/Common/Extensions/ByteExtensions.cs b/src/ImageSharp/Common/Extensions/ByteExtensions.cs index 89cfe69742..cca0140736 100644 --- a/src/ImageSharp/Common/Extensions/ByteExtensions.cs +++ b/src/ImageSharp/Common/Extensions/ByteExtensions.cs @@ -24,7 +24,7 @@ namespace ImageSharp public static byte[] ToArrayByBitsLength(this byte[] source, int bits) { Guard.NotNull(source, nameof(source)); - Guard.MustBeGreaterThan(bits, 0, "bits"); + Guard.MustBeGreaterThan(bits, 0, nameof(bits)); byte[] result; diff --git a/src/ImageSharp/Formats/Png/Filters/SubFilter.cs b/src/ImageSharp/Formats/Png/Filters/SubFilter.cs index ddcce0b4d0..6cf5c6cdb4 100644 --- a/src/ImageSharp/Formats/Png/Filters/SubFilter.cs +++ b/src/ImageSharp/Formats/Png/Filters/SubFilter.cs @@ -17,7 +17,6 @@ namespace ImageSharp.Formats /// /// The scanline to decode /// The bytes per pixel. - /// The public static void Decode(byte[] scanline, int bytesPerPixel) { // Sub(x) + Raw(x-bpp) diff --git a/src/ImageSharp/Formats/Png/PngDecoderCore.cs b/src/ImageSharp/Formats/Png/PngDecoderCore.cs index f8567e45f0..a5fd051b38 100644 --- a/src/ImageSharp/Formats/Png/PngDecoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngDecoderCore.cs @@ -132,39 +132,49 @@ namespace ImageSharp.Formats throw new ImageFormatException("Image does not end with end chunk."); } - switch (currentChunk.Type) + try { - case PngChunkTypes.Header: - this.ReadHeaderChunk(currentChunk.Data); - this.ValidateHeader(); - break; - case PngChunkTypes.Physical: - this.ReadPhysicalChunk(currentImage, currentChunk.Data); - break; - case PngChunkTypes.Data: - dataStream.Write(currentChunk.Data, 0, currentChunk.Data.Length); - break; - case PngChunkTypes.Palette: - this.palette = currentChunk.Data; - image.Quality = this.palette.Length / 3; - break; - case PngChunkTypes.PaletteAlpha: - this.paletteAlpha = currentChunk.Data; - break; - case PngChunkTypes.Text: - this.ReadTextChunk(currentImage, currentChunk.Data); - break; - case PngChunkTypes.End: - isEndChunkReached = true; - break; + switch (currentChunk.Type) + { + case PngChunkTypes.Header: + this.ReadHeaderChunk(currentChunk.Data); + this.ValidateHeader(); + break; + case PngChunkTypes.Physical: + this.ReadPhysicalChunk(currentImage, currentChunk.Data); + break; + case PngChunkTypes.Data: + dataStream.Write(currentChunk.Data, 0, currentChunk.Length); + break; + case PngChunkTypes.Palette: + byte[] pal = new byte[currentChunk.Length]; + Buffer.BlockCopy(currentChunk.Data, 0, pal, 0, currentChunk.Length); + this.palette = pal; + image.Quality = pal.Length / 3; + break; + case PngChunkTypes.PaletteAlpha: + byte[] alpha = new byte[currentChunk.Length]; + Buffer.BlockCopy(currentChunk.Data, 0, alpha, 0, currentChunk.Length); + this.paletteAlpha = alpha; + break; + case PngChunkTypes.Text: + this.ReadTextChunk(currentImage, currentChunk.Data, currentChunk.Length); + break; + case PngChunkTypes.End: + isEndChunkReached = true; + break; + } + } + finally + { + // Data is rented in ReadChunkData() + ArrayPool.Shared.Return(currentChunk.Data); } } if (this.header.Width > image.MaxWidth || this.header.Height > image.MaxHeight) { - throw new ArgumentOutOfRangeException( - $"The input png '{this.header.Width}x{this.header.Height}' is bigger than the " - + $"max allowed size '{image.MaxWidth}x{image.MaxHeight}'"); + throw new ArgumentOutOfRangeException($"The input png '{this.header.Width}x{this.header.Height}' is bigger than the max allowed size '{image.MaxWidth}x{image.MaxHeight}'"); } image.InitPixels(this.header.Width, this.header.Height); @@ -396,6 +406,10 @@ namespace ImageSharp.Formats byte b = this.palette[pixelOffset + 2]; color.PackFromBytes(r, g, b, a); } + else + { + color.PackFromBytes(0, 0, 0, 0); + } pixels[x, row] = color; } @@ -460,13 +474,14 @@ namespace ImageSharp.Formats /// The packed format. uint, long, float. /// The image to decode to. /// The containing data. - private void ReadTextChunk(Image image, byte[] data) + /// The maximum length to read. + private void ReadTextChunk(Image image, byte[] data, int length) where TColor : struct, IPackedPixel where TPacked : struct { int zeroIndex = 0; - for (int i = 0; i < data.Length; i++) + for (int i = 0; i < length; i++) { if (data[i] == 0) { @@ -476,7 +491,7 @@ namespace ImageSharp.Formats } string name = Encoding.Unicode.GetString(data, 0, zeroIndex); - string value = Encoding.Unicode.GetString(data, zeroIndex + 1, data.Length - zeroIndex - 1); + string value = Encoding.Unicode.GetString(data, zeroIndex + 1, length - zeroIndex - 1); image.Properties.Add(new ImageProperty(name, value)); } @@ -577,7 +592,7 @@ namespace ImageSharp.Formats Crc32 crc = new Crc32(); crc.Update(this.chunkTypeBuffer); - crc.Update(chunk.Data); + crc.Update(chunk.Data, 0, chunk.Length); if (crc.Value != chunk.Crc) { @@ -591,8 +606,8 @@ namespace ImageSharp.Formats /// The chunk. private void ReadChunkData(PngChunk chunk) { - // TODO: It might be possible to rent this but that could also lead to issues assigning the data to various properties - chunk.Data = new byte[chunk.Length]; + // We rent the buffer here to return it afterwards in Decode() + chunk.Data = ArrayPool.Shared.Rent(chunk.Length); this.currentStream.Read(chunk.Data, 0, chunk.Length); } @@ -645,4 +660,4 @@ namespace ImageSharp.Formats chunk.Length = BitConverter.ToInt32(this.chunkLengthBuffer, 0); } } -} +} \ No newline at end of file