@@ -88,18 +88,24 @@ public void Encode<TPixel>(Image<TPixel> image, Stream stream, CancellationToken
88
88
GifMetadata gifMetadata = GetGifMetadata ( image ) ;
89
89
this . colorTableMode ??= gifMetadata . ColorTableMode ;
90
90
bool useGlobalTable = this . colorTableMode == GifColorTableMode . Global ;
91
-
92
- // Quantize the first image frame returning a palette.
93
- IndexedImageFrame < TPixel > ? quantized = null ;
91
+ bool useGlobalTableForFirstFrame = useGlobalTable ;
94
92
95
93
// Work out if there is an explicit transparent index set for the frame. We use that to ensure the
96
94
// correct value is set for the background index when quantizing.
97
95
GifFrameMetadata frameMetadata = GetGifFrameMetadata ( image . Frames . RootFrame , - 1 ) ;
96
+ if ( frameMetadata . ColorTableMode == GifColorTableMode . Local )
97
+ {
98
+ useGlobalTableForFirstFrame = false ;
99
+ }
100
+
101
+ // TODO: The first frame should not need to be quantized using the global table if it has a local color table.
98
102
103
+ // Quantize the first image frame returning a palette.
104
+ IndexedImageFrame < TPixel > ? quantized = null ;
99
105
if ( this . quantizer is null )
100
106
{
101
107
// Is this a gif with color information. If so use that, otherwise use octree.
102
- if ( gifMetadata . ColorTableMode == GifColorTableMode . Global && gifMetadata . GlobalColorTable ? . Length > 0 )
108
+ if ( useGlobalTable && gifMetadata . GlobalColorTable ? . Length > 0 )
103
109
{
104
110
// We avoid dithering by default to preserve the original colors.
105
111
int transparencyIndex = GetTransparentIndex ( quantized , frameMetadata ) ;
@@ -118,8 +124,9 @@ public void Encode<TPixel>(Image<TPixel> image, Stream stream, CancellationToken
118
124
}
119
125
}
120
126
121
- using ( IQuantizer < TPixel > frameQuantizer = this . quantizer . CreatePixelSpecificQuantizer < TPixel > ( this . configuration ) )
127
+ if ( useGlobalTableForFirstFrame )
122
128
{
129
+ using IQuantizer < TPixel > frameQuantizer = this . quantizer . CreatePixelSpecificQuantizer < TPixel > ( this . configuration ) ;
123
130
if ( useGlobalTable )
124
131
{
125
132
frameQuantizer . BuildPalette ( this . pixelSamplingStrategy , image ) ;
@@ -131,6 +138,17 @@ public void Encode<TPixel>(Image<TPixel> image, Stream stream, CancellationToken
131
138
quantized = frameQuantizer . QuantizeFrame ( image . Frames . RootFrame , image . Bounds ) ;
132
139
}
133
140
}
141
+ else
142
+ {
143
+ quantized = this . QuantizeAdditionalFrameAndUpdateMetadata (
144
+ image . Frames . RootFrame ,
145
+ image . Frames . RootFrame . Bounds ( ) ,
146
+ frameMetadata ,
147
+ true ,
148
+ default ,
149
+ false ,
150
+ frameMetadata . HasTransparency ? frameMetadata . TransparencyIndex : - 1 ) ;
151
+ }
134
152
135
153
// Write the header.
136
154
WriteHeader ( stream ) ;
@@ -243,8 +261,8 @@ private void EncodeAdditionalFrames<TPixel>(
243
261
return ;
244
262
}
245
263
246
- PaletteQuantizer < TPixel > paletteQuantizer = default ;
247
- bool hasPaletteQuantizer = false ;
264
+ PaletteQuantizer < TPixel > globalPaletteQuantizer = default ;
265
+ bool hasGlobalPaletteQuantizer = false ;
248
266
249
267
// Store the first frame as a reference for de-duplication comparison.
250
268
ImageFrame < TPixel > previousFrame = image . Frames . RootFrame ;
@@ -260,14 +278,14 @@ private void EncodeAdditionalFrames<TPixel>(
260
278
GifFrameMetadata gifMetadata = GetGifFrameMetadata ( currentFrame , globalTransparencyIndex ) ;
261
279
bool useLocal = this . colorTableMode == GifColorTableMode . Local || ( gifMetadata . ColorTableMode == GifColorTableMode . Local ) ;
262
280
263
- if ( ! useLocal && ! hasPaletteQuantizer && i > 0 )
281
+ if ( ! useLocal && ! hasGlobalPaletteQuantizer && i > 0 )
264
282
{
265
283
// The palette quantizer can reuse the same global pixel map across multiple frames since the palette is unchanging.
266
284
// This allows a reduction of memory usage across multi-frame gifs using a global palette
267
285
// and also allows use to reuse the cache from previous runs.
268
286
int transparencyIndex = gifMetadata . HasTransparency ? gifMetadata . TransparencyIndex : - 1 ;
269
- paletteQuantizer = new ( this . configuration , this . quantizer ! . Options , globalPalette , transparencyIndex ) ;
270
- hasPaletteQuantizer = true ;
287
+ globalPaletteQuantizer = new ( this . configuration , this . quantizer ! . Options , globalPalette , transparencyIndex ) ;
288
+ hasGlobalPaletteQuantizer = true ;
271
289
}
272
290
273
291
this . EncodeAdditionalFrame (
@@ -278,16 +296,16 @@ private void EncodeAdditionalFrames<TPixel>(
278
296
encodingFrame ,
279
297
useLocal ,
280
298
gifMetadata ,
281
- paletteQuantizer ,
299
+ globalPaletteQuantizer ,
282
300
previousDisposalMethod ) ;
283
301
284
302
previousFrame = currentFrame ;
285
303
previousDisposalMethod = gifMetadata . DisposalMethod ;
286
304
}
287
305
288
- if ( hasPaletteQuantizer )
306
+ if ( hasGlobalPaletteQuantizer )
289
307
{
290
- paletteQuantizer . Dispose ( ) ;
308
+ globalPaletteQuantizer . Dispose ( ) ;
291
309
}
292
310
}
293
311
0 commit comments