Browse Source

Merge pull request #399 from SixLabors/js/fix-390

Fix 390
af/merge-core
James Jackson-South 8 years ago
committed by GitHub
parent
commit
4e5e5c1c28
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 34
      src/ImageSharp/Formats/Gif/GifDecoderCore.cs
  2. 2
      src/ImageSharp/Formats/Gif/LzwDecoder.cs
  3. 4
      src/ImageSharp/Image/PixelArea{TPixel}.cs
  4. 19
      tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs
  5. 4
      tests/ImageSharp.Tests/TestImages.cs
  6. 1
      tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs
  7. 3
      tests/Images/Input/Gif/kumin.gif
  8. 3
      tests/Images/Input/Png/icon.png

34
src/ImageSharp/Formats/Gif/GifDecoderCore.cs

@ -7,6 +7,7 @@ using System.IO;
using System.Runtime.CompilerServices;
using System.Text;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.MetaData;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Primitives;
@ -38,7 +39,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
/// <summary>
/// The global color table.
/// </summary>
private byte[] globalColorTable;
private Buffer<byte> globalColorTable;
/// <summary>
/// The global color table length
@ -123,10 +124,10 @@ namespace SixLabors.ImageSharp.Formats.Gif
if (this.logicalScreenDescriptor.GlobalColorTableFlag)
{
this.globalColorTableLength = this.logicalScreenDescriptor.GlobalColorTableSize * 3;
this.globalColorTable = ArrayPool<byte>.Shared.Rent(this.globalColorTableLength);
this.globalColorTable = Buffer<byte>.CreateClean(this.globalColorTableLength);
// Read the global color table from the stream
stream.Read(this.globalColorTable, 0, this.globalColorTableLength);
stream.Read(this.globalColorTable.Array, 0, this.globalColorTableLength);
}
// Loop though the respective gif parts and read the data.
@ -175,10 +176,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
}
finally
{
if (this.globalColorTable != null)
{
ArrayPool<byte>.Shared.Return(this.globalColorTable);
}
this.globalColorTable?.Dispose();
}
return this.image;
@ -309,19 +307,19 @@ namespace SixLabors.ImageSharp.Formats.Gif
{
GifImageDescriptor imageDescriptor = this.ReadImageDescriptor();
byte[] localColorTable = null;
byte[] indices = null;
Buffer<byte> localColorTable = null;
Buffer<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.
if (imageDescriptor.LocalColorTableFlag)
{
int length = imageDescriptor.LocalColorTableSize * 3;
localColorTable = ArrayPool<byte>.Shared.Rent(length);
this.currentStream.Read(localColorTable, 0, length);
localColorTable = Buffer<byte>.CreateClean(length);
this.currentStream.Read(localColorTable.Array, 0, length);
}
indices = ArrayPool<byte>.Shared.Rent(imageDescriptor.Width * imageDescriptor.Height);
indices = Buffer<byte>.CreateClean(imageDescriptor.Width * imageDescriptor.Height);
this.ReadFrameIndices(imageDescriptor, indices);
this.ReadFrameColors(indices, localColorTable ?? this.globalColorTable, imageDescriptor);
@ -331,12 +329,8 @@ namespace SixLabors.ImageSharp.Formats.Gif
}
finally
{
if (localColorTable != null)
{
ArrayPool<byte>.Shared.Return(localColorTable);
}
ArrayPool<byte>.Shared.Return(indices);
localColorTable?.Dispose();
indices?.Dispose();
}
}
@ -346,7 +340,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
/// <param name="imageDescriptor">The <see cref="GifImageDescriptor"/>.</param>
/// <param name="indices">The pixel array to write to.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void ReadFrameIndices(GifImageDescriptor imageDescriptor, byte[] indices)
private void ReadFrameIndices(GifImageDescriptor imageDescriptor, Span<byte> indices)
{
int dataSize = this.currentStream.ReadByte();
using (var lzwDecoder = new LzwDecoder(this.currentStream))
@ -361,7 +355,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
/// <param name="indices">The indexed pixels.</param>
/// <param name="colorTable">The color table containing the available colors.</param>
/// <param name="descriptor">The <see cref="GifImageDescriptor"/></param>
private void ReadFrameColors(byte[] indices, byte[] colorTable, GifImageDescriptor descriptor)
private void ReadFrameColors(Span<byte> indices, Span<byte> colorTable, GifImageDescriptor descriptor)
{
int imageWidth = this.logicalScreenDescriptor.Width;
int imageHeight = this.logicalScreenDescriptor.Height;

2
src/ImageSharp/Formats/Gif/LzwDecoder.cs

@ -83,7 +83,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
/// <param name="height">The height of the pixel index array.</param>
/// <param name="dataSize">Size of the data.</param>
/// <param name="pixels">The pixel array to decode to.</param>
public void DecodePixels(int width, int height, int dataSize, byte[] pixels)
public void DecodePixels(int width, int height, int dataSize, Span<byte> pixels)
{
Guard.MustBeLessThan(dataSize, int.MaxValue, nameof(dataSize));

4
src/ImageSharp/Image/PixelArea{TPixel}.cs

@ -30,7 +30,7 @@ namespace SixLabors.ImageSharp
/// <summary>
/// The underlying buffer containing the raw pixel data.
/// </summary>
private Buffer<byte> byteBuffer;
private readonly Buffer<byte> byteBuffer;
/// <summary>
/// Initializes a new instance of the <see cref="PixelArea{TPixel}"/> class.
@ -116,7 +116,7 @@ namespace SixLabors.ImageSharp
this.RowStride = (width * GetComponentCount(componentOrder)) + padding;
this.Length = this.RowStride * height;
this.byteBuffer = new Buffer<byte>(this.Length);
this.byteBuffer = Buffer<byte>.CreateClean(this.Length);
}
/// <summary>

19
tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs

@ -10,12 +10,15 @@ using Xunit;
// ReSharper disable InconsistentNaming
namespace SixLabors.ImageSharp.Tests
{
using SixLabors.ImageSharp.Advanced;
public class GifDecoderTests
{
private const PixelTypes PixelTypes = Tests.PixelTypes.Rgba32 | Tests.PixelTypes.RgbaVector | Tests.PixelTypes.Argb32;
public static readonly string[] TestFiles = { TestImages.Gif.Giphy, TestImages.Gif.Rings, TestImages.Gif.Trans };
[Theory]
[WithFileCollection(nameof(TestFiles), PixelTypes)]
public void DecodeAndReSave<TPixel>(TestImageProvider<TPixel> imageProvider)
@ -113,5 +116,21 @@ namespace SixLabors.ImageSharp.Tests
Assert.True(image.Frames.Count > 1);
}
}
[Fact]
public void CanDecodeIntermingledImages()
{
using (var kumin1 = Image.Load(TestFile.Create(TestImages.Gif.Kumin).Bytes))
using (var icon = Image.Load(TestFile.Create(TestImages.Png.Icon).Bytes))
using (var kumin2 = Image.Load(TestFile.Create(TestImages.Gif.Kumin).Bytes))
{
for (int i = 0; i < kumin1.Frames.Count; i++)
{
ImageFrame<Rgba32> first = kumin1.Frames[i];
ImageFrame<Rgba32> second = kumin2.Frames[i];
first.ComparePixelBufferTo(second.GetPixelSpan());
}
}
}
}
}

