From 67f3a2fb2d62adebab6b96ce50cd32a57be7e458 Mon Sep 17 00:00:00 2001 From: James South Date: Thu, 30 Apr 2015 23:33:24 +0100 Subject: [PATCH] A bit more gif encoder work Not going well :frowning: Former-commit-id: 0fc05546fcc3a29e61620da83b7421ee4601f18e Former-commit-id: 13403576c1acfa541456e97568852d845e9a8a42 Former-commit-id: f81fa27c751ee3171e9e9f330133d2bfa671d081 --- .../Imaging/Quantizers/IQuantizer.cs | 4 +- .../Common/Extensions/ByteExtensions.cs | 4 +- .../Formats/Gif/GifDecoderCore.cs | 2 + src/ImageProcessor/Formats/Gif/GifEncoder.cs | 30 +++++++--- .../Formats/Gif/Quantizer/IQuantizer.cs | 27 +++++++++ .../Formats/Gif/Quantizer/OctreeQuantizer.cs | 55 +++++++++++++++++++ .../Formats/Gif/Quantizer/Quantizer.cs | 51 +++++++++++++++++ .../Formats/Png/GrayscaleReader.cs | 2 +- .../Formats/Png/PaletteIndexReader.cs | 2 +- .../Formats/Png/TrueColorReader.cs | 2 +- src/ImageProcessor/ImageProcessor.csproj | 3 + .../ImageProcessor.csproj.DotSettings | 1 + src/ImageProcessor/Settings.StyleCop | 2 + 13 files changed, 169 insertions(+), 16 deletions(-) create mode 100644 src/ImageProcessor/Formats/Gif/Quantizer/IQuantizer.cs create mode 100644 src/ImageProcessor/Formats/Gif/Quantizer/OctreeQuantizer.cs create mode 100644 src/ImageProcessor/Formats/Gif/Quantizer/Quantizer.cs diff --git a/old/src/ImageProcessor/Imaging/Quantizers/IQuantizer.cs b/old/src/ImageProcessor/Imaging/Quantizers/IQuantizer.cs index 697055af1..48feff2d1 100644 --- a/old/src/ImageProcessor/Imaging/Quantizers/IQuantizer.cs +++ b/old/src/ImageProcessor/Imaging/Quantizers/IQuantizer.cs @@ -4,7 +4,7 @@ // Licensed under the Apache License, Version 2.0. // // -// The Quantizer interface for allowing quantization of images. +// Encapsulates methods to calculate the color palette of an image. // // -------------------------------------------------------------------------------------------------------------------- @@ -13,7 +13,7 @@ namespace ImageProcessor.Imaging.Quantizers using System.Drawing; /// - /// The Quantizer interface for allowing quantization of images. + /// Encapsulates methods to calculate the color palette of an image. /// public interface IQuantizer { diff --git a/src/ImageProcessor/Common/Extensions/ByteExtensions.cs b/src/ImageProcessor/Common/Extensions/ByteExtensions.cs index 2b180e77e..0c0bc6b1f 100644 --- a/src/ImageProcessor/Common/Extensions/ByteExtensions.cs +++ b/src/ImageProcessor/Common/Extensions/ByteExtensions.cs @@ -25,14 +25,14 @@ result = new byte[bytes.Length * 8 / bits]; int factor = (int)Math.Pow(2, bits) - 1; - int mask = (0xFF >> (8 - bits)); + int mask = 0xFF >> (8 - bits); int resultOffset = 0; foreach (byte b in bytes) { for (int shift = 0; shift < 8; shift += bits) { - int colorIndex = (((b) >> (8 - bits - shift)) & mask) * (255 / factor); + int colorIndex = ((b >> (8 - bits - shift)) & mask) * (255 / factor); result[resultOffset] = (byte)colorIndex; diff --git a/src/ImageProcessor/Formats/Gif/GifDecoderCore.cs b/src/ImageProcessor/Formats/Gif/GifDecoderCore.cs index 2c7b9ee73..e8df9337d 100644 --- a/src/ImageProcessor/Formats/Gif/GifDecoderCore.cs +++ b/src/ImageProcessor/Formats/Gif/GifDecoderCore.cs @@ -32,6 +32,8 @@ this.image = image; this.currentStream = stream; + + // Skip the identifier this.currentStream.Seek(6, SeekOrigin.Current); this.ReadLogicalScreenDescriptor(); diff --git a/src/ImageProcessor/Formats/Gif/GifEncoder.cs b/src/ImageProcessor/Formats/Gif/GifEncoder.cs index f32853d34..64d210872 100644 --- a/src/ImageProcessor/Formats/Gif/GifEncoder.cs +++ b/src/ImageProcessor/Formats/Gif/GifEncoder.cs @@ -2,7 +2,6 @@ namespace ImageProcessor.Formats { using System; - using System.Diagnostics.CodeAnalysis; using System.IO; public class GifEncoder : IImageEncoder @@ -32,10 +31,7 @@ namespace ImageProcessor.Formats /// /// Gets the default file extension for this encoder. /// - public string Extension - { - get { return "GIF"; } - } + public string Extension => "GIF"; /// /// Returns a value indicating whether the supports the specified @@ -53,6 +49,11 @@ namespace ImageProcessor.Formats return extension.Equals("GIF", StringComparison.OrdinalIgnoreCase); } + /// + /// Encodes the image to the specified stream from the . + /// + /// The to encode from. + /// The to encode the image data to. public void Encode(ImageBase image, Stream stream) { Guard.NotNull(image, "image"); @@ -73,6 +74,8 @@ namespace ImageProcessor.Formats this.WriteGlobalLogicalScreenDescriptor(stream, descriptor); + + throw new System.NotImplementedException(); } @@ -80,15 +83,24 @@ namespace ImageProcessor.Formats { this.WriteShort(stream, descriptor.Width); this.WriteShort(stream, descriptor.Width); - int bitdepth = this.GetBitsNeededForColorDepth(descriptor.GlobalColorTableSize) - 1; - int packed = 0x80 | // 1 : global color table flag = 1 (gct used) + int size = descriptor.GlobalColorTableSize; + int bitdepth = this.GetBitsNeededForColorDepth(size) - 1; + int packed = 0x80 | // 1 : global color table flag = 1 (GCT used) 0x70 | // 2-4 : color resolution - 0x00 | // 5 : gct sort flag = 0 - bitdepth; // 6-8 : gct size` + 0x00 | // 5 : GCT sort flag = 0 + bitdepth; // 6-8 : GCT size assume 1:1 this.WriteByte(stream, packed); this.WriteByte(stream, descriptor.BackgroundColorIndex); // Background Color Index this.WriteByte(stream, descriptor.PixelAspectRatio); // Pixel aspect ratio + + // Write the global color table. + this.WriteColorTable(stream, size); + } + + private void WriteColorTable(Stream stream, int size) + { + } /// diff --git a/src/ImageProcessor/Formats/Gif/Quantizer/IQuantizer.cs b/src/ImageProcessor/Formats/Gif/Quantizer/IQuantizer.cs new file mode 100644 index 000000000..f9867d674 --- /dev/null +++ b/src/ImageProcessor/Formats/Gif/Quantizer/IQuantizer.cs @@ -0,0 +1,27 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright © James South and contributors. +// Licensed under the Apache License, Version 2.0. +// +// +// Provides methods for allowing quantization of images pixels. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace ImageProcessor.Formats +{ + /// + /// Provides methods for allowing quantization of images pixels. + /// + public interface IQuantizer + { + /// + /// Quantize an image and return the resulting output pixels. + /// + /// The image to quantize. + /// + /// A representing a quantized version of the image pixels. + /// + byte[] Quantize(ImageBase image); + } +} diff --git a/src/ImageProcessor/Formats/Gif/Quantizer/OctreeQuantizer.cs b/src/ImageProcessor/Formats/Gif/Quantizer/OctreeQuantizer.cs new file mode 100644 index 000000000..838caf57c --- /dev/null +++ b/src/ImageProcessor/Formats/Gif/Quantizer/OctreeQuantizer.cs @@ -0,0 +1,55 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright © James South and contributors. +// Licensed under the Apache License, Version 2.0. +// +// +// Encapsulates methods to calculate the color palette of an image using an Octree pattern. +// +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace ImageProcessor.Formats +{ + /// + /// Encapsulates methods to calculate the color palette of an image using an Octree pattern. + /// + /// + public class OctreeQuantizer : Quantizer + { + /// + /// Maximum allowed color depth + /// + private readonly int maxColors; + + /// + /// Initializes a new instance of the class. + /// + /// + /// 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. + /// + /// Defaults to return a maximum of 255 colors plus transparency with 8 significant bits. + /// + /// + public OctreeQuantizer() + : this(255, 8) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// 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 + /// + /// The maximum number of colors to return + /// The number of significant bits + public OctreeQuantizer(int maxColors, int maxColorBits) + : base(false) + { + Guard.LessEquals(maxColors, 255, "maxColors"); + } + } +} diff --git a/src/ImageProcessor/Formats/Gif/Quantizer/Quantizer.cs b/src/ImageProcessor/Formats/Gif/Quantizer/Quantizer.cs new file mode 100644 index 000000000..002715e52 --- /dev/null +++ b/src/ImageProcessor/Formats/Gif/Quantizer/Quantizer.cs @@ -0,0 +1,51 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright © James South and contributors. +// Licensed under the Apache License, Version 2.0. +// +// +// Encapsulates methods to calculate the color palette of an image. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace ImageProcessor.Formats +{ + /// + /// Encapsulates methods to calculate the color palette of an image. + /// + public abstract class Quantizer : IQuantizer + { + /// + /// Flag used to indicate whether a single pass or two passes are needed for quantization. + /// + private readonly bool singlePass; + + /// + /// Initializes a new instance of the class. + /// + /// + /// If true, the quantization only needs to loop through the source pixels once + /// + /// + /// If you construct this class with a true value for singlePass, then the code will, when quantizing your image, + /// only call the 'QuantizeImage' function. If two passes are required, the code will call 'InitialQuantizeImage' + /// and then 'QuantizeImage'. + /// + protected Quantizer(bool singlePass) + { + this.singlePass = singlePass; + } + + /// + /// Quantize an image and return the resulting output pixels. + /// + /// The image to quantize. + /// + /// A representing a quantized version of the image pixels. + /// + public byte[] Quantize(ImageBase image) + { + throw new System.NotImplementedException(); + } + } +} diff --git a/src/ImageProcessor/Formats/Png/GrayscaleReader.cs b/src/ImageProcessor/Formats/Png/GrayscaleReader.cs index 0069b8a0d..8c96a3cf1 100644 --- a/src/ImageProcessor/Formats/Png/GrayscaleReader.cs +++ b/src/ImageProcessor/Formats/Png/GrayscaleReader.cs @@ -41,7 +41,7 @@ namespace ImageProcessor.Formats /// Reads the specified scanline. /// /// The scanline. - /// The pixels, where the colors should be stored in RGBA format. + /// The pixels, where the colors should be stored in BGRA format. /// /// The header, which contains information about the png file, like /// the width of the image and the height. diff --git a/src/ImageProcessor/Formats/Png/PaletteIndexReader.cs b/src/ImageProcessor/Formats/Png/PaletteIndexReader.cs index 140da5e5d..f6795f8fd 100644 --- a/src/ImageProcessor/Formats/Png/PaletteIndexReader.cs +++ b/src/ImageProcessor/Formats/Png/PaletteIndexReader.cs @@ -47,7 +47,7 @@ namespace ImageProcessor.Formats /// Reads the specified scanline. /// /// The scanline. - /// The pixels, where the colors should be stored in RGBA format. + /// The pixels, where the colors should be stored in BGRA format. /// The header, which contains information about the png file, like /// the width of the image and the height. public void ReadScanline(byte[] scanline, byte[] pixels, PngHeader header) diff --git a/src/ImageProcessor/Formats/Png/TrueColorReader.cs b/src/ImageProcessor/Formats/Png/TrueColorReader.cs index bb78ecf1f..ebae1c8ca 100644 --- a/src/ImageProcessor/Formats/Png/TrueColorReader.cs +++ b/src/ImageProcessor/Formats/Png/TrueColorReader.cs @@ -41,7 +41,7 @@ namespace ImageProcessor.Formats /// Reads the specified scanline. /// /// The scanline. - /// The pixels, where the colors should be stored in RGBA format. + /// The pixels, where the colors should be stored in BGRA format. /// The header, which contains information about the png file, like /// the width of the image and the height. public void ReadScanline(byte[] scanline, byte[] pixels, PngHeader header) diff --git a/src/ImageProcessor/ImageProcessor.csproj b/src/ImageProcessor/ImageProcessor.csproj index 86b578617..b840766ae 100644 --- a/src/ImageProcessor/ImageProcessor.csproj +++ b/src/ImageProcessor/ImageProcessor.csproj @@ -52,6 +52,9 @@ + + + diff --git a/src/ImageProcessor/ImageProcessor.csproj.DotSettings b/src/ImageProcessor/ImageProcessor.csproj.DotSettings index cd4ba94c1..36b7564a4 100644 --- a/src/ImageProcessor/ImageProcessor.csproj.DotSettings +++ b/src/ImageProcessor/ImageProcessor.csproj.DotSettings @@ -7,6 +7,7 @@ True True True + True True True True \ No newline at end of file diff --git a/src/ImageProcessor/Settings.StyleCop b/src/ImageProcessor/Settings.StyleCop index 0e93ffff4..67a1af2f0 100644 --- a/src/ImageProcessor/Settings.StyleCop +++ b/src/ImageProcessor/Settings.StyleCop @@ -2,6 +2,8 @@ cb + octree + quantizer cr EX png