diff --git a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs
index 4cb524ecb..385c79896 100644
--- a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs
+++ b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs
@@ -10,7 +10,6 @@ using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.MetaData;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Memory;
-using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Formats.Bmp
{
@@ -165,9 +164,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
public IImageInfo Identify(Stream stream)
{
this.ReadImageHeaders(stream, out _, out _);
-
- var size = new Size(this.infoHeader.Width, this.infoHeader.Height);
- return new BmpInfo(new PixelTypeInfo(this.infoHeader.BitsPerPixel), size, this.metaData);
+ return new ImageInfo(new PixelTypeInfo(this.infoHeader.BitsPerPixel), this.infoHeader.Width, this.infoHeader.Height, this.metaData);
}
///
diff --git a/src/ImageSharp/Formats/Bmp/BmpInfo.cs b/src/ImageSharp/Formats/Bmp/BmpInfo.cs
deleted file mode 100644
index dfffe94db..000000000
--- a/src/ImageSharp/Formats/Bmp/BmpInfo.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (c) Six Labors and contributors.
-// Licensed under the Apache License, Version 2.0.
-
-using SixLabors.ImageSharp.MetaData;
-using SixLabors.Primitives;
-
-namespace SixLabors.ImageSharp.Formats.Bmp
-{
- ///
- /// Contains information about the bmp including dimensions, pixel type information and additional metadata.
- ///
- public class BmpInfo : ImageInfo
- {
- ///
- /// Initializes a new instance of the class.
- ///
- /// The image pixel type information.
- /// The size of the image in pixels.
- /// The images metadata.
- internal BmpInfo(PixelTypeInfo pixelType, Size size, ImageMetaData metaData)
- : base(pixelType, size, metaData)
- {
- }
- }
-}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Gif/GifColorTableMode.cs b/src/ImageSharp/Formats/Gif/GifColorTableMode.cs
index aa4192863..95b333562 100644
--- a/src/ImageSharp/Formats/Gif/GifColorTableMode.cs
+++ b/src/ImageSharp/Formats/Gif/GifColorTableMode.cs
@@ -4,7 +4,7 @@
namespace SixLabors.ImageSharp.Formats.Gif
{
///
- /// Provides enumeration for the available Gif color table modes.
+ /// Provides enumeration for the available color table modes.
///
public enum GifColorTableMode
{
diff --git a/src/ImageSharp/Formats/Gif/GifConstants.cs b/src/ImageSharp/Formats/Gif/GifConstants.cs
index 0dbd39b99..cc80b0cce 100644
--- a/src/ImageSharp/Formats/Gif/GifConstants.cs
+++ b/src/ImageSharp/Formats/Gif/GifConstants.cs
@@ -26,6 +26,11 @@ namespace SixLabors.ImageSharp.Formats.Gif
///
internal static readonly byte[] MagicNumber = Encoding.UTF8.GetBytes(FileType + FileVersion);
+ ///
+ /// Gets the key used for storing and retriving metadata.
+ ///
+ public const string MetaDataKey = FileType;
+
///
/// The extension block introducer !.
///
@@ -41,20 +46,25 @@ namespace SixLabors.ImageSharp.Formats.Gif
///
public const byte ApplicationExtensionLabel = 0xFF;
+ ///
+ /// The application block size.
+ ///
+ public const byte ApplicationBlockSize = 11;
+
///
/// The application identification.
///
- public const string ApplicationIdentification = "NETSCAPE2.0";
+ public const string NetscapeApplicationIdentification = "NETSCAPE2.0";
///
/// The ASCII encoded application identification bytes.
///
- internal static readonly byte[] ApplicationIdentificationBytes = Encoding.UTF8.GetBytes(ApplicationIdentification);
+ internal static readonly byte[] NetscapeApplicationIdentificationBytes = Encoding.UTF8.GetBytes(NetscapeApplicationIdentification);
///
- /// The application block size.
+ /// The Netscape looping application sub block size.
///
- public const byte ApplicationBlockSize = 11;
+ public const byte NetscapeLoopingSubBlockSize = 3;
///
/// The comment label.
diff --git a/src/ImageSharp/Formats/Gif/GifDecoder.cs b/src/ImageSharp/Formats/Gif/GifDecoder.cs
index ac451a355..42c76d640 100644
--- a/src/ImageSharp/Formats/Gif/GifDecoder.cs
+++ b/src/ImageSharp/Formats/Gif/GifDecoder.cs
@@ -3,6 +3,7 @@
using System.IO;
using System.Text;
+using SixLabors.ImageSharp.MetaData;
using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Formats.Gif
diff --git a/src/ImageSharp/Formats/Gif/GifDecoderCore.cs b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs
index e79151752..092ac859d 100644
--- a/src/ImageSharp/Formats/Gif/GifDecoderCore.cs
+++ b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs
@@ -61,10 +61,15 @@ namespace SixLabors.ImageSharp.Formats.Gif
private GifImageDescriptor imageDescriptor;
///
- /// The metadata
+ /// The abstract metadata.
///
private ImageMetaData metaData;
+ ///
+ /// The gif specific metadata.
+ ///
+ private GifMetaData gifMetaData;
+
///
/// Initializes a new instance of the class.
///
@@ -134,11 +139,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
this.ReadComments();
break;
case GifConstants.ApplicationExtensionLabel:
-
- // The application extension length should be 11 but we've got test images that incorrectly
- // set this to 252.
- int appLength = stream.ReadByte();
- this.Skip(appLength); // No need to read.
+ this.ReadApplicationExtension();
break;
case GifConstants.PlainTextLabel:
int plainLength = stream.ReadByte();
@@ -163,6 +164,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
this.globalColorTable?.Dispose();
}
+ image?.MetaData.AddOrUpdateGifMetaData(this.gifMetaData);
return image;
}
@@ -197,11 +199,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
this.ReadComments();
break;
case GifConstants.ApplicationExtensionLabel:
-
- // The application extension length should be 11 but we've got test images that incorrectly
- // set this to 252.
- int appLength = stream.ReadByte();
- this.Skip(appLength); // No need to read.
+ this.ReadApplicationExtension();
break;
case GifConstants.PlainTextLabel:
int plainLength = stream.ReadByte();
@@ -226,16 +224,11 @@ namespace SixLabors.ImageSharp.Formats.Gif
this.globalColorTable?.Dispose();
}
- GifColorTableMode colorTableMode = this.logicalScreenDescriptor.GlobalColorTableFlag
- ? GifColorTableMode.Global
- : GifColorTableMode.Local;
-
- var size = new Size(this.logicalScreenDescriptor.Width, this.logicalScreenDescriptor.Height);
-
- return new GifInfo(
- colorTableMode,
+ this.metaData.AddOrUpdateGifMetaData(this.gifMetaData);
+ return new ImageInfo(
new PixelTypeInfo(this.logicalScreenDescriptor.BitsPerPixel),
- size,
+ this.logicalScreenDescriptor.Width,
+ this.logicalScreenDescriptor.Height,
this.metaData);
}
@@ -269,6 +262,41 @@ namespace SixLabors.ImageSharp.Formats.Gif
this.logicalScreenDescriptor = GifLogicalScreenDescriptor.Parse(this.buffer);
}
+ ///
+ /// Reads the application extension block parsing any animation information
+ /// if present.
+ ///
+ private void ReadApplicationExtension()
+ {
+ int appLength = this.stream.ReadByte();
+
+ // If the length is 11 then it's a valid extension and most likely
+ // a NETSCAPE or ANIMEXTS extension. We want the loop count from this.
+ if (appLength == GifConstants.ApplicationBlockSize)
+ {
+ this.stream.Skip(appLength);
+ int subBlockSize = this.stream.ReadByte();
+
+ // TODO: There's also a NETSCAPE buffer extension.
+ // http://www.vurdalakov.net/misc/gif/netscape-buffering-application-extension
+ if (subBlockSize == GifConstants.NetscapeLoopingSubBlockSize)
+ {
+ this.stream.Read(this.buffer, 0, GifConstants.NetscapeLoopingSubBlockSize);
+ this.gifMetaData.RepeatCount = GifNetscapeLoopingApplicationExtension.Parse(this.buffer.AsSpan(1)).RepeatCount;
+ this.stream.Skip(1); // Skip the terminator.
+ return;
+ }
+
+ // Could be XMP or something else not supported yet.
+ // Back up and skip.
+ this.stream.Position -= appLength + 1;
+ this.Skip(appLength);
+ return;
+ }
+
+ this.Skip(appLength); // Not supported by any known decoder.
+ }
+
///
/// Skips the designated number of bytes in the stream.
///
@@ -399,7 +427,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
}
else
{
- if (this.graphicsControlExtension.DisposalMethod == DisposalMethod.RestoreToPrevious)
+ if (this.graphicsControlExtension.DisposalMethod == GifDisposalMethod.RestoreToPrevious)
{
prevFrame = previousFrame;
}
@@ -482,7 +510,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
previousFrame = currentFrame ?? image.Frames.RootFrame;
- if (this.graphicsControlExtension.DisposalMethod == DisposalMethod.RestoreToBackground)
+ if (this.graphicsControlExtension.DisposalMethod == GifDisposalMethod.RestoreToBackground)
{
this.restoreArea = new Rectangle(descriptor.Left, descriptor.Top, descriptor.Width, descriptor.Height);
}
@@ -514,24 +542,26 @@ namespace SixLabors.ImageSharp.Formats.Gif
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void SetFrameMetaData(ImageFrameMetaData meta)
{
+ var gifMeta = new GifFrameMetaData();
if (this.graphicsControlExtension.DelayTime > 0)
{
- meta.FrameDelay = this.graphicsControlExtension.DelayTime;
+ gifMeta.FrameDelay = this.graphicsControlExtension.DelayTime;
}
// Frames can either use the global table or their own local table.
if (this.logicalScreenDescriptor.GlobalColorTableFlag
&& this.logicalScreenDescriptor.GlobalColorTableSize > 0)
{
- meta.ColorTableLength = this.logicalScreenDescriptor.GlobalColorTableSize;
+ gifMeta.ColorTableLength = this.logicalScreenDescriptor.GlobalColorTableSize;
}
else if (this.imageDescriptor.LocalColorTableFlag
&& this.imageDescriptor.LocalColorTableSize > 0)
{
- meta.ColorTableLength = this.imageDescriptor.LocalColorTableSize;
+ gifMeta.ColorTableLength = this.imageDescriptor.LocalColorTableSize;
}
- meta.DisposalMethod = this.graphicsControlExtension.DisposalMethod;
+ gifMeta.DisposalMethod = this.graphicsControlExtension.DisposalMethod;
+ meta.AddOrUpdateGifFrameMetaData(gifMeta);
}
///
@@ -575,10 +605,17 @@ namespace SixLabors.ImageSharp.Formats.Gif
}
this.metaData = meta;
+ this.gifMetaData = new GifMetaData
+ {
+ ColorTableMode = this.logicalScreenDescriptor.GlobalColorTableFlag
+ ? GifColorTableMode.Global
+ : GifColorTableMode.Local
+ };
if (this.logicalScreenDescriptor.GlobalColorTableFlag)
{
int globalColorTableLength = this.logicalScreenDescriptor.GlobalColorTableSize * 3;
+ this.gifMetaData.GlobalColorTableLength = globalColorTableLength;
this.globalColorTable = this.MemoryAllocator.AllocateManagedByteBuffer(globalColorTableLength, AllocationOptions.Clean);
diff --git a/src/ImageSharp/Formats/Gif/DisposalMethod.cs b/src/ImageSharp/Formats/Gif/GifDisposalMethod.cs
similarity index 97%
rename from src/ImageSharp/Formats/Gif/DisposalMethod.cs
rename to src/ImageSharp/Formats/Gif/GifDisposalMethod.cs
index 5d3e1b4d8..982340db6 100644
--- a/src/ImageSharp/Formats/Gif/DisposalMethod.cs
+++ b/src/ImageSharp/Formats/Gif/GifDisposalMethod.cs
@@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
/// in an animation sequence.
/// section 23
///
- public enum DisposalMethod
+ public enum GifDisposalMethod
{
///
/// No disposal specified.
diff --git a/src/ImageSharp/Formats/Gif/GifEncoder.cs b/src/ImageSharp/Formats/Gif/GifEncoder.cs
index e8e28ccdd..9f376044d 100644
--- a/src/ImageSharp/Formats/Gif/GifEncoder.cs
+++ b/src/ImageSharp/Formats/Gif/GifEncoder.cs
@@ -33,7 +33,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
///
/// Gets or sets the color table mode: Global or local.
///
- public GifColorTableMode ColorTableMode { get; set; }
+ public GifColorTableMode? ColorTableMode { get; set; }
///
public void Encode(Image image, Stream stream)
diff --git a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs
index ab0ee1fb6..6f0068f35 100644
--- a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs
+++ b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs
@@ -2,7 +2,6 @@
// Licensed under the Apache License, Version 2.0.
using System;
-using System.Buffers.Binary;
using System.IO;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
@@ -44,7 +43,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
///
/// The color table mode: Global or local.
///
- private readonly GifColorTableMode colorTableMode;
+ private GifColorTableMode? colorTableMode;
///
/// A flag indicating whether to ingore the metadata when writing the image.
@@ -56,6 +55,11 @@ namespace SixLabors.ImageSharp.Formats.Gif
///
private int bitDepth;
+ ///
+ /// Gif specific meta data.
+ ///
+ private GifMetaData gifMetaData;
+
///
/// Initializes a new instance of the class.
///
@@ -66,7 +70,6 @@ namespace SixLabors.ImageSharp.Formats.Gif
this.memoryAllocator = memoryAllocator;
this.textEncoding = options.TextEncoding ?? GifConstants.DefaultEncoding;
this.quantizer = options.Quantizer;
- this.colorTableMode = options.ColorTableMode;
this.ignoreMetadata = options.IgnoreMetadata;
}
@@ -82,6 +85,10 @@ namespace SixLabors.ImageSharp.Formats.Gif
Guard.NotNull(image, nameof(image));
Guard.NotNull(stream, nameof(stream));
+ this.gifMetaData = image.MetaData.GetGifMetaData() ?? new GifMetaData();
+ this.colorTableMode = this.colorTableMode ?? this.gifMetaData.ColorTableMode;
+ bool useGlobalTable = this.colorTableMode.Equals(GifColorTableMode.Global);
+
// Quantize the image returning a palette.
QuantizedFrame quantized =
this.quantizer.CreateFrameQuantizer().QuantizeFrame(image.Frames.RootFrame);
@@ -94,7 +101,6 @@ namespace SixLabors.ImageSharp.Formats.Gif
// Write the LSD.
int index = this.GetTransparentIndex(quantized);
- bool useGlobalTable = this.colorTableMode.Equals(GifColorTableMode.Global);
this.WriteLogicalScreenDescriptor(image, index, useGlobalTable, stream);
if (useGlobalTable)
@@ -108,7 +114,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
// Write application extension to allow additional frames.
if (image.Frames.Count > 1)
{
- this.WriteApplicationExtension(stream, image.MetaData.RepeatCount);
+ this.WriteApplicationExtension(stream, this.gifMetaData.RepeatCount);
}
if (useGlobalTable)
@@ -136,8 +142,8 @@ namespace SixLabors.ImageSharp.Formats.Gif
for (int i = 0; i < image.Frames.Count; i++)
{
ImageFrame frame = image.Frames[i];
-
- this.WriteGraphicalControlExtension(frame.MetaData, transparencyIndex, stream);
+ GifFrameMetaData frameMetaData = frame.MetaData.GetGifFrameMetaData() ?? new GifFrameMetaData();
+ this.WriteGraphicalControlExtension(frameMetaData, transparencyIndex, stream);
this.WriteImageDescriptor(frame, false, stream);
if (i == 0)
@@ -159,16 +165,18 @@ namespace SixLabors.ImageSharp.Formats.Gif
where TPixel : struct, IPixel
{
ImageFrame previousFrame = null;
+ GifFrameMetaData previousMeta = null;
foreach (ImageFrame frame in image.Frames)
{
+ GifFrameMetaData meta = frame.MetaData.GetGifFrameMetaData() ?? new GifFrameMetaData();
if (quantized is null)
{
// Allow each frame to be encoded at whatever color depth the frame designates if set.
if (previousFrame != null
- && previousFrame.MetaData.ColorTableLength != frame.MetaData.ColorTableLength
- && frame.MetaData.ColorTableLength > 0)
+ && previousMeta.ColorTableLength != meta.ColorTableLength
+ && meta.ColorTableLength > 0)
{
- quantized = this.quantizer.CreateFrameQuantizer(frame.MetaData.ColorTableLength).QuantizeFrame(frame);
+ quantized = this.quantizer.CreateFrameQuantizer(meta.ColorTableLength).QuantizeFrame(frame);
}
else
{
@@ -177,7 +185,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
}
this.bitDepth = ImageMaths.GetBitsNeededForColorDepth(quantized.Palette.Length).Clamp(1, 8);
- this.WriteGraphicalControlExtension(frame.MetaData, this.GetTransparentIndex(quantized), stream);
+ this.WriteGraphicalControlExtension(meta, this.GetTransparentIndex(quantized), stream);
this.WriteImageDescriptor(frame, true, stream);
this.WriteColorTable(quantized, stream);
this.WriteImageData(quantized, stream);
@@ -185,6 +193,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
quantized?.Dispose();
quantized = null; // So next frame can regenerate it
previousFrame = frame;
+ previousMeta = meta;
}
}
@@ -290,25 +299,8 @@ namespace SixLabors.ImageSharp.Formats.Gif
// Application Extension Header
if (repeatCount != 1)
{
- this.buffer[0] = GifConstants.ExtensionIntroducer;
- this.buffer[1] = GifConstants.ApplicationExtensionLabel;
- this.buffer[2] = GifConstants.ApplicationBlockSize;
-
- // Write NETSCAPE2.0
- GifConstants.ApplicationIdentificationBytes.AsSpan().CopyTo(this.buffer.AsSpan(3, 11));
-
- // Application Data ----
- this.buffer[14] = 3; // Application block length
- this.buffer[15] = 1; // Data sub-block index (always 1)
-
- // 0 means loop indefinitely. Count is set as play n + 1 times.
- repeatCount = (ushort)Math.Max(0, repeatCount - 1);
-
- BinaryPrimitives.WriteUInt16LittleEndian(this.buffer.AsSpan(16, 2), repeatCount); // Repeat count for images.
-
- this.buffer[18] = GifConstants.Terminator; // Terminator
-
- stream.Write(this.buffer, 0, 19);
+ var loopingExtension = new GifNetscapeLoopingApplicationExtension(repeatCount);
+ this.WriteExtension(loopingExtension, stream);
}
}
@@ -348,7 +340,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
/// The metadata of the image or frame.
/// The index of the color in the color palette to make transparent.
/// The stream to write to.
- private void WriteGraphicalControlExtension(ImageFrameMetaData metaData, int transparencyIndex, Stream stream)
+ private void WriteGraphicalControlExtension(GifFrameMetaData metaData, int transparencyIndex, Stream stream)
{
byte packedValue = GifGraphicControlExtension.GetPackedValue(
disposalMethod: metaData.DisposalMethod,
diff --git a/src/ImageSharp/Formats/Gif/GifFrameMetaData.cs b/src/ImageSharp/Formats/Gif/GifFrameMetaData.cs
new file mode 100644
index 000000000..cc04d4831
--- /dev/null
+++ b/src/ImageSharp/Formats/Gif/GifFrameMetaData.cs
@@ -0,0 +1,33 @@
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
+namespace SixLabors.ImageSharp.Formats.Gif
+{
+ ///
+ /// Provides Gif specific metadata information for the image frame.
+ ///
+ public class GifFrameMetaData
+ {
+ ///
+ /// Gets or sets the length of the color table for paletted images.
+ /// If not 0, then this field indicates the maximum number of colors to use when quantizing the
+ /// image frame.
+ ///
+ public int ColorTableLength { get; set; }
+
+ ///
+ /// Gets or sets the frame delay for animated images.
+ /// If not 0, when utilized in Gif animation, this field specifies the number of hundredths (1/100) of a second to
+ /// wait before continuing with the processing of the Data Stream.
+ /// The clock starts ticking immediately after the graphic is rendered.
+ ///
+ public int FrameDelay { get; set; }
+
+ ///
+ /// Gets or sets the disposal method for animated images.
+ /// Primarily used in Gif animation, this field indicates the way in which the graphic is to
+ /// be treated after being displayed.
+ ///
+ public GifDisposalMethod DisposalMethod { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Gif/GifInfo.cs b/src/ImageSharp/Formats/Gif/GifInfo.cs
deleted file mode 100644
index 1c345a576..000000000
--- a/src/ImageSharp/Formats/Gif/GifInfo.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright (c) Six Labors and contributors.
-// Licensed under the Apache License, Version 2.0.
-
-using SixLabors.ImageSharp.MetaData;
-using SixLabors.Primitives;
-
-namespace SixLabors.ImageSharp.Formats.Gif
-{
- ///
- /// Contains information about the bmp including dimensions, pixel type information and additional metadata.
- ///
- public class GifInfo : ImageInfo
- {
- ///
- /// Initializes a new instance of the class.
- ///
- /// The color table mode.
- /// The image pixel type information.
- /// The size of the image in pixels.
- /// The images metadata.
- internal GifInfo(
- GifColorTableMode colorTableMode,
- PixelTypeInfo pixelType,
- Size size,
- ImageMetaData metaData)
- : base(pixelType, size, metaData) => this.ColorTableMode = colorTableMode;
-
- ///
- /// Gets the color table mode.
- ///
- public GifColorTableMode ColorTableMode { get; }
- }
-}
diff --git a/src/ImageSharp/Formats/Gif/GifMetaData.cs b/src/ImageSharp/Formats/Gif/GifMetaData.cs
new file mode 100644
index 000000000..f58f5dff3
--- /dev/null
+++ b/src/ImageSharp/Formats/Gif/GifMetaData.cs
@@ -0,0 +1,29 @@
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
+namespace SixLabors.ImageSharp.Formats.Gif
+{
+ ///
+ /// Provides Gif specific metadata information for the image.
+ ///
+ public class GifMetaData
+ {
+ ///
+ /// Gets or sets the number of times any animation is repeated.
+ ///
+ /// 0 means to repeat indefinitely, count is set as play n + 1 times
+ ///
+ ///
+ public ushort RepeatCount { get; set; }
+
+ ///
+ /// Gets or sets the color table mode.
+ ///
+ public GifColorTableMode ColorTableMode { get; set; }
+
+ ///
+ /// Gets or sets the length of the global color table if present.
+ ///
+ public int GlobalColorTableLength { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Gif/GifMetaDataExtensions.cs b/src/ImageSharp/Formats/Gif/GifMetaDataExtensions.cs
new file mode 100644
index 000000000..04b542d2d
--- /dev/null
+++ b/src/ImageSharp/Formats/Gif/GifMetaDataExtensions.cs
@@ -0,0 +1,49 @@
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
+using SixLabors.ImageSharp.MetaData;
+
+namespace SixLabors.ImageSharp.Formats.Gif
+{
+ ///
+ /// Extension methods for storing meta data specific to Gif images.
+ ///
+ public static class GifMetaDataExtensions
+ {
+ ///
+ /// Adds or updates the Gif specific meta data to the image.
+ ///
+ /// The image meta data.
+ /// The gif meta data.
+ public static void AddOrUpdateGifMetaData(this ImageMetaData meta, GifMetaData value) => meta.AddOrUpdateMetaData(GifConstants.MetaDataKey, value);
+
+ ///
+ /// Gets the Gif format specific meta data from the image.
+ ///
+ /// The image meta data.
+ /// The or null.
+ public static GifMetaData GetGifMetaData(this ImageMetaData meta)
+ {
+ meta.TryGetMetaData(GifConstants.MetaDataKey, out GifMetaData value);
+ return value;
+ }
+
+ ///
+ /// Adds or updates the Gif specific meta data to the image frame.
+ ///
+ /// The image meta data.
+ /// The gif meta data.
+ public static void AddOrUpdateGifFrameMetaData(this ImageFrameMetaData meta, GifFrameMetaData value) => meta.AddOrUpdateMetaData(GifConstants.MetaDataKey, value);
+
+ ///
+ /// Gets the Gif format specific meta data from the image frame.
+ ///
+ /// The image meta data.
+ /// The or null.
+ public static GifFrameMetaData GetGifFrameMetaData(this ImageFrameMetaData meta)
+ {
+ meta.TryGetMetaData(GifConstants.MetaDataKey, out GifFrameMetaData value);
+ return value;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Gif/IGifDecoderOptions.cs b/src/ImageSharp/Formats/Gif/IGifDecoderOptions.cs
index e99f09add..42c202a3d 100644
--- a/src/ImageSharp/Formats/Gif/IGifDecoderOptions.cs
+++ b/src/ImageSharp/Formats/Gif/IGifDecoderOptions.cs
@@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System.Text;
+using SixLabors.ImageSharp.MetaData;
namespace SixLabors.ImageSharp.Formats.Gif
{
diff --git a/src/ImageSharp/Formats/Gif/IGifEncoderOptions.cs b/src/ImageSharp/Formats/Gif/IGifEncoderOptions.cs
index bad6e0031..7dd558c80 100644
--- a/src/ImageSharp/Formats/Gif/IGifEncoderOptions.cs
+++ b/src/ImageSharp/Formats/Gif/IGifEncoderOptions.cs
@@ -29,6 +29,6 @@ namespace SixLabors.ImageSharp.Formats.Gif
///
/// Gets the color table mode: Global or local.
///
- GifColorTableMode ColorTableMode { get; }
+ GifColorTableMode? ColorTableMode { get; }
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Gif/Sections/GifGraphicControlExtension.cs b/src/ImageSharp/Formats/Gif/Sections/GifGraphicControlExtension.cs
index 7ec5f2030..cb548d687 100644
--- a/src/ImageSharp/Formats/Gif/Sections/GifGraphicControlExtension.cs
+++ b/src/ImageSharp/Formats/Gif/Sections/GifGraphicControlExtension.cs
@@ -53,7 +53,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
/// Gets the disposal method which indicates the way in which the
/// graphic is to be treated after being displayed.
///
- public DisposalMethod DisposalMethod => (DisposalMethod)((this.Packed & 0x1C) >> 2);
+ public GifDisposalMethod DisposalMethod => (GifDisposalMethod)((this.Packed & 0x1C) >> 2);
///
/// Gets a value indicating whether transparency flag is to be set.
@@ -77,7 +77,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
return MemoryMarshal.Cast(buffer)[0];
}
- public static byte GetPackedValue(DisposalMethod disposalMethod, bool userInputFlag = false, bool transparencyFlag = false)
+ public static byte GetPackedValue(GifDisposalMethod disposalMethod, bool userInputFlag = false, bool transparencyFlag = false)
{
/*
Reserved | 3 Bits
diff --git a/src/ImageSharp/Formats/Gif/Sections/GifNetscapeLoopingApplicationExtension.cs b/src/ImageSharp/Formats/Gif/Sections/GifNetscapeLoopingApplicationExtension.cs
new file mode 100644
index 000000000..49a52edf6
--- /dev/null
+++ b/src/ImageSharp/Formats/Gif/Sections/GifNetscapeLoopingApplicationExtension.cs
@@ -0,0 +1,44 @@
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
+using System;
+using System.Buffers.Binary;
+
+namespace SixLabors.ImageSharp.Formats.Gif
+{
+ internal readonly struct GifNetscapeLoopingApplicationExtension : IGifExtension
+ {
+ public GifNetscapeLoopingApplicationExtension(ushort repeatCount) => this.RepeatCount = repeatCount;
+
+ public byte Label => GifConstants.ApplicationExtensionLabel;
+
+ ///
+ /// Gets the repeat count.
+ /// 0 means loop indefinitely. Count is set as play n + 1 times.
+ ///
+ public ushort RepeatCount { get; }
+
+ public static GifNetscapeLoopingApplicationExtension Parse(ReadOnlySpan buffer)
+ {
+ ushort repeatCount = BinaryPrimitives.ReadUInt16LittleEndian(buffer.Slice(0, 2));
+ return new GifNetscapeLoopingApplicationExtension(repeatCount);
+ }
+
+ public int WriteTo(Span buffer)
+ {
+ buffer[0] = GifConstants.ApplicationBlockSize;
+
+ // Write NETSCAPE2.0
+ GifConstants.NetscapeApplicationIdentificationBytes.AsSpan().CopyTo(buffer.Slice(1, 11));
+
+ // Application Data ----
+ buffer[12] = 3; // Application block length (always 3)
+ buffer[13] = 1; // Data sub-block indentity (always 1)
+
+ // 0 means loop indefinitely. Count is set as play n + 1 times.
+ BinaryPrimitives.WriteUInt16LittleEndian(buffer.Slice(14, 2), this.RepeatCount);
+
+ return 16; // Length - Introducer + Label + Terminator.
+ }
+ }
+}
diff --git a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs
index fb717d3fb..8c5230a1c 100644
--- a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs
+++ b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs
@@ -235,7 +235,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
this.InitIccProfile();
this.InitDerivedMetaDataProperties();
- return new JpegInfo(new PixelTypeInfo(this.BitsPerPixel), new Size(this.ImageWidth, this.ImageHeight), this.MetaData);
+ return new ImageInfo(new PixelTypeInfo(this.BitsPerPixel), this.ImageWidth, this.ImageHeight, this.MetaData);
}
///
diff --git a/src/ImageSharp/Formats/Jpeg/JpegInfo.cs b/src/ImageSharp/Formats/Jpeg/JpegInfo.cs
deleted file mode 100644
index 8e9b6257c..000000000
--- a/src/ImageSharp/Formats/Jpeg/JpegInfo.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (c) Six Labors and contributors.
-// Licensed under the Apache License, Version 2.0.
-
-using SixLabors.ImageSharp.MetaData;
-using SixLabors.Primitives;
-
-namespace SixLabors.ImageSharp.Formats.Jpeg
-{
- ///
- /// Contains information about the bmp including dimensions, pixel type information and additional metadata.
- ///
- public class JpegInfo : ImageInfo
- {
- ///
- /// Initializes a new instance of the class.
- ///
- /// The image pixel type information.
- /// The size of the image in pixels.
- /// The images metadata.
- internal JpegInfo(PixelTypeInfo pixelType, Size size, ImageMetaData metaData)
- : base(pixelType, size, metaData)
- {
- }
- }
-}
diff --git a/src/ImageSharp/Formats/Png/PngDecoderCore.cs b/src/ImageSharp/Formats/Png/PngDecoderCore.cs
index 903256016..be1914174 100644
--- a/src/ImageSharp/Formats/Png/PngDecoderCore.cs
+++ b/src/ImageSharp/Formats/Png/PngDecoderCore.cs
@@ -17,7 +17,6 @@ using SixLabors.ImageSharp.MetaData;
using SixLabors.ImageSharp.MetaData.Profiles.Exif;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Memory;
-using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Formats.Png
{
@@ -349,7 +348,7 @@ namespace SixLabors.ImageSharp.Formats.Png
throw new ImageFormatException("PNG Image does not contain a header chunk");
}
- return new PngInfo(new PixelTypeInfo(this.CalculateBitsPerPixel()), new Size(this.header.Width, this.header.Height), metadata);
+ return new ImageInfo(new PixelTypeInfo(this.CalculateBitsPerPixel()), this.header.Width, this.header.Height, metadata);
}
///
diff --git a/src/ImageSharp/Formats/Png/PngInfo.cs b/src/ImageSharp/Formats/Png/PngInfo.cs
deleted file mode 100644
index 2bb0b16b7..000000000
--- a/src/ImageSharp/Formats/Png/PngInfo.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (c) Six Labors and contributors.
-// Licensed under the Apache License, Version 2.0.
-
-using SixLabors.ImageSharp.MetaData;
-using SixLabors.Primitives;
-
-namespace SixLabors.ImageSharp.Formats.Png
-{
- ///
- /// Contains information about the bmp including dimensions, pixel type information and additional metadata.
- ///
- public class PngInfo : ImageInfo
- {
- ///
- /// Initializes a new instance of the class.
- ///
- /// The image pixel type information.
- /// The size of the image in pixels.
- /// The images metadata.
- internal PngInfo(PixelTypeInfo pixelType, Size size, ImageMetaData metaData)
- : base(pixelType, size, metaData)
- {
- }
- }
-}
diff --git a/src/ImageSharp/ImageInfo.cs b/src/ImageSharp/ImageInfo.cs
index eed1c6691..6f894cb59 100644
--- a/src/ImageSharp/ImageInfo.cs
+++ b/src/ImageSharp/ImageInfo.cs
@@ -3,26 +3,26 @@
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.MetaData;
-using SixLabors.Primitives;
namespace SixLabors.ImageSharp
{
///
/// Contains information about the image including dimensions, pixel type information and additional metadata
///
- public abstract class ImageInfo : IImageInfo
+ internal sealed class ImageInfo : IImageInfo
{
///
/// Initializes a new instance of the class.
///
/// The image pixel type information.
- /// The size of the image in pixels.
+ /// The width of the image in pixels.
+ /// The height of the image in pixels.
/// The images metadata.
- protected ImageInfo(PixelTypeInfo pixelType, Size size, ImageMetaData metaData)
+ public ImageInfo(PixelTypeInfo pixelType, int width, int height, ImageMetaData metaData)
{
this.PixelType = pixelType;
- this.Width = size.Width;
- this.Height = size.Height;
+ this.Width = width;
+ this.Height = height;
this.MetaData = metaData;
}
diff --git a/src/ImageSharp/Formats/Gif/FrameDecodingMode.cs b/src/ImageSharp/MetaData/FrameDecodingMode.cs
similarity index 91%
rename from src/ImageSharp/Formats/Gif/FrameDecodingMode.cs
rename to src/ImageSharp/MetaData/FrameDecodingMode.cs
index 05791c92e..2863fbf8f 100644
--- a/src/ImageSharp/Formats/Gif/FrameDecodingMode.cs
+++ b/src/ImageSharp/MetaData/FrameDecodingMode.cs
@@ -1,7 +1,7 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
-namespace SixLabors.ImageSharp.Formats.Gif
+namespace SixLabors.ImageSharp.MetaData
{
///
/// Enumerated frame process modes to apply to multi-frame images.
diff --git a/src/ImageSharp/MetaData/ImageFrameMetaData.cs b/src/ImageSharp/MetaData/ImageFrameMetaData.cs
index f83e092c9..55678789e 100644
--- a/src/ImageSharp/MetaData/ImageFrameMetaData.cs
+++ b/src/ImageSharp/MetaData/ImageFrameMetaData.cs
@@ -1,7 +1,8 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
-using SixLabors.ImageSharp.Formats.Gif;
+using System;
+using System.Collections.Generic;
namespace SixLabors.ImageSharp.MetaData
{
@@ -10,6 +11,8 @@ namespace SixLabors.ImageSharp.MetaData
///
public sealed class ImageFrameMetaData
{
+ private readonly Dictionary metaData = new Dictionary(StringComparer.OrdinalIgnoreCase);
+
///
/// Initializes a new instance of the class.
///
@@ -28,37 +31,57 @@ namespace SixLabors.ImageSharp.MetaData
{
DebugGuard.NotNull(other, nameof(other));
- this.ColorTableLength = other.ColorTableLength;
- this.FrameDelay = other.FrameDelay;
- this.DisposalMethod = other.DisposalMethod;
+ foreach (KeyValuePair meta in other.metaData)
+ {
+ this.metaData.Add(meta.Key, meta.Value);
+ }
}
///
- /// Gets or sets the length of the color table for paletted images.
- /// If not 0, then this field indicates the maximum number of colors to use when quantizing the
- /// image frame.
+ /// Clones this ImageFrameMetaData.
///
- public int ColorTableLength { get; set; }
+ /// The cloned instance.
+ public ImageFrameMetaData Clone() => new ImageFrameMetaData(this);
///
- /// Gets or sets the frame delay for animated images.
- /// If not 0, when utilized in Gif animation, this field specifies the number of hundredths (1/100) of a second to
- /// wait before continuing with the processing of the Data Stream.
- /// The clock starts ticking immediately after the graphic is rendered.
+ /// Adds or updates the specified key and value to the .
///
- public int FrameDelay { get; set; }
+ /// The key of the metadata to add.
+ /// The value of the element to add.
+ /// key is null.
+ /// value is null.
+ /// An element with the same key already exists in the .
+ public void AddOrUpdateMetaData(string key, object value)
+ {
+ // Don't think this needs to be threadsafe.
+ Guard.NotNull(value, nameof(value));
+ this.metaData[key] = value;
+ }
///
- /// Gets or sets the disposal method for animated images.
- /// Primarily used in Gif animation, this field indicates the way in which the graphic is to
- /// be treated after being displayed.
+ /// Gets the metadata value associated with the specified key.
///
- public DisposalMethod DisposalMethod { get; set; }
+ /// The type of value.
+ /// The key of the value to get.
+ ///
+ /// When this method returns, contains the metadata value associated with the specified key,
+ /// if the key is found; otherwise, the default value for the type of the value parameter.
+ /// This parameter is passed uninitialized.
+ ///
+ ///
+ /// true if the contains an element with
+ /// the specified key; otherwise, false.
+ ///
+ public bool TryGetMetaData(string key, out T value)
+ {
+ if (this.metaData.TryGetValue(key, out object meta))
+ {
+ value = (T)meta;
+ return true;
+ }
- ///
- /// Clones this ImageFrameMetaData.
- ///
- /// The cloned instance.
- public ImageFrameMetaData Clone() => new ImageFrameMetaData(this);
+ value = default;
+ return false;
+ }
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/MetaData/ImageMetaData.cs b/src/ImageSharp/MetaData/ImageMetaData.cs
index 40880bd08..8233798c2 100644
--- a/src/ImageSharp/MetaData/ImageMetaData.cs
+++ b/src/ImageSharp/MetaData/ImageMetaData.cs
@@ -1,6 +1,7 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
+using System;
using System.Collections.Generic;
using SixLabors.ImageSharp.MetaData.Profiles.Exif;
using SixLabors.ImageSharp.MetaData.Profiles.Icc;
@@ -24,6 +25,7 @@ namespace SixLabors.ImageSharp.MetaData
///
public const double DefaultVerticalResolution = 96;
+ private readonly Dictionary metaData = new Dictionary(StringComparer.OrdinalIgnoreCase);
private double horizontalResolution;
private double verticalResolution;
@@ -48,7 +50,11 @@ namespace SixLabors.ImageSharp.MetaData
this.HorizontalResolution = other.HorizontalResolution;
this.VerticalResolution = other.VerticalResolution;
this.ResolutionUnits = other.ResolutionUnits;
- this.RepeatCount = other.RepeatCount;
+
+ foreach (KeyValuePair meta in other.metaData)
+ {
+ this.metaData.Add(meta.Key, meta.Value);
+ }
foreach (ImageProperty property in other.Properties)
{
@@ -125,10 +131,51 @@ namespace SixLabors.ImageSharp.MetaData
public IList Properties { get; } = new List();
///
- /// Gets or sets the number of times any animation is repeated.
- /// 0 means to repeat indefinitely.
+ /// Adds or updates the specified key and value to the .
+ ///
+ /// The key of the metadata to add.
+ /// The value of the element to add.
+ /// key is null.
+ /// value is null.
+ /// An element with the same key already exists in the .
+ public void AddOrUpdateMetaData(string key, object value)
+ {
+ // Don't think this needs to be threadsafe.
+ Guard.NotNull(value, nameof(value));
+ this.metaData[key] = value;
+ }
+
+ ///
+ /// Gets the metadata value associated with the specified key.
///
- public ushort RepeatCount { get; set; }
+ /// The type of value.
+ /// The key of the value to get.
+ ///
+ /// When this method returns, contains the metadata value associated with the specified key,
+ /// if the key is found; otherwise, the default value for the type of the value parameter.
+ /// This parameter is passed uninitialized.
+ ///
+ ///
+ /// true if the contains an element with
+ /// the specified key; otherwise, false.
+ ///
+ public bool TryGetMetaData(string key, out T value)
+ {
+ if (this.metaData.TryGetValue(key, out object meta))
+ {
+ value = (T)meta;
+ return true;
+ }
+
+ value = default;
+ return false;
+ }
+
+ ///
+ /// Clones this into a new instance
+ ///
+ /// The cloned metadata instance
+ public ImageMetaData Clone() => new ImageMetaData(this);
///
/// Looks up a property with the provided name.
@@ -153,21 +200,9 @@ namespace SixLabors.ImageSharp.MetaData
return false;
}
- ///
- /// Clones this into a new instance
- ///
- /// The cloned metadata instance
- public ImageMetaData Clone()
- {
- return new ImageMetaData(this);
- }
-
///
/// Synchronizes the profiles with the current meta data.
///
- internal void SyncProfiles()
- {
- this.ExifProfile?.Sync(this);
- }
+ internal void SyncProfiles() => this.ExifProfile?.Sync(this);
}
}
diff --git a/tests/ImageSharp.Tests/Formats/Gif/GifEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Gif/GifEncoderTests.cs
index 11fa4d5d5..2b08bf20d 100644
--- a/tests/ImageSharp.Tests/Formats/Gif/GifEncoderTests.cs
+++ b/tests/ImageSharp.Tests/Formats/Gif/GifEncoderTests.cs
@@ -186,32 +186,37 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif
using (var inStream = new MemoryStream(TestFile.Create(TestImages.Gif.Leo).Bytes))
using (var outStream = new MemoryStream())
{
- var info = (GifInfo)Image.Identify(inStream);
- GifColorTableMode colorMode = info.ColorTableMode;
inStream.Position = 0;
var image = Image.Load(inStream);
+ GifMetaData metaData = image.MetaData.GetGifMetaData();
+ GifFrameMetaData frameMetaData = image.Frames.RootFrame.MetaData.GetGifFrameMetaData();
+ GifColorTableMode colorMode = metaData.ColorTableMode;
var encoder = new GifEncoder()
{
ColorTableMode = colorMode,
- Quantizer = new OctreeQuantizer(image.Frames.RootFrame.MetaData.ColorTableLength)
+ Quantizer = new OctreeQuantizer(frameMetaData.ColorTableLength)
};
image.Save(outStream, encoder);
outStream.Position = 0;
- var cloneInfo = (GifInfo)Image.Identify(outStream);
outStream.Position = 0;
var clone = Image.Load(outStream);
+ GifMetaData cloneMetaData = clone.MetaData.GetGifMetaData();
+ Assert.Equal(metaData.ColorTableMode, cloneMetaData.ColorTableMode);
+
// Gifiddle and Cyotek GifInfo say this image has 64 colors.
- Assert.Equal(64, image.Frames.RootFrame.MetaData.ColorTableLength);
- Assert.Equal(info.ColorTableMode, cloneInfo.ColorTableMode);
+ Assert.Equal(64, frameMetaData.ColorTableLength);
for (int i = 0; i < image.Frames.Count; i++)
{
- Assert.Equal(image.Frames[i].MetaData.ColorTableLength, clone.Frames[i].MetaData.ColorTableLength);
- Assert.Equal(image.Frames[i].MetaData.FrameDelay, clone.Frames[i].MetaData.FrameDelay);
+ GifFrameMetaData ifm = image.Frames[i].MetaData.GetGifFrameMetaData();
+ GifFrameMetaData cifm = clone.Frames[i].MetaData.GetGifFrameMetaData();
+
+ Assert.Equal(ifm.ColorTableLength, cifm.ColorTableLength);
+ Assert.Equal(ifm.FrameDelay, cifm.FrameDelay);
}
image.Dispose();
diff --git a/tests/ImageSharp.Tests/Formats/Gif/Sections/GifGraphicControlExtensionTests.cs b/tests/ImageSharp.Tests/Formats/Gif/Sections/GifGraphicControlExtensionTests.cs
index 2790b1a57..dc0da5e2d 100644
--- a/tests/ImageSharp.Tests/Formats/Gif/Sections/GifGraphicControlExtensionTests.cs
+++ b/tests/ImageSharp.Tests/Formats/Gif/Sections/GifGraphicControlExtensionTests.cs
@@ -12,10 +12,10 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif
[Fact]
public void TestPackedValue()
{
- Assert.Equal(0, GifGraphicControlExtension.GetPackedValue(DisposalMethod.Unspecified, false, false));
- Assert.Equal(11, GifGraphicControlExtension.GetPackedValue(DisposalMethod.RestoreToBackground, true, true));
- Assert.Equal(4, GifGraphicControlExtension.GetPackedValue(DisposalMethod.NotDispose, false, false));
- Assert.Equal(14, GifGraphicControlExtension.GetPackedValue(DisposalMethod.RestoreToPrevious, true, false));
+ Assert.Equal(0, GifGraphicControlExtension.GetPackedValue(GifDisposalMethod.Unspecified, false, false));
+ Assert.Equal(11, GifGraphicControlExtension.GetPackedValue(GifDisposalMethod.RestoreToBackground, true, true));
+ Assert.Equal(4, GifGraphicControlExtension.GetPackedValue(GifDisposalMethod.NotDispose, false, false));
+ Assert.Equal(14, GifGraphicControlExtension.GetPackedValue(GifDisposalMethod.RestoreToPrevious, true, false));
}
}
}
\ No newline at end of file
diff --git a/tests/ImageSharp.Tests/ImageInfoTests.cs b/tests/ImageSharp.Tests/ImageInfoTests.cs
index d46e34052..91f6804c0 100644
--- a/tests/ImageSharp.Tests/ImageInfoTests.cs
+++ b/tests/ImageSharp.Tests/ImageInfoTests.cs
@@ -2,10 +2,6 @@
// Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.Formats;
-using SixLabors.ImageSharp.Formats.Bmp;
-using SixLabors.ImageSharp.Formats.Gif;
-using SixLabors.ImageSharp.Formats.Jpeg;
-using SixLabors.ImageSharp.Formats.Png;
using SixLabors.ImageSharp.MetaData;
using SixLabors.Primitives;
@@ -16,7 +12,7 @@ namespace SixLabors.ImageSharp.Tests
public class ImageInfoTests
{
[Fact]
- public void JpegInfoInitializesCorrectly()
+ public void ImageInfoInitializesCorrectly()
{
const int Width = 50;
const int Height = 60;
@@ -25,7 +21,7 @@ namespace SixLabors.ImageSharp.Tests
var pixelType = new PixelTypeInfo(8);
var meta = new ImageMetaData();
- var info = new JpegInfo(pixelType, size, meta);
+ var info = new ImageInfo(pixelType, Width, Height, meta);
Assert.Equal(pixelType, info.PixelType);
Assert.Equal(Width, info.Width);
@@ -34,67 +30,5 @@ namespace SixLabors.ImageSharp.Tests
Assert.Equal(rectangle, info.Bounds());
Assert.Equal(meta, info.MetaData);
}
-
- [Fact]
- public void BmpInfoInitializesCorrectly()
- {
- const int Width = 50;
- const int Height = 60;
- var size = new Size(Width, Height);
- var rectangle = new Rectangle(0, 0, Width, Height);
- var pixelType = new PixelTypeInfo(8);
- var meta = new ImageMetaData();
-
- var info = new BmpInfo(pixelType, size, meta);
-
- Assert.Equal(pixelType, info.PixelType);
- Assert.Equal(Width, info.Width);
- Assert.Equal(Height, info.Height);
- Assert.Equal(size, info.Size());
- Assert.Equal(rectangle, info.Bounds());
- Assert.Equal(meta, info.MetaData);
- }
-
- [Fact]
- public void PngInfoInitializesCorrectly()
- {
- const int Width = 50;
- const int Height = 60;
- var size = new Size(Width, Height);
- var rectangle = new Rectangle(0, 0, Width, Height);
- var pixelType = new PixelTypeInfo(8);
- var meta = new ImageMetaData();
-
- var info = new PngInfo(pixelType, size, meta);
-
- Assert.Equal(pixelType, info.PixelType);
- Assert.Equal(Width, info.Width);
- Assert.Equal(Height, info.Height);
- Assert.Equal(size, info.Size());
- Assert.Equal(rectangle, info.Bounds());
- Assert.Equal(meta, info.MetaData);
- }
-
- [Fact]
- public void GifInfoInitializesCorrectly()
- {
- const GifColorTableMode mode = GifColorTableMode.Local;
- const int Width = 50;
- const int Height = 60;
- var size = new Size(Width, Height);
- var rectangle = new Rectangle(0, 0, Width, Height);
- var pixelType = new PixelTypeInfo(8);
- var meta = new ImageMetaData();
-
- var info = new GifInfo(mode, pixelType, size, meta);
-
- Assert.Equal(mode, info.ColorTableMode);
- Assert.Equal(pixelType, info.PixelType);
- Assert.Equal(Width, info.Width);
- Assert.Equal(Height, info.Height);
- Assert.Equal(size, info.Size());
- Assert.Equal(rectangle, info.Bounds());
- Assert.Equal(meta, info.MetaData);
- }
}
}
diff --git a/tests/ImageSharp.Tests/MetaData/ImageFrameMetaDataTests.cs b/tests/ImageSharp.Tests/MetaData/ImageFrameMetaDataTests.cs
index 6e18fe253..c250d973b 100644
--- a/tests/ImageSharp.Tests/MetaData/ImageFrameMetaDataTests.cs
+++ b/tests/ImageSharp.Tests/MetaData/ImageFrameMetaDataTests.cs
@@ -17,20 +17,24 @@ namespace SixLabors.ImageSharp.Tests
{
const int frameDelay = 42;
const int colorTableLength = 128;
- const DisposalMethod disposalMethod = DisposalMethod.RestoreToBackground;
+ const GifDisposalMethod disposalMethod = GifDisposalMethod.RestoreToBackground;
- var metaData = new ImageFrameMetaData
+ var gifFrameMetaData = new GifFrameMetaData
{
FrameDelay = frameDelay,
ColorTableLength = colorTableLength,
DisposalMethod = disposalMethod
};
+ var metaData = new ImageFrameMetaData();
+ metaData.AddOrUpdateGifFrameMetaData(gifFrameMetaData);
+
var clone = new ImageFrameMetaData(metaData);
+ GifFrameMetaData cloneGifFrameMetaData = clone.GetGifFrameMetaData();
- Assert.Equal(frameDelay, clone.FrameDelay);
- Assert.Equal(colorTableLength, clone.ColorTableLength);
- Assert.Equal(disposalMethod, clone.DisposalMethod);
+ Assert.Equal(frameDelay, cloneGifFrameMetaData.FrameDelay);
+ Assert.Equal(colorTableLength, cloneGifFrameMetaData.ColorTableLength);
+ Assert.Equal(disposalMethod, cloneGifFrameMetaData.DisposalMethod);
}
}
}
diff --git a/tests/ImageSharp.Tests/MetaData/ImageMetaDataTests.cs b/tests/ImageSharp.Tests/MetaData/ImageMetaDataTests.cs
index 8934ebc36..d681c90ba 100644
--- a/tests/ImageSharp.Tests/MetaData/ImageMetaDataTests.cs
+++ b/tests/ImageSharp.Tests/MetaData/ImageMetaDataTests.cs
@@ -28,7 +28,6 @@ namespace SixLabors.ImageSharp.Tests
metaData.HorizontalResolution = 4;
metaData.VerticalResolution = 2;
metaData.Properties.Add(imageProperty);
- metaData.RepeatCount = 1;
ImageMetaData clone = metaData.Clone();
@@ -36,7 +35,6 @@ namespace SixLabors.ImageSharp.Tests
Assert.Equal(4, clone.HorizontalResolution);
Assert.Equal(2, clone.VerticalResolution);
Assert.Equal(imageProperty, clone.Properties[0]);
- Assert.Equal(1, clone.RepeatCount);
}
[Fact]
diff --git a/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingReferenceDecoder.cs b/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingReferenceDecoder.cs
index 3696accdd..427a56542 100644
--- a/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingReferenceDecoder.cs
+++ b/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingReferenceDecoder.cs
@@ -48,16 +48,7 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs
using (var sourceBitmap = new System.Drawing.Bitmap(stream))
{
var pixelType = new PixelTypeInfo(System.Drawing.Image.GetPixelFormatSize(sourceBitmap.PixelFormat));
- var size = new SixLabors.Primitives.Size(sourceBitmap.Width, sourceBitmap.Height);
- return new SystemDrawingInfo(pixelType, size, new ImageMetaData());
- }
- }
-
- private class SystemDrawingInfo : ImageInfo
- {
- public SystemDrawingInfo(PixelTypeInfo pixelType, SixLabors.Primitives.Size size, ImageMetaData metaData)
- : base(pixelType, size, metaData)
- {
+ return new ImageInfo(pixelType, sourceBitmap.Width, sourceBitmap.Height, new ImageMetaData());
}
}
}