4
tests/ImageSharp.Tests/TestImages.cs

@ -31,6 +31,7 @@ namespace SixLabors.ImageSharp.Tests
public const string BikeGrayscale = "Png/BikeGrayscale.png";
public const string Rgb48BppInterlaced = "Png/rgb-48bpp-interlaced.png";
public const string SnakeGame = "Png/SnakeGame.png";
public const string Icon = "Png/icon.png";
// Filtered test images from http://www.schaik.com/pngsuite/pngsuite_fil_png.html
public const string Filter0 = "Png/filter0.png";
@ -154,8 +155,9 @@ namespace SixLabors.ImageSharp.Tests
public const string Giphy = "Gif/giphy.gif";
public const string Cheers = "Gif/cheers.gif";
public const string Trans = "Gif/trans.gif";
public const string Kumin = "Gif/kumin.gif";
public static readonly string[] All = { Rings, Giphy, Cheers, Trans };
public static readonly string[] All = { Rings, Giphy, Cheers, Trans, Kumin };
}
}
}

1
tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs

@ -29,7 +29,6 @@ namespace SixLabors.ImageSharp.Tests
/// <param name="provider">The image provider</param>
/// <param name="testOutputDetails">Details to be concatenated to the test output file, describing the parameters of the test.</param>
/// <param name="extension">The extension</param>
/// <param name="grayscale">A boolean indicating whether we should save a smaller in size.</param>
/// <param name="appendPixelTypeToFileName">A boolean indicating whether to append the pixel type to the output file name.</param>
public static Image<TPixel> DebugSave<TPixel>(
this Image<TPixel> image,

3
tests/Images/Input/Gif/kumin.gif

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:345556b9a0e064412acc3b2ee87a9226113eb65c0a1791c2f855ac3fa1e6b7ad
size 868269

3
tests/Images/Input/Png/icon.png

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:18f1eb7c5019153f4a0b2de90e7e0f0521193f003fabd6ac31c2f58c2562ae42
size 4040
Loading…
Cancel
Save