Skip to content

Commit b126b77

Browse files
Use background index as fallback during dedup.
1 parent fc7219d commit b126b77

File tree

1 file changed

+30
-12
lines changed

1 file changed

+30
-12
lines changed

src/ImageSharp/Formats/Gif/GifEncoderCore.cs

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -135,13 +135,15 @@ public void Encode<TPixel>(Image<TPixel> image, Stream stream, CancellationToken
135135

136136
// Write the LSD.
137137
image.Frames.RootFrame.Metadata.TryGetGifMetadata(out GifFrameMetadata? frameMetadata);
138-
int index = GetTransparentIndex(quantized, frameMetadata);
139-
if (index == -1)
138+
139+
int transparentIndex = GetTransparentIndex(quantized, frameMetadata);
140+
byte backgroundIndex = unchecked((byte)transparentIndex);
141+
if (transparentIndex == -1)
140142
{
141-
index = gifMetadata.BackgroundColor;
143+
backgroundIndex = gifMetadata.BackgroundColor;
142144
}
143145

144-
this.WriteLogicalScreenDescriptor(metadata, image.Width, image.Height, index, useGlobalTable, stream);
146+
this.WriteLogicalScreenDescriptor(metadata, image.Width, image.Height, backgroundIndex, useGlobalTable, stream);
145147

146148
if (useGlobalTable)
147149
{
@@ -158,14 +160,15 @@ public void Encode<TPixel>(Image<TPixel> image, Stream stream, CancellationToken
158160
this.WriteApplicationExtensions(stream, image.Frames.Count, gifMetadata.RepeatCount, xmpProfile);
159161
}
160162

161-
this.EncodeFrames(stream, image, quantized, quantized.Palette.ToArray());
163+
this.EncodeFrames(stream, image, backgroundIndex, quantized, quantized.Palette.ToArray());
162164

163165
stream.WriteByte(GifConstants.EndIntroducer);
164166
}
165167

166168
private void EncodeFrames<TPixel>(
167169
Stream stream,
168170
Image<TPixel> image,
171+
byte backgroundIndex,
169172
IndexedImageFrame<TPixel> quantized,
170173
ReadOnlyMemory<TPixel> palette)
171174
where TPixel : unmanaged, IPixel<TPixel>
@@ -197,7 +200,17 @@ private void EncodeFrames<TPixel>(
197200
paletteQuantizer = new(this.configuration, this.quantizer!.Options, palette);
198201
}
199202

200-
this.EncodeFrame(stream, frame, i, useLocal, frameMetadata, indices, ref previousQuantized, ref quantized!, ref paletteQuantizer);
203+
this.EncodeFrame(
204+
stream,
205+
frame,
206+
i,
207+
useLocal,
208+
frameMetadata,
209+
indices,
210+
backgroundIndex,
211+
ref previousQuantized,
212+
ref quantized!,
213+
ref paletteQuantizer);
201214

202215
// Clean up for the next run.
203216
if (quantized != previousQuantized)
@@ -222,6 +235,7 @@ private void EncodeFrame<TPixel>(
222235
bool useLocal,
223236
GifFrameMetadata? metadata,
224237
Buffer2D<byte> indices,
238+
byte backgroundIndex,
225239
ref IndexedImageFrame<TPixel> previousQuantized,
226240
ref IndexedImageFrame<TPixel> quantized,
227241
ref PaletteQuantizer<TPixel> globalPaletteQuantizer)
@@ -256,10 +270,16 @@ private void EncodeFrame<TPixel>(
256270
quantized = globalPaletteQuantizer.QuantizeFrame(frame, frame.Bounds());
257271
transparencyIndex = GetTransparentIndex(quantized, metadata);
258272

273+
byte replacementIndex = unchecked((byte)transparencyIndex);
274+
if (transparencyIndex == -1)
275+
{
276+
replacementIndex = backgroundIndex;
277+
}
278+
259279
// De-duplicate pixels comparing to the previous frame.
260280
// Only global is supported for now as the color palettes as the operation required to compare
261281
// and offset the index lookups is too expensive for local palettes.
262-
DeDuplicatePixels(previousQuantized, quantized, indices, transparencyIndex);
282+
DeDuplicatePixels(previousQuantized, quantized, indices, replacementIndex);
263283
}
264284

265285
this.bitDepth = ColorNumerics.GetBitsNeededForColorDepth(quantized.Palette.Length);
@@ -290,11 +310,9 @@ private static void DeDuplicatePixels<TPixel>(
290310
IndexedImageFrame<TPixel> background,
291311
IndexedImageFrame<TPixel> source,
292312
Buffer2D<byte> indices,
293-
int transparencyIndex)
313+
byte replacementIndex)
294314
where TPixel : unmanaged, IPixel<TPixel>
295315
{
296-
// TODO: This should be the background color if not transparent.
297-
byte replacementIndex = unchecked((byte)transparencyIndex);
298316
for (int y = 0; y < background.Height; y++)
299317
{
300318
ref byte backgroundRowBase = ref MemoryMarshal.GetReference(background.DangerousGetRowSpan(y));
@@ -421,7 +439,7 @@ private void WriteLogicalScreenDescriptor(
421439
ImageMetadata metadata,
422440
int width,
423441
int height,
424-
int backgroundIndex,
442+
byte backgroundIndex,
425443
bool useGlobalTable,
426444
Stream stream)
427445
{
@@ -459,7 +477,7 @@ private void WriteLogicalScreenDescriptor(
459477
width: (ushort)width,
460478
height: (ushort)height,
461479
packed: packedValue,
462-
backgroundColorIndex: unchecked((byte)backgroundIndex),
480+
backgroundColorIndex: backgroundIndex,
463481
ratio);
464482

465483
Span<byte> buffer = stackalloc byte[20];

0 commit comments

Comments
 (0)