Browse Source

Reduce memory used during LZW decoding

af/merge-core
James Jackson-South 9 years ago
parent
commit
d24b20f81f
  1. 14
      src/ImageSharp/Formats/Gif/GifDecoderCore.cs
  2. 13
      src/ImageSharp/Formats/Gif/LzwDecoder.cs

14
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<byte>.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<byte>.Shared.Return(localColorTable);
}
ArrayPool<byte>.Shared.Return(indices);
}
}
@ -283,13 +287,13 @@ namespace ImageSharp.Formats
/// Reads the frame indices marking the color to use for each pixel.
/// </summary>
/// <param name="imageDescriptor">The <see cref="GifImageDescriptor"/>.</param>
/// <returns>The <see cref="T:byte[]"/></returns>
private byte[] ReadFrameIndices(GifImageDescriptor imageDescriptor)
/// <param name="indices">The pixel array to write to.</param>
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);
}
}

13
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.
// </copyright>
namespace ImageSharp.Formats
{
using System;
@ -83,13 +84,13 @@ namespace ImageSharp.Formats
/// <param name="width">The width of the pixel index array.</param>
/// <param name="height">The height of the pixel index array.</param>
/// <param name="dataSize">Size of the data.</param>
/// <returns>The decoded and uncompressed array.</returns>
public byte[] DecodePixels(int width, int height, int dataSize)
/// <param name="pixels">The pixel array to decode to.</param>
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;
}
/// <inheritdoc />

Loading…
Cancel
Save