Skip to content

Commit 5d6f389

Browse files
Merge pull request #1980 from SixLabors/js/fix-1962
Handle missing global color table.
2 parents 6d434ea + 438a97b commit 5d6f389

File tree

5 files changed

+51
-7
lines changed

5 files changed

+51
-7
lines changed

src/ImageSharp/Formats/Gif/GifDecoderCore.cs

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,17 @@ private void ReadFrame<TPixel>(ref Image<TPixel> image, ref ImageFrame<TPixel> p
376376
indices = this.Configuration.MemoryAllocator.Allocate2D<byte>(this.imageDescriptor.Width, this.imageDescriptor.Height, AllocationOptions.Clean);
377377

378378
this.ReadFrameIndices(indices);
379-
ReadOnlySpan<Rgb24> colorTable = MemoryMarshal.Cast<byte, Rgb24>((localColorTable ?? this.globalColorTable).GetSpan());
379+
Span<byte> rawColorTable = default;
380+
if (localColorTable != null)
381+
{
382+
rawColorTable = localColorTable.GetSpan();
383+
}
384+
else if (this.globalColorTable != null)
385+
{
386+
rawColorTable = this.globalColorTable.GetSpan();
387+
}
388+
389+
ReadOnlySpan<Rgb24> colorTable = MemoryMarshal.Cast<byte, Rgb24>(rawColorTable);
380390
this.ReadFrameColors(ref image, ref previousFrame, indices, colorTable, this.imageDescriptor);
381391

382392
// Skip any remaining blocks
@@ -415,15 +425,23 @@ private void ReadFrameColors<TPixel>(ref Image<TPixel> image, ref ImageFrame<TPi
415425
{
416426
int imageWidth = this.logicalScreenDescriptor.Width;
417427
int imageHeight = this.logicalScreenDescriptor.Height;
428+
bool transFlag = this.graphicsControlExtension.TransparencyFlag;
418429

419430
ImageFrame<TPixel> prevFrame = null;
420431
ImageFrame<TPixel> currentFrame = null;
421432
ImageFrame<TPixel> imageFrame;
422433

423434
if (previousFrame is null)
424435
{
425-
// This initializes the image to become fully transparent because the alpha channel is zero.
426-
image = new Image<TPixel>(this.Configuration, imageWidth, imageHeight, this.metadata);
436+
if (!transFlag)
437+
{
438+
image = new Image<TPixel>(this.Configuration, imageWidth, imageHeight, Color.Black.ToPixel<TPixel>(), this.metadata);
439+
}
440+
else
441+
{
442+
// This initializes the image to become fully transparent because the alpha channel is zero.
443+
image = new Image<TPixel>(this.Configuration, imageWidth, imageHeight, this.metadata);
444+
}
427445

428446
this.SetFrameMetadata(image.Frames.RootFrame.Metadata);
429447

@@ -445,14 +463,18 @@ private void ReadFrameColors<TPixel>(ref Image<TPixel> image, ref ImageFrame<TPi
445463
this.RestoreToBackground(imageFrame);
446464
}
447465

466+
if (colorTable.Length == 0)
467+
{
468+
return;
469+
}
470+
448471
int interlacePass = 0; // The interlace pass
449472
int interlaceIncrement = 8; // The interlacing line increment
450473
int interlaceY = 0; // The current interlaced line
451474
int descriptorTop = descriptor.Top;
452475
int descriptorBottom = descriptorTop + descriptor.Height;
453476
int descriptorLeft = descriptor.Left;
454477
int descriptorRight = descriptorLeft + descriptor.Width;
455-
bool transFlag = this.graphicsControlExtension.TransparencyFlag;
456478
byte transIndex = this.graphicsControlExtension.TransparencyIndex;
457479
int colorTableMaxIdx = colorTable.Length - 1;
458480

@@ -635,10 +657,13 @@ private void ReadLogicalScreenDescriptorAndGlobalColorTable(BufferedReadStream s
635657
int globalColorTableLength = this.logicalScreenDescriptor.GlobalColorTableSize * 3;
636658
this.gifMetadata.GlobalColorTableLength = globalColorTableLength;
637659

638-
this.globalColorTable = this.MemoryAllocator.Allocate<byte>(globalColorTableLength, AllocationOptions.Clean);
660+
if (globalColorTableLength > 0)
661+
{
662+
this.globalColorTable = this.MemoryAllocator.Allocate<byte>(globalColorTableLength, AllocationOptions.Clean);
639663

640-
// Read the global color table data from the stream
641-
stream.Read(this.globalColorTable.GetSpan());
664+
// Read the global color table data from the stream
665+
stream.Read(this.globalColorTable.GetSpan());
666+
}
642667
}
643668
}
644669
}

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,5 +247,17 @@ TestImageProvider<Rgba32> provider
247247
"Disco")
248248
.Dispose();
249249
}
250+
251+
// https://github.com/SixLabors/ImageSharp/issues/1962
252+
[Theory]
253+
[WithFile(TestImages.Gif.Issues.Issue1962NoColorTable, PixelTypes.Rgba32)]
254+
public void Issue1962<TPixel>(TestImageProvider<TPixel> provider)
255+
where TPixel : unmanaged, IPixel<TPixel>
256+
{
257+
using Image<TPixel> image = provider.GetImage();
258+
image.DebugSave(provider);
259+
260+
image.CompareFirstFrameToReferenceOutput(ImageComparer.Exact, provider);
261+
}
250262
}
251263
}

tests/ImageSharp.Tests/TestImages.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,7 @@ public static class Issues
451451
public const string Issue1505 = "Gif/issues/issue1505_argumentoutofrange.png";
452452
public const string Issue1530 = "Gif/issues/issue1530.gif";
453453
public const string InvalidColorIndex = "Gif/issues/issue1668_invalidcolorindex.gif";
454+
public const string Issue1962NoColorTable = "Gif/issues/issue1962_tiniest_gif_1st.gif";
454455
}
455456

456457
public static readonly string[] All = { Rings, Giphy, Cheers, Trans, Kumin, Leo, Ratio4x1, Ratio1x4 };
Lines changed: 3 additions & 0 deletions
Loading
Lines changed: 3 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)