Skip to content

Commit 43aaad1

Browse files
Make color tables mutable
1 parent 73067b9 commit 43aaad1

10 files changed

Lines changed: 34 additions & 32 deletions

File tree

src/ImageSharp/Formats/Gif/GifDecoderCore.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -716,7 +716,7 @@ private void SetFrameMetadata(ImageFrameMetadata metadata)
716716
colorTable[i] = new Color(Unsafe.Add(ref localBase, (uint)i));
717717
}
718718

719-
gifMeta.DecodedLocalColorTable = colorTable;
719+
gifMeta.LocalColorTable = colorTable;
720720
}
721721

722722
// Graphics control extensions is optional.
@@ -793,7 +793,7 @@ private void ReadLogicalScreenDescriptorAndGlobalColorTable(BufferedReadStream s
793793
colorTable[i] = new Color(Unsafe.Add(ref globalBase, (uint)i));
794794
}
795795

796-
this.gifMetadata.DecodedGlobalColorTable = colorTable;
796+
this.gifMetadata.GlobalColorTable = colorTable;
797797
}
798798
}
799799
}

src/ImageSharp/Formats/Gif/GifEncoderCore.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -102,10 +102,10 @@ public void Encode<TPixel>(Image<TPixel> image, Stream stream, CancellationToken
102102
if (this.quantizer is null)
103103
{
104104
// Is this a gif with color information. If so use that, otherwise use octree.
105-
if (gifMetadata.ColorTableMode == GifColorTableMode.Global && gifMetadata.DecodedGlobalColorTable.Length > 0)
105+
if (gifMetadata.ColorTableMode == GifColorTableMode.Global && gifMetadata.GlobalColorTable?.Length > 0)
106106
{
107107
// We avoid dithering by default to preserve the original colors.
108-
this.quantizer = new PaletteQuantizer(gifMetadata.DecodedGlobalColorTable, new() { Dither = null });
108+
this.quantizer = new PaletteQuantizer(gifMetadata.GlobalColorTable.Value, new() { Dither = null });
109109
}
110110
else
111111
{
@@ -234,11 +234,11 @@ private void EncodeFrame<TPixel>(
234234
if (useLocal)
235235
{
236236
// Reassign using the current frame and details.
237-
if (metadata?.DecodedLocalColorTable.Length > 0)
237+
if (metadata?.LocalColorTable?.Length > 0)
238238
{
239239
// We can use the color data from the decoded metadata here.
240240
// We avoid dithering by default to preserve the original colors.
241-
PaletteQuantizer localQuantizer = new(metadata.DecodedLocalColorTable, new() { Dither = null });
241+
PaletteQuantizer localQuantizer = new(metadata.LocalColorTable.Value, new() { Dither = null });
242242
using IQuantizer<TPixel> frameQuantizer = localQuantizer.CreatePixelSpecificQuantizer<TPixel>(this.configuration, localQuantizer.Options);
243243
quantized = frameQuantizer.BuildPaletteAndQuantizeFrame(frame, frame.Bounds());
244244
}

src/ImageSharp/Formats/Gif/GifFrameMetadata.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@ private GifFrameMetadata(GifFrameMetadata other)
2525
this.FrameDelay = other.FrameDelay;
2626
this.DisposalMethod = other.DisposalMethod;
2727

28-
if (other.DecodedLocalColorTable.Length > 0)
28+
if (other.LocalColorTable?.Length > 0)
2929
{
30-
this.DecodedLocalColorTable = other.DecodedLocalColorTable.ToArray();
30+
this.LocalColorTable = other.LocalColorTable.Value.ToArray();
3131
}
3232

3333
this.HasTransparency = other.HasTransparency;
@@ -40,9 +40,9 @@ private GifFrameMetadata(GifFrameMetadata other)
4040
public GifColorTableMode ColorTableMode { get; set; }
4141

4242
/// <summary>
43-
/// Gets the decoded global color table, if any.
43+
/// Gets or sets the local color table, if any.
4444
/// </summary>
45-
public ReadOnlyMemory<Color> DecodedLocalColorTable { get; internal set; }
45+
public ReadOnlyMemory<Color>? LocalColorTable { get; set; }
4646

4747
/// <summary>
4848
/// Gets or sets a value indicating whether the frame has transparency

src/ImageSharp/Formats/Gif/GifMetadata.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@ private GifMetadata(GifMetadata other)
2525
this.ColorTableMode = other.ColorTableMode;
2626
this.BackgroundColor = other.BackgroundColor;
2727

28-
if (other.DecodedGlobalColorTable.Length > 0)
28+
if (other.GlobalColorTable?.Length > 0)
2929
{
30-
this.DecodedGlobalColorTable = other.DecodedGlobalColorTable.ToArray();
30+
this.GlobalColorTable = other.GlobalColorTable.Value.ToArray();
3131
}
3232

3333
for (int i = 0; i < other.Comments.Count; i++)
@@ -50,12 +50,12 @@ private GifMetadata(GifMetadata other)
5050
public GifColorTableMode ColorTableMode { get; set; }
5151

5252
/// <summary>
53-
/// Gets the decoded global color table, if any.
53+
/// Gets or sets the global color table, if any.
5454
/// </summary>
55-
public ReadOnlyMemory<Color> DecodedGlobalColorTable { get; internal set; }
55+
public ReadOnlyMemory<Color>? GlobalColorTable { get; set; }
5656

5757
/// <summary>
58-
/// Gets or sets the index at the <see cref="DecodedGlobalColorTable"/> for the background color.
58+
/// Gets or sets the index at the <see cref="GlobalColorTable"/> for the background color.
5959
/// The background color is the color used for those pixels on the screen that are not covered by an image.
6060
/// </summary>
6161
public byte BackgroundColor { get; set; }

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -175,11 +175,11 @@ public void NonMutatingEncodePreservesPaletteCount()
175175
int maxColors;
176176
if (colorMode == GifColorTableMode.Global)
177177
{
178-
maxColors = metaData.DecodedGlobalColorTable.Length;
178+
maxColors = metaData.GlobalColorTable.Value.Length;
179179
}
180180
else
181181
{
182-
maxColors = frameMetadata.DecodedLocalColorTable.Length;
182+
maxColors = frameMetadata.LocalColorTable.Value.Length;
183183
}
184184

185185
GifEncoder encoder = new()
@@ -201,11 +201,11 @@ public void NonMutatingEncodePreservesPaletteCount()
201201
colorMode = cloneMetadata.ColorTableMode;
202202
if (colorMode == GifColorTableMode.Global)
203203
{
204-
maxColors = metaData.DecodedGlobalColorTable.Length;
204+
maxColors = metaData.GlobalColorTable.Value.Length;
205205
}
206206
else
207207
{
208-
maxColors = frameMetadata.DecodedLocalColorTable.Length;
208+
maxColors = frameMetadata.LocalColorTable.Value.Length;
209209
}
210210

211211
Assert.Equal(64, maxColors);
@@ -217,7 +217,7 @@ public void NonMutatingEncodePreservesPaletteCount()
217217

218218
if (iMeta.ColorTableMode == GifColorTableMode.Local)
219219
{
220-
Assert.Equal(iMeta.DecodedLocalColorTable.Length, cMeta.DecodedLocalColorTable.Length);
220+
Assert.Equal(iMeta.LocalColorTable.Value.Length, cMeta.LocalColorTable.Value.Length);
221221
}
222222

223223
Assert.Equal(iMeta.FrameDelay, cMeta.FrameDelay);

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,18 @@ public void CloneIsDeep()
1515
{
1616
FrameDelay = 1,
1717
DisposalMethod = GifDisposalMethod.RestoreToBackground,
18-
DecodedLocalColorTable = new[] { Color.Black, Color.White }
18+
LocalColorTable = new[] { Color.Black, Color.White }
1919
};
2020

2121
GifFrameMetadata clone = (GifFrameMetadata)meta.DeepClone();
2222

2323
clone.FrameDelay = 2;
2424
clone.DisposalMethod = GifDisposalMethod.RestoreToPrevious;
25-
clone.DecodedLocalColorTable = new[] { Color.Black };
25+
clone.LocalColorTable = new[] { Color.Black };
2626

2727
Assert.False(meta.FrameDelay.Equals(clone.FrameDelay));
2828
Assert.False(meta.DisposalMethod.Equals(clone.DisposalMethod));
29-
Assert.False(meta.DecodedLocalColorTable.Length == clone.DecodedLocalColorTable.Length);
30-
Assert.Equal(1, clone.DecodedLocalColorTable.Length);
29+
Assert.False(meta.LocalColorTable.Value.Length == clone.LocalColorTable.Value.Length);
30+
Assert.Equal(1, clone.LocalColorTable.Value.Length);
3131
}
3232
}

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,20 +34,20 @@ public void CloneIsDeep()
3434
{
3535
RepeatCount = 1,
3636
ColorTableMode = GifColorTableMode.Global,
37-
DecodedGlobalColorTable = new[] { Color.Black, Color.White },
37+
GlobalColorTable = new[] { Color.Black, Color.White },
3838
Comments = new List<string> { "Foo" }
3939
};
4040

4141
GifMetadata clone = (GifMetadata)meta.DeepClone();
4242

4343
clone.RepeatCount = 2;
4444
clone.ColorTableMode = GifColorTableMode.Local;
45-
clone.DecodedGlobalColorTable = new[] { Color.Black };
45+
clone.GlobalColorTable = new[] { Color.Black };
4646

4747
Assert.False(meta.RepeatCount.Equals(clone.RepeatCount));
4848
Assert.False(meta.ColorTableMode.Equals(clone.ColorTableMode));
49-
Assert.False(meta.DecodedGlobalColorTable.Length == clone.DecodedGlobalColorTable.Length);
50-
Assert.Equal(1, clone.DecodedGlobalColorTable.Length);
49+
Assert.False(meta.GlobalColorTable.Value.Length == clone.GlobalColorTable.Value.Length);
50+
Assert.Equal(1, clone.GlobalColorTable.Value.Length);
5151
Assert.False(meta.Comments.Equals(clone.Comments));
5252
Assert.True(meta.Comments.SequenceEqual(clone.Comments));
5353
}
@@ -208,7 +208,7 @@ public void Identify_Frames(
208208

209209
if (colorTableMode == GifColorTableMode.Global)
210210
{
211-
Assert.Equal(globalColorTableLength, gifMetadata.DecodedGlobalColorTable.Length);
211+
Assert.Equal(globalColorTableLength, gifMetadata.GlobalColorTable.Value.Length);
212212
}
213213

214214
Assert.Equal(frameDelay, gifFrameMetadata.FrameDelay);

tests/ImageSharp.Tests/Image/ImageFrameCollectionTests.NonGeneric.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ private static void CompareGifMetadata(ImageFrame a, ImageFrame b)
318318

319319
if (aData.ColorTableMode == GifColorTableMode.Local && bData.ColorTableMode == GifColorTableMode.Local)
320320
{
321-
Assert.Equal(aData.DecodedLocalColorTable.Length, bData.DecodedLocalColorTable.Length);
321+
Assert.Equal(aData.LocalColorTable.Value.Length, bData.LocalColorTable.Value.Length);
322322
}
323323
}
324324
}

tests/ImageSharp.Tests/Metadata/ImageFrameMetadataTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,14 @@ public void ConstructorImageFrameMetadata()
2626
ImageFrameMetadata metaData = new();
2727
GifFrameMetadata gifFrameMetadata = metaData.GetGifMetadata();
2828
gifFrameMetadata.FrameDelay = frameDelay;
29-
gifFrameMetadata.DecodedLocalColorTable = Enumerable.Repeat(Color.HotPink, colorTableLength).ToArray();
29+
gifFrameMetadata.LocalColorTable = Enumerable.Repeat(Color.HotPink, colorTableLength).ToArray();
3030
gifFrameMetadata.DisposalMethod = disposalMethod;
3131

3232
ImageFrameMetadata clone = new(metaData);
3333
GifFrameMetadata cloneGifFrameMetadata = clone.GetGifMetadata();
3434

3535
Assert.Equal(frameDelay, cloneGifFrameMetadata.FrameDelay);
36-
Assert.Equal(colorTableLength, cloneGifFrameMetadata.DecodedLocalColorTable.Length);
36+
Assert.Equal(colorTableLength, cloneGifFrameMetadata.LocalColorTable.Value.Length);
3737
Assert.Equal(disposalMethod, cloneGifFrameMetadata.DisposalMethod);
3838
}
3939

tests/ImageSharp.Tests/TestImages.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,8 @@ public static class Issues
482482
public const string Issue2288_B = "Gif/issues/issue_2288_2.gif";
483483
public const string Issue2288_C = "Gif/issues/issue_2288_3.gif";
484484
public const string Issue2288_D = "Gif/issues/issue_2288_4.gif";
485+
public const string Issue2450 = "Gif/issues/issue_2450.gif";
486+
public const string Issue2198 = "Gif/issues/issue_2198.gif";
485487
}
486488

487489
public static readonly string[] All = { Rings, Giphy, Cheers, Trans, Kumin, Leo, Ratio4x1, Ratio1x4 };

0 commit comments

Comments
 (0)