diff --git a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs index be08c0da90..ccf8feaccd 100644 --- a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs +++ b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs @@ -135,7 +135,7 @@ internal sealed class GifEncoderCore : IImageEncoderInternals byte backgroundIndex = unchecked((byte)transparencyIndex); if (transparencyIndex == -1) { - backgroundIndex = gifMetadata.BackgroundColor; + backgroundIndex = gifMetadata.BackgroundColorIndex; } // Get the number of bits. @@ -236,18 +236,19 @@ internal sealed class GifEncoderCore : IImageEncoderInternals { this.WriteGraphicalControlExtension(metadata, transparencyIndex, stream); - Buffer2DRegion region = ((IPixelSource)quantized).PixelBuffer.GetRegion(); + Buffer2D indices = ((IPixelSource)quantized).PixelBuffer; + Rectangle interest = indices.FullRectangle(); bool useLocal = this.colorTableMode == GifColorTableMode.Local || (metadata?.ColorTableMode == GifColorTableMode.Local); int bitDepth = ColorNumerics.GetBitsNeededForColorDepth(quantized.Palette.Length); - this.WriteImageDescriptor(region.Rectangle, useLocal, bitDepth, stream); + this.WriteImageDescriptor(interest, useLocal, bitDepth, stream); if (useLocal) { this.WriteColorTable(quantized, bitDepth, stream); } - this.WriteImageData(region, stream, quantized.Palette.Length, transparencyIndex); + this.WriteImageData(indices, interest, stream, quantized.Palette.Length, transparencyIndex); } private void EncodeAdditionalFrame( @@ -322,20 +323,20 @@ internal sealed class GifEncoderCore : IImageEncoderInternals transparencyIndex = GetTransparentIndex(quantized, metadata); // Trim down the buffer to the minimum size required. - // Buffer2DRegion region = ((IPixelSource)quantized).PixelBuffer.GetRegion(); - Buffer2DRegion region = TrimTransparentPixels(((IPixelSource)quantized).PixelBuffer, transparencyIndex); + Buffer2D indices = ((IPixelSource)quantized).PixelBuffer; + Rectangle interest = TrimTransparentPixels(indices, transparencyIndex); this.WriteGraphicalControlExtension(metadata, transparencyIndex, stream); int bitDepth = ColorNumerics.GetBitsNeededForColorDepth(quantized.Palette.Length); - this.WriteImageDescriptor(region.Rectangle, useLocal, bitDepth, stream); + this.WriteImageDescriptor(interest, useLocal, bitDepth, stream); if (useLocal) { this.WriteColorTable(quantized, bitDepth, stream); } - this.WriteImageData(region, stream, quantized.Palette.Length, transparencyIndex); + this.WriteImageData(indices, interest, stream, quantized.Palette.Length, transparencyIndex); } private void DeDuplicatePixels( @@ -399,11 +400,11 @@ internal sealed class GifEncoderCore : IImageEncoderInternals } } - private static Buffer2DRegion TrimTransparentPixels(Buffer2D buffer, int transparencyIndex) + private static Rectangle TrimTransparentPixels(Buffer2D buffer, int transparencyIndex) { if (transparencyIndex < 0) { - return buffer.GetRegion(); + return buffer.FullRectangle(); } byte trimmableIndex = unchecked((byte)transparencyIndex); @@ -596,7 +597,7 @@ internal sealed class GifEncoderCore : IImageEncoderInternals if (top == bottom || left == right) { // The entire image is transparent. - return buffer.GetRegion(); + return buffer.FullRectangle(); } if (!isTransparentRow) @@ -605,7 +606,7 @@ internal sealed class GifEncoderCore : IImageEncoderInternals bottom = buffer.Height; } - return buffer.GetRegion(Rectangle.FromLTRB(left, top, Math.Min(right + 1, buffer.Width), Math.Min(bottom + 1, buffer.Height))); + return Rectangle.FromLTRB(left, top, Math.Min(right + 1, buffer.Width), Math.Min(bottom + 1, buffer.Height)); } /// @@ -923,11 +924,14 @@ internal sealed class GifEncoderCore : IImageEncoderInternals /// Writes the image pixel data to the stream. /// /// The containing indexed pixels. + /// The region of interest. /// The stream to write to. /// The length of the frame color palette. /// The index of the color used to represent transparency. - private void WriteImageData(Buffer2DRegion indices, Stream stream, int paletteLength, int transparencyIndex) + private void WriteImageData(Buffer2D indices, Rectangle interest, Stream stream, int paletteLength, int transparencyIndex) { + Buffer2DRegion region = indices.GetRegion(interest); + // Pad the bit depth when required for encoding the image data. // This is a common trick which allows to use out of range indexes for transparency and avoid allocating a larger color palette // as decoders skip indexes that are out of range. @@ -936,6 +940,6 @@ internal sealed class GifEncoderCore : IImageEncoderInternals : 0; using LzwEncoder encoder = new(this.memoryAllocator, ColorNumerics.GetBitsNeededForColorDepth(paletteLength + padding)); - encoder.Encode(indices, stream); + encoder.Encode(region, stream); } } diff --git a/src/ImageSharp/Formats/Gif/GifMetadata.cs b/src/ImageSharp/Formats/Gif/GifMetadata.cs index 184ccd644f..0172344ff9 100644 --- a/src/ImageSharp/Formats/Gif/GifMetadata.cs +++ b/src/ImageSharp/Formats/Gif/GifMetadata.cs @@ -23,7 +23,7 @@ public class GifMetadata : IDeepCloneable { this.RepeatCount = other.RepeatCount; this.ColorTableMode = other.ColorTableMode; - this.BackgroundColor = other.BackgroundColor; + this.BackgroundColorIndex = other.BackgroundColorIndex; if (other.GlobalColorTable?.Length > 0) { @@ -58,7 +58,7 @@ public class GifMetadata : IDeepCloneable /// Gets or sets the index at the for the background color. /// The background color is the color used for those pixels on the screen that are not covered by an image. /// - public byte BackgroundColor { get; set; } + public byte BackgroundColorIndex { get; set; } /// /// Gets or sets the collection of comments about the graphics, credits, descriptions or any