From 4b9c68458628d7989eca0868d430c81aa337fc05 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Mon, 3 Sep 2018 22:40:59 +0100 Subject: [PATCH 01/11] Add derived format info types and allow persistance of palette lengths --- src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs | 21 +++--- src/ImageSharp/Formats/Bmp/BmpInfo.cs | 25 +++++++ src/ImageSharp/Formats/Gif/GifDecoderCore.cs | 57 +++++++++----- src/ImageSharp/Formats/Gif/GifEncoderCore.cs | 30 +++++--- src/ImageSharp/Formats/Gif/GifInfo.cs | 33 +++++++++ .../Gif/Sections/GifImageDescriptor.cs | 2 +- .../Formats/Jpeg/JpegDecoderCore.cs | 7 +- src/ImageSharp/Formats/Jpeg/JpegInfo.cs | 25 +++++++ src/ImageSharp/Formats/Png/PngDecoderCore.cs | 8 +- src/ImageSharp/Formats/Png/PngInfo.cs | 25 +++++++ src/ImageSharp/ImageInfo.cs | 12 +-- src/ImageSharp/MetaData/ImageFrameMetaData.cs | 13 +++- .../Processors/Quantization/IQuantizer.cs | 9 +++ .../OctreeFrameQuantizer{TPixel}.cs | 32 +++++--- .../Quantization/OctreeQuantizer.cs | 23 ++++-- .../PaletteFrameQuantizer{TPixel}.cs | 2 + .../Quantization/PaletteQuantizer.cs | 20 ++++- .../Quantization/WuFrameQuantizer{TPixel}.cs | 16 +++- .../Processors/Quantization/WuQuantizer.cs | 21 ++++-- .../Formats/Gif/GifEncoderTests.cs | 39 ++++++++++ tests/ImageSharp.Tests/ImageInfoTests.cs | 70 +++++++++++++++++- .../MetaData/ImageFrameMetaDataTests.cs | 21 ++++-- tests/ImageSharp.Tests/TestImages.cs | 3 +- .../ImageProviders/FileProvider.cs | 62 +++++++++------- .../SystemDrawingReferenceDecoder.cs | 11 ++- tests/Images/Input/Gif/leo.gif | Bin 0 -> 454544 bytes 26 files changed, 463 insertions(+), 124 deletions(-) create mode 100644 src/ImageSharp/Formats/Bmp/BmpInfo.cs create mode 100644 src/ImageSharp/Formats/Gif/GifInfo.cs create mode 100644 src/ImageSharp/Formats/Jpeg/JpegInfo.cs create mode 100644 src/ImageSharp/Formats/Png/PngInfo.cs create mode 100644 tests/Images/Input/Gif/leo.gif diff --git a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs index d67beb036..4cb524ecb 100644 --- a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs +++ b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs @@ -10,6 +10,7 @@ using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.MetaData; using SixLabors.ImageSharp.PixelFormats; using SixLabors.Memory; +using SixLabors.Primitives; namespace SixLabors.ImageSharp.Formats.Bmp { @@ -164,7 +165,9 @@ namespace SixLabors.ImageSharp.Formats.Bmp public IImageInfo Identify(Stream stream) { this.ReadImageHeaders(stream, out _, out _); - return new ImageInfo(new PixelTypeInfo(this.infoHeader.BitsPerPixel), this.infoHeader.Width, this.infoHeader.Height, this.metaData); + + var size = new Size(this.infoHeader.Width, this.infoHeader.Height); + return new BmpInfo(new PixelTypeInfo(this.infoHeader.BitsPerPixel), size, this.metaData); } /// @@ -175,10 +178,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// Whether the bitmap is inverted. /// The representing the inverted value. [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static int Invert(int y, int height, bool inverted) - { - return (!inverted) ? height - y - 1 : y; - } + private static int Invert(int y, int height, bool inverted) => (!inverted) ? height - y - 1 : y; /// /// Calculates the amount of bytes to pad a row. @@ -206,10 +206,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// The masked and shifted value /// The [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static byte GetBytesFrom5BitValue(int value) - { - return (byte)((value << 3) | (value >> 2)); - } + private static byte GetBytesFrom5BitValue(int value) => (byte)((value << 3) | (value >> 2)); /// /// Looks up color values and builds the image from de-compressed RLE8 data. @@ -524,8 +521,10 @@ namespace SixLabors.ImageSharp.Formats.Bmp } // Resolution is stored in PPM. - var meta = new ImageMetaData(); - meta.ResolutionUnits = PixelResolutionUnit.PixelsPerMeter; + var meta = new ImageMetaData + { + ResolutionUnits = PixelResolutionUnit.PixelsPerMeter + }; if (this.infoHeader.XPelsPerMeter > 0 && this.infoHeader.YPelsPerMeter > 0) { meta.HorizontalResolution = this.infoHeader.XPelsPerMeter; diff --git a/src/ImageSharp/Formats/Bmp/BmpInfo.cs b/src/ImageSharp/Formats/Bmp/BmpInfo.cs new file mode 100644 index 000000000..dfffe94db --- /dev/null +++ b/src/ImageSharp/Formats/Bmp/BmpInfo.cs @@ -0,0 +1,25 @@ +// 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/GifDecoderCore.cs b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs index 2a4d981eb..e79151752 100644 --- a/src/ImageSharp/Formats/Gif/GifDecoderCore.cs +++ b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs @@ -55,6 +55,11 @@ namespace SixLabors.ImageSharp.Formats.Gif /// private GifGraphicControlExtension graphicsControlExtension; + /// + /// The image desciptor. + /// + private GifImageDescriptor imageDescriptor; + /// /// The metadata /// @@ -120,8 +125,7 @@ namespace SixLabors.ImageSharp.Formats.Gif } else if (nextFlag == GifConstants.ExtensionIntroducer) { - int label = stream.ReadByte(); - switch (label) + switch (stream.ReadByte()) { case GifConstants.GraphicControlLabel: this.ReadGraphicalControlExtension(); @@ -178,13 +182,11 @@ namespace SixLabors.ImageSharp.Formats.Gif { if (nextFlag == GifConstants.ImageLabel) { - // Skip image block - this.Skip(0); + this.ReadImageDescriptor(); } else if (nextFlag == GifConstants.ExtensionIntroducer) { - int label = stream.ReadByte(); - switch (label) + switch (stream.ReadByte()) { case GifConstants.GraphicControlLabel: @@ -224,7 +226,17 @@ namespace SixLabors.ImageSharp.Formats.Gif this.globalColorTable?.Dispose(); } - return new ImageInfo(new PixelTypeInfo(this.logicalScreenDescriptor.BitsPerPixel), this.logicalScreenDescriptor.Width, this.logicalScreenDescriptor.Height, this.metaData); + GifColorTableMode colorTableMode = this.logicalScreenDescriptor.GlobalColorTableFlag + ? GifColorTableMode.Global + : GifColorTableMode.Local; + + var size = new Size(this.logicalScreenDescriptor.Width, this.logicalScreenDescriptor.Height); + + return new GifInfo( + colorTableMode, + new PixelTypeInfo(this.logicalScreenDescriptor.BitsPerPixel), + size, + this.metaData); } /// @@ -238,14 +250,13 @@ namespace SixLabors.ImageSharp.Formats.Gif } /// - /// Reads the image descriptor + /// Reads the image descriptor. /// - /// - private GifImageDescriptor ReadImageDescriptor() + private void ReadImageDescriptor() { this.stream.Read(this.buffer, 0, 9); - return GifImageDescriptor.Parse(this.buffer); + this.imageDescriptor = GifImageDescriptor.Parse(this.buffer); } /// @@ -312,25 +323,25 @@ namespace SixLabors.ImageSharp.Formats.Gif private void ReadFrame(ref Image image, ref ImageFrame previousFrame) where TPixel : struct, IPixel { - GifImageDescriptor imageDescriptor = this.ReadImageDescriptor(); + this.ReadImageDescriptor(); IManagedByteBuffer localColorTable = null; IManagedByteBuffer indices = null; try { // Determine the color table for this frame. If there is a local one, use it otherwise use the global color table. - if (imageDescriptor.LocalColorTableFlag) + if (this.imageDescriptor.LocalColorTableFlag) { - int length = imageDescriptor.LocalColorTableSize * 3; + int length = this.imageDescriptor.LocalColorTableSize * 3; localColorTable = this.configuration.MemoryAllocator.AllocateManagedByteBuffer(length, AllocationOptions.Clean); this.stream.Read(localColorTable.Array, 0, length); } - indices = this.configuration.MemoryAllocator.AllocateManagedByteBuffer(imageDescriptor.Width * imageDescriptor.Height, AllocationOptions.Clean); + indices = this.configuration.MemoryAllocator.AllocateManagedByteBuffer(this.imageDescriptor.Width * this.imageDescriptor.Height, AllocationOptions.Clean); - this.ReadFrameIndices(imageDescriptor, indices.GetSpan()); + this.ReadFrameIndices(this.imageDescriptor, indices.GetSpan()); ReadOnlySpan colorTable = MemoryMarshal.Cast((localColorTable ?? this.globalColorTable).GetSpan()); - this.ReadFrameColors(ref image, ref previousFrame, indices.GetSpan(), colorTable, imageDescriptor); + this.ReadFrameColors(ref image, ref previousFrame, indices.GetSpan(), colorTable, this.imageDescriptor); // Skip any remaining blocks this.Skip(0); @@ -508,6 +519,18 @@ namespace SixLabors.ImageSharp.Formats.Gif meta.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; + } + else if (this.imageDescriptor.LocalColorTableFlag + && this.imageDescriptor.LocalColorTableSize > 0) + { + meta.ColorTableLength = this.imageDescriptor.LocalColorTableSize; + } + meta.DisposalMethod = this.graphicsControlExtension.DisposalMethod; } diff --git a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs index 553290035..ab0ee1fb6 100644 --- a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs +++ b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs @@ -146,7 +146,8 @@ namespace SixLabors.ImageSharp.Formats.Gif } else { - using (QuantizedFrame paletteQuantized = palleteQuantizer.CreateFrameQuantizer(() => quantized.Palette).QuantizeFrame(frame)) + using (QuantizedFrame paletteQuantized + = palleteQuantizer.CreateFrameQuantizer(() => quantized.Palette).QuantizeFrame(frame)) { this.WriteImageData(paletteQuantized, stream); } @@ -157,13 +158,25 @@ namespace SixLabors.ImageSharp.Formats.Gif private void EncodeLocal(Image image, QuantizedFrame quantized, Stream stream) where TPixel : struct, IPixel { + ImageFrame previousFrame = null; foreach (ImageFrame frame in image.Frames) { if (quantized is null) { - quantized = this.quantizer.CreateFrameQuantizer().QuantizeFrame(frame); + // 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) + { + quantized = this.quantizer.CreateFrameQuantizer(frame.MetaData.ColorTableLength).QuantizeFrame(frame); + } + else + { + quantized = this.quantizer.CreateFrameQuantizer().QuantizeFrame(frame); + } } + this.bitDepth = ImageMaths.GetBitsNeededForColorDepth(quantized.Palette.Length).Clamp(1, 8); this.WriteGraphicalControlExtension(frame.MetaData, this.GetTransparentIndex(quantized), stream); this.WriteImageDescriptor(frame, true, stream); this.WriteColorTable(quantized, stream); @@ -171,6 +184,7 @@ namespace SixLabors.ImageSharp.Formats.Gif quantized?.Dispose(); quantized = null; // So next frame can regenerate it + previousFrame = frame; } } @@ -210,10 +224,7 @@ namespace SixLabors.ImageSharp.Formats.Gif /// /// The stream to write to. [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void WriteHeader(Stream stream) - { - stream.Write(GifConstants.MagicNumber, 0, GifConstants.MagicNumber.Length); - } + private void WriteHeader(Stream stream) => stream.Write(GifConstants.MagicNumber, 0, GifConstants.MagicNumber.Length); /// /// Writes the logical screen descriptor to the stream. @@ -226,7 +237,7 @@ namespace SixLabors.ImageSharp.Formats.Gif private void WriteLogicalScreenDescriptor(Image image, int transparencyIndex, bool useGlobalTable, Stream stream) where TPixel : struct, IPixel { - byte packedValue = GifLogicalScreenDescriptor.GetPackedValue(useGlobalTable, this.bitDepth - 1, false, this.bitDepth - 1); + byte packedValue = GifLogicalScreenDescriptor.GetPackedValue(useGlobalTable, this.bitDepth, false, this.bitDepth - 1); // The Pixel Aspect Ratio is defined to be the quotient of the pixel's // width over its height. The value range in this field allows @@ -382,7 +393,7 @@ namespace SixLabors.ImageSharp.Formats.Gif localColorTableFlag: hasColorTable, interfaceFlag: false, sortFlag: false, - localColorTableSize: (byte)this.bitDepth); + localColorTableSize: this.bitDepth - 1); var descriptor = new GifImageDescriptor( left: 0, @@ -407,7 +418,8 @@ namespace SixLabors.ImageSharp.Formats.Gif { int pixelCount = image.Palette.Length; - int colorTableLength = (int)Math.Pow(2, this.bitDepth) * 3; // The maximium number of colors for the bit depth + // The maximium number of colors for the bit depth + int colorTableLength = (int)Math.Pow(2, this.bitDepth) * 3; Rgb24 rgb = default; using (IManagedByteBuffer colorTable = this.memoryAllocator.AllocateManagedByteBuffer(colorTableLength)) diff --git a/src/ImageSharp/Formats/Gif/GifInfo.cs b/src/ImageSharp/Formats/Gif/GifInfo.cs new file mode 100644 index 000000000..1c345a576 --- /dev/null +++ b/src/ImageSharp/Formats/Gif/GifInfo.cs @@ -0,0 +1,33 @@ +// 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/Sections/GifImageDescriptor.cs b/src/ImageSharp/Formats/Gif/Sections/GifImageDescriptor.cs index c5360729e..e2f5bee78 100644 --- a/src/ImageSharp/Formats/Gif/Sections/GifImageDescriptor.cs +++ b/src/ImageSharp/Formats/Gif/Sections/GifImageDescriptor.cs @@ -81,7 +81,7 @@ namespace SixLabors.ImageSharp.Formats.Gif return MemoryMarshal.Cast(buffer)[0]; } - public static byte GetPackedValue(bool localColorTableFlag, bool interfaceFlag, bool sortFlag, byte localColorTableSize) + public static byte GetPackedValue(bool localColorTableFlag, bool interfaceFlag, bool sortFlag, int localColorTableSize) { /* Local Color Table Flag | 1 Bit diff --git a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs index 7561afa1e..fb717d3fb 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs @@ -234,7 +234,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg this.InitExifProfile(); this.InitIccProfile(); this.InitDerivedMetaDataProperties(); - return new ImageInfo(new PixelTypeInfo(this.BitsPerPixel), this.ImageWidth, this.ImageHeight, this.MetaData); + + return new JpegInfo(new PixelTypeInfo(this.BitsPerPixel), new Size(this.ImageWidth, this.ImageHeight), this.MetaData); } /// @@ -899,9 +900,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg /// The values [MethodImpl(MethodImplOptions.AggressiveInlining)] private void BuildHuffmanTable(HuffmanTables tables, int index, ReadOnlySpan codeLengths, ReadOnlySpan values) - { - tables[index] = new HuffmanTable(this.configuration.MemoryAllocator, codeLengths, values); - } + => tables[index] = new HuffmanTable(this.configuration.MemoryAllocator, codeLengths, values); /// /// Reads a from the stream advancing it by two bytes diff --git a/src/ImageSharp/Formats/Jpeg/JpegInfo.cs b/src/ImageSharp/Formats/Jpeg/JpegInfo.cs new file mode 100644 index 000000000..8e9b6257c --- /dev/null +++ b/src/ImageSharp/Formats/Jpeg/JpegInfo.cs @@ -0,0 +1,25 @@ +// 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 aa96b926c..903256016 100644 --- a/src/ImageSharp/Formats/Png/PngDecoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngDecoderCore.cs @@ -10,7 +10,6 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text; using SixLabors.ImageSharp.Advanced; -using SixLabors.ImageSharp.Common.Helpers; using SixLabors.ImageSharp.Formats.Png.Filters; using SixLabors.ImageSharp.Formats.Png.Zlib; using SixLabors.ImageSharp.Memory; @@ -18,6 +17,7 @@ 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 +349,7 @@ namespace SixLabors.ImageSharp.Formats.Png throw new ImageFormatException("PNG Image does not contain a header chunk"); } - return new ImageInfo(new PixelTypeInfo(this.CalculateBitsPerPixel()), this.header.Width, this.header.Height, metadata); + return new PngInfo(new PixelTypeInfo(this.CalculateBitsPerPixel()), new Size(this.header.Width, this.header.Height), metadata); } /// @@ -360,9 +360,7 @@ namespace SixLabors.ImageSharp.Formats.Png /// The [MethodImpl(MethodImplOptions.AggressiveInlining)] private static byte ReadByteLittleEndian(ReadOnlySpan buffer, int offset) - { - return (byte)(((buffer[offset] & 0xFF) << 16) | (buffer[offset + 1] & 0xFF)); - } + => (byte)(((buffer[offset] & 0xFF) << 16) | (buffer[offset + 1] & 0xFF)); /// /// Attempts to convert a byte array to a new array where each value in the original array is represented by the diff --git a/src/ImageSharp/Formats/Png/PngInfo.cs b/src/ImageSharp/Formats/Png/PngInfo.cs new file mode 100644 index 000000000..2bb0b16b7 --- /dev/null +++ b/src/ImageSharp/Formats/Png/PngInfo.cs @@ -0,0 +1,25 @@ +// 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 6f894cb59..eed1c6691 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 /// - internal sealed class ImageInfo : IImageInfo + public abstract class ImageInfo : IImageInfo { /// /// Initializes a new instance of the class. /// /// The image pixel type information. - /// The width of the image in pixels. - /// The height of the image in pixels. + /// The size of the image in pixels. /// The images metadata. - public ImageInfo(PixelTypeInfo pixelType, int width, int height, ImageMetaData metaData) + protected ImageInfo(PixelTypeInfo pixelType, Size size, ImageMetaData metaData) { this.PixelType = pixelType; - this.Width = width; - this.Height = height; + this.Width = size.Width; + this.Height = size.Height; this.MetaData = metaData; } diff --git a/src/ImageSharp/MetaData/ImageFrameMetaData.cs b/src/ImageSharp/MetaData/ImageFrameMetaData.cs index 47a2fb775..f83e092c9 100644 --- a/src/ImageSharp/MetaData/ImageFrameMetaData.cs +++ b/src/ImageSharp/MetaData/ImageFrameMetaData.cs @@ -28,10 +28,18 @@ namespace SixLabors.ImageSharp.MetaData { DebugGuard.NotNull(other, nameof(other)); + this.ColorTableLength = other.ColorTableLength; this.FrameDelay = other.FrameDelay; this.DisposalMethod = other.DisposalMethod; } + /// + /// 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 @@ -51,9 +59,6 @@ namespace SixLabors.ImageSharp.MetaData /// Clones this ImageFrameMetaData. /// /// The cloned instance. - public ImageFrameMetaData Clone() - { - return new ImageFrameMetaData(this); - } + public ImageFrameMetaData Clone() => new ImageFrameMetaData(this); } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Quantization/IQuantizer.cs b/src/ImageSharp/Processing/Processors/Quantization/IQuantizer.cs index 0f6846d1b..3da09cde0 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/IQuantizer.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/IQuantizer.cs @@ -23,5 +23,14 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// The IFrameQuantizer CreateFrameQuantizer() where TPixel : struct, IPixel; + + /// + /// Creates the generic frame quantizer + /// + /// The pixel format. + /// The maximum number of colors to hold in the color palette. + /// The + IFrameQuantizer CreateFrameQuantizer(int maxColors) + where TPixel : struct, IPixel; } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Quantization/OctreeFrameQuantizer{TPixel}.cs b/src/ImageSharp/Processing/Processors/Quantization/OctreeFrameQuantizer{TPixel}.cs index 3eac70eea..39546d63f 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/OctreeFrameQuantizer{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/OctreeFrameQuantizer{TPixel}.cs @@ -22,7 +22,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// /// Maximum allowed color depth /// - private readonly byte colors; + private readonly int colors; /// /// Stores the tree @@ -43,9 +43,23 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// the second pass quantizes a color based on the nodes in the tree /// public OctreeFrameQuantizer(OctreeQuantizer quantizer) + : this(quantizer, quantizer.MaxColors) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The octree quantizer. + /// The maximum number of colors to hold in the color palette. + /// + /// The Octree quantizer is a two pass algorithm. The initial pass sets up the Octree, + /// the second pass quantizes a color based on the nodes in the tree + /// + public OctreeFrameQuantizer(OctreeQuantizer quantizer, int maxColors) : base(quantizer, false) { - this.colors = (byte)quantizer.MaxColors; + this.colors = maxColors; this.octree = new Octree(ImageMaths.GetBitsNeededForColorDepth(this.colors).Clamp(1, 8)); } @@ -261,13 +275,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization [MethodImpl(MethodImplOptions.AggressiveInlining)] public TPixel[] Palletize(int colorCount) { - while (this.Leaves > colorCount) + while (this.Leaves > colorCount - 1) { this.Reduce(); } // Now palletize the nodes - var palette = new TPixel[colorCount + 1]; + var palette = new TPixel[colorCount]; int paletteIndex = 0; this.root.ConstructPalette(palette, ref paletteIndex); @@ -285,10 +299,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// The . /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int GetPaletteIndex(ref TPixel pixel, ref Rgba32 rgba) - { - return this.root.GetPaletteIndex(ref pixel, 0, ref rgba); - } + public int GetPaletteIndex(ref TPixel pixel, ref Rgba32 rgba) => this.root.GetPaletteIndex(ref pixel, 0, ref rgba); /// /// Keep track of the previous node that was quantized @@ -297,10 +308,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// The node last quantized /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected void TrackPrevious(OctreeNode node) - { - this.previousNode = node; - } + protected void TrackPrevious(OctreeNode node) => this.previousNode = node; /// /// Reduce the depth of the tree diff --git a/src/ImageSharp/Processing/Processors/Quantization/OctreeQuantizer.cs b/src/ImageSharp/Processing/Processors/Quantization/OctreeQuantizer.cs index 385f6246f..22bb5223f 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/OctreeQuantizer.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/OctreeQuantizer.cs @@ -15,6 +15,11 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// public class OctreeQuantizer : IQuantizer { + /// + /// The default maximum number of colors to use when quantizing the image. + /// + public const int DefaultMaxColors = 256; + /// /// Initializes a new instance of the class. /// @@ -26,7 +31,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// /// Initializes a new instance of the class. /// - /// The maximum number of colors to hold in the color palette + /// The maximum number of colors to hold in the color palette. public OctreeQuantizer(int maxColors) : this(GetDiffuser(true), maxColors) { @@ -37,7 +42,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// /// Whether to apply dithering to the output image public OctreeQuantizer(bool dither) - : this(GetDiffuser(dither), 255) + : this(GetDiffuser(dither), DefaultMaxColors) { } @@ -46,7 +51,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// /// The error diffusion algorithm, if any, to apply to the output image public OctreeQuantizer(IErrorDiffuser diffuser) - : this(diffuser, 255) + : this(diffuser, DefaultMaxColors) { } @@ -57,10 +62,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// The maximum number of colors to hold in the color palette public OctreeQuantizer(IErrorDiffuser diffuser, int maxColors) { - Guard.MustBeBetweenOrEqualTo(maxColors, 1, 255, nameof(maxColors)); - this.Diffuser = diffuser; - this.MaxColors = maxColors; + this.MaxColors = maxColors.Clamp(1, DefaultMaxColors); } /// @@ -76,6 +79,14 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization where TPixel : struct, IPixel => new OctreeFrameQuantizer(this); + /// + public IFrameQuantizer CreateFrameQuantizer(int maxColors) + where TPixel : struct, IPixel + { + maxColors = maxColors.Clamp(1, DefaultMaxColors); + return new OctreeFrameQuantizer(this, maxColors); + } + private static IErrorDiffuser GetDiffuser(bool dither) => dither ? KnownDiffusers.FloydSteinberg : null; } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Quantization/PaletteFrameQuantizer{TPixel}.cs b/src/ImageSharp/Processing/Processors/Quantization/PaletteFrameQuantizer{TPixel}.cs index 8df81b426..cdf3514e2 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/PaletteFrameQuantizer{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/PaletteFrameQuantizer{TPixel}.cs @@ -36,6 +36,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization public PaletteFrameQuantizer(PaletteQuantizer quantizer, TPixel[] colors) : base(quantizer, true) { + // TODO: Why is this value constrained? Gif has limitations but theoretically + // we might want to reduce the palette of an image to greater than that limitation. Guard.MustBeBetweenOrEqualTo(colors.Length, 1, 256, nameof(colors)); this.palette = colors; this.paletteVector = new Vector4[this.palette.Length]; diff --git a/src/ImageSharp/Processing/Processors/Quantization/PaletteQuantizer.cs b/src/ImageSharp/Processing/Processors/Quantization/PaletteQuantizer.cs index 8ae917718..27ef05dfe 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/PaletteQuantizer.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/PaletteQuantizer.cs @@ -37,10 +37,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// Initializes a new instance of the class. /// /// The error diffusion algorithm, if any, to apply to the output image - public PaletteQuantizer(IErrorDiffuser diffuser) - { - this.Diffuser = diffuser; - } + public PaletteQuantizer(IErrorDiffuser diffuser) => this.Diffuser = diffuser; /// public IErrorDiffuser Diffuser { get; } @@ -50,6 +47,21 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization where TPixel : struct, IPixel => this.CreateFrameQuantizer(() => NamedColors.WebSafePalette); + /// + public IFrameQuantizer CreateFrameQuantizer(int maxColors) + where TPixel : struct, IPixel + { + TPixel[] websafe = NamedColors.WebSafePalette; + int max = Math.Min(maxColors, websafe.Length); + + if (max != websafe.Length) + { + return this.CreateFrameQuantizer(() => NamedColors.WebSafePalette.AsSpan(0, max).ToArray()); + } + + return this.CreateFrameQuantizer(() => websafe); + } + /// /// Gets the palette to use to quantize the image. /// diff --git a/src/ImageSharp/Processing/Processors/Quantization/WuFrameQuantizer{TPixel}.cs b/src/ImageSharp/Processing/Processors/Quantization/WuFrameQuantizer{TPixel}.cs index 021dc62fb..d71221b9d 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/WuFrameQuantizer{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/WuFrameQuantizer{TPixel}.cs @@ -3,7 +3,6 @@ using System; using System.Buffers; -using System.Collections.Generic; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -128,11 +127,22 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// the second pass quantizes a color based on the position in the histogram. /// public WuFrameQuantizer(WuQuantizer quantizer) - : base(quantizer, false) + : this(quantizer, quantizer.MaxColors) { - this.colors = quantizer.MaxColors; } + /// + /// Initializes a new instance of the class. + /// + /// The wu quantizer. + /// The maximum number of colors to hold in the color palette. + /// + /// The Wu quantizer is a two pass algorithm. The initial pass sets up the 3-D color histogram, + /// the second pass quantizes a color based on the position in the histogram. + /// + public WuFrameQuantizer(WuQuantizer quantizer, int maxColors) + : base(quantizer, false) => this.colors = maxColors; + /// public override QuantizedFrame QuantizeFrame(ImageFrame image) { diff --git a/src/ImageSharp/Processing/Processors/Quantization/WuQuantizer.cs b/src/ImageSharp/Processing/Processors/Quantization/WuQuantizer.cs index 3aa1f4c5e..5123e737d 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/WuQuantizer.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/WuQuantizer.cs @@ -14,6 +14,11 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// public class WuQuantizer : IQuantizer { + /// + /// The default maximum number of colors to use when quantizing the image. + /// + public const int DefaultMaxColors = 256; + /// /// Initializes a new instance of the class. /// @@ -36,7 +41,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// /// Whether to apply dithering to the output image public WuQuantizer(bool dither) - : this(GetDiffuser(dither), 255) + : this(GetDiffuser(dither), DefaultMaxColors) { } @@ -45,7 +50,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// /// The error diffusion algorithm, if any, to apply to the output image public WuQuantizer(IErrorDiffuser diffuser) - : this(diffuser, 255) + : this(diffuser, DefaultMaxColors) { } @@ -56,10 +61,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// The maximum number of colors to hold in the color palette public WuQuantizer(IErrorDiffuser diffuser, int maxColors) { - Guard.MustBeBetweenOrEqualTo(maxColors, 1, 255, nameof(maxColors)); - this.Diffuser = diffuser; - this.MaxColors = maxColors; + this.MaxColors = maxColors.Clamp(1, DefaultMaxColors); } /// @@ -75,6 +78,14 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization where TPixel : struct, IPixel => new WuFrameQuantizer(this); + /// + public IFrameQuantizer CreateFrameQuantizer(int maxColors) + where TPixel : struct, IPixel + { + maxColors = maxColors.Clamp(1, DefaultMaxColors); + return new WuFrameQuantizer(this, maxColors); + } + private static IErrorDiffuser GetDiffuser(bool dither) => dither ? KnownDiffusers.FloydSteinberg : null; } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Formats/Gif/GifEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Gif/GifEncoderTests.cs index e9104ef8d..11fa4d5d5 100644 --- a/tests/ImageSharp.Tests/Formats/Gif/GifEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Gif/GifEncoderTests.cs @@ -179,5 +179,44 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif Assert.True(fileInfoGlobal.Length < fileInfoLocal.Length); } } + + [Fact] + public void NonMutatingEncodePreservesPaletteCount() + { + 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); + var encoder = new GifEncoder() + { + ColorTableMode = colorMode, + Quantizer = new OctreeQuantizer(image.Frames.RootFrame.MetaData.ColorTableLength) + }; + + image.Save(outStream, encoder); + outStream.Position = 0; + + var cloneInfo = (GifInfo)Image.Identify(outStream); + outStream.Position = 0; + var clone = Image.Load(outStream); + + // Gifiddle and Cyotek GifInfo say this image has 64 colors. + Assert.Equal(64, image.Frames.RootFrame.MetaData.ColorTableLength); + Assert.Equal(info.ColorTableMode, cloneInfo.ColorTableMode); + + 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); + } + + image.Dispose(); + clone.Dispose(); + } + } } } diff --git a/tests/ImageSharp.Tests/ImageInfoTests.cs b/tests/ImageSharp.Tests/ImageInfoTests.cs index 91f6804c0..d46e34052 100644 --- a/tests/ImageSharp.Tests/ImageInfoTests.cs +++ b/tests/ImageSharp.Tests/ImageInfoTests.cs @@ -2,6 +2,10 @@ // 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; @@ -12,7 +16,7 @@ namespace SixLabors.ImageSharp.Tests public class ImageInfoTests { [Fact] - public void ImageInfoInitializesCorrectly() + public void JpegInfoInitializesCorrectly() { const int Width = 50; const int Height = 60; @@ -21,7 +25,7 @@ namespace SixLabors.ImageSharp.Tests var pixelType = new PixelTypeInfo(8); var meta = new ImageMetaData(); - var info = new ImageInfo(pixelType, Width, Height, meta); + var info = new JpegInfo(pixelType, size, meta); Assert.Equal(pixelType, info.PixelType); Assert.Equal(Width, info.Width); @@ -30,5 +34,67 @@ 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 507401398..6e18fe253 100644 --- a/tests/ImageSharp.Tests/MetaData/ImageFrameMetaDataTests.cs +++ b/tests/ImageSharp.Tests/MetaData/ImageFrameMetaDataTests.cs @@ -1,7 +1,6 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.Formats; using SixLabors.ImageSharp.Formats.Gif; using SixLabors.ImageSharp.MetaData; using Xunit; @@ -16,14 +15,22 @@ namespace SixLabors.ImageSharp.Tests [Fact] public void ConstructorImageFrameMetaData() { - ImageFrameMetaData metaData = new ImageFrameMetaData(); - metaData.FrameDelay = 42; - metaData.DisposalMethod = DisposalMethod.RestoreToBackground; + const int frameDelay = 42; + const int colorTableLength = 128; + const DisposalMethod disposalMethod = DisposalMethod.RestoreToBackground; - ImageFrameMetaData clone = new ImageFrameMetaData(metaData); + var metaData = new ImageFrameMetaData + { + FrameDelay = frameDelay, + ColorTableLength = colorTableLength, + DisposalMethod = disposalMethod + }; - Assert.Equal(42, clone.FrameDelay); - Assert.Equal(DisposalMethod.RestoreToBackground, clone.DisposalMethod); + var clone = new ImageFrameMetaData(metaData); + + Assert.Equal(frameDelay, clone.FrameDelay); + Assert.Equal(colorTableLength, clone.ColorTableLength); + Assert.Equal(disposalMethod, clone.DisposalMethod); } } } diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs index 1ee3f9675..7a82a618c 100644 --- a/tests/ImageSharp.Tests/TestImages.cs +++ b/tests/ImageSharp.Tests/TestImages.cs @@ -201,6 +201,7 @@ namespace SixLabors.ImageSharp.Tests public const string Cheers = "Gif/cheers.gif"; public const string Trans = "Gif/trans.gif"; public const string Kumin = "Gif/kumin.gif"; + public const string Leo = "Gif/leo.gif"; public const string Ratio4x1 = "Gif/base_4x1.gif"; public const string Ratio1x4 = "Gif/base_1x4.gif"; @@ -211,7 +212,7 @@ namespace SixLabors.ImageSharp.Tests public const string BadDescriptorWidth = "Gif/issues/issue403_baddescriptorwidth.gif"; } - public static readonly string[] All = { Rings, Giphy, Cheers, Trans, Kumin, Ratio4x1, Ratio1x4 }; + public static readonly string[] All = { Rings, Giphy, Cheers, Trans, Kumin, Leo, Ratio4x1, Ratio1x4 }; } } } diff --git a/tests/ImageSharp.Tests/TestUtilities/ImageProviders/FileProvider.cs b/tests/ImageSharp.Tests/TestUtilities/ImageProviders/FileProvider.cs index 6475547a0..3ed696c47 100644 --- a/tests/ImageSharp.Tests/TestUtilities/ImageProviders/FileProvider.cs +++ b/tests/ImageSharp.Tests/TestUtilities/ImageProviders/FileProvider.cs @@ -55,9 +55,20 @@ namespace SixLabors.ImageSharp.Tests public bool Equals(Key other) { - if (other is null) return false; - if (ReferenceEquals(this, other)) return true; - if (!this.commonValues.Equals(other.commonValues)) return false; + if (other is null) + { + return false; + } + + if (ReferenceEquals(this, other)) + { + return true; + } + + if (!this.commonValues.Equals(other.commonValues)) + { + return false; + } if (this.decoderParameters.Count != other.decoderParameters.Count) { @@ -66,8 +77,7 @@ namespace SixLabors.ImageSharp.Tests foreach (KeyValuePair kv in this.decoderParameters) { - object otherVal; - if (!other.decoderParameters.TryGetValue(kv.Key, out otherVal)) + if (!other.decoderParameters.TryGetValue(kv.Key, out object otherVal)) { return false; } @@ -81,26 +91,29 @@ namespace SixLabors.ImageSharp.Tests public override bool Equals(object obj) { - if (obj is null) return false; - if (ReferenceEquals(this, obj)) return true; - if (obj.GetType() != this.GetType()) return false; + if (obj is null) + { + return false; + } + + if (ReferenceEquals(this, obj)) + { + return true; + } + + if (obj.GetType() != this.GetType()) + { + return false; + } + return this.Equals((Key)obj); } - public override int GetHashCode() - { - return this.commonValues.GetHashCode(); - } + public override int GetHashCode() => this.commonValues.GetHashCode(); - public static bool operator ==(Key left, Key right) - { - return Equals(left, right); - } + public static bool operator ==(Key left, Key right) => Equals(left, right); - public static bool operator !=(Key left, Key right) - { - return !Equals(left, right); - } + public static bool operator !=(Key left, Key right) => !Equals(left, right); } private static readonly ConcurrentDictionary> cache = new ConcurrentDictionary>(); @@ -111,10 +124,7 @@ namespace SixLabors.ImageSharp.Tests { } - public FileProvider(string filePath) - { - this.FilePath = filePath; - } + public FileProvider(string filePath) => this.FilePath = filePath; /// /// Gets the file path relative to the "~/tests/images" folder @@ -135,12 +145,12 @@ namespace SixLabors.ImageSharp.Tests if (!TestEnvironment.Is64BitProcess) { - return LoadImage(decoder); + return this.LoadImage(decoder); } var key = new Key(this.PixelType, this.FilePath, decoder); - Image cachedImage = cache.GetOrAdd(key, fn => { return LoadImage(decoder); }); + Image cachedImage = cache.GetOrAdd(key, _ => this.LoadImage(decoder)); return cachedImage.Clone(); } diff --git a/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingReferenceDecoder.cs b/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingReferenceDecoder.cs index 427a56542..3696accdd 100644 --- a/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingReferenceDecoder.cs +++ b/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingReferenceDecoder.cs @@ -48,7 +48,16 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs using (var sourceBitmap = new System.Drawing.Bitmap(stream)) { var pixelType = new PixelTypeInfo(System.Drawing.Image.GetPixelFormatSize(sourceBitmap.PixelFormat)); - return new ImageInfo(pixelType, sourceBitmap.Width, sourceBitmap.Height, new ImageMetaData()); + 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) + { } } } diff --git a/tests/Images/Input/Gif/leo.gif b/tests/Images/Input/Gif/leo.gif new file mode 100644 index 0000000000000000000000000000000000000000..691842f42ca0281feb70dde6752cc0a029780e26 GIT binary patch literal 454544 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%0D^#@2 zz6T;Xn!n(N+_3Y0PNmcDsaGesJMj7wJf7qw=U6TfSbeWHe&g=?hMxT1A<*!quq3m%OiVqOoxGKm9NC_Ej zjD=fLoL&Vc`evI}Hi>zAL`%9tgh#;yTBU?ulI)b!iR@rDiF5Gmo>h1g7Ma$iAuUhO zTAXt6g2d1s#6DkVj}&k*?ZXYdVF&i`NV~}{b<_ybn9BoY*nx^UVw{*^T_fv-HOI;V zP(vc@runM>)mqM26|9#1dCMdBrbfmxEVjSKF`>>U5Kb)`%JuJgWtlO%RX{@P4`i`L z>{iIhi2FMoUUDR|+>8^p$Jn0-#A|f3N|O?xZ3*_ne#VyYgzlsK!-<#lxUcoBMV0Pj z)nD-`P1d4LN~^Qll+tE>Uv*0E~AQSH9 z1Y$|d3 zoX3&va*b8|Fp7eho{~}_p27K-ar`t%^*e6wHhA-MOXkKi(utG9y54)?CC6n<<#7W& z9FltKJE`h*0fin*uJVf`7kSrF*%e=enTx%J(way3TD|Z7yat^YDj^Z$4l%QcR5(%t zv6pdHaPfsME?Tcnkwuat;wY%`bFuZctrimuDq_|ErY$@3GqvmdxajbZQQ1D;T`j3- z|4-DLrf`dJ0u?rhL)yDO3BxaZOvdy+6nykShiLevBNj3=R6~uBMu-IpQ{`%h9A)&* zxx7DA>PnGaWG{|FaYltz2cg;CE+Zo`e7o?w=B~pORpV!8tr+0ULus1^kv9cG8@>Ci z^83|xi4lj@Xx8FONbP+5)#A}$L7wmnq3)&uS2;S8I(5C|%ibCm7;$~JdJ#Agyr7qR zEEk3yN3|PKJaKRbpd_l2_k0^3&y0q(YpXV)gpPh*^jA$~Ab#J61s-lFYZ-plK!eiO zJU$-B+>8hNtE`9NN5$CJu zzaD7|RdAxTn((dSYILYAL$Rq%d4S zxfh%;9u=c~es`bim{x|59FCgGoN`Dgvis+2@qPc-AtO`csrFv*py{f|hh12I=K~D% zIL@=aHr#s(qd+jFnl3-B+a2k!kZADhIY5_Mk}Ik>ZjK@P`5$~3n*bm@7-ya6U!%sH zwIz>&%{CILq7N$`Y#qJYj-Si{AXG*8HD+XM&uYbuj6WIQYp?q!;<|pV+I#ORw56=@ zM*kE9tOw1lg0~ttjs~NCJ<$4H?m{2EbPELC!LJIAB3a8nGBCQ{aUZ$Vf`KJx9O6Ua z#FR_V)K8pehU)*#wJ+3-( z7uy)|$^K9Cj`4*j23EioTi4$mZYeLGQ^YJ)R&_b#8*~}x-BG4*PHorC-GK*jz*f61 z`2gP?Ob%7f=UDUzkttAfs?dtgA@1yl*Ut}hggjAe6}BsdxxHzhX>|V(@6|%bpD`A# z^OY_a`0EXwGho2z7=NhxyU-?;pN$U{>vu|>v-I1r5vkr0*n*Hm|`oQ^*D0nZ& zDE}N>_xZ=aC(J+l!dtq|iMCP(&rem=KZNmfTw}pqsnEOEs}3Kk4#`{lq;4OQ_Y_wz z*X-s~S^t@hmdI6CLt3MXejs*w=7Tmu>;IY7RWYfb4ziO;VlAJC`O+>pp1<EokrxDqcs8YAn_GIJdnRAUrj=V*M4h~2M|H8FG8Ao0x8YG?g+)Z?q`YNdX^}&#k zZEE@mm`TclXHR4+bM$abav@s+nhSXBr>8h`IXP`@C$qCAZ0vgN?bT)q)}@Q2nl>CB zN>Szu?YXSRENC6y^;1$jM1RUx%iT($nnAN|?2-SxG-1BPIj;HP3-MM<-=8v?07yEd zQByAA^^P>j^vekb0t zK*Z2*l6mqX3Qy9McsiM$aRG^yzpdlRP{c2G@cqLuc+D0rL&|zHA(fx9kMyON${N53 z9c1gwFu`MNrM88{@U4Cf-B#)4ZC5xMUj;0&pI;CG3O!erdPKC!88#a0qynLXc7v2F zco7-%N1o@X=adf?j@vn?b#tMdi^X-VF0Zgtd!f+O6AQ(kwWECR@@q$o%WPgZUFzak z!v1jtr10|+f5r1;tHkB=v63Jcu21dOwC=Bu z79g4I3CB=JKen%zDVZgUWs*m@x|<0zoN|SIAkkRS)go+kdEbF*E;|GrH}G_Tjr$6p zoa9kFO@?HyF^n{CC#e!4oQj#t2V?GCa$iOk65=fQjHx^y3k+W72DBKoh3A9ZvJ^Xz zyX^F!0_aI?wEA)eGpNW*L_wB>=-xYA3a}npkWvTPoZGA@i5ES-c7NfrCA|aBuhKk} z!PhChbbtrv$@m0~$D6E0%6z^`gyV3xCFofkN=&l6RI1h^!{Z{IEr--+-462%4e4!N zAk!fTR&NBgQ3(xGOn@eqG7^JsycZ7=@V8*B+?rHa5a`e)jjAUoM_kH>s`lI@R#V?%g<~Dha&3?#EHhjv0ZASw3 z91?>xh@a%*iAm`qq>dP}`Vvm?PlS+OhUa&>u25%)%h0I?m%G}PW>+aNiH;{Q*@U}X zTL{Q53c_RlxtmQs%_Y@x0Ju_P67w|V*vrpPZ)RKFK)8Lx37%dP!qH8SL}bd~ZHCiN zFPTNMZ^IwbAzEmNdCT+5&W0<;^5aethte#M{$&HL4XNo2A~Bk9+kd{#A0qHxJ@zRJ zjgr|u$SY91b5y-+@uvKjJ58#%u#NDGbA8{g(a%tP~BFl0sY8g;roD}@I+Eg*n`)4b^@{utkDU4`s zWM7fo1QeW&(>Vx)F8FMJ!+HHts0xam^*wb!v-?1f6UoXApU?3=bx!p9^dLn!?!!t{O(}xW-&A$eZKDUhEz5oR;XRIB&`@<3iI9pKo(%G`#wJlOkiv z)wrL`LtpJM2B3#J+73K=R!c0OwGJC(!c>OB9DS!bvzmcK`W34KDoHNFWmoIV6Rdd1 zz`XrS%?p-k%0h#jU=5x_^~-2RQ^ZeI$#VeMN)>ZnGjOK&mS#m|DNhOFbhuPPp=#f` z(KBz9=XL_Rq*o`{Z$Y9)+a z==fFxbaAP5gCtcaWJR46g4aI`ifAfwz}4-7o^?3N<$ed;rwz+f5)iH>2AoHN^B(tX zU5E4X!GANM-GbN>3$0HTtyiGpbOy+OZKRyl0P4UG>Qz68{CGZ1mP$9L+6sH7`k1+O4<0#S9dZ9umwc{mVA0)=kBbvF>m9owJl){Sg~Nlj7<6?dpM?*@?U6f?wD z*Zq&K+Ov8a!#qR)a`1@Xl$CJ(&E`v<*6P%!x7!wCGQ=Qf9I3Df#RqiK@4lSf=<6#% zAG$UVi%wP2XXHZk^6sh3jk#B=(rQ)C+3rBT%XPYy-qnS3u^B$tQ%$1CpsTe5lhI!Q zgeb#Fg!1Ek!j1mPe1!f$<#k{s;+C5jb-0EeR=!kb!}Z0tD9!4_+r*k1Gnb~to;YAi zU0HAXZACv@$2#67ONworx%faB!P*f)lHcTXMZz?4`k>;s>Cl1q=FLKqD|V{MaTZ@w z&NIzI88!f1!Z`3);`pUg4~PdZcv%H4U%Fa-PkgJsH4i_3>IL~*dlxPX7jU8Yi!vIx zCkB{t35)p$`&7ZJZXbo>__BrY*r{iS_u?+y`Nq{*Ils0h!r5YWuD?{X&17oOcCa#N z&{`fYy9MWVD!G}H_A*FU&(`}`0ff_u4ypKiLy&bR+xWs;Xo=q!c2f$G+CMNH+1H$& zV6W=Fyz6xK%Iig<5QKLKhZ@Kh%^p=SArWUpgOz4;EFOe;O@in?qBRl4qVY%I?#6MC?@DIgtYj;$IzFEICsToV&X}>tUVisvaFu2r za4eC{n)k0A$A{#lRU*D;d9A`-Ydh<-VWqd@5s#%Q10-vaeMzOA0$A?j zSGnLK@mY&cPCJ&)^VJ5L>y+T)*pX?+F$M&tPX@kl)(N4E{LXmVbe}n| z$F)=FCCAI(=|Fw?hyG*JX72`c?~B_v`tak*60B>ksw3}GrZq)kikskW8Yp(a>+r~X zKQc-B`!H$E-4EBaqLa)Si>0M?2=&f+QGOp6cOoa%t~tGOC_cwiNILr4q}ie{F&qu4wTC_LucNn-egu3vRLCMKUL z)+X?0cioM|cu~pSpXn5 zaQ;CjLZeLZpKjg5<3a;X@JDnU363!qK_Q_wsc}JvQ=QxbQo{ob0`Z4TamLAp$&oRU z34XZbNHzz)VX_I{FEH9a$dLU#GAO}M9gq7@iG*+yyxG5h;Ql?NMRZ&cPDhQP8bHt` z;B+A4ngk7kIzdxiLsL~l&rnO#kU+rw_Xlrk92XdD=t{Es??bWoOzg+TuwUcVmaVOL@3=9nZtwB>$m0dtJJ|!x_FIhDzUIx!@?7tO|g5m?>LSqs_ zqoZ(f!G?bR(TNErcs%a!e>)Hv^M7iMidXxOGim|Rk?P5QG3pv>gnu3SFHa+593B7v zi$+HNr!@Oi#3#50{omI9kM+j8rNjiOy9UKaC&mQ?v5U+6d!!gci?|@agy=Z8=;(<5 zeG17T(FxJU61asTnyF!cY`7DF>#9SdDelHUJV+kcw!U#5ZoLrebKR{#Ig zR-N4zb@o;Le_Z7M{PJIc^Y7RHidS}IvUmPZ#0NzMn*7Dbu>%_Nm-XlOub)4@fBX7n z|MTAN&Zmzb-oJbMX8ZNltIdt|HReArUp#-d`gG;V(&EDW-0b5=4`&`sPfgyR7#|xQ z8D`wOd*}A8n>U88U%NUu(0`@xa_^;{?yk;`_O{lRi_J~+3ytT`HPqMD)>KzjR+N{O zmJ}Bi7UbvU=45AOX3)~9XV0XaK9!o1d@?C9AwDiPCORrIB0MZK-YgMttMP+^Y@z&>OR01zx< zw!c0JE5PM{5fW;OFXL*ByFpQ_;?B~{GrpS-8=>GzA8yAzJ?(*+kNK9$s_vfpe)~*> z>}TG9Gt^TliL}&+bWRetxqS&Q5?NYNX3uYL!NpZk?pIh;#LJI7*NA|20#Hb2PbY$x z6Pf`-qR=7&7x_`g9UO-RP-HTiJa(_8+}zyHKmF8Mn+97teTihdY%$aL@*%1C{IY*I ztOo)C-hO!h0owiP9q{Grm)^m|h9?he{?-!yTwJt858E-(O30<2rUBPSy`f##-b|L6 zo%uM5X%W0-3AN8399xQe=(cWO@Rp*qjoQe6T_cjeM z3J=d)4Y|_q`=`cmuHM%t3TysWWg-31X#SD!y#Wqz(gpS=zE_uRE4TUkLxH?r@rs~>ImnEA|$hz!ib zJwvUgTZ;JuH*rO$FMS%b={SL>7ig=p`BDW&P9P7U&Uk2Wk!)|M*)Rq>D!cVAbK-E_ zbTcKm_-P^pk@ROBrZI`dz>kd%21;qw`y_BCAK1klJ@F!80cC+==|aWz&$BRmz3%1sx}HxxD1Jz31)?_X|m&k~rJD!npgb@VuT^;&L}_09VX z5l2CpVPTIzDq6@ZLZeW23l)?j5lXe?h|iM9!Z<&Z?hG!+;1eaKO}+FRi=b~pE~4#8 zZ4M=@Y`;y;7Nq2u5r0UTYB5Jj7;hCb(Ex3AY)1`d%iYfT!Vd7G!Nkpls-rJX+V~ypN{aco zRB`+_cApdGV?%Bao#GlUv*A;7$ydBU*aZ-hAw)AUU!IN)%;zKUK*Vozi$Xh)rBqmX z;o|Go`mj};8Oc0AvV7U_R;@)x+S`ZjGkxA#;4yN`RtTUbjM6h`)3 z1Lntdiz52FL%-MOwE7S6TKW^?#UH3!z7wI?YsW4}3nHg4Rk>5;hv_$@$E$YI19BfB6lQtu2Wpc?kh=TCQBD-L zFMr&Bu=zL|zyj%5*kCzzgRTDS3$4QEcCvhG=Ul`3Tl;#nOAlV zTl`G_NBIY*Nq68IN;cjz|8TsLmVuh&d-VjgQM(-fwJw$12|c4PI?|6kp1ru!`!w$8 zh(qYtr=j6Zo%dQ{>(8J49^g4I?N4(Djs!Opk`=t+gGa22_uDi)6`V1XRD>ZFQmR3O z9@r)#43jRrLDC@#W&G@go^*i@I{aWRLmbVdNquK#;dkI;o*Ke#DEgtIJuFO+LKV5Q zmdysX-lyd71kSv|e(Qc9!d-srX~b*l*-@)Q&jYZMLM=MI0#af0IKrPB>&ld;qMv0m zlur$D8n#RqR78=)e3_h{jtv!|EZ2n9i zH^k&Fs5{)wG}!zh+&(-Pcw>&y- z6BPU4!F_C+N3+l?rTXBVW7b{zJ(L?|o@8lfHq)6GLat1)OM_n-3#8y3aeY{oz{ zv8eJK!O&J2;c<@Q&bsDdL|S#!;Brfec4yE92!fXDg3jlDZRcIMS$NEOEI%c4R}yBE&Y#>jjS*m{4J5DeVkt1*Nn)*O z$gnIecj&a69)O_IUVHli@=*V5E+$4^U&UxwY3{J!Qo*3PqL=8dfGmJGUd)N-Yq;^m zYHIF6z)12x_ghAL=YLJ}r~BVkRf-ISC2bsXK3uifx75dHwRBc)entF{N5A=SeR890 zA!{h)!DwC&&GHT%8&BCZs@JZ7oJCJna<{fze!1HEciZ!_MgX!XcPRi!tJ_u#0|z=* z5T|FMn7;m45rttcZzhdzG6*V%9p>>O<8(aH#KcBPKzIQvXuQ9DK&p{}S1dyQpZ($?@AkIK9l177 z(hwV;-S*=(`HGl`w7z*h6G}VbIfE9&n;`-Y#NsPWFxU16XYFGKe7j3m25FNPj#=f0 z86u#?!W|EBVwIi3RRTx*yW`!vtIFC zWQYn^KtVX|7&M_CBEonjoiDI7eaUtNkfxd;>J1^tj@f_S*})O|fJX61M<==z#~DaY z_jIGGMJuY;->8(h)G1>8X~OrUJY~e+*L{}~o2|J{I~?cEQa+xbT7_V{D*r3ldh**Mkx2pa9j13=j(z_Os18CkW+4u33dk4;o(xF@a5Gz=2o=B(Ky?&! zh6Bn5xcPnu6$T@80Ux6nNH_t3*#RYY03o7+z^uk;1dr|}Ps$hM5R3;|3ejRh1ZNM# z&%vwEVz`l%SN?ucx>&B2Bh(N$Xc<7&}2S&%fhS_Qb)>%0rABhqbe3kZlVv4zpol96LzrXP#p{tNwZyQ)|>Am zrdgcg6)GrRDxArUy(Qq@S_$C$*q9%v4Dr|?3WCFdXhI13GvF!2gJ#1}nOUzDpflgV zcPm*MM0+&?R0gNVmK7PF2E$ry?(aHOPbnPvd9%aEVL!2Q_ZMt?$Xvibre zR!xf<`MMt@6^C_p!D03Dzv!MweJxXQFh%ADRv#IFL|1^ExYt3tG1TRj0c9%|c9OGY^!O zAnDvQ8GIB7XYe3~QI=cyO5sRDI`uPp_%i zJu!PR&yX!E*MDSBNVj=AR}U0x`K554PawP%JolW=SeDRFKlR?u15SA;p8); zKw`^3>Ey?>)F*DHx6hULfLP5pqJl}XKQQM9Txc(5g|mNzDx~W+C+RD22zD-ccT@=& zzCHVXL?R!Mk{2q7T$Ym4Z(T0ubxq}wqzm)+LDc)epW6hBm;)pX$(ye5c7FCP0A`QsW-Hn@FC{3OR#V2D_Zr1;0 zky6|SJes{aF_2b057_Lir`5KU)IsEhHk*4~YAN!CCz?}3_wt8M=&4_m*9vZM%}?>D zr+IviLJ{;on?W9IL3jyKn9`aY4$eOUkmuQe5S5FK=u+&1s4y}q`cO?G)cyn**qLTT z1`p3dWSJm5zvheVkqmWb50Ib@>Y*t4)bi&QCJ_nsnU@8gByRc0iR`2zm!1Hw$W@vb9i9WkME?05$A`sxk>! zBB;sEz)6L0&DJF=)F14=+ya5GqteQuC%v}SN#KWrBJYgg<`Q$`Tc zgu4$krPvSe_;x-ko!=2SEi1LYATIyZIl;B;qdT_kD}ryu7^is4zw$uUvy{Cmtew^f z*Xyo=YfeWhQ3b*}?A+l4&#iS7#b>8XpD|-eg(ZarE_eLw5!=U zsBqpktaF*oYkT<8<#mWjA9NfB5#Ql&r2uyrFb_~uVi=OU35nOZ7dRP_^#1gTr}xxi zst-~@4JN1nLgG*u zxuWpagj>LL`btwg+^RLK|C4seoq5qLmS1|4L%so$U^p|HT;tJ!6?hY!p3^FZ4crmCurPC*qbm1VUhd2j~+A$lNCzKve?h zPDV?TCrkPuvH*C1tiVeFQ*Yl-o+(av$G#fuPQeCyf+{$uWGR59vPWPD--1QOu7Qs( z=X5$X)aXFbY~HQlebymnpkKL%ea7Dz zo4hj|QAmF0KPPrcU$KE@apx*^SBbapk$4LrgMuKL5G^9qFa~;Xwq2|bvN2(U-MJ^j zgnYXm@#w_kqz|W6V%SjxktBo41hyLtp;<|?J0Lrmmp}z&`oOt%vymov@L^Din5In!WhtNn1N>76J!bgN zo@B2Okp<2@0rQoLWlABaQk&P`4AgyuVMh?<3$Q71uAGy=yqS7# zrsr?sg8|<88zxk`Q2(U|tABO-zw3l(&J6Giqgxa;2YFMpRabAM8JnCQ*=>E`I(Nt7 zj`*Iyxf@|&X$uF)BZ_flaGMui$Ec}}_O`(zwbwlPo?NQbZhztOY|2WeVd&@ap;!op ztN>#|G^pT0`#p6k`1r^Qn@=#}JVch>j%Pw-DF3eBO7%gc37`fcP?O9?z_L%Yp&$-) zXFuSgK!F{IGErfJtq#n~lU54TuedgbQqZ}mQCb0Pm;m*>onkI64L+^rYJ40lVU=*R zk#k+@oXeKI3G=GHZU=@i#&ai?%7<%es@cikE1MLqzDg6wl#V+29?q>B43mff<#6DU7*LCttsMhZ zMuBRZAgrhaiUxnYxHt3lz9J5kC}lGpKuw8IdB!Ot0w_s@NRSf`5nXo^R7$Y(*;w(w_x)!hzh2Z^nLR!l#=37iWltERtFq*WZG8F`!@jE7 z*Lxq&AioS9H{FgC)~!N?-kvzxIaFWPHUR43pi02@*j5%h-}aRPG#zPlYZmaKLzMfV zwy&UuWT@sWsE+fIW3nk9KfYDLAuZS%3NYzXi1bC_kDJ^bF+Wr@#3%bm=F}hE1I8%a z_w?EaH-D#oH2?ad$a%wMU9a$F(?h4$nKGW|O}CPE^Ka*#=6H8;?w!Vmx8r-s9S=q= z|HkB8J!0lGj>`YNhLS0I@_R$|C(#%{0r0q_Xd4q??)TsF?9J zsi|muBo`OHMQUpHr8hOLt)VfWFE3~v)*>hL^}Ci16I|XY(;p- z?R9ywcUj+`*1X=_Or!bx(=s_nUt+@sJBqPc`D27sLA7(kKC!~X6(@H~NftrV
  • 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%0A1{=^iGtkEbpM3C7`x=gL-P*o~#41;PXl& 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

    PPtc>)M%^{m)d#BLiGO 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

    {~% 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ʑS5h*B7^%Mx!XTdPv`Djiw#ZB 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 literal 0 HcmV?d00001 From a50c3eb985c3d573d7433dbc888c43364e910faa Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Wed, 5 Sep 2018 20:07:19 +0100 Subject: [PATCH 02/11] Use dictionaries to store format specific metadata --- src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs | 5 +- src/ImageSharp/Formats/Bmp/BmpInfo.cs | 25 ------ .../Formats/Gif/GifColorTableMode.cs | 2 +- src/ImageSharp/Formats/Gif/GifConstants.cs | 18 +++- src/ImageSharp/Formats/Gif/GifDecoder.cs | 1 + src/ImageSharp/Formats/Gif/GifDecoderCore.cs | 89 +++++++++++++------ ...DisposalMethod.cs => GifDisposalMethod.cs} | 2 +- src/ImageSharp/Formats/Gif/GifEncoder.cs | 2 +- src/ImageSharp/Formats/Gif/GifEncoderCore.cs | 54 +++++------ .../Formats/Gif/GifFrameMetaData.cs | 33 +++++++ src/ImageSharp/Formats/Gif/GifInfo.cs | 33 ------- src/ImageSharp/Formats/Gif/GifMetaData.cs | 29 ++++++ .../Formats/Gif/GifMetaDataExtensions.cs | 49 ++++++++++ .../Formats/Gif/IGifDecoderOptions.cs | 1 + .../Formats/Gif/IGifEncoderOptions.cs | 2 +- .../Sections/GifGraphicControlExtension.cs | 4 +- .../GifNetscapeLoopingApplicationExtension.cs | 44 +++++++++ .../Formats/Jpeg/JpegDecoderCore.cs | 2 +- src/ImageSharp/Formats/Jpeg/JpegInfo.cs | 25 ------ src/ImageSharp/Formats/Png/PngDecoderCore.cs | 3 +- src/ImageSharp/Formats/Png/PngInfo.cs | 25 ------ src/ImageSharp/ImageInfo.cs | 12 +-- .../Gif => MetaData}/FrameDecodingMode.cs | 2 +- src/ImageSharp/MetaData/ImageFrameMetaData.cs | 67 +++++++++----- src/ImageSharp/MetaData/ImageMetaData.cs | 69 ++++++++++---- .../Formats/Gif/GifEncoderTests.cs | 21 +++-- .../GifGraphicControlExtensionTests.cs | 8 +- tests/ImageSharp.Tests/ImageInfoTests.cs | 70 +-------------- .../MetaData/ImageFrameMetaDataTests.cs | 14 +-- .../MetaData/ImageMetaDataTests.cs | 2 - .../SystemDrawingReferenceDecoder.cs | 11 +-- 31 files changed, 399 insertions(+), 325 deletions(-) delete mode 100644 src/ImageSharp/Formats/Bmp/BmpInfo.cs rename src/ImageSharp/Formats/Gif/{DisposalMethod.cs => GifDisposalMethod.cs} (97%) create mode 100644 src/ImageSharp/Formats/Gif/GifFrameMetaData.cs delete mode 100644 src/ImageSharp/Formats/Gif/GifInfo.cs create mode 100644 src/ImageSharp/Formats/Gif/GifMetaData.cs create mode 100644 src/ImageSharp/Formats/Gif/GifMetaDataExtensions.cs create mode 100644 src/ImageSharp/Formats/Gif/Sections/GifNetscapeLoopingApplicationExtension.cs delete mode 100644 src/ImageSharp/Formats/Jpeg/JpegInfo.cs delete mode 100644 src/ImageSharp/Formats/Png/PngInfo.cs rename src/ImageSharp/{Formats/Gif => MetaData}/FrameDecodingMode.cs (91%) 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 ///
  • c_ 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

    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()); } } } From 6bc07e6a6d018b98b8119fbbbb405bb333922a75 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Thu, 6 Sep 2018 10:44:10 +0100 Subject: [PATCH 03/11] Fix local color table encoding. --- src/ImageSharp/Formats/Gif/GifEncoderCore.cs | 3 ++- .../Formats/Gif/Sections/GifImageDescriptor.cs | 2 +- .../Gif/Sections/GifImageDescriptorTests.cs | 14 +++++++------- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs index 6f0068f35..b37344658 100644 --- a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs +++ b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs @@ -71,6 +71,7 @@ namespace SixLabors.ImageSharp.Formats.Gif this.textEncoding = options.TextEncoding ?? GifConstants.DefaultEncoding; this.quantizer = options.Quantizer; this.ignoreMetadata = options.IgnoreMetadata; + this.colorTableMode = options.ColorTableMode; } /// @@ -246,7 +247,7 @@ namespace SixLabors.ImageSharp.Formats.Gif private void WriteLogicalScreenDescriptor(Image image, int transparencyIndex, bool useGlobalTable, Stream stream) where TPixel : struct, IPixel { - byte packedValue = GifLogicalScreenDescriptor.GetPackedValue(useGlobalTable, this.bitDepth, false, this.bitDepth - 1); + byte packedValue = GifLogicalScreenDescriptor.GetPackedValue(useGlobalTable, this.bitDepth - 1, false, this.bitDepth - 1); // The Pixel Aspect Ratio is defined to be the quotient of the pixel's // width over its height. The value range in this field allows diff --git a/src/ImageSharp/Formats/Gif/Sections/GifImageDescriptor.cs b/src/ImageSharp/Formats/Gif/Sections/GifImageDescriptor.cs index e2f5bee78..c3504dfe7 100644 --- a/src/ImageSharp/Formats/Gif/Sections/GifImageDescriptor.cs +++ b/src/ImageSharp/Formats/Gif/Sections/GifImageDescriptor.cs @@ -108,7 +108,7 @@ namespace SixLabors.ImageSharp.Formats.Gif value |= 1 << 5; } - value |= (byte)(localColorTableSize - 1); + value |= (byte)localColorTableSize; return value; } diff --git a/tests/ImageSharp.Tests/Formats/Gif/Sections/GifImageDescriptorTests.cs b/tests/ImageSharp.Tests/Formats/Gif/Sections/GifImageDescriptorTests.cs index 4ef4c12d9..6a90c0c27 100644 --- a/tests/ImageSharp.Tests/Formats/Gif/Sections/GifImageDescriptorTests.cs +++ b/tests/ImageSharp.Tests/Formats/Gif/Sections/GifImageDescriptorTests.cs @@ -12,13 +12,13 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif [Fact] public void TestPackedValue() { - Assert.Equal(128, GifImageDescriptor.GetPackedValue(true, false, false, 1)); // localColorTable - Assert.Equal(64, GifImageDescriptor.GetPackedValue(false, true, false, 1)); // interfaceFlag - Assert.Equal(32, GifImageDescriptor.GetPackedValue(false, false, true, 1)); // sortFlag - Assert.Equal(224, GifImageDescriptor.GetPackedValue(true, true, true, 1)); // all - Assert.Equal(7, GifImageDescriptor.GetPackedValue(false, false, false, 8)); - Assert.Equal(227, GifImageDescriptor.GetPackedValue(true, true, true, 4)); - Assert.Equal(231, GifImageDescriptor.GetPackedValue(true, true, true, 8)); + Assert.Equal(129, GifImageDescriptor.GetPackedValue(true, false, false, 1)); // localColorTable + Assert.Equal(65, GifImageDescriptor.GetPackedValue(false, true, false, 1)); // interfaceFlag + Assert.Equal(33, GifImageDescriptor.GetPackedValue(false, false, true, 1)); // sortFlag + Assert.Equal(225, GifImageDescriptor.GetPackedValue(true, true, true, 1)); // all + Assert.Equal(8, GifImageDescriptor.GetPackedValue(false, false, false, 8)); + Assert.Equal(228, GifImageDescriptor.GetPackedValue(true, true, true, 4)); + Assert.Equal(232, GifImageDescriptor.GetPackedValue(true, true, true, 8)); } } } \ No newline at end of file From eb318f1502ad5740712a46a5bd9a48e53fafc6e6 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Fri, 7 Sep 2018 22:01:18 +0100 Subject: [PATCH 04/11] Strong type meta query + format singletons --- .../Formats/Bmp/BmpConfigurationModule.cs | 8 +-- src/ImageSharp/Formats/Bmp/BmpFormat.cs | 14 ++++-- .../Formats/Bmp/BmpImageFormatDetector.cs | 2 +- src/ImageSharp/Formats/Bmp/BmpMetaData.cs | 15 ++++++ src/ImageSharp/Formats/Bmp/ImageExtensions.cs | 2 +- .../Formats/Gif/GifConfigurationModule.cs | 9 ++-- src/ImageSharp/Formats/Gif/GifConstants.cs | 5 -- src/ImageSharp/Formats/Gif/GifDecoderCore.cs | 6 +-- src/ImageSharp/Formats/Gif/GifEncoderCore.cs | 6 +-- src/ImageSharp/Formats/Gif/GifFormat.cs | 14 ++++-- .../Formats/Gif/GifFrameMetaData.cs | 4 +- .../Formats/Gif/GifImageFormatDetector.cs | 2 +- src/ImageSharp/Formats/Gif/GifMetaData.cs | 4 +- .../Formats/Gif/GifMetaDataExtensions.cs | 49 ------------------- src/ImageSharp/Formats/Gif/ImageExtensions.cs | 2 +- src/ImageSharp/Formats/ImageFormatBase{T}.cs | 38 ++++++++++++++ .../Formats/Jpeg/ImageExtensions.cs | 2 +- .../Formats/Jpeg/JpegConfigurationModule.cs | 9 ++-- src/ImageSharp/Formats/Jpeg/JpegFormat.cs | 14 ++++-- .../Formats/Jpeg/JpegImageFormatDetector.cs | 2 +- src/ImageSharp/Formats/Jpeg/JpegMetaData.cs | 15 ++++++ src/ImageSharp/Formats/Png/ImageExtensions.cs | 2 +- .../Formats/Png/PngConfigurationModule.cs | 4 +- src/ImageSharp/Formats/Png/PngFormat.cs | 14 ++++-- .../Formats/Png/PngImageFormatDetector.cs | 2 +- src/ImageSharp/Formats/Png/PngMetaData.cs | 15 ++++++ src/ImageSharp/ImageFormats.cs | 37 -------------- .../MetaData/IImageFormatFrameMetaData.cs | 13 +++++ .../MetaData/IImageFormatMetaData.cs | 13 +++++ src/ImageSharp/MetaData/ImageFrameMetaData.cs | 30 +++++------- src/ImageSharp/MetaData/ImageMetaData.cs | 30 +++++------- tests/ImageSharp.Tests/ConfigurationTests.cs | 13 ++--- .../Formats/GeneralFormatTests.cs | 2 +- .../Formats/Gif/GifEncoderTests.cs | 10 ++-- .../Formats/ImageFormatManagerTests.cs | 4 +- .../MetaData/ImageFrameMetaDataTests.cs | 4 +- .../TestUtilities/TestEnvironment.Formats.cs | 4 +- 37 files changed, 221 insertions(+), 198 deletions(-) create mode 100644 src/ImageSharp/Formats/Bmp/BmpMetaData.cs delete mode 100644 src/ImageSharp/Formats/Gif/GifMetaDataExtensions.cs create mode 100644 src/ImageSharp/Formats/ImageFormatBase{T}.cs create mode 100644 src/ImageSharp/Formats/Jpeg/JpegMetaData.cs create mode 100644 src/ImageSharp/Formats/Png/PngMetaData.cs delete mode 100644 src/ImageSharp/ImageFormats.cs create mode 100644 src/ImageSharp/MetaData/IImageFormatFrameMetaData.cs create mode 100644 src/ImageSharp/MetaData/IImageFormatMetaData.cs diff --git a/src/ImageSharp/Formats/Bmp/BmpConfigurationModule.cs b/src/ImageSharp/Formats/Bmp/BmpConfigurationModule.cs index 956acc157..57117cc07 100644 --- a/src/ImageSharp/Formats/Bmp/BmpConfigurationModule.cs +++ b/src/ImageSharp/Formats/Bmp/BmpConfigurationModule.cs @@ -9,11 +9,11 @@ namespace SixLabors.ImageSharp.Formats.Bmp public sealed class BmpConfigurationModule : IConfigurationModule { /// - public void Configure(Configuration config) + public void Configure(Configuration configuration) { - config.ImageFormatsManager.SetEncoder(ImageFormats.Bmp, new BmpEncoder()); - config.ImageFormatsManager.SetDecoder(ImageFormats.Bmp, new BmpDecoder()); - config.ImageFormatsManager.AddImageFormatDetector(new BmpImageFormatDetector()); + configuration.ImageFormatsManager.SetEncoder(BmpFormat.Instance, new BmpEncoder()); + configuration.ImageFormatsManager.SetDecoder(BmpFormat.Instance, new BmpDecoder()); + configuration.ImageFormatsManager.AddImageFormatDetector(new BmpImageFormatDetector()); } } } \ No newline at end of file diff --git a/src/ImageSharp/Formats/Bmp/BmpFormat.cs b/src/ImageSharp/Formats/Bmp/BmpFormat.cs index 64c6574c1..de3f6f3f4 100644 --- a/src/ImageSharp/Formats/Bmp/BmpFormat.cs +++ b/src/ImageSharp/Formats/Bmp/BmpFormat.cs @@ -8,18 +8,22 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// /// Registers the image encoders, decoders and mime type detectors for the bmp format. /// - internal sealed class BmpFormat : IImageFormat + internal sealed class BmpFormat : ImageFormatBase { + private BmpFormat() + { + } + /// - public string Name => "BMP"; + public override string Name => "BMP"; /// - public string DefaultMimeType => "image/bmp"; + public override string DefaultMimeType => "image/bmp"; /// - public IEnumerable MimeTypes => BmpConstants.MimeTypes; + public override IEnumerable MimeTypes => BmpConstants.MimeTypes; /// - public IEnumerable FileExtensions => BmpConstants.FileExtensions; + public override IEnumerable FileExtensions => BmpConstants.FileExtensions; } } \ No newline at end of file diff --git a/src/ImageSharp/Formats/Bmp/BmpImageFormatDetector.cs b/src/ImageSharp/Formats/Bmp/BmpImageFormatDetector.cs index bb884019b..6a740d47d 100644 --- a/src/ImageSharp/Formats/Bmp/BmpImageFormatDetector.cs +++ b/src/ImageSharp/Formats/Bmp/BmpImageFormatDetector.cs @@ -16,7 +16,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// public IImageFormat DetectFormat(ReadOnlySpan header) { - return this.IsSupportedFileFormat(header) ? ImageFormats.Bmp : null; + return this.IsSupportedFileFormat(header) ? BmpFormat.Instance : null; } private bool IsSupportedFileFormat(ReadOnlySpan header) diff --git a/src/ImageSharp/Formats/Bmp/BmpMetaData.cs b/src/ImageSharp/Formats/Bmp/BmpMetaData.cs new file mode 100644 index 000000000..1e350200a --- /dev/null +++ b/src/ImageSharp/Formats/Bmp/BmpMetaData.cs @@ -0,0 +1,15 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using SixLabors.ImageSharp.MetaData; + +namespace SixLabors.ImageSharp.Formats.Bmp +{ + /// + /// Provides Bmp specific metadata information for the image. + /// + public class BmpMetaData : IImageFormatMetaData + { + // TODO: Analyse what properties we would like to preserve. + } +} diff --git a/src/ImageSharp/Formats/Bmp/ImageExtensions.cs b/src/ImageSharp/Formats/Bmp/ImageExtensions.cs index 57e4615ba..aa1c353db 100644 --- a/src/ImageSharp/Formats/Bmp/ImageExtensions.cs +++ b/src/ImageSharp/Formats/Bmp/ImageExtensions.cs @@ -34,6 +34,6 @@ namespace SixLabors.ImageSharp /// Thrown if the stream is null. public static void SaveAsBmp(this Image source, Stream stream, BmpEncoder encoder) where TPixel : struct, IPixel - => source.Save(stream, encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(ImageFormats.Bmp)); + => source.Save(stream, encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(BmpFormat.Instance)); } } diff --git a/src/ImageSharp/Formats/Gif/GifConfigurationModule.cs b/src/ImageSharp/Formats/Gif/GifConfigurationModule.cs index 0bb62779e..861d3e036 100644 --- a/src/ImageSharp/Formats/Gif/GifConfigurationModule.cs +++ b/src/ImageSharp/Formats/Gif/GifConfigurationModule.cs @@ -9,12 +9,11 @@ namespace SixLabors.ImageSharp.Formats.Gif public sealed class GifConfigurationModule : IConfigurationModule { /// - public void Configure(Configuration config) + public void Configure(Configuration configuration) { - config.ImageFormatsManager.SetEncoder(ImageFormats.Gif, new GifEncoder()); - config.ImageFormatsManager.SetDecoder(ImageFormats.Gif, new GifDecoder()); - - config.ImageFormatsManager.AddImageFormatDetector(new GifImageFormatDetector()); + configuration.ImageFormatsManager.SetEncoder(GifFormat.Instance, new GifEncoder()); + configuration.ImageFormatsManager.SetDecoder(GifFormat.Instance, new GifDecoder()); + configuration.ImageFormatsManager.AddImageFormatDetector(new GifImageFormatDetector()); } } } \ No newline at end of file diff --git a/src/ImageSharp/Formats/Gif/GifConstants.cs b/src/ImageSharp/Formats/Gif/GifConstants.cs index cc80b0cce..8167d0d2e 100644 --- a/src/ImageSharp/Formats/Gif/GifConstants.cs +++ b/src/ImageSharp/Formats/Gif/GifConstants.cs @@ -26,11 +26,6 @@ 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 !. /// diff --git a/src/ImageSharp/Formats/Gif/GifDecoderCore.cs b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs index 092ac859d..f50381264 100644 --- a/src/ImageSharp/Formats/Gif/GifDecoderCore.cs +++ b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs @@ -164,7 +164,7 @@ namespace SixLabors.ImageSharp.Formats.Gif this.globalColorTable?.Dispose(); } - image?.MetaData.AddOrUpdateGifMetaData(this.gifMetaData); + image?.MetaData.AddOrUpdateFormatMetaData(GifFormat.Instance, this.gifMetaData); return image; } @@ -224,7 +224,7 @@ namespace SixLabors.ImageSharp.Formats.Gif this.globalColorTable?.Dispose(); } - this.metaData.AddOrUpdateGifMetaData(this.gifMetaData); + this.metaData.AddOrUpdateFormatMetaData(GifFormat.Instance, this.gifMetaData); return new ImageInfo( new PixelTypeInfo(this.logicalScreenDescriptor.BitsPerPixel), this.logicalScreenDescriptor.Width, @@ -561,7 +561,7 @@ namespace SixLabors.ImageSharp.Formats.Gif } gifMeta.DisposalMethod = this.graphicsControlExtension.DisposalMethod; - meta.AddOrUpdateGifFrameMetaData(gifMeta); + meta.AddOrUpdateFormatMetaData(GifFormat.Instance, gifMeta); } /// diff --git a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs index b37344658..20f2f1d33 100644 --- a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs +++ b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs @@ -86,7 +86,7 @@ namespace SixLabors.ImageSharp.Formats.Gif Guard.NotNull(image, nameof(image)); Guard.NotNull(stream, nameof(stream)); - this.gifMetaData = image.MetaData.GetGifMetaData() ?? new GifMetaData(); + this.gifMetaData = image.MetaData.GetOrAddFormatMetaData(GifFormat.Instance); this.colorTableMode = this.colorTableMode ?? this.gifMetaData.ColorTableMode; bool useGlobalTable = this.colorTableMode.Equals(GifColorTableMode.Global); @@ -143,7 +143,7 @@ namespace SixLabors.ImageSharp.Formats.Gif for (int i = 0; i < image.Frames.Count; i++) { ImageFrame frame = image.Frames[i]; - GifFrameMetaData frameMetaData = frame.MetaData.GetGifFrameMetaData() ?? new GifFrameMetaData(); + GifFrameMetaData frameMetaData = frame.MetaData.GetOrAddFormatMetaData(GifFormat.Instance); this.WriteGraphicalControlExtension(frameMetaData, transparencyIndex, stream); this.WriteImageDescriptor(frame, false, stream); @@ -169,7 +169,7 @@ namespace SixLabors.ImageSharp.Formats.Gif GifFrameMetaData previousMeta = null; foreach (ImageFrame frame in image.Frames) { - GifFrameMetaData meta = frame.MetaData.GetGifFrameMetaData() ?? new GifFrameMetaData(); + GifFrameMetaData meta = frame.MetaData.GetOrAddFormatMetaData(GifFormat.Instance); if (quantized is null) { // Allow each frame to be encoded at whatever color depth the frame designates if set. diff --git a/src/ImageSharp/Formats/Gif/GifFormat.cs b/src/ImageSharp/Formats/Gif/GifFormat.cs index 6353690f4..2d14abb44 100644 --- a/src/ImageSharp/Formats/Gif/GifFormat.cs +++ b/src/ImageSharp/Formats/Gif/GifFormat.cs @@ -8,18 +8,22 @@ namespace SixLabors.ImageSharp.Formats.Gif /// /// Registers the image encoders, decoders and mime type detectors for the gif format. /// - internal sealed class GifFormat : IImageFormat + internal sealed class GifFormat : ImageFormatBase { + private GifFormat() + { + } + /// - public string Name => "GIF"; + public override string Name => "GIF"; /// - public string DefaultMimeType => "image/gif"; + public override string DefaultMimeType => "image/gif"; /// - public IEnumerable MimeTypes => GifConstants.MimeTypes; + public override IEnumerable MimeTypes => GifConstants.MimeTypes; /// - public IEnumerable FileExtensions => GifConstants.FileExtensions; + public override IEnumerable FileExtensions => GifConstants.FileExtensions; } } \ No newline at end of file diff --git a/src/ImageSharp/Formats/Gif/GifFrameMetaData.cs b/src/ImageSharp/Formats/Gif/GifFrameMetaData.cs index cc04d4831..a7b68e6e8 100644 --- a/src/ImageSharp/Formats/Gif/GifFrameMetaData.cs +++ b/src/ImageSharp/Formats/Gif/GifFrameMetaData.cs @@ -1,12 +1,14 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using SixLabors.ImageSharp.MetaData; + namespace SixLabors.ImageSharp.Formats.Gif { /// /// Provides Gif specific metadata information for the image frame. /// - public class GifFrameMetaData + public class GifFrameMetaData : IImageFormatFrameMetaData { /// /// Gets or sets the length of the color table for paletted images. diff --git a/src/ImageSharp/Formats/Gif/GifImageFormatDetector.cs b/src/ImageSharp/Formats/Gif/GifImageFormatDetector.cs index bfbd334b0..b8f9a03f1 100644 --- a/src/ImageSharp/Formats/Gif/GifImageFormatDetector.cs +++ b/src/ImageSharp/Formats/Gif/GifImageFormatDetector.cs @@ -16,7 +16,7 @@ namespace SixLabors.ImageSharp.Formats.Gif /// public IImageFormat DetectFormat(ReadOnlySpan header) { - return this.IsSupportedFileFormat(header) ? ImageFormats.Gif : null; + return this.IsSupportedFileFormat(header) ? GifFormat.Instance : null; } private bool IsSupportedFileFormat(ReadOnlySpan header) diff --git a/src/ImageSharp/Formats/Gif/GifMetaData.cs b/src/ImageSharp/Formats/Gif/GifMetaData.cs index f58f5dff3..cc0716ec5 100644 --- a/src/ImageSharp/Formats/Gif/GifMetaData.cs +++ b/src/ImageSharp/Formats/Gif/GifMetaData.cs @@ -1,12 +1,14 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using SixLabors.ImageSharp.MetaData; + namespace SixLabors.ImageSharp.Formats.Gif { /// /// Provides Gif specific metadata information for the image. /// - public class GifMetaData + public class GifMetaData : IImageFormatMetaData { /// /// Gets or sets the number of times any animation is repeated. diff --git a/src/ImageSharp/Formats/Gif/GifMetaDataExtensions.cs b/src/ImageSharp/Formats/Gif/GifMetaDataExtensions.cs deleted file mode 100644 index 04b542d2d..000000000 --- a/src/ImageSharp/Formats/Gif/GifMetaDataExtensions.cs +++ /dev/null @@ -1,49 +0,0 @@ -// 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/ImageExtensions.cs b/src/ImageSharp/Formats/Gif/ImageExtensions.cs index 1c41285a9..8ddd4247e 100644 --- a/src/ImageSharp/Formats/Gif/ImageExtensions.cs +++ b/src/ImageSharp/Formats/Gif/ImageExtensions.cs @@ -34,6 +34,6 @@ namespace SixLabors.ImageSharp /// Thrown if the stream is null. public static void SaveAsGif(this Image source, Stream stream, GifEncoder encoder) where TPixel : struct, IPixel - => source.Save(stream, encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(ImageFormats.Gif)); + => source.Save(stream, encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(GifFormat.Instance)); } } diff --git a/src/ImageSharp/Formats/ImageFormatBase{T}.cs b/src/ImageSharp/Formats/ImageFormatBase{T}.cs new file mode 100644 index 000000000..85273db2b --- /dev/null +++ b/src/ImageSharp/Formats/ImageFormatBase{T}.cs @@ -0,0 +1,38 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Collections.Generic; + +namespace SixLabors.ImageSharp.Formats +{ + /// + /// The base class for all image formats. + /// Inheriting classes should implement the singleton pattern by creating a private constructor. + /// + /// The type of image format. + public abstract class ImageFormatBase : IImageFormat + where T : class, IImageFormat + { + private static readonly Lazy Lazy = new Lazy(CreateInstance); + + /// + /// Gets the current instance. + /// + public static T Instance => Lazy.Value; + + /// + public abstract string Name { get; } + + /// + public abstract string DefaultMimeType { get; } + + /// + public abstract IEnumerable MimeTypes { get; } + + /// + public abstract IEnumerable FileExtensions { get; } + + private static T CreateInstance() => (T)Activator.CreateInstance(typeof(T), true); + } +} diff --git a/src/ImageSharp/Formats/Jpeg/ImageExtensions.cs b/src/ImageSharp/Formats/Jpeg/ImageExtensions.cs index 1d3be063d..cb7fc1944 100644 --- a/src/ImageSharp/Formats/Jpeg/ImageExtensions.cs +++ b/src/ImageSharp/Formats/Jpeg/ImageExtensions.cs @@ -34,6 +34,6 @@ namespace SixLabors.ImageSharp /// Thrown if the stream is null. public static void SaveAsJpeg(this Image source, Stream stream, JpegEncoder encoder) where TPixel : struct, IPixel - => source.Save(stream, encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(ImageFormats.Jpeg)); + => source.Save(stream, encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(JpegFormat.Instance)); } } diff --git a/src/ImageSharp/Formats/Jpeg/JpegConfigurationModule.cs b/src/ImageSharp/Formats/Jpeg/JpegConfigurationModule.cs index c3bf801ac..9840a2ae8 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegConfigurationModule.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegConfigurationModule.cs @@ -9,12 +9,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg public sealed class JpegConfigurationModule : IConfigurationModule { /// - public void Configure(Configuration config) + public void Configure(Configuration configuration) { - config.ImageFormatsManager.SetEncoder(ImageFormats.Jpeg, new JpegEncoder()); - config.ImageFormatsManager.SetDecoder(ImageFormats.Jpeg, new JpegDecoder()); - - config.ImageFormatsManager.AddImageFormatDetector(new JpegImageFormatDetector()); + configuration.ImageFormatsManager.SetEncoder(JpegFormat.Instance, new JpegEncoder()); + configuration.ImageFormatsManager.SetDecoder(JpegFormat.Instance, new JpegDecoder()); + configuration.ImageFormatsManager.AddImageFormatDetector(new JpegImageFormatDetector()); } } } \ No newline at end of file diff --git a/src/ImageSharp/Formats/Jpeg/JpegFormat.cs b/src/ImageSharp/Formats/Jpeg/JpegFormat.cs index 9a18f14d3..21757dcb3 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegFormat.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegFormat.cs @@ -8,18 +8,22 @@ namespace SixLabors.ImageSharp.Formats.Jpeg /// /// Registers the image encoders, decoders and mime type detectors for the jpeg format. /// - internal sealed class JpegFormat : IImageFormat + internal sealed class JpegFormat : ImageFormatBase { + private JpegFormat() + { + } + /// - public string Name => "JPEG"; + public override string Name => "JPEG"; /// - public string DefaultMimeType => "image/jpeg"; + public override string DefaultMimeType => "image/jpeg"; /// - public IEnumerable MimeTypes => JpegConstants.MimeTypes; + public override IEnumerable MimeTypes => JpegConstants.MimeTypes; /// - public IEnumerable FileExtensions => JpegConstants.FileExtensions; + public override IEnumerable FileExtensions => JpegConstants.FileExtensions; } } \ No newline at end of file diff --git a/src/ImageSharp/Formats/Jpeg/JpegImageFormatDetector.cs b/src/ImageSharp/Formats/Jpeg/JpegImageFormatDetector.cs index e25957efc..7594f4477 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegImageFormatDetector.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegImageFormatDetector.cs @@ -16,7 +16,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg /// public IImageFormat DetectFormat(ReadOnlySpan header) { - return this.IsSupportedFileFormat(header) ? ImageFormats.Jpeg : null; + return this.IsSupportedFileFormat(header) ? JpegFormat.Instance : null; } private bool IsSupportedFileFormat(ReadOnlySpan header) diff --git a/src/ImageSharp/Formats/Jpeg/JpegMetaData.cs b/src/ImageSharp/Formats/Jpeg/JpegMetaData.cs new file mode 100644 index 000000000..eec0efa80 --- /dev/null +++ b/src/ImageSharp/Formats/Jpeg/JpegMetaData.cs @@ -0,0 +1,15 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using SixLabors.ImageSharp.MetaData; + +namespace SixLabors.ImageSharp.Formats.Jpeg +{ + /// + /// Provides Jpeg specific metadata information for the image. + /// + public class JpegMetaData : IImageFormatMetaData + { + // TODO: Analyse what properties we would like to preserve. + } +} diff --git a/src/ImageSharp/Formats/Png/ImageExtensions.cs b/src/ImageSharp/Formats/Png/ImageExtensions.cs index a65845e02..c73ec6f57 100644 --- a/src/ImageSharp/Formats/Png/ImageExtensions.cs +++ b/src/ImageSharp/Formats/Png/ImageExtensions.cs @@ -35,6 +35,6 @@ namespace SixLabors.ImageSharp /// Thrown if the stream is null. public static void SaveAsPng(this Image source, Stream stream, PngEncoder encoder) where TPixel : struct, IPixel - => source.Save(stream, encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(ImageFormats.Png)); + => source.Save(stream, encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(PngFormat.Instance)); } } \ No newline at end of file diff --git a/src/ImageSharp/Formats/Png/PngConfigurationModule.cs b/src/ImageSharp/Formats/Png/PngConfigurationModule.cs index 64dad23bc..3c9fddbad 100644 --- a/src/ImageSharp/Formats/Png/PngConfigurationModule.cs +++ b/src/ImageSharp/Formats/Png/PngConfigurationModule.cs @@ -11,8 +11,8 @@ namespace SixLabors.ImageSharp.Formats.Png /// public void Configure(Configuration configuration) { - configuration.ImageFormatsManager.SetEncoder(ImageFormats.Png, new PngEncoder()); - configuration.ImageFormatsManager.SetDecoder(ImageFormats.Png, new PngDecoder()); + configuration.ImageFormatsManager.SetEncoder(PngFormat.Instance, new PngEncoder()); + configuration.ImageFormatsManager.SetDecoder(PngFormat.Instance, new PngDecoder()); configuration.ImageFormatsManager.AddImageFormatDetector(new PngImageFormatDetector()); } } diff --git a/src/ImageSharp/Formats/Png/PngFormat.cs b/src/ImageSharp/Formats/Png/PngFormat.cs index 142f66071..00ebbde52 100644 --- a/src/ImageSharp/Formats/Png/PngFormat.cs +++ b/src/ImageSharp/Formats/Png/PngFormat.cs @@ -8,18 +8,22 @@ namespace SixLabors.ImageSharp.Formats.Png /// /// Registers the image encoders, decoders and mime type detectors for the png format. /// - internal sealed class PngFormat : IImageFormat + internal sealed class PngFormat : ImageFormatBase { + private PngFormat() + { + } + /// - public string Name => "PNG"; + public override string Name => "PNG"; /// - public string DefaultMimeType => "image/png"; + public override string DefaultMimeType => "image/png"; /// - public IEnumerable MimeTypes => PngConstants.MimeTypes; + public override IEnumerable MimeTypes => PngConstants.MimeTypes; /// - public IEnumerable FileExtensions => PngConstants.FileExtensions; + public override IEnumerable FileExtensions => PngConstants.FileExtensions; } } \ No newline at end of file diff --git a/src/ImageSharp/Formats/Png/PngImageFormatDetector.cs b/src/ImageSharp/Formats/Png/PngImageFormatDetector.cs index c1c039a1b..5deed86e3 100644 --- a/src/ImageSharp/Formats/Png/PngImageFormatDetector.cs +++ b/src/ImageSharp/Formats/Png/PngImageFormatDetector.cs @@ -17,7 +17,7 @@ namespace SixLabors.ImageSharp.Formats.Png /// public IImageFormat DetectFormat(ReadOnlySpan header) { - return this.IsSupportedFileFormat(header) ? ImageFormats.Png : null; + return this.IsSupportedFileFormat(header) ? PngFormat.Instance : null; } private bool IsSupportedFileFormat(ReadOnlySpan header) diff --git a/src/ImageSharp/Formats/Png/PngMetaData.cs b/src/ImageSharp/Formats/Png/PngMetaData.cs new file mode 100644 index 000000000..1d76cf580 --- /dev/null +++ b/src/ImageSharp/Formats/Png/PngMetaData.cs @@ -0,0 +1,15 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using SixLabors.ImageSharp.MetaData; + +namespace SixLabors.ImageSharp.Formats.Png +{ + /// + /// Provides Png specific metadata information for the image. + /// + public class PngMetaData : IImageFormatMetaData + { + // TODO: Analyse what properties we would like to preserve. + } +} diff --git a/src/ImageSharp/ImageFormats.cs b/src/ImageSharp/ImageFormats.cs deleted file mode 100644 index bc437e5a5..000000000 --- a/src/ImageSharp/ImageFormats.cs +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// 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; - -namespace SixLabors.ImageSharp -{ - /// - /// The static collection of all the default image formats - /// - public static class ImageFormats - { - /// - /// The format details for the jpegs. - /// - public static readonly IImageFormat Jpeg = new JpegFormat(); - - /// - /// The format details for the pngs. - /// - public static readonly IImageFormat Png = new PngFormat(); - - /// - /// The format details for the gifs. - /// - public static readonly IImageFormat Gif = new GifFormat(); - - /// - /// The format details for the bitmaps. - /// - public static readonly IImageFormat Bmp = new BmpFormat(); - } -} \ No newline at end of file diff --git a/src/ImageSharp/MetaData/IImageFormatFrameMetaData.cs b/src/ImageSharp/MetaData/IImageFormatFrameMetaData.cs new file mode 100644 index 000000000..5df6fa433 --- /dev/null +++ b/src/ImageSharp/MetaData/IImageFormatFrameMetaData.cs @@ -0,0 +1,13 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +namespace SixLabors.ImageSharp.MetaData +{ + /// + /// Encapsulates the format specific metadata of an image frame. + /// This interface exists to allow type saftey and avoid the performance overhead of parsing attributes. + /// + public interface IImageFormatFrameMetaData + { + } +} \ No newline at end of file diff --git a/src/ImageSharp/MetaData/IImageFormatMetaData.cs b/src/ImageSharp/MetaData/IImageFormatMetaData.cs new file mode 100644 index 000000000..ded8df801 --- /dev/null +++ b/src/ImageSharp/MetaData/IImageFormatMetaData.cs @@ -0,0 +1,13 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +namespace SixLabors.ImageSharp.MetaData +{ + /// + /// Encapsulates the format specific metadata of an image. + /// This interface exists to allow type saftey and avoid the performance overhead of parsing attributes. + /// + public interface IImageFormatMetaData + { + } +} \ No newline at end of file diff --git a/src/ImageSharp/MetaData/ImageFrameMetaData.cs b/src/ImageSharp/MetaData/ImageFrameMetaData.cs index 55678789e..31bad29b8 100644 --- a/src/ImageSharp/MetaData/ImageFrameMetaData.cs +++ b/src/ImageSharp/MetaData/ImageFrameMetaData.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using SixLabors.ImageSharp.Formats; namespace SixLabors.ImageSharp.MetaData { @@ -11,7 +12,7 @@ namespace SixLabors.ImageSharp.MetaData /// public sealed class ImageFrameMetaData { - private readonly Dictionary metaData = new Dictionary(StringComparer.OrdinalIgnoreCase); + private readonly Dictionary metaData = new Dictionary(); /// /// Initializes a new instance of the class. @@ -31,7 +32,7 @@ namespace SixLabors.ImageSharp.MetaData { DebugGuard.NotNull(other, nameof(other)); - foreach (KeyValuePair meta in other.metaData) + foreach (KeyValuePair meta in other.metaData) { this.metaData.Add(meta.Key, meta.Value); } @@ -51,7 +52,7 @@ namespace SixLabors.ImageSharp.MetaData /// key is null. /// value is null. /// An element with the same key already exists in the . - public void AddOrUpdateMetaData(string key, object value) + public void AddOrUpdateFormatMetaData(IImageFormat key, IImageFormatFrameMetaData value) { // Don't think this needs to be threadsafe. Guard.NotNull(value, nameof(value)); @@ -61,27 +62,22 @@ namespace SixLabors.ImageSharp.MetaData /// /// Gets the metadata value associated with the specified key. /// - /// The type of value. + /// The type of metadata. /// 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. + /// The . /// - public bool TryGetMetaData(string key, out T value) + public T GetOrAddFormatMetaData(IImageFormat key) + where T : IImageFormatFrameMetaData, new() { - if (this.metaData.TryGetValue(key, out object meta)) + if (this.metaData.TryGetValue(key, out IImageFormatFrameMetaData meta)) { - value = (T)meta; - return true; + return (T)meta; } - value = default; - return false; + var newMeta = new T(); + this.AddOrUpdateFormatMetaData(key, newMeta); + return newMeta; } } } \ No newline at end of file diff --git a/src/ImageSharp/MetaData/ImageMetaData.cs b/src/ImageSharp/MetaData/ImageMetaData.cs index 8233798c2..d907e8b8a 100644 --- a/src/ImageSharp/MetaData/ImageMetaData.cs +++ b/src/ImageSharp/MetaData/ImageMetaData.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using SixLabors.ImageSharp.Formats; using SixLabors.ImageSharp.MetaData.Profiles.Exif; using SixLabors.ImageSharp.MetaData.Profiles.Icc; @@ -25,7 +26,7 @@ namespace SixLabors.ImageSharp.MetaData /// public const double DefaultVerticalResolution = 96; - private readonly Dictionary metaData = new Dictionary(StringComparer.OrdinalIgnoreCase); + private readonly Dictionary metaData = new Dictionary(); private double horizontalResolution; private double verticalResolution; @@ -51,7 +52,7 @@ namespace SixLabors.ImageSharp.MetaData this.VerticalResolution = other.VerticalResolution; this.ResolutionUnits = other.ResolutionUnits; - foreach (KeyValuePair meta in other.metaData) + foreach (KeyValuePair meta in other.metaData) { this.metaData.Add(meta.Key, meta.Value); } @@ -138,7 +139,7 @@ namespace SixLabors.ImageSharp.MetaData /// key is null. /// value is null. /// An element with the same key already exists in the . - public void AddOrUpdateMetaData(string key, object value) + public void AddOrUpdateFormatMetaData(IImageFormat key, IImageFormatMetaData value) { // Don't think this needs to be threadsafe. Guard.NotNull(value, nameof(value)); @@ -148,27 +149,22 @@ namespace SixLabors.ImageSharp.MetaData /// /// Gets the metadata value associated with the specified key. /// - /// The type of value. + /// The type of metadata. /// 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. + /// The . /// - public bool TryGetMetaData(string key, out T value) + public T GetOrAddFormatMetaData(IImageFormat key) + where T : IImageFormatMetaData, new() { - if (this.metaData.TryGetValue(key, out object meta)) + if (this.metaData.TryGetValue(key, out IImageFormatMetaData meta)) { - value = (T)meta; - return true; + return (T)meta; } - value = default; - return false; + var newMeta = new T(); + this.AddOrUpdateFormatMetaData(key, newMeta); + return newMeta; } /// diff --git a/tests/ImageSharp.Tests/ConfigurationTests.cs b/tests/ImageSharp.Tests/ConfigurationTests.cs index 4bec25f7a..6a8479b2b 100644 --- a/tests/ImageSharp.Tests/ConfigurationTests.cs +++ b/tests/ImageSharp.Tests/ConfigurationTests.cs @@ -4,6 +4,7 @@ using System; using System.Linq; using Moq; +using SixLabors.ImageSharp.Formats.Bmp; using SixLabors.ImageSharp.IO; using Xunit; // ReSharper disable InconsistentNaming @@ -37,19 +38,13 @@ namespace SixLabors.ImageSharp.Tests /// Test that the default configuration is not null. /// [Fact] - public void TestDefaultConfigurationIsNotNull() - { - Assert.True(Configuration.Default != null); - } + public void TestDefaultConfigurationIsNotNull() => Assert.True(Configuration.Default != null); /// /// Test that the default configuration read origin options is set to begin. /// [Fact] - public void TestDefaultConfigurationReadOriginIsCurrent() - { - Assert.True(Configuration.Default.ReadOrigin == ReadOrigin.Current); - } + public void TestDefaultConfigurationReadOriginIsCurrent() => Assert.True(Configuration.Default.ReadOrigin == ReadOrigin.Current); /// /// Test that the default configuration parallel options max degrees of parallelism matches the @@ -101,7 +96,7 @@ namespace SixLabors.ImageSharp.Tests Assert.Equal(count, config.ImageFormats.Count()); - config.ImageFormatsManager.AddImageFormat(ImageFormats.Bmp); + config.ImageFormatsManager.AddImageFormat(BmpFormat.Instance); Assert.Equal(count, config.ImageFormats.Count()); } diff --git a/tests/ImageSharp.Tests/Formats/GeneralFormatTests.cs b/tests/ImageSharp.Tests/Formats/GeneralFormatTests.cs index 23b806767..f8b035ca8 100644 --- a/tests/ImageSharp.Tests/Formats/GeneralFormatTests.cs +++ b/tests/ImageSharp.Tests/Formats/GeneralFormatTests.cs @@ -44,7 +44,7 @@ namespace SixLabors.ImageSharp.Tests using (Image image = file.CreateImage()) { string filename = path + "/" + file.FileNameWithoutExtension + ".txt"; - File.WriteAllText(filename, image.ToBase64String(ImageFormats.Png)); + File.WriteAllText(filename, image.ToBase64String(PngFormat.Instance)); } } } diff --git a/tests/ImageSharp.Tests/Formats/Gif/GifEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Gif/GifEncoderTests.cs index 2b08bf20d..4ddcded5e 100644 --- a/tests/ImageSharp.Tests/Formats/Gif/GifEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Gif/GifEncoderTests.cs @@ -189,8 +189,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif inStream.Position = 0; var image = Image.Load(inStream); - GifMetaData metaData = image.MetaData.GetGifMetaData(); - GifFrameMetaData frameMetaData = image.Frames.RootFrame.MetaData.GetGifFrameMetaData(); + GifMetaData metaData = image.MetaData.GetOrAddFormatMetaData(GifFormat.Instance); + GifFrameMetaData frameMetaData = image.Frames.RootFrame.MetaData.GetOrAddFormatMetaData(GifFormat.Instance); GifColorTableMode colorMode = metaData.ColorTableMode; var encoder = new GifEncoder() { @@ -204,7 +204,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif outStream.Position = 0; var clone = Image.Load(outStream); - GifMetaData cloneMetaData = clone.MetaData.GetGifMetaData(); + GifMetaData cloneMetaData = clone.MetaData.GetOrAddFormatMetaData(GifFormat.Instance); Assert.Equal(metaData.ColorTableMode, cloneMetaData.ColorTableMode); // Gifiddle and Cyotek GifInfo say this image has 64 colors. @@ -212,8 +212,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif for (int i = 0; i < image.Frames.Count; i++) { - GifFrameMetaData ifm = image.Frames[i].MetaData.GetGifFrameMetaData(); - GifFrameMetaData cifm = clone.Frames[i].MetaData.GetGifFrameMetaData(); + GifFrameMetaData ifm = image.Frames[i].MetaData.GetOrAddFormatMetaData(GifFormat.Instance); + GifFrameMetaData cifm = clone.Frames[i].MetaData.GetOrAddFormatMetaData(GifFormat.Instance); Assert.Equal(ifm.ColorTableLength, cifm.ColorTableLength); Assert.Equal(ifm.FrameDelay, cifm.FrameDelay); diff --git a/tests/ImageSharp.Tests/Formats/ImageFormatManagerTests.cs b/tests/ImageSharp.Tests/Formats/ImageFormatManagerTests.cs index f10a4ce84..464b1564b 100644 --- a/tests/ImageSharp.Tests/Formats/ImageFormatManagerTests.cs +++ b/tests/ImageSharp.Tests/Formats/ImageFormatManagerTests.cs @@ -61,7 +61,7 @@ namespace SixLabors.ImageSharp.Tests }); Assert.Throws(() => { - this.DefaultFormatsManager.SetEncoder(ImageFormats.Bmp, null); + this.DefaultFormatsManager.SetEncoder(BmpFormat.Instance, null); }); Assert.Throws(() => { @@ -78,7 +78,7 @@ namespace SixLabors.ImageSharp.Tests }); Assert.Throws(() => { - this.DefaultFormatsManager.SetDecoder(ImageFormats.Bmp, null); + this.DefaultFormatsManager.SetDecoder(BmpFormat.Instance, null); }); Assert.Throws(() => { diff --git a/tests/ImageSharp.Tests/MetaData/ImageFrameMetaDataTests.cs b/tests/ImageSharp.Tests/MetaData/ImageFrameMetaDataTests.cs index c250d973b..00d03dce4 100644 --- a/tests/ImageSharp.Tests/MetaData/ImageFrameMetaDataTests.cs +++ b/tests/ImageSharp.Tests/MetaData/ImageFrameMetaDataTests.cs @@ -27,10 +27,10 @@ namespace SixLabors.ImageSharp.Tests }; var metaData = new ImageFrameMetaData(); - metaData.AddOrUpdateGifFrameMetaData(gifFrameMetaData); + metaData.AddOrUpdateFormatMetaData(GifFormat.Instance, gifFrameMetaData); var clone = new ImageFrameMetaData(metaData); - GifFrameMetaData cloneGifFrameMetaData = clone.GetGifFrameMetaData(); + GifFrameMetaData cloneGifFrameMetaData = clone.GetOrAddFormatMetaData(GifFormat.Instance); Assert.Equal(frameDelay, cloneGifFrameMetaData.FrameDelay); Assert.Equal(colorTableLength, cloneGifFrameMetaData.ColorTableLength); diff --git a/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Formats.cs b/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Formats.cs index 90c999f7c..334b6552a 100644 --- a/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Formats.cs +++ b/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Formats.cs @@ -62,13 +62,13 @@ namespace SixLabors.ImageSharp.Tests IImageEncoder bmpEncoder = IsWindows ? (IImageEncoder)SystemDrawingReferenceEncoder.Bmp : new BmpEncoder(); cfg.ConfigureCodecs( - ImageFormats.Png, + PngFormat.Instance, MagickReferenceDecoder.Instance, pngEncoder, new PngImageFormatDetector()); cfg.ConfigureCodecs( - ImageFormats.Bmp, + BmpFormat.Instance, SystemDrawingReferenceDecoder.Instance, bmpEncoder, new BmpImageFormatDetector()); From 25e5d48dcab89b6e25ccef85efb077d35ba2c5da Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Sun, 9 Sep 2018 20:42:53 +0100 Subject: [PATCH 05/11] Much better type safety. --- src/ImageSharp/Formats/Bmp/BmpFormat.cs | 18 ++++++--- src/ImageSharp/Formats/Bmp/BmpMetaData.cs | 4 +- src/ImageSharp/Formats/Gif/GifEncoderCore.cs | 4 +- src/ImageSharp/Formats/Gif/GifFormat.cs | 21 +++++++--- .../Formats/Gif/GifFrameMetaData.cs | 4 +- src/ImageSharp/Formats/Gif/GifMetaData.cs | 4 +- src/ImageSharp/Formats/IImageFormat.cs | 32 +++++++++++++++- src/ImageSharp/Formats/ImageFormatBase{T}.cs | 38 ------------------- src/ImageSharp/Formats/Jpeg/JpegFormat.cs | 18 ++++++--- src/ImageSharp/Formats/Jpeg/JpegMetaData.cs | 4 +- src/ImageSharp/Formats/Png/PngFormat.cs | 18 ++++++--- src/ImageSharp/Formats/Png/PngMetaData.cs | 4 +- .../MetaData/IImageFormatFrameMetaData.cs | 13 ------- .../MetaData/IImageFormatMetaData.cs | 13 ------- src/ImageSharp/MetaData/ImageFrameMetaData.cs | 26 ++++++++----- src/ImageSharp/MetaData/ImageMetaData.cs | 22 ++++++----- .../Formats/Gif/GifEncoderTests.cs | 8 ++-- .../MetaData/ImageFrameMetaDataTests.cs | 2 +- 18 files changed, 126 insertions(+), 127 deletions(-) delete mode 100644 src/ImageSharp/Formats/ImageFormatBase{T}.cs delete mode 100644 src/ImageSharp/MetaData/IImageFormatFrameMetaData.cs delete mode 100644 src/ImageSharp/MetaData/IImageFormatMetaData.cs diff --git a/src/ImageSharp/Formats/Bmp/BmpFormat.cs b/src/ImageSharp/Formats/Bmp/BmpFormat.cs index de3f6f3f4..665f492da 100644 --- a/src/ImageSharp/Formats/Bmp/BmpFormat.cs +++ b/src/ImageSharp/Formats/Bmp/BmpFormat.cs @@ -8,22 +8,30 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// /// Registers the image encoders, decoders and mime type detectors for the bmp format. /// - internal sealed class BmpFormat : ImageFormatBase + internal sealed class BmpFormat : IImageFormat { private BmpFormat() { } + /// + /// Gets the current instance. + /// + public static BmpFormat Instance { get; } = new BmpFormat(); + + /// + public string Name => "BMP"; + /// - public override string Name => "BMP"; + public string DefaultMimeType => "image/bmp"; /// - public override string DefaultMimeType => "image/bmp"; + public IEnumerable MimeTypes => BmpConstants.MimeTypes; /// - public override IEnumerable MimeTypes => BmpConstants.MimeTypes; + public IEnumerable FileExtensions => BmpConstants.FileExtensions; /// - public override IEnumerable FileExtensions => BmpConstants.FileExtensions; + public BmpMetaData CreateDefaultFormatMetaData() => new BmpMetaData(); } } \ No newline at end of file diff --git a/src/ImageSharp/Formats/Bmp/BmpMetaData.cs b/src/ImageSharp/Formats/Bmp/BmpMetaData.cs index 1e350200a..aa60f3866 100644 --- a/src/ImageSharp/Formats/Bmp/BmpMetaData.cs +++ b/src/ImageSharp/Formats/Bmp/BmpMetaData.cs @@ -1,14 +1,12 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.MetaData; - namespace SixLabors.ImageSharp.Formats.Bmp { /// /// Provides Bmp specific metadata information for the image. /// - public class BmpMetaData : IImageFormatMetaData + public class BmpMetaData { // TODO: Analyse what properties we would like to preserve. } diff --git a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs index 20f2f1d33..7a880b0f9 100644 --- a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs +++ b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs @@ -143,7 +143,7 @@ namespace SixLabors.ImageSharp.Formats.Gif for (int i = 0; i < image.Frames.Count; i++) { ImageFrame frame = image.Frames[i]; - GifFrameMetaData frameMetaData = frame.MetaData.GetOrAddFormatMetaData(GifFormat.Instance); + GifFrameMetaData frameMetaData = frame.MetaData.GetOrAddFormatMetaData(GifFormat.Instance); this.WriteGraphicalControlExtension(frameMetaData, transparencyIndex, stream); this.WriteImageDescriptor(frame, false, stream); @@ -169,7 +169,7 @@ namespace SixLabors.ImageSharp.Formats.Gif GifFrameMetaData previousMeta = null; foreach (ImageFrame frame in image.Frames) { - GifFrameMetaData meta = frame.MetaData.GetOrAddFormatMetaData(GifFormat.Instance); + GifFrameMetaData meta = frame.MetaData.GetOrAddFormatMetaData(GifFormat.Instance); if (quantized is null) { // Allow each frame to be encoded at whatever color depth the frame designates if set. diff --git a/src/ImageSharp/Formats/Gif/GifFormat.cs b/src/ImageSharp/Formats/Gif/GifFormat.cs index 2d14abb44..f91269ced 100644 --- a/src/ImageSharp/Formats/Gif/GifFormat.cs +++ b/src/ImageSharp/Formats/Gif/GifFormat.cs @@ -8,22 +8,33 @@ namespace SixLabors.ImageSharp.Formats.Gif /// /// Registers the image encoders, decoders and mime type detectors for the gif format. /// - internal sealed class GifFormat : ImageFormatBase + internal sealed class GifFormat : IImageFormat { private GifFormat() { } + /// + /// Gets the current instance. + /// + public static GifFormat Instance { get; } = new GifFormat(); + + /// + public string Name => "GIF"; + + /// + public string DefaultMimeType => "image/gif"; + /// - public override string Name => "GIF"; + public IEnumerable MimeTypes => GifConstants.MimeTypes; /// - public override string DefaultMimeType => "image/gif"; + public IEnumerable FileExtensions => GifConstants.FileExtensions; /// - public override IEnumerable MimeTypes => GifConstants.MimeTypes; + public GifMetaData CreateDefaultFormatMetaData() => new GifMetaData(); /// - public override IEnumerable FileExtensions => GifConstants.FileExtensions; + public GifFrameMetaData CreateDefaultFormatFrameMetaData() => new GifFrameMetaData(); } } \ No newline at end of file diff --git a/src/ImageSharp/Formats/Gif/GifFrameMetaData.cs b/src/ImageSharp/Formats/Gif/GifFrameMetaData.cs index a7b68e6e8..cc04d4831 100644 --- a/src/ImageSharp/Formats/Gif/GifFrameMetaData.cs +++ b/src/ImageSharp/Formats/Gif/GifFrameMetaData.cs @@ -1,14 +1,12 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.MetaData; - namespace SixLabors.ImageSharp.Formats.Gif { /// /// Provides Gif specific metadata information for the image frame. /// - public class GifFrameMetaData : IImageFormatFrameMetaData + public class GifFrameMetaData { /// /// Gets or sets the length of the color table for paletted images. diff --git a/src/ImageSharp/Formats/Gif/GifMetaData.cs b/src/ImageSharp/Formats/Gif/GifMetaData.cs index cc0716ec5..f58f5dff3 100644 --- a/src/ImageSharp/Formats/Gif/GifMetaData.cs +++ b/src/ImageSharp/Formats/Gif/GifMetaData.cs @@ -1,14 +1,12 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.MetaData; - namespace SixLabors.ImageSharp.Formats.Gif { /// /// Provides Gif specific metadata information for the image. /// - public class GifMetaData : IImageFormatMetaData + public class GifMetaData { /// /// Gets or sets the number of times any animation is repeated. diff --git a/src/ImageSharp/Formats/IImageFormat.cs b/src/ImageSharp/Formats/IImageFormat.cs index 15bdc73a8..972035275 100644 --- a/src/ImageSharp/Formats/IImageFormat.cs +++ b/src/ImageSharp/Formats/IImageFormat.cs @@ -6,7 +6,37 @@ using System.Collections.Generic; namespace SixLabors.ImageSharp.Formats { /// - /// Describes an image format. + /// Defines the contract for an image format containing metadata with multiple frames. + /// + /// The type of format metadata. + /// The type of format frame metadata. + public interface IImageFormat : IImageFormat + where TFormatMetaData : class + where TFormatFrameMetaData : class + { + /// + /// Creates a default instance of the format frame metadata. + /// + /// The . + TFormatFrameMetaData CreateDefaultFormatFrameMetaData(); + } + + /// + /// Defines the contract for an image format containing metadata. + /// + /// The type of format metadata. + public interface IImageFormat : IImageFormat + where TFormatMetaData : class + { + /// + /// Creates a default instance of the format metadata. + /// + /// The . + TFormatMetaData CreateDefaultFormatMetaData(); + } + + /// + /// Defines the contract for an image format. /// public interface IImageFormat { diff --git a/src/ImageSharp/Formats/ImageFormatBase{T}.cs b/src/ImageSharp/Formats/ImageFormatBase{T}.cs deleted file mode 100644 index 85273db2b..000000000 --- a/src/ImageSharp/Formats/ImageFormatBase{T}.cs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.Collections.Generic; - -namespace SixLabors.ImageSharp.Formats -{ - /// - /// The base class for all image formats. - /// Inheriting classes should implement the singleton pattern by creating a private constructor. - /// - /// The type of image format. - public abstract class ImageFormatBase : IImageFormat - where T : class, IImageFormat - { - private static readonly Lazy Lazy = new Lazy(CreateInstance); - - /// - /// Gets the current instance. - /// - public static T Instance => Lazy.Value; - - /// - public abstract string Name { get; } - - /// - public abstract string DefaultMimeType { get; } - - /// - public abstract IEnumerable MimeTypes { get; } - - /// - public abstract IEnumerable FileExtensions { get; } - - private static T CreateInstance() => (T)Activator.CreateInstance(typeof(T), true); - } -} diff --git a/src/ImageSharp/Formats/Jpeg/JpegFormat.cs b/src/ImageSharp/Formats/Jpeg/JpegFormat.cs index 21757dcb3..94c0895b9 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegFormat.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegFormat.cs @@ -8,22 +8,30 @@ namespace SixLabors.ImageSharp.Formats.Jpeg /// /// Registers the image encoders, decoders and mime type detectors for the jpeg format. /// - internal sealed class JpegFormat : ImageFormatBase + internal sealed class JpegFormat : IImageFormat { private JpegFormat() { } + /// + /// Gets the current instance. + /// + public static JpegFormat Instance { get; } = new JpegFormat(); + + /// + public string Name => "JPEG"; + /// - public override string Name => "JPEG"; + public string DefaultMimeType => "image/jpeg"; /// - public override string DefaultMimeType => "image/jpeg"; + public IEnumerable MimeTypes => JpegConstants.MimeTypes; /// - public override IEnumerable MimeTypes => JpegConstants.MimeTypes; + public IEnumerable FileExtensions => JpegConstants.FileExtensions; /// - public override IEnumerable FileExtensions => JpegConstants.FileExtensions; + public JpegMetaData CreateDefaultFormatMetaData() => new JpegMetaData(); } } \ No newline at end of file diff --git a/src/ImageSharp/Formats/Jpeg/JpegMetaData.cs b/src/ImageSharp/Formats/Jpeg/JpegMetaData.cs index eec0efa80..b05f9fa15 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegMetaData.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegMetaData.cs @@ -1,14 +1,12 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.MetaData; - namespace SixLabors.ImageSharp.Formats.Jpeg { /// /// Provides Jpeg specific metadata information for the image. /// - public class JpegMetaData : IImageFormatMetaData + public class JpegMetaData { // TODO: Analyse what properties we would like to preserve. } diff --git a/src/ImageSharp/Formats/Png/PngFormat.cs b/src/ImageSharp/Formats/Png/PngFormat.cs index 00ebbde52..b5223cb5a 100644 --- a/src/ImageSharp/Formats/Png/PngFormat.cs +++ b/src/ImageSharp/Formats/Png/PngFormat.cs @@ -8,22 +8,30 @@ namespace SixLabors.ImageSharp.Formats.Png /// /// Registers the image encoders, decoders and mime type detectors for the png format. /// - internal sealed class PngFormat : ImageFormatBase + internal sealed class PngFormat : IImageFormat { private PngFormat() { } + /// + /// Gets the current instance. + /// + public static PngFormat Instance { get; } = new PngFormat(); + + /// + public string Name => "PNG"; + /// - public override string Name => "PNG"; + public string DefaultMimeType => "image/png"; /// - public override string DefaultMimeType => "image/png"; + public IEnumerable MimeTypes => PngConstants.MimeTypes; /// - public override IEnumerable MimeTypes => PngConstants.MimeTypes; + public IEnumerable FileExtensions => PngConstants.FileExtensions; /// - public override IEnumerable FileExtensions => PngConstants.FileExtensions; + public PngMetaData CreateDefaultFormatMetaData() => new PngMetaData(); } } \ No newline at end of file diff --git a/src/ImageSharp/Formats/Png/PngMetaData.cs b/src/ImageSharp/Formats/Png/PngMetaData.cs index 1d76cf580..90dbb83b6 100644 --- a/src/ImageSharp/Formats/Png/PngMetaData.cs +++ b/src/ImageSharp/Formats/Png/PngMetaData.cs @@ -1,14 +1,12 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.MetaData; - namespace SixLabors.ImageSharp.Formats.Png { /// /// Provides Png specific metadata information for the image. /// - public class PngMetaData : IImageFormatMetaData + public class PngMetaData { // TODO: Analyse what properties we would like to preserve. } diff --git a/src/ImageSharp/MetaData/IImageFormatFrameMetaData.cs b/src/ImageSharp/MetaData/IImageFormatFrameMetaData.cs deleted file mode 100644 index 5df6fa433..000000000 --- a/src/ImageSharp/MetaData/IImageFormatFrameMetaData.cs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -namespace SixLabors.ImageSharp.MetaData -{ - /// - /// Encapsulates the format specific metadata of an image frame. - /// This interface exists to allow type saftey and avoid the performance overhead of parsing attributes. - /// - public interface IImageFormatFrameMetaData - { - } -} \ No newline at end of file diff --git a/src/ImageSharp/MetaData/IImageFormatMetaData.cs b/src/ImageSharp/MetaData/IImageFormatMetaData.cs deleted file mode 100644 index ded8df801..000000000 --- a/src/ImageSharp/MetaData/IImageFormatMetaData.cs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -namespace SixLabors.ImageSharp.MetaData -{ - /// - /// Encapsulates the format specific metadata of an image. - /// This interface exists to allow type saftey and avoid the performance overhead of parsing attributes. - /// - public interface IImageFormatMetaData - { - } -} \ No newline at end of file diff --git a/src/ImageSharp/MetaData/ImageFrameMetaData.cs b/src/ImageSharp/MetaData/ImageFrameMetaData.cs index 31bad29b8..07d4bdb05 100644 --- a/src/ImageSharp/MetaData/ImageFrameMetaData.cs +++ b/src/ImageSharp/MetaData/ImageFrameMetaData.cs @@ -12,7 +12,7 @@ namespace SixLabors.ImageSharp.MetaData /// public sealed class ImageFrameMetaData { - private readonly Dictionary metaData = new Dictionary(); + private readonly Dictionary metaData = new Dictionary(); /// /// Initializes a new instance of the class. @@ -32,7 +32,7 @@ namespace SixLabors.ImageSharp.MetaData { DebugGuard.NotNull(other, nameof(other)); - foreach (KeyValuePair meta in other.metaData) + foreach (KeyValuePair meta in other.metaData) { this.metaData.Add(meta.Key, meta.Value); } @@ -47,12 +47,16 @@ namespace SixLabors.ImageSharp.MetaData /// /// Adds or updates the specified key and value to the . /// + /// The type of format metadata. + /// The type of format frame metadata. /// 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 AddOrUpdateFormatMetaData(IImageFormat key, IImageFormatFrameMetaData value) + public void AddOrUpdateFormatMetaData(IImageFormat key, TFormatFrameMetaData value) + where TFormatMetaData : class + where TFormatFrameMetaData : class { // Don't think this needs to be threadsafe. Guard.NotNull(value, nameof(value)); @@ -62,20 +66,22 @@ namespace SixLabors.ImageSharp.MetaData /// /// Gets the metadata value associated with the specified key. /// - /// The type of metadata. + /// The type of format metadata. + /// The type of format frame metadata. /// The key of the value to get. /// - /// The . + /// The . /// - public T GetOrAddFormatMetaData(IImageFormat key) - where T : IImageFormatFrameMetaData, new() + public TFormatFrameMetaData GetOrAddFormatMetaData(IImageFormat key) + where TFormatMetaData : class + where TFormatFrameMetaData : class { - if (this.metaData.TryGetValue(key, out IImageFormatFrameMetaData meta)) + if (this.metaData.TryGetValue(key, out object meta)) { - return (T)meta; + return (TFormatFrameMetaData)meta; } - var newMeta = new T(); + TFormatFrameMetaData newMeta = key.CreateDefaultFormatFrameMetaData(); this.AddOrUpdateFormatMetaData(key, newMeta); return newMeta; } diff --git a/src/ImageSharp/MetaData/ImageMetaData.cs b/src/ImageSharp/MetaData/ImageMetaData.cs index d907e8b8a..aa084728c 100644 --- a/src/ImageSharp/MetaData/ImageMetaData.cs +++ b/src/ImageSharp/MetaData/ImageMetaData.cs @@ -26,7 +26,7 @@ namespace SixLabors.ImageSharp.MetaData /// public const double DefaultVerticalResolution = 96; - private readonly Dictionary metaData = new Dictionary(); + private readonly Dictionary metaData = new Dictionary(); private double horizontalResolution; private double verticalResolution; @@ -52,7 +52,7 @@ namespace SixLabors.ImageSharp.MetaData this.VerticalResolution = other.VerticalResolution; this.ResolutionUnits = other.ResolutionUnits; - foreach (KeyValuePair meta in other.metaData) + foreach (KeyValuePair meta in other.metaData) { this.metaData.Add(meta.Key, meta.Value); } @@ -134,12 +134,14 @@ namespace SixLabors.ImageSharp.MetaData /// /// Adds or updates the specified key and value to the . /// + /// The type of format metadata. /// 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 AddOrUpdateFormatMetaData(IImageFormat key, IImageFormatMetaData value) + public void AddOrUpdateFormatMetaData(IImageFormat key, TFormatMetaData value) + where TFormatMetaData : class { // Don't think this needs to be threadsafe. Guard.NotNull(value, nameof(value)); @@ -149,20 +151,20 @@ namespace SixLabors.ImageSharp.MetaData /// /// Gets the metadata value associated with the specified key. /// - /// The type of metadata. + /// The type of metadata. /// The key of the value to get. /// - /// The . + /// The . /// - public T GetOrAddFormatMetaData(IImageFormat key) - where T : IImageFormatMetaData, new() + public TFormatMetaData GetOrAddFormatMetaData(IImageFormat key) + where TFormatMetaData : class { - if (this.metaData.TryGetValue(key, out IImageFormatMetaData meta)) + if (this.metaData.TryGetValue(key, out object meta)) { - return (T)meta; + return (TFormatMetaData)meta; } - var newMeta = new T(); + TFormatMetaData newMeta = key.CreateDefaultFormatMetaData(); this.AddOrUpdateFormatMetaData(key, newMeta); return newMeta; } diff --git a/tests/ImageSharp.Tests/Formats/Gif/GifEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Gif/GifEncoderTests.cs index 4ddcded5e..0c32689f0 100644 --- a/tests/ImageSharp.Tests/Formats/Gif/GifEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Gif/GifEncoderTests.cs @@ -189,8 +189,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif inStream.Position = 0; var image = Image.Load(inStream); - GifMetaData metaData = image.MetaData.GetOrAddFormatMetaData(GifFormat.Instance); - GifFrameMetaData frameMetaData = image.Frames.RootFrame.MetaData.GetOrAddFormatMetaData(GifFormat.Instance); + GifMetaData metaData = image.MetaData.GetOrAddFormatMetaData(GifFormat.Instance); + GifFrameMetaData frameMetaData = image.Frames.RootFrame.MetaData.GetOrAddFormatMetaData(GifFormat.Instance); GifColorTableMode colorMode = metaData.ColorTableMode; var encoder = new GifEncoder() { @@ -212,8 +212,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif for (int i = 0; i < image.Frames.Count; i++) { - GifFrameMetaData ifm = image.Frames[i].MetaData.GetOrAddFormatMetaData(GifFormat.Instance); - GifFrameMetaData cifm = clone.Frames[i].MetaData.GetOrAddFormatMetaData(GifFormat.Instance); + GifFrameMetaData ifm = image.Frames[i].MetaData.GetOrAddFormatMetaData(GifFormat.Instance); + GifFrameMetaData cifm = clone.Frames[i].MetaData.GetOrAddFormatMetaData(GifFormat.Instance); Assert.Equal(ifm.ColorTableLength, cifm.ColorTableLength); Assert.Equal(ifm.FrameDelay, cifm.FrameDelay); diff --git a/tests/ImageSharp.Tests/MetaData/ImageFrameMetaDataTests.cs b/tests/ImageSharp.Tests/MetaData/ImageFrameMetaDataTests.cs index 00d03dce4..54441f0cb 100644 --- a/tests/ImageSharp.Tests/MetaData/ImageFrameMetaDataTests.cs +++ b/tests/ImageSharp.Tests/MetaData/ImageFrameMetaDataTests.cs @@ -30,7 +30,7 @@ namespace SixLabors.ImageSharp.Tests metaData.AddOrUpdateFormatMetaData(GifFormat.Instance, gifFrameMetaData); var clone = new ImageFrameMetaData(metaData); - GifFrameMetaData cloneGifFrameMetaData = clone.GetOrAddFormatMetaData(GifFormat.Instance); + GifFrameMetaData cloneGifFrameMetaData = clone.GetOrAddFormatMetaData(GifFormat.Instance); Assert.Equal(frameDelay, cloneGifFrameMetaData.FrameDelay); Assert.Equal(colorTableLength, cloneGifFrameMetaData.ColorTableLength); From 34c0bbeee50c8fb43b610f6191848394214f5ea5 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Tue, 11 Sep 2018 00:31:35 +0200 Subject: [PATCH 06/11] minor code cleanup --- src/ImageSharp/Formats/IImageFormat.cs | 58 +++++++++---------- src/ImageSharp/MetaData/ImageFrameMetaData.cs | 14 +++-- src/ImageSharp/MetaData/ImageMetaData.cs | 10 ++-- 3 files changed, 42 insertions(+), 40 deletions(-) diff --git a/src/ImageSharp/Formats/IImageFormat.cs b/src/ImageSharp/Formats/IImageFormat.cs index 972035275..94191c149 100644 --- a/src/ImageSharp/Formats/IImageFormat.cs +++ b/src/ImageSharp/Formats/IImageFormat.cs @@ -6,26 +6,36 @@ using System.Collections.Generic; namespace SixLabors.ImageSharp.Formats { /// - /// Defines the contract for an image format containing metadata with multiple frames. + /// Defines the contract for an image format. /// - /// The type of format metadata. - /// The type of format frame metadata. - public interface IImageFormat : IImageFormat - where TFormatMetaData : class - where TFormatFrameMetaData : class + public interface IImageFormat { /// - /// Creates a default instance of the format frame metadata. + /// Gets the name that describes this image format. /// - /// The . - TFormatFrameMetaData CreateDefaultFormatFrameMetaData(); + string Name { get; } + + /// + /// Gets the default mimetype that the image foramt uses + /// + string DefaultMimeType { get; } + + /// + /// Gets all the mimetypes that have been used by this image foramt. + /// + IEnumerable MimeTypes { get; } + + /// + /// Gets the file extensions this image format commonly uses. + /// + IEnumerable FileExtensions { get; } } /// /// Defines the contract for an image format containing metadata. /// /// The type of format metadata. - public interface IImageFormat : IImageFormat + public interface IImageFormat : IImageFormat where TFormatMetaData : class { /// @@ -36,28 +46,18 @@ namespace SixLabors.ImageSharp.Formats } /// - /// Defines the contract for an image format. + /// Defines the contract for an image format containing metadata with multiple frames. /// - public interface IImageFormat + /// The type of format metadata. + /// The type of format frame metadata. + public interface IImageFormat : IImageFormat + where TFormatMetaData : class + where TFormatFrameMetaData : class { /// - /// Gets the name that describes this image format. - /// - string Name { get; } - - /// - /// Gets the default mimetype that the image foramt uses - /// - string DefaultMimeType { get; } - - /// - /// Gets all the mimetypes that have been used by this image foramt. - /// - IEnumerable MimeTypes { get; } - - /// - /// Gets the file extensions this image format commonly uses. + /// Creates a default instance of the format frame metadata. /// - IEnumerable FileExtensions { get; } + /// The . + TFormatFrameMetaData CreateDefaultFormatFrameMetaData(); } } \ No newline at end of file diff --git a/src/ImageSharp/MetaData/ImageFrameMetaData.cs b/src/ImageSharp/MetaData/ImageFrameMetaData.cs index 07d4bdb05..908a0e624 100644 --- a/src/ImageSharp/MetaData/ImageFrameMetaData.cs +++ b/src/ImageSharp/MetaData/ImageFrameMetaData.cs @@ -12,7 +12,7 @@ namespace SixLabors.ImageSharp.MetaData /// public sealed class ImageFrameMetaData { - private readonly Dictionary metaData = new Dictionary(); + private readonly Dictionary formatMetaData = new Dictionary(); /// /// Initializes a new instance of the class. @@ -32,9 +32,9 @@ namespace SixLabors.ImageSharp.MetaData { DebugGuard.NotNull(other, nameof(other)); - foreach (KeyValuePair meta in other.metaData) + foreach (KeyValuePair meta in other.formatMetaData) { - this.metaData.Add(meta.Key, meta.Value); + this.formatMetaData.Add(meta.Key, meta.Value); } } @@ -54,13 +54,15 @@ namespace SixLabors.ImageSharp.MetaData /// key is null. /// value is null. /// An element with the same key already exists in the . - public void AddOrUpdateFormatMetaData(IImageFormat key, TFormatFrameMetaData value) + public void AddOrUpdateFormatMetaData( + IImageFormat key, + TFormatFrameMetaData value) where TFormatMetaData : class where TFormatFrameMetaData : class { // Don't think this needs to be threadsafe. Guard.NotNull(value, nameof(value)); - this.metaData[key] = value; + this.formatMetaData[key] = value; } /// @@ -76,7 +78,7 @@ namespace SixLabors.ImageSharp.MetaData where TFormatMetaData : class where TFormatFrameMetaData : class { - if (this.metaData.TryGetValue(key, out object meta)) + if (this.formatMetaData.TryGetValue(key, out object meta)) { return (TFormatFrameMetaData)meta; } diff --git a/src/ImageSharp/MetaData/ImageMetaData.cs b/src/ImageSharp/MetaData/ImageMetaData.cs index aa084728c..74c00cf8a 100644 --- a/src/ImageSharp/MetaData/ImageMetaData.cs +++ b/src/ImageSharp/MetaData/ImageMetaData.cs @@ -26,7 +26,7 @@ namespace SixLabors.ImageSharp.MetaData /// public const double DefaultVerticalResolution = 96; - private readonly Dictionary metaData = new Dictionary(); + private readonly Dictionary formatMetaData = new Dictionary(); private double horizontalResolution; private double verticalResolution; @@ -52,9 +52,9 @@ namespace SixLabors.ImageSharp.MetaData this.VerticalResolution = other.VerticalResolution; this.ResolutionUnits = other.ResolutionUnits; - foreach (KeyValuePair meta in other.metaData) + foreach (KeyValuePair meta in other.formatMetaData) { - this.metaData.Add(meta.Key, meta.Value); + this.formatMetaData.Add(meta.Key, meta.Value); } foreach (ImageProperty property in other.Properties) @@ -145,7 +145,7 @@ namespace SixLabors.ImageSharp.MetaData { // Don't think this needs to be threadsafe. Guard.NotNull(value, nameof(value)); - this.metaData[key] = value; + this.formatMetaData[key] = value; } /// @@ -159,7 +159,7 @@ namespace SixLabors.ImageSharp.MetaData public TFormatMetaData GetOrAddFormatMetaData(IImageFormat key) where TFormatMetaData : class { - if (this.metaData.TryGetValue(key, out object meta)) + if (this.formatMetaData.TryGetValue(key, out object meta)) { return (TFormatMetaData)meta; } From df62dd66ddd4e061d22fd0e25f0caa35daca6150 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Tue, 11 Sep 2018 11:41:52 +0100 Subject: [PATCH 07/11] Use metadata as fallback forpng encoder options. --- .../Formats/Png/IPngEncoderOptions.cs | 18 ++---- src/ImageSharp/Formats/Png/PngChunkType.cs | 52 ++++++++-------- src/ImageSharp/Formats/Png/PngDecoderCore.cs | 58 ++++++++++++++---- src/ImageSharp/Formats/Png/PngEncoder.cs | 14 ++--- src/ImageSharp/Formats/Png/PngEncoderCore.cs | 61 ++++++++++--------- src/ImageSharp/Formats/Png/PngMetaData.cs | 18 +++++- 6 files changed, 129 insertions(+), 92 deletions(-) diff --git a/src/ImageSharp/Formats/Png/IPngEncoderOptions.cs b/src/ImageSharp/Formats/Png/IPngEncoderOptions.cs index f3231fa22..77bc9f7a0 100644 --- a/src/ImageSharp/Formats/Png/IPngEncoderOptions.cs +++ b/src/ImageSharp/Formats/Png/IPngEncoderOptions.cs @@ -14,12 +14,12 @@ namespace SixLabors.ImageSharp.Formats.Png /// Gets the number of bits per sample or per palette index (not per pixel). /// Not all values are allowed for all values. /// - PngBitDepth BitDepth { get; } + PngBitDepth? BitDepth { get; } /// /// Gets the color type /// - PngColorType ColorType { get; } + PngColorType? ColorType { get; } /// /// Gets the filter method. @@ -33,15 +33,13 @@ namespace SixLabors.ImageSharp.Formats.Png int CompressionLevel { get; } /// - /// Gets the gamma value, that will be written - /// the the stream, when the property - /// is set to true. The default value is 2.2F. + /// Gets the gamma value, that will be written the the image. /// /// The gamma value of the image. - float Gamma { get; } + float? Gamma { get; } /// - /// Gets quantizer for reducing the color count. + /// Gets the quantizer for reducing the color count. /// IQuantizer Quantizer { get; } @@ -49,11 +47,5 @@ namespace SixLabors.ImageSharp.Formats.Png /// Gets the transparency threshold. /// byte Threshold { get; } - - /// - /// Gets a value indicating whether this instance should write - /// gamma information to the stream. The default value is false. - /// - bool WriteGamma { get; } } } \ No newline at end of file diff --git a/src/ImageSharp/Formats/Png/PngChunkType.cs b/src/ImageSharp/Formats/Png/PngChunkType.cs index e0844ca6b..7654c1701 100644 --- a/src/ImageSharp/Formats/Png/PngChunkType.cs +++ b/src/ImageSharp/Formats/Png/PngChunkType.cs @@ -8,58 +8,58 @@ namespace SixLabors.ImageSharp.Formats.Png /// internal enum PngChunkType : uint { - /// - /// The first chunk in a png file. Can only exists once. Contains - /// common information like the width and the height of the image or - /// the used compression method. - /// - Header = 0x49484452U, // IHDR - - /// - /// The PLTE chunk contains from 1 to 256 palette entries, each a three byte - /// series in the RGB format. - /// - Palette = 0x504C5445U, // PLTE - /// /// The IDAT chunk contains the actual image data. The image can contains more /// than one chunk of this type. All chunks together are the whole image. /// - Data = 0x49444154U, // IDAT + Data = 0x49444154U, /// /// This chunk must appear last. It marks the end of the PNG data stream. /// The chunk's data field is empty. /// - End = 0x49454E44U, // IEND + End = 0x49454E44U, /// - /// This chunk specifies that the image uses simple transparency: - /// either alpha values associated with palette entries (for indexed-color images) - /// or a single transparent color (for grayscale and true color images). + /// The first chunk in a png file. Can only exists once. Contains + /// common information like the width and the height of the image or + /// the used compression method. /// - PaletteAlpha = 0x74524E53U, // tRNS + Header = 0x49484452U, /// - /// Textual information that the encoder wishes to record with the image can be stored in - /// tEXt chunks. Each tEXt chunk contains a keyword and a text string. + /// The PLTE chunk contains from 1 to 256 palette entries, each a three byte + /// series in the RGB format. + /// + Palette = 0x504C5445U, + + /// + /// The eXIf data chunk which contains the Exif profile. /// - Text = 0x74455874U, // tEXt + Exif = 0x65584966U, /// /// This chunk specifies the relationship between the image samples and the desired /// display output intensity. /// - Gamma = 0x67414D41U, // gAMA + Gamma = 0x67414D41U, /// /// The pHYs chunk specifies the intended pixel size or aspect ratio for display of the image. /// - Physical = 0x70485973U, // pHYs + Physical = 0x70485973U, /// - /// The data chunk which contains the Exif profile. + /// Textual information that the encoder wishes to record with the image can be stored in + /// tEXt chunks. Each tEXt chunk contains a keyword and a text string. + /// + Text = 0x74455874U, + + /// + /// This chunk specifies that the image uses simple transparency: + /// either alpha values associated with palette entries (for indexed-color images) + /// or a single transparent color (for grayscale and true color images). /// - Exif = 0x65584966U // eXIf + PaletteAlpha = 0x74524E53U } } \ No newline at end of file diff --git a/src/ImageSharp/Formats/Png/PngDecoderCore.cs b/src/ImageSharp/Formats/Png/PngDecoderCore.cs index be1914174..4bc483301 100644 --- a/src/ImageSharp/Formats/Png/PngDecoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngDecoderCore.cs @@ -216,7 +216,9 @@ namespace SixLabors.ImageSharp.Formats.Png public Image Decode(Stream stream) where TPixel : struct, IPixel { - var metadata = new ImageMetaData(); + var metaData = new ImageMetaData(); + var pngMetaData = new PngMetaData(); + metaData.AddOrUpdateFormatMetaData(PngFormat.Instance, pngMetaData); this.currentStream = stream; this.currentStream.Skip(8); Image image = null; @@ -231,16 +233,19 @@ namespace SixLabors.ImageSharp.Formats.Png switch (chunk.Type) { case PngChunkType.Header: - this.ReadHeaderChunk(chunk.Data.Array); + this.ReadHeaderChunk(pngMetaData, chunk.Data.Array); this.ValidateHeader(); break; case PngChunkType.Physical: - this.ReadPhysicalChunk(metadata, chunk.Data.GetSpan()); + this.ReadPhysicalChunk(metaData, chunk.Data.GetSpan()); + break; + case PngChunkType.Gamma: + this.ReadGammaChunk(pngMetaData, chunk.Data.GetSpan()); break; case PngChunkType.Data: if (image is null) { - this.InitializeImage(metadata, out image); + this.InitializeImage(metaData, out image); } deframeStream.AllocateNewBytes(chunk.Length); @@ -259,14 +264,14 @@ namespace SixLabors.ImageSharp.Formats.Png this.AssignTransparentMarkers(alpha); break; case PngChunkType.Text: - this.ReadTextChunk(metadata, chunk.Data.Array, chunk.Length); + this.ReadTextChunk(metaData, chunk.Data.Array, chunk.Length); break; case PngChunkType.Exif: if (!this.ignoreMetadata) { byte[] exifData = new byte[chunk.Length]; Buffer.BlockCopy(chunk.Data.Array, 0, exifData, 0, chunk.Length); - metadata.ExifProfile = new ExifProfile(exifData); + metaData.ExifProfile = new ExifProfile(exifData); } break; @@ -302,7 +307,9 @@ namespace SixLabors.ImageSharp.Formats.Png /// The containing image data. public IImageInfo Identify(Stream stream) { - var metadata = new ImageMetaData(); + var metaData = new ImageMetaData(); + var pngMetaData = new PngMetaData(); + metaData.AddOrUpdateFormatMetaData(PngFormat.Instance, pngMetaData); this.currentStream = stream; this.currentStream.Skip(8); try @@ -314,17 +321,20 @@ namespace SixLabors.ImageSharp.Formats.Png switch (chunk.Type) { case PngChunkType.Header: - this.ReadHeaderChunk(chunk.Data.Array); + this.ReadHeaderChunk(pngMetaData, chunk.Data.Array); this.ValidateHeader(); break; case PngChunkType.Physical: - this.ReadPhysicalChunk(metadata, chunk.Data.GetSpan()); + this.ReadPhysicalChunk(metaData, chunk.Data.GetSpan()); + break; + case PngChunkType.Gamma: + this.ReadGammaChunk(pngMetaData, chunk.Data.GetSpan()); break; case PngChunkType.Data: this.SkipChunkDataAndCrc(chunk); break; case PngChunkType.Text: - this.ReadTextChunk(metadata, chunk.Data.Array, chunk.Length); + this.ReadTextChunk(metaData, chunk.Data.Array, chunk.Length); break; case PngChunkType.End: this.isEndChunkReached = true; @@ -348,7 +358,7 @@ namespace SixLabors.ImageSharp.Formats.Png throw new ImageFormatException("PNG Image does not contain a header chunk"); } - return new ImageInfo(new PixelTypeInfo(this.CalculateBitsPerPixel()), this.header.Width, this.header.Height, metadata); + return new ImageInfo(new PixelTypeInfo(this.CalculateBitsPerPixel()), this.header.Width, this.header.Height, metaData); } /// @@ -427,6 +437,18 @@ namespace SixLabors.ImageSharp.Formats.Png metadata.VerticalResolution = vResolution; } + /// + /// Reads the data chunk containing gamma data. + /// + /// The metadata to read to. + /// The data containing physical data. + private void ReadGammaChunk(PngMetaData pngMetadata, ReadOnlySpan data) + { + // The value is encoded as a 4-byte unsigned integer, representing gamma times 100000. + // For example, a gamma of 1/2.2 would be stored as 45455. + pngMetadata.Gamma = BinaryPrimitives.ReadUInt32BigEndian(data) / 100_000F; + } + /// /// Initializes the image and various buffers needed for processing /// @@ -1267,17 +1289,27 @@ namespace SixLabors.ImageSharp.Formats.Png /// /// Reads a header chunk from the data. /// + /// The png metadata. /// The containing data. - private void ReadHeaderChunk(ReadOnlySpan data) + private void ReadHeaderChunk(PngMetaData pngMetaData, ReadOnlySpan data) { + byte bitDepth = data[8]; this.header = new PngHeader( width: BinaryPrimitives.ReadInt32BigEndian(data.Slice(0, 4)), height: BinaryPrimitives.ReadInt32BigEndian(data.Slice(4, 4)), - bitDepth: data[8], + bitDepth: bitDepth, colorType: (PngColorType)data[9], compressionMethod: data[10], filterMethod: data[11], interlaceMethod: (PngInterlaceMode)data[12]); + + // TODO: Figure out how we can determine the number of colors and support more bit depths. + if (bitDepth == 8 || bitDepth == 16) + { + pngMetaData.BitDepth = (PngBitDepth)bitDepth; + } + + pngMetaData.ColorType = this.header.ColorType; } /// diff --git a/src/ImageSharp/Formats/Png/PngEncoder.cs b/src/ImageSharp/Formats/Png/PngEncoder.cs index 109e6ad77..435d0abbc 100644 --- a/src/ImageSharp/Formats/Png/PngEncoder.cs +++ b/src/ImageSharp/Formats/Png/PngEncoder.cs @@ -4,6 +4,7 @@ using System.IO; using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; using SixLabors.ImageSharp.Processing.Processors.Quantization; namespace SixLabors.ImageSharp.Formats.Png @@ -17,12 +18,12 @@ namespace SixLabors.ImageSharp.Formats.Png /// Gets or sets the number of bits per sample or per palette index (not per pixel). /// Not all values are allowed for all values. /// - public PngBitDepth BitDepth { get; set; } = PngBitDepth.Bit8; + public PngBitDepth? BitDepth { get; set; } /// /// Gets or sets the color type. /// - public PngColorType ColorType { get; set; } = PngColorType.RgbWithAlpha; + public PngColorType? ColorType { get; set; } /// /// Gets or sets the filter method. @@ -36,18 +37,15 @@ namespace SixLabors.ImageSharp.Formats.Png public int CompressionLevel { get; set; } = 6; /// - /// Gets or sets the gamma value, that will be written - /// the the stream, when the property - /// is set to true. The default value is 2.2F. + /// Gets or sets the gamma value, that will be written the the image. /// - /// The gamma value of the image. - public float Gamma { get; set; } = 2.2F; + public float? Gamma { get; set; } /// /// Gets or sets quantizer for reducing the color count. /// Defaults to the /// - public IQuantizer Quantizer { get; set; } = new WuQuantizer(); + public IQuantizer Quantizer { get; set; } = KnownQuantizers.Wu; /// /// Gets or sets the transparency threshold. diff --git a/src/ImageSharp/Formats/Png/PngEncoderCore.cs b/src/ImageSharp/Formats/Png/PngEncoderCore.cs index ffe29aeca..9d9de71b1 100644 --- a/src/ImageSharp/Formats/Png/PngEncoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngEncoderCore.cs @@ -4,7 +4,6 @@ using System; using System.Buffers.Binary; using System.IO; -using System.Linq; using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Common.Helpers; using SixLabors.ImageSharp.Formats.Png.Filters; @@ -45,49 +44,49 @@ namespace SixLabors.ImageSharp.Formats.Png private readonly Crc32 crc = new Crc32(); /// - /// The png bit depth + /// The png filter method. /// - private readonly PngBitDepth pngBitDepth; + private readonly PngFilterMethod pngFilterMethod; /// - /// Gets or sets a value indicating whether to use 16 bit encoding for supported color types. + /// The quantizer for reducing the color count. /// - private readonly bool use16Bit; + private readonly IQuantizer quantizer; /// - /// The png color type. + /// Gets or sets the CompressionLevel value /// - private readonly PngColorType pngColorType; + private readonly int compressionLevel; /// - /// The png filter method. + /// Gets or sets the alpha threshold value /// - private readonly PngFilterMethod pngFilterMethod; + private readonly byte threshold; /// - /// The quantizer for reducing the color count. + /// Gets or sets a value indicating whether to write the gamma chunk /// - private readonly IQuantizer quantizer; + private bool writeGamma; /// - /// Gets or sets the CompressionLevel value + /// The png bit depth /// - private readonly int compressionLevel; + private PngBitDepth? pngBitDepth; /// - /// Gets or sets the Gamma value + /// Gets or sets a value indicating whether to use 16 bit encoding for supported color types. /// - private readonly float gamma; + private bool use16Bit; /// - /// Gets or sets the Threshold value + /// The png color type. /// - private readonly byte threshold; + private PngColorType? pngColorType; /// - /// Gets or sets a value indicating whether to Write Gamma + /// Gets or sets the Gamma value /// - private readonly bool writeGamma; + private float? gamma; /// /// The image width. @@ -158,14 +157,12 @@ namespace SixLabors.ImageSharp.Formats.Png { this.memoryAllocator = memoryAllocator; this.pngBitDepth = options.BitDepth; - this.use16Bit = this.pngBitDepth.Equals(PngBitDepth.Bit16); this.pngColorType = options.ColorType; this.pngFilterMethod = options.FilterMethod; this.compressionLevel = options.CompressionLevel; this.gamma = options.Gamma; this.quantizer = options.Quantizer; this.threshold = options.Threshold; - this.writeGamma = options.WriteGamma; } /// @@ -183,6 +180,16 @@ namespace SixLabors.ImageSharp.Formats.Png this.width = image.Width; this.height = image.Height; + // Always take the encoder options over the metadata values. + PngMetaData pngMetaData = image.MetaData.GetOrAddFormatMetaData(PngFormat.Instance); + this.gamma = this.gamma ?? pngMetaData.Gamma; + this.writeGamma = this.gamma > 0; + this.pngColorType = this.pngColorType ?? pngMetaData.ColorType; + + // TODO: We don't take full advantage of this information yet. + this.pngBitDepth = this.pngBitDepth ?? pngMetaData.BitDepth; + this.use16Bit = this.pngBitDepth.Equals(PngBitDepth.Bit16); + stream.Write(PngConstants.HeaderBytes, 0, PngConstants.HeaderBytes.Length); QuantizedFrame quantized = null; @@ -217,7 +224,7 @@ namespace SixLabors.ImageSharp.Formats.Png width: image.Width, height: image.Height, bitDepth: this.bitDepth, - colorType: this.pngColorType, + colorType: this.pngColorType.Value, compressionMethod: 0, // None filterMethod: 0, interlaceMethod: 0); // TODO: Can't write interlaced yet. @@ -781,10 +788,7 @@ namespace SixLabors.ImageSharp.Formats.Png /// Writes the chunk end to the stream. /// /// The containing image data. - private void WriteEndChunk(Stream stream) - { - this.WriteChunk(stream, PngChunkType.End, null); - } + private void WriteEndChunk(Stream stream) => this.WriteChunk(stream, PngChunkType.End, null); /// /// Writes a chunk to the stream. @@ -792,10 +796,7 @@ namespace SixLabors.ImageSharp.Formats.Png /// The to write to. /// The type of chunk to write. /// The containing data. - private void WriteChunk(Stream stream, PngChunkType type, byte[] data) - { - this.WriteChunk(stream, type, data, 0, data?.Length ?? 0); - } + private void WriteChunk(Stream stream, PngChunkType type, byte[] data) => this.WriteChunk(stream, type, data, 0, data?.Length ?? 0); /// /// Writes a chunk of a specified length to the stream at the given offset. diff --git a/src/ImageSharp/Formats/Png/PngMetaData.cs b/src/ImageSharp/Formats/Png/PngMetaData.cs index 90dbb83b6..1eb3cdad6 100644 --- a/src/ImageSharp/Formats/Png/PngMetaData.cs +++ b/src/ImageSharp/Formats/Png/PngMetaData.cs @@ -8,6 +8,20 @@ namespace SixLabors.ImageSharp.Formats.Png /// public class PngMetaData { - // TODO: Analyse what properties we would like to preserve. + /// + /// Gets or sets the number of bits per sample or per palette index (not per pixel). + /// Not all values are allowed for all values. + /// + public PngBitDepth BitDepth { get; set; } = PngBitDepth.Bit8; + + /// + /// Gets or sets the color type. + /// + public PngColorType ColorType { get; set; } = PngColorType.RgbWithAlpha; + + /// + /// Gets or sets the gamma value for the image. + /// + public float Gamma { get; set; } } -} +} \ No newline at end of file From 9907d78d3ee5c09eac20c8cf7b655d2a095f1466 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Tue, 11 Sep 2018 15:58:42 +0100 Subject: [PATCH 08/11] Preserve BmpBitsPerPixel --- src/ImageSharp/Formats/Bmp/BmpBitsPerPixel.cs | 6 +-- src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs | 17 +++++-- src/ImageSharp/Formats/Bmp/BmpEncoder.cs | 2 +- src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs | 17 ++++--- src/ImageSharp/Formats/Bmp/BmpMetaData.cs | 7 ++- .../Formats/Bmp/IBmpEncoderOptions.cs | 2 +- .../Formats/Bmp/BmpEncoderTests.cs | 45 +++++++++++++----- tests/ImageSharp.Tests/TestImages.cs | 1 + tests/Images/Input/Bmp/rgb32.bmp | Bin 0 -> 32566 bytes 9 files changed, 68 insertions(+), 29 deletions(-) create mode 100644 tests/Images/Input/Bmp/rgb32.bmp diff --git a/src/ImageSharp/Formats/Bmp/BmpBitsPerPixel.cs b/src/ImageSharp/Formats/Bmp/BmpBitsPerPixel.cs index 0029a6b68..618999c87 100644 --- a/src/ImageSharp/Formats/Bmp/BmpBitsPerPixel.cs +++ b/src/ImageSharp/Formats/Bmp/BmpBitsPerPixel.cs @@ -6,16 +6,16 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// /// Enumerates the available bits per pixel for bitmap. /// - public enum BmpBitsPerPixel + public enum BmpBitsPerPixel : short { /// /// 24 bits per pixel. Each pixel consists of 3 bytes. /// - Pixel24 = 3, + Pixel24 = 24, /// /// 32 bits per pixel. Each pixel consists of 4 bytes. /// - Pixel32 = 4 + Pixel32 = 32 } } \ No newline at end of file diff --git a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs index 385c79896..3bb44f1d0 100644 --- a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs +++ b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs @@ -536,6 +536,17 @@ namespace SixLabors.ImageSharp.Formats.Bmp this.metaData = meta; + short bitsPerPixel = this.infoHeader.BitsPerPixel; + var bmpMetaData = new BmpMetaData(); + this.metaData.AddOrUpdateFormatMetaData(BmpFormat.Instance, bmpMetaData); + + // We can only encode at these bit rates so far. + if (bitsPerPixel.Equals((short)BmpBitsPerPixel.Pixel24) + || bitsPerPixel.Equals((short)BmpBitsPerPixel.Pixel32)) + { + bmpMetaData.BitsPerPixel = (BmpBitsPerPixel)bitsPerPixel; + } + // skip the remaining header because we can't read those parts this.stream.Skip(skipAmount); } @@ -581,9 +592,9 @@ namespace SixLabors.ImageSharp.Formats.Bmp if (this.infoHeader.ClrUsed == 0) { - if (this.infoHeader.BitsPerPixel == 1 || - this.infoHeader.BitsPerPixel == 4 || - this.infoHeader.BitsPerPixel == 8) + if (this.infoHeader.BitsPerPixel == 1 + || this.infoHeader.BitsPerPixel == 4 + || this.infoHeader.BitsPerPixel == 8) { colorMapSize = (int)Math.Pow(2, this.infoHeader.BitsPerPixel) * 4; } diff --git a/src/ImageSharp/Formats/Bmp/BmpEncoder.cs b/src/ImageSharp/Formats/Bmp/BmpEncoder.cs index 23b01ae9e..b1a66acce 100644 --- a/src/ImageSharp/Formats/Bmp/BmpEncoder.cs +++ b/src/ImageSharp/Formats/Bmp/BmpEncoder.cs @@ -16,7 +16,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// /// Gets or sets the number of bits per pixel. /// - public BmpBitsPerPixel BitsPerPixel { get; set; } = BmpBitsPerPixel.Pixel24; + public BmpBitsPerPixel? BitsPerPixel { get; set; } /// public void Encode(Image image, Stream stream) diff --git a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs index b49b8a895..7a09a47f7 100644 --- a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs +++ b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs @@ -21,10 +21,10 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// private int padding; - private readonly BmpBitsPerPixel bitsPerPixel; - private readonly MemoryAllocator memoryAllocator; + private BmpBitsPerPixel? bitsPerPixel; + /// /// Initializes a new instance of the class. /// @@ -48,10 +48,12 @@ namespace SixLabors.ImageSharp.Formats.Bmp Guard.NotNull(image, nameof(image)); Guard.NotNull(stream, nameof(stream)); - // Cast to int will get the bytes per pixel - short bpp = (short)(8 * (int)this.bitsPerPixel); + BmpMetaData bmpMetaData = image.MetaData.GetOrAddFormatMetaData(BmpFormat.Instance); + this.bitsPerPixel = this.bitsPerPixel ?? bmpMetaData.BitsPerPixel; + + short bpp = (short)this.bitsPerPixel; int bytesPerLine = 4 * (((image.Width * bpp) + 31) / 32); - this.padding = bytesPerLine - (image.Width * (int)this.bitsPerPixel); + this.padding = bytesPerLine - (int)(image.Width * (bpp / 8F)); // Set Resolution. ImageMetaData meta = image.MetaData; @@ -145,10 +147,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp } } - private IManagedByteBuffer AllocateRow(int width, int bytesPerPixel) - { - return this.memoryAllocator.AllocatePaddedPixelRowBuffer(width, bytesPerPixel, this.padding); - } + private IManagedByteBuffer AllocateRow(int width, int bytesPerPixel) => this.memoryAllocator.AllocatePaddedPixelRowBuffer(width, bytesPerPixel, this.padding); /// /// Writes the 32bit color palette to the stream. diff --git a/src/ImageSharp/Formats/Bmp/BmpMetaData.cs b/src/ImageSharp/Formats/Bmp/BmpMetaData.cs index aa60f3866..3d678c13e 100644 --- a/src/ImageSharp/Formats/Bmp/BmpMetaData.cs +++ b/src/ImageSharp/Formats/Bmp/BmpMetaData.cs @@ -8,6 +8,11 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// public class BmpMetaData { - // TODO: Analyse what properties we would like to preserve. + /// + /// Gets or sets the number of bits per pixel. + /// + public BmpBitsPerPixel BitsPerPixel { get; set; } = BmpBitsPerPixel.Pixel24; + + // TODO: Colors used once we support encoding palette bmps. } } diff --git a/src/ImageSharp/Formats/Bmp/IBmpEncoderOptions.cs b/src/ImageSharp/Formats/Bmp/IBmpEncoderOptions.cs index 56952f035..f62504d08 100644 --- a/src/ImageSharp/Formats/Bmp/IBmpEncoderOptions.cs +++ b/src/ImageSharp/Formats/Bmp/IBmpEncoderOptions.cs @@ -12,6 +12,6 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// /// Gets the number of bits per pixel. /// - BmpBitsPerPixel BitsPerPixel { get; } + BmpBitsPerPixel? BitsPerPixel { get; } } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs index d887d23ad..c75c65691 100644 --- a/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs @@ -28,10 +28,14 @@ namespace SixLabors.ImageSharp.Tests { TestImages.Bmp.RLE, 2835, 2835, PixelResolutionUnit.PixelsPerMeter } }; - public BmpEncoderTests(ITestOutputHelper output) + public static readonly TheoryData BmpBitsPerPixelFiles = + new TheoryData { - this.Output = output; - } + { TestImages.Bmp.Car, BmpBitsPerPixel.Pixel24 }, + { TestImages.Bmp.Bit32Rgb, BmpBitsPerPixel.Pixel32 } + }; + + public BmpEncoderTests(ITestOutputHelper output) => this.Output = output; private ITestOutputHelper Output { get; } @@ -61,13 +65,35 @@ namespace SixLabors.ImageSharp.Tests } [Theory] - [WithTestPatternImages(nameof(BitsPerPixel), 24, 24, PixelTypes.Rgba32 | PixelTypes.Bgra32 | PixelTypes.Rgb24)] - public void Encode_IsNotBoundToSinglePixelType(TestImageProvider provider, BmpBitsPerPixel bitsPerPixel) - where TPixel : struct, IPixel + [MemberData(nameof(BmpBitsPerPixelFiles))] + public void Encode_PreserveBitsPerPixel(string imagePath, BmpBitsPerPixel bmpBitsPerPixel) { - TestBmpEncoderCore(provider, bitsPerPixel); + var options = new BmpEncoder(); + + var testFile = TestFile.Create(imagePath); + using (Image input = testFile.CreateImage()) + { + using (var memStream = new MemoryStream()) + { + input.Save(memStream, options); + + memStream.Position = 0; + using (var output = Image.Load(memStream)) + { + BmpMetaData meta = output.MetaData.GetOrAddFormatMetaData(BmpFormat.Instance); + + Assert.Equal(bmpBitsPerPixel, meta.BitsPerPixel); + } + } + } } + + [Theory] + [WithTestPatternImages(nameof(BitsPerPixel), 24, 24, PixelTypes.Rgba32 | PixelTypes.Bgra32 | PixelTypes.Rgb24)] + public void Encode_IsNotBoundToSinglePixelType(TestImageProvider provider, BmpBitsPerPixel bitsPerPixel) + where TPixel : struct, IPixel => TestBmpEncoderCore(provider, bitsPerPixel); + [Theory] [WithTestPatternImages(nameof(BitsPerPixel), 48, 24, PixelTypes.Rgba32)] [WithTestPatternImages(nameof(BitsPerPixel), 47, 8, PixelTypes.Rgba32)] @@ -75,10 +101,7 @@ namespace SixLabors.ImageSharp.Tests [WithSolidFilledImages(nameof(BitsPerPixel), 1, 1, 255, 100, 50, 255, PixelTypes.Rgba32)] [WithTestPatternImages(nameof(BitsPerPixel), 7, 5, PixelTypes.Rgba32)] public void Encode_WorksWithDifferentSizes(TestImageProvider provider, BmpBitsPerPixel bitsPerPixel) - where TPixel : struct, IPixel - { - TestBmpEncoderCore(provider, bitsPerPixel); - } + where TPixel : struct, IPixel => TestBmpEncoderCore(provider, bitsPerPixel); private static void TestBmpEncoderCore(TestImageProvider provider, BmpBitsPerPixel bitsPerPixel) where TPixel : struct, IPixel diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs index df015f755..acfad042e 100644 --- a/tests/ImageSharp.Tests/TestImages.cs +++ b/tests/ImageSharp.Tests/TestImages.cs @@ -178,6 +178,7 @@ namespace SixLabors.ImageSharp.Tests public const string Bit8Inverted = "Bmp/test8-inverted.bmp"; public const string Bit16 = "Bmp/test16.bmp"; public const string Bit16Inverted = "Bmp/test16-inverted.bmp"; + public const string Bit32Rgb = "Bmp/rgb32.bmp"; public static readonly string[] All = { diff --git a/tests/Images/Input/Bmp/rgb32.bmp b/tests/Images/Input/Bmp/rgb32.bmp new file mode 100644 index 0000000000000000000000000000000000000000..5d57eaaea8a503668a94d43dcb62a9c840b5ca39 GIT binary patch literal 32566 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 literal 0 HcmV?d00001 From ea0ab8bb502155afdd95f5b0390a7c96ffb3f6bf Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Tue, 11 Sep 2018 19:38:23 +0100 Subject: [PATCH 09/11] Png now correctly encodes 1, 2, 4 bit images --- src/ImageSharp/Common/Helpers/ImageMaths.cs | 18 ++++--- src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs | 2 +- src/ImageSharp/Formats/Gif/GifEncoderCore.cs | 4 +- src/ImageSharp/Formats/Png/PngBitDepth.cs | 15 ++++++ src/ImageSharp/Formats/Png/PngDecoderCore.cs | 11 ++-- src/ImageSharp/Formats/Png/PngEncoder.cs | 3 +- src/ImageSharp/Formats/Png/PngEncoderCore.cs | 51 +++++++++++++++---- .../Formats/Bmp/BmpEncoderTests.cs | 1 - .../Formats/Png/PngEncoderTests.cs | 31 +++++++++++ 9 files changed, 103 insertions(+), 33 deletions(-) diff --git a/src/ImageSharp/Common/Helpers/ImageMaths.cs b/src/ImageSharp/Common/Helpers/ImageMaths.cs index 3c48488ec..cacaca0bb 100644 --- a/src/ImageSharp/Common/Helpers/ImageMaths.cs +++ b/src/ImageSharp/Common/Helpers/ImageMaths.cs @@ -36,10 +36,15 @@ namespace SixLabors.ImageSharp /// The /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int GetBitsNeededForColorDepth(int colors) - { - return Math.Max(1, (int)Math.Ceiling(Math.Log(colors, 2))); - } + public static int GetBitsNeededForColorDepth(int colors) => Math.Max(1, (int)Math.Ceiling(Math.Log(colors, 2))); + + /// + /// Returns how many colors will be created by the specified number of bits. + /// + /// The bit depth. + /// The + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int GetColorCountForBitDepth(int bitDepth) => (int)Math.Pow(2, bitDepth); /// /// Implementation of 1D Gaussian G(x) function @@ -132,10 +137,7 @@ namespace SixLabors.ImageSharp /// The bounding . /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Rectangle GetBoundingRectangle(Point topLeft, Point bottomRight) - { - return new Rectangle(topLeft.X, topLeft.Y, bottomRight.X - topLeft.X, bottomRight.Y - topLeft.Y); - } + public static Rectangle GetBoundingRectangle(Point topLeft, Point bottomRight) => new Rectangle(topLeft.X, topLeft.Y, bottomRight.X - topLeft.X, bottomRight.Y - topLeft.Y); /// /// Finds the bounding rectangle based on the first instance of any color component other diff --git a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs index 3bb44f1d0..a574d5178 100644 --- a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs +++ b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs @@ -596,7 +596,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp || this.infoHeader.BitsPerPixel == 4 || this.infoHeader.BitsPerPixel == 8) { - colorMapSize = (int)Math.Pow(2, this.infoHeader.BitsPerPixel) * 4; + colorMapSize = ImageMaths.GetColorCountForBitDepth(this.infoHeader.BitsPerPixel) * 4; } } else diff --git a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs index 7a880b0f9..f2e0eab5c 100644 --- a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs +++ b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs @@ -86,7 +86,7 @@ namespace SixLabors.ImageSharp.Formats.Gif Guard.NotNull(image, nameof(image)); Guard.NotNull(stream, nameof(stream)); - this.gifMetaData = image.MetaData.GetOrAddFormatMetaData(GifFormat.Instance); + this.gifMetaData = image.MetaData.GetOrAddFormatMetaData(GifFormat.Instance); this.colorTableMode = this.colorTableMode ?? this.gifMetaData.ColorTableMode; bool useGlobalTable = this.colorTableMode.Equals(GifColorTableMode.Global); @@ -412,7 +412,7 @@ namespace SixLabors.ImageSharp.Formats.Gif int pixelCount = image.Palette.Length; // The maximium number of colors for the bit depth - int colorTableLength = (int)Math.Pow(2, this.bitDepth) * 3; + int colorTableLength = ImageMaths.GetColorCountForBitDepth(this.bitDepth) * 3; Rgb24 rgb = default; using (IManagedByteBuffer colorTable = this.memoryAllocator.AllocateManagedByteBuffer(colorTableLength)) diff --git a/src/ImageSharp/Formats/Png/PngBitDepth.cs b/src/ImageSharp/Formats/Png/PngBitDepth.cs index 0c22a4c91..396f2c160 100644 --- a/src/ImageSharp/Formats/Png/PngBitDepth.cs +++ b/src/ImageSharp/Formats/Png/PngBitDepth.cs @@ -9,6 +9,21 @@ namespace SixLabors.ImageSharp.Formats.Png /// public enum PngBitDepth { + /// + /// 1 bit per sample or per palette index (not per pixel). + /// + Bit1 = 1, + + /// + /// 2 bits per sample or per palette index (not per pixel). + /// + Bit2 = 2, + + /// + /// 4 bits per sample or per palette index (not per pixel). + /// + Bit4 = 4, + /// /// 8 bits per sample or per palette index (not per pixel). /// diff --git a/src/ImageSharp/Formats/Png/PngDecoderCore.cs b/src/ImageSharp/Formats/Png/PngDecoderCore.cs index 4bc483301..3daee991c 100644 --- a/src/ImageSharp/Formats/Png/PngDecoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngDecoderCore.cs @@ -730,7 +730,7 @@ namespace SixLabors.ImageSharp.Formats.Png { case PngColorType.Grayscale: - int factor = 255 / ((int)Math.Pow(2, this.header.BitDepth) - 1); + int factor = 255 / (ImageMaths.GetColorCountForBitDepth(this.header.BitDepth) - 1); if (!this.hasTrans) { @@ -952,7 +952,7 @@ namespace SixLabors.ImageSharp.Formats.Png { case PngColorType.Grayscale: - int factor = 255 / ((int)Math.Pow(2, this.header.BitDepth) - 1); + int factor = 255 / (ImageMaths.GetColorCountForBitDepth(this.header.BitDepth) - 1); if (!this.hasTrans) { @@ -1303,12 +1303,7 @@ namespace SixLabors.ImageSharp.Formats.Png filterMethod: data[11], interlaceMethod: (PngInterlaceMode)data[12]); - // TODO: Figure out how we can determine the number of colors and support more bit depths. - if (bitDepth == 8 || bitDepth == 16) - { - pngMetaData.BitDepth = (PngBitDepth)bitDepth; - } - + pngMetaData.BitDepth = (PngBitDepth)bitDepth; pngMetaData.ColorType = this.header.ColorType; } diff --git a/src/ImageSharp/Formats/Png/PngEncoder.cs b/src/ImageSharp/Formats/Png/PngEncoder.cs index 435d0abbc..05d687a88 100644 --- a/src/ImageSharp/Formats/Png/PngEncoder.cs +++ b/src/ImageSharp/Formats/Png/PngEncoder.cs @@ -4,7 +4,6 @@ using System.IO; using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; using SixLabors.ImageSharp.Processing.Processors.Quantization; namespace SixLabors.ImageSharp.Formats.Png @@ -45,7 +44,7 @@ namespace SixLabors.ImageSharp.Formats.Png /// Gets or sets quantizer for reducing the color count. /// Defaults to the /// - public IQuantizer Quantizer { get; set; } = KnownQuantizers.Wu; + public IQuantizer Quantizer { get; set; } /// /// Gets or sets the transparency threshold. diff --git a/src/ImageSharp/Formats/Png/PngEncoderCore.cs b/src/ImageSharp/Formats/Png/PngEncoderCore.cs index 9d9de71b1..20fc8b8e3 100644 --- a/src/ImageSharp/Formats/Png/PngEncoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngEncoderCore.cs @@ -48,11 +48,6 @@ namespace SixLabors.ImageSharp.Formats.Png /// private readonly PngFilterMethod pngFilterMethod; - /// - /// The quantizer for reducing the color count. - /// - private readonly IQuantizer quantizer; - /// /// Gets or sets the CompressionLevel value /// @@ -63,6 +58,11 @@ namespace SixLabors.ImageSharp.Formats.Png /// private readonly byte threshold; + /// + /// The quantizer for reducing the color count. + /// + private IQuantizer quantizer; + /// /// Gets or sets a value indicating whether to write the gamma chunk /// @@ -185,8 +185,6 @@ namespace SixLabors.ImageSharp.Formats.Png this.gamma = this.gamma ?? pngMetaData.Gamma; this.writeGamma = this.gamma > 0; this.pngColorType = this.pngColorType ?? pngMetaData.ColorType; - - // TODO: We don't take full advantage of this information yet. this.pngBitDepth = this.pngBitDepth ?? pngMetaData.BitDepth; this.use16Bit = this.pngBitDepth.Equals(PngBitDepth.Bit16); @@ -196,17 +194,27 @@ namespace SixLabors.ImageSharp.Formats.Png ReadOnlySpan quantizedPixelsSpan = default; if (this.pngColorType == PngColorType.Palette) { + byte bits; + + // Use the metadata to determine what quantization depth to use if no quantizer has been set. + if (this.quantizer == null) + { + bits = (byte)Math.Min(8u, (short)this.pngBitDepth); + int colorSize = ImageMaths.GetColorCountForBitDepth(bits); + this.quantizer = new WuQuantizer(colorSize); + } + // Create quantized frame returning the palette and set the bit depth. quantized = this.quantizer.CreateFrameQuantizer().QuantizeFrame(image.Frames.RootFrame); quantizedPixelsSpan = quantized.GetPixelSpan(); - byte bits = (byte)ImageMaths.GetBitsNeededForColorDepth(quantized.Palette.Length).Clamp(1, 8); + bits = (byte)ImageMaths.GetBitsNeededForColorDepth(quantized.Palette.Length).Clamp(1, 8); // Png only supports in four pixel depths: 1, 2, 4, and 8 bits when using the PLTE chunk if (bits == 3) { bits = 4; } - else if (bits >= 5 || bits <= 7) + else if (bits >= 5 && bits <= 7) { bits = 8; } @@ -556,7 +564,7 @@ namespace SixLabors.ImageSharp.Formats.Png byte pixelCount = palette.Length.ToByte(); // Get max colors for bit depth. - int colorTableLength = (int)Math.Pow(2, header.BitDepth) * 3; + int colorTableLength = ImageMaths.GetColorCountForBitDepth(header.BitDepth) * 3; Rgba32 rgba = default; bool anyAlpha = false; @@ -700,7 +708,7 @@ namespace SixLabors.ImageSharp.Formats.Png private void WriteDataChunks(ImageFrame pixels, ReadOnlySpan quantizedPixelsSpan, Stream stream) where TPixel : struct, IPixel { - this.bytesPerScanline = this.width * this.bytesPerPixel; + this.bytesPerScanline = this.CalculateScanlineLength(this.width); int resultLength = this.bytesPerScanline + 1; this.previousScanline = this.memoryAllocator.AllocateManagedByteBuffer(this.bytesPerScanline, AllocationOptions.Clean); @@ -828,5 +836,26 @@ namespace SixLabors.ImageSharp.Formats.Png stream.Write(this.buffer, 0, 4); // write the crc } + + /// + /// Calculates the scanline length. + /// + /// The width of the row. + /// + /// The representing the length. + /// + private int CalculateScanlineLength(int width) + { + int mod = this.bitDepth == 16 ? 16 : 8; + int scanlineLength = width * this.bitDepth * this.bytesPerPixel; + + int amount = scanlineLength % mod; + if (amount != 0) + { + scanlineLength += mod - amount; + } + + return scanlineLength / mod; + } } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs index c75c65691..311b28f2d 100644 --- a/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs @@ -88,7 +88,6 @@ namespace SixLabors.ImageSharp.Tests } } - [Theory] [WithTestPatternImages(nameof(BitsPerPixel), 24, 24, PixelTypes.Rgba32 | PixelTypes.Bgra32 | PixelTypes.Rgb24)] public void Encode_IsNotBoundToSinglePixelType(TestImageProvider provider, BmpBitsPerPixel bitsPerPixel) diff --git a/tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs index 62de45064..c9435a37d 100644 --- a/tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs @@ -23,6 +23,13 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png // The images are an exact match. Maybe the submodule isn't updating? private const float ToleranceThresholdForPaletteEncoder = 1.3F / 100; + public static readonly TheoryData PngBitDepthFiles = + new TheoryData + { + { TestImages.Png.Rgb48Bpp, PngBitDepth.Bit16 }, + { TestImages.Png.Bpp1, PngBitDepth.Bit1 } + }; + /// /// All types except Palette /// @@ -290,5 +297,29 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png } } } + + [Theory] + [MemberData(nameof(PngBitDepthFiles))] + public void Encode_PreserveBits(string imagePath, PngBitDepth pngBitDepth) + { + var options = new PngEncoder(); + + var testFile = TestFile.Create(imagePath); + using (Image input = testFile.CreateImage()) + { + using (var memStream = new MemoryStream()) + { + input.Save(memStream, options); + + memStream.Position = 0; + using (var output = Image.Load(memStream)) + { + PngMetaData meta = output.MetaData.GetOrAddFormatMetaData(PngFormat.Instance); + + Assert.Equal(pngBitDepth, meta.BitDepth); + } + } + } + } } } \ No newline at end of file From c91d9154f663d2fbc9816462cbb6d1a68588331f Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Wed, 12 Sep 2018 08:30:42 +0100 Subject: [PATCH 10/11] Simplify metadata API --- src/ImageSharp/Common/Helpers/ImageMaths.cs | 2 +- src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs | 3 +-- src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs | 2 +- src/ImageSharp/Formats/Gif/GifDecoderCore.cs | 15 ++++------- src/ImageSharp/Formats/Gif/GifEncoderCore.cs | 6 ++--- src/ImageSharp/Formats/Png/PngDecoderCore.cs | 6 ++--- src/ImageSharp/Formats/Png/PngEncoderCore.cs | 2 +- src/ImageSharp/MetaData/ImageFrameMetaData.cs | 25 ++----------------- src/ImageSharp/MetaData/ImageMetaData.cs | 21 ++-------------- .../Formats/Bmp/BmpEncoderTests.cs | 2 +- .../Formats/Gif/GifEncoderTests.cs | 10 ++++---- .../Formats/Png/PngEncoderTests.cs | 4 +-- .../MetaData/ImageFrameMetaDataTests.cs | 14 ++++------- 13 files changed, 31 insertions(+), 81 deletions(-) diff --git a/src/ImageSharp/Common/Helpers/ImageMaths.cs b/src/ImageSharp/Common/Helpers/ImageMaths.cs index cacaca0bb..c15e0a732 100644 --- a/src/ImageSharp/Common/Helpers/ImageMaths.cs +++ b/src/ImageSharp/Common/Helpers/ImageMaths.cs @@ -44,7 +44,7 @@ namespace SixLabors.ImageSharp /// The bit depth. /// The [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int GetColorCountForBitDepth(int bitDepth) => (int)Math.Pow(2, bitDepth); + public static int GetColorCountForBitDepth(int bitDepth) => 1 << bitDepth; /// /// Implementation of 1D Gaussian G(x) function diff --git a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs index a574d5178..71852acdd 100644 --- a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs +++ b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs @@ -537,8 +537,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp this.metaData = meta; short bitsPerPixel = this.infoHeader.BitsPerPixel; - var bmpMetaData = new BmpMetaData(); - this.metaData.AddOrUpdateFormatMetaData(BmpFormat.Instance, bmpMetaData); + var bmpMetaData = this.metaData.GetFormatMetaData(BmpFormat.Instance); // We can only encode at these bit rates so far. if (bitsPerPixel.Equals((short)BmpBitsPerPixel.Pixel24) diff --git a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs index 7a09a47f7..4ffaf3950 100644 --- a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs +++ b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs @@ -48,7 +48,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp Guard.NotNull(image, nameof(image)); Guard.NotNull(stream, nameof(stream)); - BmpMetaData bmpMetaData = image.MetaData.GetOrAddFormatMetaData(BmpFormat.Instance); + BmpMetaData bmpMetaData = image.MetaData.GetFormatMetaData(BmpFormat.Instance); this.bitsPerPixel = this.bitsPerPixel ?? bmpMetaData.BitsPerPixel; short bpp = (short)this.bitsPerPixel; diff --git a/src/ImageSharp/Formats/Gif/GifDecoderCore.cs b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs index f50381264..207f126f9 100644 --- a/src/ImageSharp/Formats/Gif/GifDecoderCore.cs +++ b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs @@ -164,7 +164,6 @@ namespace SixLabors.ImageSharp.Formats.Gif this.globalColorTable?.Dispose(); } - image?.MetaData.AddOrUpdateFormatMetaData(GifFormat.Instance, this.gifMetaData); return image; } @@ -224,7 +223,6 @@ namespace SixLabors.ImageSharp.Formats.Gif this.globalColorTable?.Dispose(); } - this.metaData.AddOrUpdateFormatMetaData(GifFormat.Instance, this.gifMetaData); return new ImageInfo( new PixelTypeInfo(this.logicalScreenDescriptor.BitsPerPixel), this.logicalScreenDescriptor.Width, @@ -542,7 +540,7 @@ namespace SixLabors.ImageSharp.Formats.Gif [MethodImpl(MethodImplOptions.AggressiveInlining)] private void SetFrameMetaData(ImageFrameMetaData meta) { - var gifMeta = new GifFrameMetaData(); + GifFrameMetaData gifMeta = meta.GetFormatMetaData(GifFormat.Instance); if (this.graphicsControlExtension.DelayTime > 0) { gifMeta.FrameDelay = this.graphicsControlExtension.DelayTime; @@ -561,7 +559,6 @@ namespace SixLabors.ImageSharp.Formats.Gif } gifMeta.DisposalMethod = this.graphicsControlExtension.DisposalMethod; - meta.AddOrUpdateFormatMetaData(GifFormat.Instance, gifMeta); } /// @@ -605,12 +602,10 @@ namespace SixLabors.ImageSharp.Formats.Gif } this.metaData = meta; - this.gifMetaData = new GifMetaData - { - ColorTableMode = this.logicalScreenDescriptor.GlobalColorTableFlag - ? GifColorTableMode.Global - : GifColorTableMode.Local - }; + this.gifMetaData = meta.GetFormatMetaData(GifFormat.Instance); + this.gifMetaData.ColorTableMode = this.logicalScreenDescriptor.GlobalColorTableFlag + ? GifColorTableMode.Global + : GifColorTableMode.Local; if (this.logicalScreenDescriptor.GlobalColorTableFlag) { diff --git a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs index f2e0eab5c..a516b5fef 100644 --- a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs +++ b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs @@ -86,7 +86,7 @@ namespace SixLabors.ImageSharp.Formats.Gif Guard.NotNull(image, nameof(image)); Guard.NotNull(stream, nameof(stream)); - this.gifMetaData = image.MetaData.GetOrAddFormatMetaData(GifFormat.Instance); + this.gifMetaData = image.MetaData.GetFormatMetaData(GifFormat.Instance); this.colorTableMode = this.colorTableMode ?? this.gifMetaData.ColorTableMode; bool useGlobalTable = this.colorTableMode.Equals(GifColorTableMode.Global); @@ -143,7 +143,7 @@ namespace SixLabors.ImageSharp.Formats.Gif for (int i = 0; i < image.Frames.Count; i++) { ImageFrame frame = image.Frames[i]; - GifFrameMetaData frameMetaData = frame.MetaData.GetOrAddFormatMetaData(GifFormat.Instance); + GifFrameMetaData frameMetaData = frame.MetaData.GetFormatMetaData(GifFormat.Instance); this.WriteGraphicalControlExtension(frameMetaData, transparencyIndex, stream); this.WriteImageDescriptor(frame, false, stream); @@ -169,7 +169,7 @@ namespace SixLabors.ImageSharp.Formats.Gif GifFrameMetaData previousMeta = null; foreach (ImageFrame frame in image.Frames) { - GifFrameMetaData meta = frame.MetaData.GetOrAddFormatMetaData(GifFormat.Instance); + GifFrameMetaData meta = frame.MetaData.GetFormatMetaData(GifFormat.Instance); if (quantized is null) { // Allow each frame to be encoded at whatever color depth the frame designates if set. diff --git a/src/ImageSharp/Formats/Png/PngDecoderCore.cs b/src/ImageSharp/Formats/Png/PngDecoderCore.cs index 3daee991c..7837c2da5 100644 --- a/src/ImageSharp/Formats/Png/PngDecoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngDecoderCore.cs @@ -217,8 +217,7 @@ namespace SixLabors.ImageSharp.Formats.Png where TPixel : struct, IPixel { var metaData = new ImageMetaData(); - var pngMetaData = new PngMetaData(); - metaData.AddOrUpdateFormatMetaData(PngFormat.Instance, pngMetaData); + var pngMetaData = metaData.GetFormatMetaData(PngFormat.Instance); this.currentStream = stream; this.currentStream.Skip(8); Image image = null; @@ -308,8 +307,7 @@ namespace SixLabors.ImageSharp.Formats.Png public IImageInfo Identify(Stream stream) { var metaData = new ImageMetaData(); - var pngMetaData = new PngMetaData(); - metaData.AddOrUpdateFormatMetaData(PngFormat.Instance, pngMetaData); + var pngMetaData = metaData.GetFormatMetaData(PngFormat.Instance); this.currentStream = stream; this.currentStream.Skip(8); try diff --git a/src/ImageSharp/Formats/Png/PngEncoderCore.cs b/src/ImageSharp/Formats/Png/PngEncoderCore.cs index 20fc8b8e3..906e6d000 100644 --- a/src/ImageSharp/Formats/Png/PngEncoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngEncoderCore.cs @@ -181,7 +181,7 @@ namespace SixLabors.ImageSharp.Formats.Png this.height = image.Height; // Always take the encoder options over the metadata values. - PngMetaData pngMetaData = image.MetaData.GetOrAddFormatMetaData(PngFormat.Instance); + PngMetaData pngMetaData = image.MetaData.GetFormatMetaData(PngFormat.Instance); this.gamma = this.gamma ?? pngMetaData.Gamma; this.writeGamma = this.gamma > 0; this.pngColorType = this.pngColorType ?? pngMetaData.ColorType; diff --git a/src/ImageSharp/MetaData/ImageFrameMetaData.cs b/src/ImageSharp/MetaData/ImageFrameMetaData.cs index 908a0e624..4b819e201 100644 --- a/src/ImageSharp/MetaData/ImageFrameMetaData.cs +++ b/src/ImageSharp/MetaData/ImageFrameMetaData.cs @@ -44,27 +44,6 @@ namespace SixLabors.ImageSharp.MetaData /// The cloned instance. public ImageFrameMetaData Clone() => new ImageFrameMetaData(this); - /// - /// Adds or updates the specified key and value to the . - /// - /// The type of format metadata. - /// The type of format frame metadata. - /// 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 AddOrUpdateFormatMetaData( - IImageFormat key, - TFormatFrameMetaData value) - where TFormatMetaData : class - where TFormatFrameMetaData : class - { - // Don't think this needs to be threadsafe. - Guard.NotNull(value, nameof(value)); - this.formatMetaData[key] = value; - } - /// /// Gets the metadata value associated with the specified key. /// @@ -74,7 +53,7 @@ namespace SixLabors.ImageSharp.MetaData /// /// The . /// - public TFormatFrameMetaData GetOrAddFormatMetaData(IImageFormat key) + public TFormatFrameMetaData GetFormatMetaData(IImageFormat key) where TFormatMetaData : class where TFormatFrameMetaData : class { @@ -84,7 +63,7 @@ namespace SixLabors.ImageSharp.MetaData } TFormatFrameMetaData newMeta = key.CreateDefaultFormatFrameMetaData(); - this.AddOrUpdateFormatMetaData(key, newMeta); + this.formatMetaData[key] = newMeta; return newMeta; } } diff --git a/src/ImageSharp/MetaData/ImageMetaData.cs b/src/ImageSharp/MetaData/ImageMetaData.cs index 74c00cf8a..7e74157e7 100644 --- a/src/ImageSharp/MetaData/ImageMetaData.cs +++ b/src/ImageSharp/MetaData/ImageMetaData.cs @@ -131,23 +131,6 @@ namespace SixLabors.ImageSharp.MetaData /// public IList Properties { get; } = new List(); - /// - /// Adds or updates the specified key and value to the . - /// - /// The type of format metadata. - /// 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 AddOrUpdateFormatMetaData(IImageFormat key, TFormatMetaData value) - where TFormatMetaData : class - { - // Don't think this needs to be threadsafe. - Guard.NotNull(value, nameof(value)); - this.formatMetaData[key] = value; - } - /// /// Gets the metadata value associated with the specified key. /// @@ -156,7 +139,7 @@ namespace SixLabors.ImageSharp.MetaData /// /// The . /// - public TFormatMetaData GetOrAddFormatMetaData(IImageFormat key) + public TFormatMetaData GetFormatMetaData(IImageFormat key) where TFormatMetaData : class { if (this.formatMetaData.TryGetValue(key, out object meta)) @@ -165,7 +148,7 @@ namespace SixLabors.ImageSharp.MetaData } TFormatMetaData newMeta = key.CreateDefaultFormatMetaData(); - this.AddOrUpdateFormatMetaData(key, newMeta); + this.formatMetaData[key] = newMeta; return newMeta; } diff --git a/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs index 311b28f2d..b9f855cf1 100644 --- a/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs @@ -80,7 +80,7 @@ namespace SixLabors.ImageSharp.Tests memStream.Position = 0; using (var output = Image.Load(memStream)) { - BmpMetaData meta = output.MetaData.GetOrAddFormatMetaData(BmpFormat.Instance); + BmpMetaData meta = output.MetaData.GetFormatMetaData(BmpFormat.Instance); Assert.Equal(bmpBitsPerPixel, meta.BitsPerPixel); } diff --git a/tests/ImageSharp.Tests/Formats/Gif/GifEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Gif/GifEncoderTests.cs index 0c32689f0..4a17f867f 100644 --- a/tests/ImageSharp.Tests/Formats/Gif/GifEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Gif/GifEncoderTests.cs @@ -189,8 +189,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif inStream.Position = 0; var image = Image.Load(inStream); - GifMetaData metaData = image.MetaData.GetOrAddFormatMetaData(GifFormat.Instance); - GifFrameMetaData frameMetaData = image.Frames.RootFrame.MetaData.GetOrAddFormatMetaData(GifFormat.Instance); + GifMetaData metaData = image.MetaData.GetFormatMetaData(GifFormat.Instance); + GifFrameMetaData frameMetaData = image.Frames.RootFrame.MetaData.GetFormatMetaData(GifFormat.Instance); GifColorTableMode colorMode = metaData.ColorTableMode; var encoder = new GifEncoder() { @@ -204,7 +204,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif outStream.Position = 0; var clone = Image.Load(outStream); - GifMetaData cloneMetaData = clone.MetaData.GetOrAddFormatMetaData(GifFormat.Instance); + GifMetaData cloneMetaData = clone.MetaData.GetFormatMetaData(GifFormat.Instance); Assert.Equal(metaData.ColorTableMode, cloneMetaData.ColorTableMode); // Gifiddle and Cyotek GifInfo say this image has 64 colors. @@ -212,8 +212,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif for (int i = 0; i < image.Frames.Count; i++) { - GifFrameMetaData ifm = image.Frames[i].MetaData.GetOrAddFormatMetaData(GifFormat.Instance); - GifFrameMetaData cifm = clone.Frames[i].MetaData.GetOrAddFormatMetaData(GifFormat.Instance); + GifFrameMetaData ifm = image.Frames[i].MetaData.GetFormatMetaData(GifFormat.Instance); + GifFrameMetaData cifm = clone.Frames[i].MetaData.GetFormatMetaData(GifFormat.Instance); Assert.Equal(ifm.ColorTableLength, cifm.ColorTableLength); Assert.Equal(ifm.FrameDelay, cifm.FrameDelay); diff --git a/tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs index c9435a37d..0508ac8c2 100644 --- a/tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs @@ -228,7 +228,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png : image; float paletteToleranceHack = 80f / paletteSize; - paletteToleranceHack = paletteToleranceHack * paletteToleranceHack; + paletteToleranceHack *= paletteToleranceHack; ImageComparer comparer = pngColorType == PngColorType.Palette ? ImageComparer.Tolerant(ToleranceThresholdForPaletteEncoder * paletteToleranceHack) : ImageComparer.Exact; @@ -314,7 +314,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png memStream.Position = 0; using (var output = Image.Load(memStream)) { - PngMetaData meta = output.MetaData.GetOrAddFormatMetaData(PngFormat.Instance); + PngMetaData meta = output.MetaData.GetFormatMetaData(PngFormat.Instance); Assert.Equal(pngBitDepth, meta.BitDepth); } diff --git a/tests/ImageSharp.Tests/MetaData/ImageFrameMetaDataTests.cs b/tests/ImageSharp.Tests/MetaData/ImageFrameMetaDataTests.cs index 54441f0cb..0a0ca1efa 100644 --- a/tests/ImageSharp.Tests/MetaData/ImageFrameMetaDataTests.cs +++ b/tests/ImageSharp.Tests/MetaData/ImageFrameMetaDataTests.cs @@ -19,18 +19,14 @@ namespace SixLabors.ImageSharp.Tests const int colorTableLength = 128; const GifDisposalMethod disposalMethod = GifDisposalMethod.RestoreToBackground; - var gifFrameMetaData = new GifFrameMetaData - { - FrameDelay = frameDelay, - ColorTableLength = colorTableLength, - DisposalMethod = disposalMethod - }; - var metaData = new ImageFrameMetaData(); - metaData.AddOrUpdateFormatMetaData(GifFormat.Instance, gifFrameMetaData); + GifFrameMetaData gifFrameMetaData = metaData.GetFormatMetaData(GifFormat.Instance); + gifFrameMetaData.FrameDelay = frameDelay; + gifFrameMetaData.ColorTableLength = colorTableLength; + gifFrameMetaData.DisposalMethod = disposalMethod; var clone = new ImageFrameMetaData(metaData); - GifFrameMetaData cloneGifFrameMetaData = clone.GetOrAddFormatMetaData(GifFormat.Instance); + GifFrameMetaData cloneGifFrameMetaData = clone.GetFormatMetaData(GifFormat.Instance); Assert.Equal(frameDelay, cloneGifFrameMetaData.FrameDelay); Assert.Equal(colorTableLength, cloneGifFrameMetaData.ColorTableLength); From 58ea9950c59a3f5b9ef3e5c6404daa2deb8229db Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Wed, 12 Sep 2018 18:10:06 +0100 Subject: [PATCH 11/11] Can now preserve jpeg quality :heart: --- .../Components/Decoder/QualityEvaluator.cs | 140 ++++++++++++++++++ .../Formats/Jpeg/IJpegEncoderOptions.cs | 7 +- .../Formats/Jpeg/JpegDecoderCore.cs | 14 +- src/ImageSharp/Formats/Jpeg/JpegEncoder.cs | 7 +- .../Formats/Jpeg/JpegEncoderCore.cs | 33 ++--- src/ImageSharp/Formats/Jpeg/JpegMetaData.cs | 7 +- .../Formats/Jpg/JpegDecoderTests.MetaData.cs | 37 +++++ .../Formats/Jpg/JpegEncoderTests.cs | 72 ++++----- 8 files changed, 232 insertions(+), 85 deletions(-) create mode 100644 src/ImageSharp/Formats/Jpeg/Components/Decoder/QualityEvaluator.cs diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/QualityEvaluator.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/QualityEvaluator.cs new file mode 100644 index 000000000..4e11568c8 --- /dev/null +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/QualityEvaluator.cs @@ -0,0 +1,140 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder +{ + /// + /// Provides methods to evaluate the quality of an image. + /// Ported from + /// + internal static class QualityEvaluator + { + private static readonly int[] Hash = new int[101] + { + 1020, 1015, 932, 848, 780, 735, 702, 679, 660, 645, + 632, 623, 613, 607, 600, 594, 589, 585, 581, 571, + 555, 542, 529, 514, 494, 474, 457, 439, 424, 410, + 397, 386, 373, 364, 351, 341, 334, 324, 317, 309, + 299, 294, 287, 279, 274, 267, 262, 257, 251, 247, + 243, 237, 232, 227, 222, 217, 213, 207, 202, 198, + 192, 188, 183, 177, 173, 168, 163, 157, 153, 148, + 143, 139, 132, 128, 125, 119, 115, 108, 104, 99, + 94, 90, 84, 79, 74, 70, 64, 59, 55, 49, + 45, 40, 34, 30, 25, 20, 15, 11, 6, 4, + 0 + }; + + private static readonly int[] Sums = new int[101] + { + 32640, 32635, 32266, 31495, 30665, 29804, 29146, 28599, 28104, + 27670, 27225, 26725, 26210, 25716, 25240, 24789, 24373, 23946, + 23572, 22846, 21801, 20842, 19949, 19121, 18386, 17651, 16998, + 16349, 15800, 15247, 14783, 14321, 13859, 13535, 13081, 12702, + 12423, 12056, 11779, 11513, 11135, 10955, 10676, 10392, 10208, + 9928, 9747, 9564, 9369, 9193, 9017, 8822, 8639, 8458, + 8270, 8084, 7896, 7710, 7527, 7347, 7156, 6977, 6788, + 6607, 6422, 6236, 6054, 5867, 5684, 5495, 5305, 5128, + 4945, 4751, 4638, 4442, 4248, 4065, 3888, 3698, 3509, + 3326, 3139, 2957, 2775, 2586, 2405, 2216, 2037, 1846, + 1666, 1483, 1297, 1109, 927, 735, 554, 375, 201, + 128, 0 + }; + + private static readonly int[] Hash1 = new int[101] + { + 510, 505, 422, 380, 355, 338, 326, 318, 311, 305, + 300, 297, 293, 291, 288, 286, 284, 283, 281, 280, + 279, 278, 277, 273, 262, 251, 243, 233, 225, 218, + 211, 205, 198, 193, 186, 181, 177, 172, 168, 164, + 158, 156, 152, 148, 145, 142, 139, 136, 133, 131, + 129, 126, 123, 120, 118, 115, 113, 110, 107, 105, + 102, 100, 97, 94, 92, 89, 87, 83, 81, 79, + 76, 74, 70, 68, 66, 63, 61, 57, 55, 52, + 50, 48, 44, 42, 39, 37, 34, 31, 29, 26, + 24, 21, 18, 16, 13, 11, 8, 6, 3, 2, + 0 + }; + + private static readonly int[] Sums1 = new int[101] + { + 16320, 16315, 15946, 15277, 14655, 14073, 13623, 13230, 12859, + 12560, 12240, 11861, 11456, 11081, 10714, 10360, 10027, 9679, + 9368, 9056, 8680, 8331, 7995, 7668, 7376, 7084, 6823, + 6562, 6345, 6125, 5939, 5756, 5571, 5421, 5240, 5086, + 4976, 4829, 4719, 4616, 4463, 4393, 4280, 4166, 4092, + 3980, 3909, 3835, 3755, 3688, 3621, 3541, 3467, 3396, + 3323, 3247, 3170, 3096, 3021, 2952, 2874, 2804, 2727, + 2657, 2583, 2509, 2437, 2362, 2290, 2211, 2136, 2068, + 1996, 1915, 1858, 1773, 1692, 1620, 1552, 1477, 1398, + 1326, 1251, 1179, 1109, 1031, 961, 884, 814, 736, + 667, 592, 518, 441, 369, 292, 221, 151, 86, + 64, 0 + }; + + /// + /// Returns an estimated quality of the image based on the quantization tables. + /// + /// The quantization tables. + /// The . + public static int EstimateQuality(Block8x8F[] quantizationTables) + { + int quality = 75; + float sum = 0; + + for (int i = 0; i < quantizationTables.Length; i++) + { + ref Block8x8F qTable = ref quantizationTables[i]; + for (int j = 0; j < Block8x8F.Size; j++) + { + sum += qTable[j]; + } + } + + ref Block8x8F qTable0 = ref quantizationTables[0]; + ref Block8x8F qTable1 = ref quantizationTables[1]; + + if (!qTable0.Equals(default)) + { + if (!qTable1.Equals(default)) + { + quality = (int)(qTable0[2] + + qTable0[53] + + qTable1[0] + + qTable1[Block8x8F.Size - 1]); + + for (int i = 0; i < 100; i++) + { + if (quality < Hash[i] && sum < Sums[i]) + { + continue; + } + + if (((quality <= Hash[i]) && (sum <= Sums[i])) || (i >= 50)) + { + return i + 1; + } + } + } + else + { + quality = (int)(qTable0[2] + qTable0[53]); + + for (int i = 0; i < 100; i++) + { + if (quality < Hash1[i] && sum < Sums1[i]) + { + continue; + } + + if (((quality <= Hash1[i]) && (sum <= Sums1[i])) || (i >= 50)) + { + return i + 1; + } + } + } + } + + return quality; + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/Formats/Jpeg/IJpegEncoderOptions.cs b/src/ImageSharp/Formats/Jpeg/IJpegEncoderOptions.cs index 4076b7da8..53108de93 100644 --- a/src/ImageSharp/Formats/Jpeg/IJpegEncoderOptions.cs +++ b/src/ImageSharp/Formats/Jpeg/IJpegEncoderOptions.cs @@ -8,17 +8,12 @@ namespace SixLabors.ImageSharp.Formats.Jpeg /// internal interface IJpegEncoderOptions { - /// - /// Gets a value indicating whether the metadata should be ignored when the image is being decoded. - /// - bool IgnoreMetadata { get; } - /// /// Gets the quality, that will be used to encode the image. Quality /// index must be between 0 and 100 (compression from max to min). /// /// The quality of the jpg image from 0 to 100. - int Quality { get; } + int? Quality { get; } /// /// Gets the subsample ration, that will be used to encode the image. diff --git a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs index 3ea24809d..011b6100d 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs @@ -259,11 +259,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg this.InputStream.Read(this.markerBuffer, 0, 2); byte marker = this.markerBuffer[1]; fileMarker = new JpegFileMarker(marker, (int)this.InputStream.Position - 2); + this.QuantizationTables = new Block8x8F[4]; // Only assign what we need if (!metadataOnly) { - this.QuantizationTables = new Block8x8F[4]; this.dcHuffmanTables = new HuffmanTables(); this.acHuffmanTables = new HuffmanTables(); this.fastACTables = new FastACTables(this.configuration.MemoryAllocator); @@ -314,15 +314,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg break; case JpegConstants.Markers.DQT: - if (metadataOnly) - { - this.InputStream.Skip(remaining); - } - else - { - this.ProcessDefineQuantizationTablesMarker(remaining); - } - + this.ProcessDefineQuantizationTablesMarker(remaining); break; case JpegConstants.Markers.DRI: @@ -708,6 +700,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg { throw new ImageFormatException("DQT has wrong length"); } + + this.MetaData.GetFormatMetaData(JpegFormat.Instance).Quality = QualityEvaluator.EstimateQuality(this.QuantizationTables); } /// diff --git a/src/ImageSharp/Formats/Jpeg/JpegEncoder.cs b/src/ImageSharp/Formats/Jpeg/JpegEncoder.cs index 0f389dee0..d649d3041 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegEncoder.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegEncoder.cs @@ -11,17 +11,12 @@ namespace SixLabors.ImageSharp.Formats.Jpeg /// public sealed class JpegEncoder : IImageEncoder, IJpegEncoderOptions { - /// - /// Gets or sets a value indicating whether the metadata should be ignored when the image is being decoded. - /// - public bool IgnoreMetadata { get; set; } - /// /// Gets or sets the quality, that will be used to encode the image. Quality /// index must be between 0 and 100 (compression from max to min). /// Defaults to 75. /// - public int Quality { get; set; } = 75; + public int? Quality { get; set; } /// /// Gets or sets the subsample ration, that will be used to encode the image. diff --git a/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs b/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs index f7b6fe996..32c50d2a0 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs @@ -123,19 +123,14 @@ namespace SixLabors.ImageSharp.Formats.Jpeg private readonly byte[] huffmanBuffer = new byte[179]; /// - /// Gets or sets a value indicating whether the metadata should be ignored when the image is being decoded. + /// Gets or sets the subsampling method to use. /// - private readonly bool ignoreMetadata; + private JpegSubsample? subsample; /// /// The quality, that will be used to encode the image. /// - private readonly int quality; - - /// - /// Gets or sets the subsampling method to use. - /// - private readonly JpegSubsample? subsample; + private readonly int? quality; /// /// The accumulated bits to write to the stream. @@ -168,11 +163,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg /// The options public JpegEncoderCore(IJpegEncoderOptions options) { - // System.Drawing produces identical output for jpegs with a quality parameter of 0 and 1. - this.quality = options.Quality.Clamp(1, 100); - this.subsample = options.Subsample ?? (this.quality >= 91 ? JpegSubsample.Ratio444 : JpegSubsample.Ratio420); - - this.ignoreMetadata = options.IgnoreMetadata; + this.quality = options.Quality; + this.subsample = options.Subsample; } /// @@ -195,15 +187,19 @@ namespace SixLabors.ImageSharp.Formats.Jpeg this.outputStream = stream; + // System.Drawing produces identical output for jpegs with a quality parameter of 0 and 1. + int qlty = (this.quality ?? image.MetaData.GetFormatMetaData(JpegFormat.Instance).Quality).Clamp(1, 100); + this.subsample = this.subsample ?? (qlty >= 91 ? JpegSubsample.Ratio444 : JpegSubsample.Ratio420); + // Convert from a quality rating to a scaling factor. int scale; - if (this.quality < 50) + if (qlty < 50) { - scale = 5000 / this.quality; + scale = 5000 / qlty; } else { - scale = 200 - (this.quality * 2); + scale = 200 - (qlty * 2); } // Initialize the quantization tables. @@ -767,11 +763,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg private void WriteProfiles(Image image) where TPixel : struct, IPixel { - if (this.ignoreMetadata) - { - return; - } - image.MetaData.SyncProfiles(); this.WriteExifProfile(image.MetaData.ExifProfile); this.WriteIccProfile(image.MetaData.IccProfile); diff --git a/src/ImageSharp/Formats/Jpeg/JpegMetaData.cs b/src/ImageSharp/Formats/Jpeg/JpegMetaData.cs index b05f9fa15..bd7232e60 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegMetaData.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegMetaData.cs @@ -8,6 +8,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg /// public class JpegMetaData { - // TODO: Analyse what properties we would like to preserve. + /// + /// Gets or sets the encoded quality. + /// + public int Quality { get; set; } = 75; } -} +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.MetaData.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.MetaData.cs index 2e67c06c1..4810985f1 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.MetaData.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.MetaData.cs @@ -49,6 +49,13 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg { TestImages.Jpeg.Baseline.GammaDalaiLamaGray, 72, 72, PixelResolutionUnit.PixelsPerInch } }; + public static readonly TheoryData QualityFiles = + new TheoryData + { + { TestImages.Jpeg.Baseline.Calliphora, 80}, + { TestImages.Jpeg.Progressive.Fb, 75 } + }; + [Theory] [MemberData(nameof(MetaDataTestData))] public void MetaDataIsParsedCorrectly( @@ -101,6 +108,36 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg } } + [Theory] + [MemberData(nameof(QualityFiles))] + public void Identify_VerifyQuality(string imagePath, int quality) + { + var testFile = TestFile.Create(imagePath); + using (var stream = new MemoryStream(testFile.Bytes, false)) + { + var decoder = new JpegDecoder(); + IImageInfo image = decoder.Identify(Configuration.Default, stream); + JpegMetaData meta = image.MetaData.GetFormatMetaData(JpegFormat.Instance); + Assert.Equal(quality, meta.Quality); + } + } + + [Theory] + [MemberData(nameof(QualityFiles))] + public void Decode_VerifyQuality(string imagePath, int quality) + { + var testFile = TestFile.Create(imagePath); + using (var stream = new MemoryStream(testFile.Bytes, false)) + { + var decoder = new JpegDecoder(); + using (Image image = decoder.Decode(Configuration.Default, stream)) + { + JpegMetaData meta = image.MetaData.GetFormatMetaData(JpegFormat.Instance); + Assert.Equal(quality, meta.Quality); + } + } + } + private static void TestImageInfo(string imagePath, IImageDecoder decoder, bool useIdentify, Action test) { var testFile = TestFile.Create(imagePath); diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegEncoderTests.cs index a31ae37b7..598d99274 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegEncoderTests.cs @@ -14,6 +14,13 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg { public class JpegEncoderTests { + public static readonly TheoryData QualityFiles = + new TheoryData + { + { TestImages.Jpeg.Baseline.Calliphora, 80}, + { TestImages.Jpeg.Progressive.Fb, 75 } + }; + public static readonly TheoryData BitsPerPixel_Quality = new TheoryData { @@ -34,6 +41,29 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg { TestImages.Jpeg.Baseline.GammaDalaiLamaGray, 72, 72, PixelResolutionUnit.PixelsPerInch } }; + [Theory] + [MemberData(nameof(QualityFiles))] + public void Encode_PreserveQuality(string imagePath, int quality) + { + var options = new JpegEncoder(); + + var testFile = TestFile.Create(imagePath); + using (Image input = testFile.CreateImage()) + { + using (var memStream = new MemoryStream()) + { + input.Save(memStream, options); + + memStream.Position = 0; + using (var output = Image.Load(memStream)) + { + JpegMetaData meta = output.MetaData.GetFormatMetaData(JpegFormat.Instance); + Assert.Equal(quality, meta.Quality); + } + } + } + } + [Theory] [WithFile(TestImages.Png.CalliphoraPartial, nameof(BitsPerPixel_Quality), PixelTypes.Rgba32)] [WithTestPatternImages(nameof(BitsPerPixel_Quality), 73, 71, PixelTypes.Rgba32)] @@ -43,18 +73,12 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg [WithSolidFilledImages(nameof(BitsPerPixel_Quality), 1, 1, 255, 100, 50, 255, PixelTypes.Rgba32)] [WithTestPatternImages(nameof(BitsPerPixel_Quality), 7, 5, PixelTypes.Rgba32)] public void EncodeBaseline_WorksWithDifferentSizes(TestImageProvider provider, JpegSubsample subsample, int quality) - where TPixel : struct, IPixel - { - TestJpegEncoderCore(provider, subsample, quality); - } + where TPixel : struct, IPixel => TestJpegEncoderCore(provider, subsample, quality); [Theory] [WithTestPatternImages(nameof(BitsPerPixel_Quality), 48, 48, PixelTypes.Rgba32 | PixelTypes.Bgra32)] public void EncodeBaseline_IsNotBoundToSinglePixelType(TestImageProvider provider, JpegSubsample subsample, int quality) - where TPixel : struct, IPixel - { - TestJpegEncoderCore(provider, subsample, quality); - } + where TPixel : struct, IPixel => TestJpegEncoderCore(provider, subsample, quality); /// /// Anton's SUPER-SCIENTIFIC tolerance threshold calculation @@ -103,38 +127,6 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg } } - [Theory] - [InlineData(false)] - [InlineData(true)] - public void IgnoreMetadata_ControlsIfExifProfileIsWritten(bool ignoreMetaData) - { - var encoder = new JpegEncoder() - { - IgnoreMetadata = ignoreMetaData - }; - - using (Image input = TestFile.Create(TestImages.Jpeg.Baseline.Floorplan).CreateImage()) - { - using (var memStream = new MemoryStream()) - { - input.Save(memStream, encoder); - - memStream.Position = 0; - using (var output = Image.Load(memStream)) - { - if (ignoreMetaData) - { - Assert.Null(output.MetaData.ExifProfile); - } - else - { - Assert.NotNull(output.MetaData.ExifProfile); - } - } - } - } - } - [Fact] public void Quality_0_And_1_Are_Identical() {