Skip to content

Commit 2752a45

Browse files
Implement up GifMetadata
1 parent d52815b commit 2752a45

22 files changed

Lines changed: 154 additions & 118 deletions

src/ImageSharp/Formats/Gif/GifColorTableMode.cs

Lines changed: 0 additions & 20 deletions
This file was deleted.

src/ImageSharp/Formats/Gif/GifDecoderCore.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -696,14 +696,14 @@ private void SetFrameMetadata(ImageFrameMetadata metadata)
696696
&& this.logicalScreenDescriptor.GlobalColorTableSize > 0)
697697
{
698698
GifFrameMetadata gifMeta = metadata.GetGifMetadata();
699-
gifMeta.ColorTableMode = GifColorTableMode.Global;
699+
gifMeta.ColorTableMode = FrameColorTableMode.Global;
700700
}
701701

702702
if (this.imageDescriptor.LocalColorTableFlag
703703
&& this.imageDescriptor.LocalColorTableSize > 0)
704704
{
705705
GifFrameMetadata gifMeta = metadata.GetGifMetadata();
706-
gifMeta.ColorTableMode = GifColorTableMode.Local;
706+
gifMeta.ColorTableMode = FrameColorTableMode.Local;
707707

708708
Color[] colorTable = new Color[this.imageDescriptor.LocalColorTableSize];
709709
ReadOnlySpan<Rgb24> rgbTable = MemoryMarshal.Cast<byte, Rgb24>(this.currentLocalColorTable!.GetSpan()[..this.currentLocalColorTableSize]);
@@ -766,8 +766,8 @@ private void ReadLogicalScreenDescriptorAndGlobalColorTable(BufferedReadStream s
766766
this.metadata = meta;
767767
this.gifMetadata = meta.GetGifMetadata();
768768
this.gifMetadata.ColorTableMode = this.logicalScreenDescriptor.GlobalColorTableFlag
769-
? GifColorTableMode.Global
770-
: GifColorTableMode.Local;
769+
? FrameColorTableMode.Global
770+
: FrameColorTableMode.Local;
771771

772772
if (this.logicalScreenDescriptor.GlobalColorTableFlag)
773773
{

src/ImageSharp/Formats/Gif/GifEncoder.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ public sealed class GifEncoder : QuantizingImageEncoder
1111
/// <summary>
1212
/// Gets the color table mode: Global or local.
1313
/// </summary>
14-
public GifColorTableMode? ColorTableMode { get; init; }
14+
public FrameColorTableMode? ColorTableMode { get; init; }
1515

1616
/// <inheritdoc/>
1717
protected override void Encode<TPixel>(Image<TPixel> image, Stream stream, CancellationToken cancellationToken)

src/ImageSharp/Formats/Gif/GifEncoderCore.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ internal sealed class GifEncoderCore : IImageEncoderInternals
4949
/// <summary>
5050
/// The color table mode: Global or local.
5151
/// </summary>
52-
private GifColorTableMode? colorTableMode;
52+
private FrameColorTableMode? colorTableMode;
5353

5454
/// <summary>
5555
/// The pixel sampling strategy for global quantization.
@@ -87,7 +87,7 @@ public void Encode<TPixel>(Image<TPixel> image, Stream stream, CancellationToken
8787

8888
GifMetadata gifMetadata = GetGifMetadata(image);
8989
this.colorTableMode ??= gifMetadata.ColorTableMode;
90-
bool useGlobalTable = this.colorTableMode == GifColorTableMode.Global;
90+
bool useGlobalTable = this.colorTableMode == FrameColorTableMode.Global;
9191

9292
// Quantize the first image frame returning a palette.
9393
IndexedImageFrame<TPixel>? quantized = null;
@@ -99,7 +99,7 @@ public void Encode<TPixel>(Image<TPixel> image, Stream stream, CancellationToken
9999
if (this.quantizer is null)
100100
{
101101
// Is this a gif with color information. If so use that, otherwise use octree.
102-
if (gifMetadata.ColorTableMode == GifColorTableMode.Global && gifMetadata.GlobalColorTable?.Length > 0)
102+
if (gifMetadata.ColorTableMode == FrameColorTableMode.Global && gifMetadata.GlobalColorTable?.Length > 0)
103103
{
104104
// We avoid dithering by default to preserve the original colors.
105105
int transparencyIndex = GetTransparentIndex(quantized, frameMetadata);
@@ -221,7 +221,7 @@ private static GifFrameMetadata GetGifFrameMetadata<TPixel>(ImageFrame<TPixel> f
221221
metadata = GifFrameMetadata.FromAnimatedMetadata(ani);
222222
}
223223

224-
if (metadata?.ColorTableMode == GifColorTableMode.Global && transparencyIndex > -1)
224+
if (metadata?.ColorTableMode == FrameColorTableMode.Global && transparencyIndex > -1)
225225
{
226226
metadata.HasTransparency = true;
227227
metadata.TransparencyIndex = ClampIndex(transparencyIndex);
@@ -258,7 +258,7 @@ private void EncodeAdditionalFrames<TPixel>(
258258
ImageFrame<TPixel> currentFrame = image.Frames[i];
259259
ImageFrame<TPixel>? nextFrame = i < image.Frames.Count - 1 ? image.Frames[i + 1] : null;
260260
GifFrameMetadata gifMetadata = GetGifFrameMetadata(currentFrame, globalTransparencyIndex);
261-
bool useLocal = this.colorTableMode == GifColorTableMode.Local || (gifMetadata.ColorTableMode == GifColorTableMode.Local);
261+
bool useLocal = this.colorTableMode == FrameColorTableMode.Local || (gifMetadata.ColorTableMode == FrameColorTableMode.Local);
262262

263263
if (!useLocal && !hasPaletteQuantizer && i > 0)
264264
{
@@ -301,7 +301,7 @@ private void EncodeFirstFrame<TPixel>(
301301

302302
Buffer2D<byte> indices = ((IPixelSource)quantized).PixelBuffer;
303303
Rectangle interest = indices.FullRectangle();
304-
bool useLocal = this.colorTableMode == GifColorTableMode.Local || (metadata.ColorTableMode == GifColorTableMode.Local);
304+
bool useLocal = this.colorTableMode == FrameColorTableMode.Local || (metadata.ColorTableMode == FrameColorTableMode.Local);
305305
int bitDepth = ColorNumerics.GetBitsNeededForColorDepth(quantized.Palette.Length);
306306

307307
this.WriteImageDescriptor(interest, useLocal, bitDepth, stream);

src/ImageSharp/Formats/Gif/GifFrameMetadata.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ private GifFrameMetadata(GifFrameMetadata other)
4040
/// <summary>
4141
/// Gets or sets the color table mode.
4242
/// </summary>
43-
public GifColorTableMode ColorTableMode { get; set; }
43+
public FrameColorTableMode ColorTableMode { get; set; }
4444

4545
/// <summary>
4646
/// Gets or sets the local color table, if any.
@@ -101,7 +101,7 @@ internal static GifFrameMetadata FromAnimatedMetadata(AnimatedImageFrameMetadata
101101
return new()
102102
{
103103
LocalColorTable = metadata.ColorTable,
104-
ColorTableMode = metadata.ColorTableMode == FrameColorTableMode.Global ? GifColorTableMode.Global : GifColorTableMode.Local,
104+
ColorTableMode = metadata.ColorTableMode,
105105
FrameDelay = (int)Math.Round(metadata.Duration.TotalMilliseconds / 10),
106106
DisposalMethod = GetMode(metadata.DisposalMode),
107107
HasTransparency = hasTransparency,

src/ImageSharp/Formats/Gif/GifMetadata.cs

Lines changed: 58 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.Formats.Gif;
88
/// <summary>
99
/// Provides Gif specific metadata information for the image.
1010
/// </summary>
11-
public class GifMetadata : IDeepCloneable
11+
public class GifMetadata : IFormatMetadata<GifMetadata>
1212
{
1313
/// <summary>
1414
/// Initializes a new instance of the <see cref="GifMetadata"/> class.
@@ -49,7 +49,7 @@ private GifMetadata(GifMetadata other)
4949
/// <summary>
5050
/// Gets or sets the color table mode.
5151
/// </summary>
52-
public GifColorTableMode ColorTableMode { get; set; }
52+
public FrameColorTableMode ColorTableMode { get; set; }
5353

5454
/// <summary>
5555
/// Gets or sets the global color table, if any.
@@ -69,9 +69,6 @@ private GifMetadata(GifMetadata other)
6969
/// </summary>
7070
public IList<string> Comments { get; set; } = [];
7171

72-
/// <inheritdoc/>
73-
public IDeepCloneable DeepClone() => new GifMetadata(this);
74-
7572
internal static GifMetadata FromAnimatedMetadata(AnimatedImageMetadata metadata)
7673
{
7774
int index = 0;
@@ -92,9 +89,64 @@ internal static GifMetadata FromAnimatedMetadata(AnimatedImageMetadata metadata)
9289
return new()
9390
{
9491
GlobalColorTable = metadata.ColorTable,
95-
ColorTableMode = metadata.ColorTableMode == FrameColorTableMode.Global ? GifColorTableMode.Global : GifColorTableMode.Local,
92+
ColorTableMode = metadata.ColorTableMode,
93+
RepeatCount = metadata.RepeatCount,
94+
BackgroundColorIndex = (byte)Numerics.Clamp(index, 0, 255),
95+
};
96+
}
97+
98+
/// <inheritdoc/>
99+
public static GifMetadata FromFormatConnectingMetadata(FormatConnectingMetadata metadata)
100+
{
101+
int index = 0;
102+
Color background = metadata.BackgroundColor;
103+
if (metadata.ColorTable.HasValue)
104+
{
105+
ReadOnlySpan<Color> colorTable = metadata.ColorTable.Value.Span;
106+
for (int i = 0; i < colorTable.Length; i++)
107+
{
108+
if (background == colorTable[i])
109+
{
110+
index = i;
111+
break;
112+
}
113+
}
114+
}
115+
116+
return new()
117+
{
118+
GlobalColorTable = metadata.ColorTable,
119+
ColorTableMode = metadata.ColorTableMode,
96120
RepeatCount = metadata.RepeatCount,
97121
BackgroundColorIndex = (byte)Numerics.Clamp(index, 0, 255),
98122
};
99123
}
124+
125+
/// <inheritdoc/>
126+
public FormatConnectingMetadata ToFormatConnectingMetadata()
127+
{
128+
Color color = this.GlobalColorTable.HasValue && this.GlobalColorTable.Value.Span.Length > this.BackgroundColorIndex
129+
? this.GlobalColorTable.Value.Span[this.BackgroundColorIndex]
130+
: Color.Transparent;
131+
132+
return new()
133+
{
134+
AnimateRootFrame = true,
135+
BackgroundColor = color,
136+
ColorTable = this.GlobalColorTable,
137+
ColorTableMode = this.ColorTableMode,
138+
PixelTypeInfo = new PixelTypeInfo(24)
139+
{
140+
ColorType = PixelColorType.Indexed,
141+
ComponentInfo = PixelComponentInfo.Create(3, 24, 8, 8, 8),
142+
},
143+
RepeatCount = this.RepeatCount,
144+
};
145+
}
146+
147+
/// <inheritdoc/>
148+
public IDeepCloneable DeepClone() => ((IDeepCloneable<GifMetadata>)this).DeepClone();
149+
150+
/// <inheritdoc/>
151+
GifMetadata IDeepCloneable<GifMetadata>.DeepClone() => new(this);
100152
}

src/ImageSharp/Formats/Gif/MetadataExtensions.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ internal static AnimatedImageMetadata ToAnimatedImageMetadata(this GifMetadata s
7070
return new()
7171
{
7272
ColorTable = source.GlobalColorTable,
73-
ColorTableMode = source.ColorTableMode == GifColorTableMode.Global ? FrameColorTableMode.Global : FrameColorTableMode.Local,
73+
ColorTableMode = source.ColorTableMode,
7474
RepeatCount = source.RepeatCount,
7575
BackgroundColor = background,
7676
};
@@ -83,12 +83,12 @@ internal static AnimatedImageFrameMetadata ToAnimatedImageFrameMetadata(this Gif
8383
bool blendSource = source.DisposalMethod == GifDisposalMethod.RestoreToBackground || (source.LocalColorTable?.Length == 256 && !source.HasTransparency);
8484

8585
// If the color table is global and frame has no transparency. Consider it 'Source' also.
86-
blendSource |= source.ColorTableMode == GifColorTableMode.Global && !source.HasTransparency;
86+
blendSource |= source.ColorTableMode == FrameColorTableMode.Global && !source.HasTransparency;
8787

8888
return new()
8989
{
9090
ColorTable = source.LocalColorTable,
91-
ColorTableMode = source.ColorTableMode == GifColorTableMode.Global ? FrameColorTableMode.Global : FrameColorTableMode.Local,
91+
ColorTableMode = source.ColorTableMode,
9292
Duration = TimeSpan.FromMilliseconds(source.FrameDelay * 10),
9393
DisposalMode = GetMode(source.DisposalMethod),
9494
BlendMode = blendSource ? FrameBlendMode.Source : FrameBlendMode.Over,

src/ImageSharp/Formats/Png/PngEncoderCore.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1680,14 +1680,14 @@ private static PngColorType SuggestColorType<TPixel>(in PixelTypeInfo info)
16801680
{
16811681
return info.ColorType switch
16821682
{
1683-
PixelColorType.Grayscale => PngColorType.Grayscale,
1683+
PixelColorType.Luminance => PngColorType.Grayscale,
16841684
_ => PngColorType.Rgb,
16851685
};
16861686
}
16871687

16881688
return info.ColorType switch
16891689
{
1690-
PixelColorType.Grayscale | PixelColorType.Alpha or PixelColorType.Alpha => PngColorType.GrayscaleWithAlpha,
1690+
PixelColorType.Luminance | PixelColorType.Alpha or PixelColorType.Alpha => PngColorType.GrayscaleWithAlpha,
16911691
_ => PngColorType.RgbWithAlpha,
16921692
};
16931693
}

src/ImageSharp/PixelFormats/PixelColorType.cs

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -35,34 +35,39 @@ public enum PixelColorType
3535
Alpha = 1 << 3,
3636

3737
/// <summary>
38-
/// Indicates that the color is in grayscale.
38+
/// Represents the Exponent component used in formats like R9G9B9E5.
3939
/// </summary>
40-
Grayscale = 1 << 4,
40+
Exponent = 1 << 4,
4141

4242
/// <summary>
43-
/// Indicates that the color is in RGB (Red, Green, Blue) format.
43+
/// Indicates that the color is in luminance (grayscale) format.
4444
/// </summary>
45-
RGB = Red | Green | Blue | (1 << 5),
45+
Luminance = 1 << 5,
4646

4747
/// <summary>
48-
/// Indicates that the color is in BGR (Blue, Green, Red) format.
48+
/// Indicates that the color is indexed using a palette.
49+
/// </summary>
50+
Indexed = 1 << 6,
51+
52+
/// <summary>
53+
/// Indicates that the color is in RGB (Red, Green, Blue) format.
4954
/// </summary>
50-
BGR = Blue | Green | Red | (1 << 6),
55+
RGB = Red | Green | Blue | (1 << 7),
5156

5257
/// <summary>
53-
/// Represents the Luminance component in YCbCr.
58+
/// Indicates that the color is in BGR (Blue, Green, Red) format.
5459
/// </summary>
55-
Luminance = 1 << 7,
60+
BGR = Blue | Green | Red | (1 << 8),
5661

5762
/// <summary>
5863
/// Represents the Chrominance Blue component in YCbCr.
5964
/// </summary>
60-
ChrominanceBlue = 1 << 8,
65+
ChrominanceBlue = 1 << 9,
6166

6267
/// <summary>
6368
/// Represents the Chrominance Red component in YCbCr.
6469
/// </summary>
65-
ChrominanceRed = 1 << 9,
70+
ChrominanceRed = 1 << 10,
6671

6772
/// <summary>
6873
/// Indicates that the color is in YCbCr (Luminance, Chrominance Blue, Chrominance Red) format.
@@ -72,22 +77,22 @@ public enum PixelColorType
7277
/// <summary>
7378
/// Represents the Cyan component in CMYK.
7479
/// </summary>
75-
Cyan = 1 << 10,
80+
Cyan = 1 << 11,
7681

7782
/// <summary>
7883
/// Represents the Magenta component in CMYK.
7984
/// </summary>
80-
Magenta = 1 << 11,
85+
Magenta = 1 << 12,
8186

8287
/// <summary>
8388
/// Represents the Yellow component in CMYK.
8489
/// </summary>
85-
Yellow = 1 << 12,
90+
Yellow = 1 << 13,
8691

8792
/// <summary>
8893
/// Represents the Key (black) component in CMYK and YCCK.
8994
/// </summary>
90-
Key = 1 << 13,
95+
Key = 1 << 14,
9196

9297
/// <summary>
9398
/// Indicates that the color is in CMYK (Cyan, Magenta, Yellow, Key) format.
@@ -99,13 +104,8 @@ public enum PixelColorType
99104
/// </summary>
100105
YCCK = Luminance | ChrominanceBlue | ChrominanceRed | Key,
101106

102-
/// <summary>
103-
/// Indicates that the color is indexed using a palette.
104-
/// </summary>
105-
Indexed = 1 << 14,
106-
107107
/// <summary>
108108
/// Indicates that the color is of a type not specified in this enum.
109109
/// </summary>
110-
Other = 1 << 15
110+
Other = 1 << 16
111111
}

src/ImageSharp/PixelFormats/PixelComponentInfo.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ public static PixelComponentInfo Create<TPixel>(int count, params int[] precisio
5353
/// <exception cref="ArgumentOutOfRangeException">The component precision and index cannot exceed the component range.</exception>
5454
public static PixelComponentInfo Create(int count, int bitsPerPixel, params int[] precision)
5555
{
56-
if (precision.Length != count || precision.Length > 16)
56+
if (precision.Length < count || precision.Length > 16)
5757
{
5858
throw new ArgumentOutOfRangeException(nameof(count), $"Count {count} must match the length of precision array and cannot exceed 16.");
5959
}

0 commit comments

Comments
 (0)