Browse Source

Handle missing global color table. Fix #1963

pull/1980/head
James Jackson-South 4 years ago
parent
commit
438a97bb9b
  1. 39
      src/ImageSharp/Formats/Gif/GifDecoderCore.cs
  2. 12
      tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs
  3. 1
      tests/ImageSharp.Tests/TestImages.cs
  4. 3
      tests/Images/External/ReferenceOutput/GifDecoderTests/Issue1962_Rgba32_issue1962_tiniest_gif_1st.png
  5. 3
      tests/Images/Input/Gif/issues/issue1962_tiniest_gif_1st.gif

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

@ -376,7 +376,17 @@ namespace SixLabors.ImageSharp.Formats.Gif
indices = this.Configuration.MemoryAllocator.Allocate2D<byte>(this.imageDescriptor.Width, this.imageDescriptor.Height, AllocationOptions.Clean);
this.ReadFrameIndices(indices);
ReadOnlySpan<Rgb24> colorTable = MemoryMarshal.Cast<byte, Rgb24>((localColorTable ?? this.globalColorTable).GetSpan());
Span<byte> rawColorTable = default;
if (localColorTable != null)
{
rawColorTable = localColorTable.GetSpan();
}
else if (this.globalColorTable != null)
{
rawColorTable = this.globalColorTable.GetSpan();
}
ReadOnlySpan<Rgb24> colorTable = MemoryMarshal.Cast<byte, Rgb24>(rawColorTable);
this.ReadFrameColors(ref image, ref previousFrame, indices, colorTable, this.imageDescriptor);
// Skip any remaining blocks
@ -415,6 +425,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
{
int imageWidth = this.logicalScreenDescriptor.Width;
int imageHeight = this.logicalScreenDescriptor.Height;
bool transFlag = this.graphicsControlExtension.TransparencyFlag;
ImageFrame<TPixel> prevFrame = null;
ImageFrame<TPixel> currentFrame = null;
@ -422,8 +433,15 @@ namespace SixLabors.ImageSharp.Formats.Gif
if (previousFrame is null)
{
// This initializes the image to become fully transparent because the alpha channel is zero.
image = new Image<TPixel>(this.Configuration, imageWidth, imageHeight, this.metadata);
if (!transFlag)
{
image = new Image<TPixel>(this.Configuration, imageWidth, imageHeight, Color.Black.ToPixel<TPixel>(), this.metadata);
}
else
{
// This initializes the image to become fully transparent because the alpha channel is zero.
image = new Image<TPixel>(this.Configuration, imageWidth, imageHeight, this.metadata);
}
this.SetFrameMetadata(image.Frames.RootFrame.Metadata);
@ -445,6 +463,11 @@ namespace SixLabors.ImageSharp.Formats.Gif
this.RestoreToBackground(imageFrame);
}
if (colorTable.Length == 0)
{
return;
}
int interlacePass = 0; // The interlace pass
int interlaceIncrement = 8; // The interlacing line increment
int interlaceY = 0; // The current interlaced line
@ -452,7 +475,6 @@ namespace SixLabors.ImageSharp.Formats.Gif
int descriptorBottom = descriptorTop + descriptor.Height;
int descriptorLeft = descriptor.Left;
int descriptorRight = descriptorLeft + descriptor.Width;
bool transFlag = this.graphicsControlExtension.TransparencyFlag;
byte transIndex = this.graphicsControlExtension.TransparencyIndex;
int colorTableMaxIdx = colorTable.Length - 1;
@ -635,10 +657,13 @@ namespace SixLabors.ImageSharp.Formats.Gif
int globalColorTableLength = this.logicalScreenDescriptor.GlobalColorTableSize * 3;
this.gifMetadata.GlobalColorTableLength = globalColorTableLength;
this.globalColorTable = this.MemoryAllocator.Allocate<byte>(globalColorTableLength, AllocationOptions.Clean);
if (globalColorTableLength > 0)
{
this.globalColorTable = this.MemoryAllocator.Allocate<byte>(globalColorTableLength, AllocationOptions.Clean);
// Read the global color table data from the stream
stream.Read(this.globalColorTable.GetSpan());
// Read the global color table data from the stream
stream.Read(this.globalColorTable.GetSpan());
}
}
}
}

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

@ -247,5 +247,17 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif
"Disco")
.Dispose();
}
// https://github.com/SixLabors/ImageSharp/issues/1962
[Theory]
[WithFile(TestImages.Gif.Issues.Issue1962NoColorTable, PixelTypes.Rgba32)]
public void Issue1962<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using Image<TPixel> image = provider.GetImage();
image.DebugSave(provider);
image.CompareFirstFrameToReferenceOutput(ImageComparer.Exact, provider);
}
}
}

1
tests/ImageSharp.Tests/TestImages.cs

@ -451,6 +451,7 @@ namespace SixLabors.ImageSharp.Tests
public const string Issue1505 = "Gif/issues/issue1505_argumentoutofrange.png";
public const string Issue1530 = "Gif/issues/issue1530.gif";
public const string InvalidColorIndex = "Gif/issues/issue1668_invalidcolorindex.gif";
public const string Issue1962NoColorTable = "Gif/issues/issue1962_tiniest_gif_1st.gif";
}
public static readonly string[] All = { Rings, Giphy, Cheers, Trans, Kumin, Leo, Ratio4x1, Ratio1x4 };

3
tests/Images/External/ReferenceOutput/GifDecoderTests/Issue1962_Rgba32_issue1962_tiniest_gif_1st.png

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:4f8c6d416f09671777934e57bc67fb52ccc97145dc6f1869e628d9ffd7d8f6e7
size 119

3
tests/Images/Input/Gif/issues/issue1962_tiniest_gif_1st.gif

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