From d24b20f81fba647c420e21a67cf9abaadd2c4529 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Thu, 22 Dec 2016 01:03:41 +1100 Subject: [PATCH] Reduce memory used during LZW decoding --- src/ImageSharp/Formats/Gif/GifDecoderCore.cs | 14 +++++++++----- src/ImageSharp/Formats/Gif/LzwDecoder.cs | 13 ++++++------- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/src/ImageSharp/Formats/Gif/GifDecoderCore.cs b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs index 3d8ec0c6b..d77ce9900 100644 --- a/src/ImageSharp/Formats/Gif/GifDecoderCore.cs +++ b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs @@ -252,7 +252,7 @@ namespace ImageSharp.Formats GifImageDescriptor imageDescriptor = this.ReadImageDescriptor(); byte[] localColorTable = null; - + byte[] indices = null; try { // Determine the color table for this frame. If there is a local one, use it otherwise use the global color table. @@ -264,7 +264,9 @@ namespace ImageSharp.Formats this.currentStream.Read(localColorTable, 0, length); } - byte[] indices = this.ReadFrameIndices(imageDescriptor); + indices = ArrayPool.Shared.Rent(imageDescriptor.Width * imageDescriptor.Height); + + this.ReadFrameIndices(imageDescriptor, indices); this.ReadFrameColors(indices, localColorTable ?? this.globalColorTable, length, imageDescriptor); // Skip any remaining blocks @@ -276,6 +278,8 @@ namespace ImageSharp.Formats { ArrayPool.Shared.Return(localColorTable); } + + ArrayPool.Shared.Return(indices); } } @@ -283,13 +287,13 @@ namespace ImageSharp.Formats /// Reads the frame indices marking the color to use for each pixel. /// /// The . - /// The - private byte[] ReadFrameIndices(GifImageDescriptor imageDescriptor) + /// The pixel array to write to. + private void ReadFrameIndices(GifImageDescriptor imageDescriptor, byte[] indices) { int dataSize = this.currentStream.ReadByte(); using (LzwDecoder lzwDecoder = new LzwDecoder(this.currentStream)) { - return lzwDecoder.DecodePixels(imageDescriptor.Width, imageDescriptor.Height, dataSize); + lzwDecoder.DecodePixels(imageDescriptor.Width, imageDescriptor.Height, dataSize, indices); } } diff --git a/src/ImageSharp/Formats/Gif/LzwDecoder.cs b/src/ImageSharp/Formats/Gif/LzwDecoder.cs index f43bae5b3..bc0e9717c 100644 --- a/src/ImageSharp/Formats/Gif/LzwDecoder.cs +++ b/src/ImageSharp/Formats/Gif/LzwDecoder.cs @@ -2,6 +2,7 @@ // Copyright (c) James Jackson-South and contributors. // Licensed under the Apache License, Version 2.0. // + namespace ImageSharp.Formats { using System; @@ -83,13 +84,13 @@ namespace ImageSharp.Formats /// The width of the pixel index array. /// The height of the pixel index array. /// Size of the data. - /// The decoded and uncompressed array. - public byte[] DecodePixels(int width, int height, int dataSize) + /// The pixel array to decode to. + public void DecodePixels(int width, int height, int dataSize, byte[] pixels) { Guard.MustBeLessThan(dataSize, int.MaxValue, nameof(dataSize)); - // The resulting index table. - byte[] pixels = new byte[width * height]; + // The resulting index table length. + int length = width * height; // Calculate the clear code. The value of the clear code is 2 ^ dataSize int clearCode = 1 << dataSize; @@ -124,7 +125,7 @@ namespace ImageSharp.Formats } byte[] buffer = new byte[255]; - while (xyz < pixels.Length) + while (xyz < length) { if (top == 0) { @@ -221,8 +222,6 @@ namespace ImageSharp.Formats // Clear missing pixels pixels[xyz++] = (byte)this.pixelStack[top]; } - - return pixels; } ///