diff --git a/src/ImageSharp.Formats.Png/IPngEncoderOptions.cs b/src/ImageSharp.Formats.Png/IPngEncoderOptions.cs
new file mode 100644
index 0000000000..0008080d3f
--- /dev/null
+++ b/src/ImageSharp.Formats.Png/IPngEncoderOptions.cs
@@ -0,0 +1,54 @@
+//
+// Copyright (c) James Jackson-South and contributors.
+// Licensed under the Apache License, Version 2.0.
+//
+
+namespace ImageSharp.Formats
+{
+ using Quantizers;
+
+ ///
+ /// Encapsulates the options for the .
+ ///
+ public interface IPngEncoderOptions : IEncoderOptions
+ {
+ ///
+ /// Gets the quality of output for images.
+ ///
+ int Quality { get; }
+
+ ///
+ /// Gets the png color type
+ ///
+ PngColorType PngColorType { get; }
+
+ ///
+ /// Gets the compression level 1-9.
+ ///
+ int CompressionLevel { get; }
+
+ ///
+ /// Gets the gamma value, that will be written
+ /// the the stream, when the property
+ /// is set to true.
+ ///
+ /// The gamma value of the image.
+ float Gamma { get; }
+
+ ///
+ /// Gets quantizer for reducing the color count.
+ ///
+ IQuantizer Quantizer { get; }
+
+ ///
+ /// Gets the transparency threshold.
+ ///
+ byte Threshold { get; }
+
+ ///
+ /// Gets a value indicating whether this instance should write
+ /// gamma information to the stream.
+ ///
+ bool WriteGamma { get; }
+ }
+}
diff --git a/src/ImageSharp.Formats.Png/ImageExtensions.cs b/src/ImageSharp.Formats.Png/ImageExtensions.cs
index dcb1c988b7..f08ab8ee71 100644
--- a/src/ImageSharp.Formats.Png/ImageExtensions.cs
+++ b/src/ImageSharp.Formats.Png/ImageExtensions.cs
@@ -5,7 +5,6 @@
namespace ImageSharp
{
- using System;
using System.IO;
using Formats;
@@ -21,15 +20,18 @@ namespace ImageSharp
/// The pixel format.
/// The image this method extends.
/// The stream to save the image to.
- /// The quality to save the image to representing the number of colors.
- /// Anything equal to 256 and below will cause the encoder to save the image in an indexed format.
- ///
+ /// The options for the encoder.
/// Thrown if the stream is null.
///
/// The .
///
- public static Image SaveAsPng(this Image source, Stream stream, int quality = int.MaxValue)
+ public static Image SaveAsPng(this Image source, Stream stream, IPngEncoderOptions options = null)
where TColor : struct, IPixel
- => source.Save(stream, new PngEncoder { Quality = quality });
+ {
+ PngEncoder encoder = new PngEncoder();
+ encoder.Encode(source, stream, options);
+
+ return source;
+ }
}
}
diff --git a/src/ImageSharp.Formats.Png/PngDecoderCore.cs b/src/ImageSharp.Formats.Png/PngDecoderCore.cs
index 4a5ad36482..076770ce51 100644
--- a/src/ImageSharp.Formats.Png/PngDecoderCore.cs
+++ b/src/ImageSharp.Formats.Png/PngDecoderCore.cs
@@ -10,7 +10,6 @@ namespace ImageSharp.Formats
using System.Collections.Generic;
using System.IO;
using System.Linq;
- using System.Text;
using static ComparableExtensions;
diff --git a/src/ImageSharp.Formats.Png/PngEncoder.cs b/src/ImageSharp.Formats.Png/PngEncoder.cs
index 8d9c4bc085..e583f381fb 100644
--- a/src/ImageSharp.Formats.Png/PngEncoder.cs
+++ b/src/ImageSharp.Formats.Png/PngEncoder.cs
@@ -5,72 +5,34 @@
namespace ImageSharp.Formats
{
- using System;
using System.IO;
- using ImageSharp.Quantizers;
-
///
/// Image encoder for writing image data to a stream in png format.
///
public class PngEncoder : IImageEncoder
{
- ///
- /// Gets or sets the quality of output for images.
- ///
- public int Quality { get; set; }
-
- ///
- /// Gets or sets the png color type
- ///
- public PngColorType PngColorType { get; set; } = PngColorType.RgbWithAlpha;
-
- ///
- /// Gets or sets the compression level 1-9.
- /// Defaults to 6.
- ///
- 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.
- ///
- /// The gamma value of the image.
- public float Gamma { get; set; } = 2.2F;
-
- ///
- /// Gets or sets quantizer for reducing the color count.
- ///
- public IQuantizer Quantizer { get; set; }
+ ///
+ public void Encode(Image image, Stream stream, IEncoderOptions options)
+ where TColor : struct, IPixel
+ {
+ IPngEncoderOptions pngOptions = PngEncoderOptions.Create(options);
- ///
- /// Gets or sets the transparency threshold.
- ///
- public byte Threshold { get; set; } = 0;
+ this.Encode(image, stream, pngOptions);
+ }
///
- /// Gets or sets a value indicating whether this instance should write
- /// gamma information to the stream. The default value is false.
+ /// Encodes the image to the specified stream from the .
///
- public bool WriteGamma { get; set; }
-
- ///
- public void Encode(Image image, Stream stream, IEncoderOptions options)
+ /// The pixel format.
+ /// The to encode from.
+ /// The to encode the image data to.
+ /// The options for the encoder.
+ public void Encode(Image image, Stream stream, IPngEncoderOptions options)
where TColor : struct, IPixel
{
- PngEncoderCore encoder = new PngEncoderCore
- {
- CompressionLevel = this.CompressionLevel,
- Gamma = this.Gamma,
- Quality = this.Quality,
- PngColorType = this.PngColorType,
- Quantizer = this.Quantizer,
- WriteGamma = this.WriteGamma,
- Threshold = this.Threshold
- };
-
- encoder.Encode(image, stream);
+ PngEncoderCore encode = new PngEncoderCore(options);
+ encode.Encode(image, stream);
}
}
}
diff --git a/src/ImageSharp.Formats.Png/PngEncoderCore.cs b/src/ImageSharp.Formats.Png/PngEncoderCore.cs
index 2324853cba..8a00c40b2e 100644
--- a/src/ImageSharp.Formats.Png/PngEncoderCore.cs
+++ b/src/ImageSharp.Formats.Png/PngEncoderCore.cs
@@ -40,6 +40,11 @@ namespace ImageSharp.Formats
///
private readonly Crc32 crc = new Crc32();
+ ///
+ /// The options for the encoder.
+ ///
+ private readonly IPngEncoderOptions options;
+
///
/// Contains the raw pixel data from an indexed image.
///
@@ -86,44 +91,28 @@ namespace ImageSharp.Formats
private byte[] paeth;
///
- /// Gets or sets the quality of output for images.
- ///
- public int Quality { get; set; }
-
- ///
- /// Gets or sets the png color type
+ /// The quality of output for images.
///
- public PngColorType PngColorType { get; set; }
+ private int quality;
///
- /// Gets or sets the compression level 1-9.
- /// Defaults to 6.
+ /// The png color type.
///
- public int CompressionLevel { get; set; } = 6;
+ private PngColorType pngColorType;
///
- /// Gets or sets a value indicating whether this instance should write
- /// gamma information to the stream. The default value is false.
+ /// The quantizer for reducing the color count.
///
- public bool WriteGamma { get; set; }
+ private IQuantizer quantizer;
///
- /// 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.
+ /// Initializes a new instance of the class.
///
- /// The gamma value of the image.
- public float Gamma { get; set; } = 2.2F;
-
- ///
- /// Gets or sets the quantizer for reducing the color count.
- ///
- public IQuantizer Quantizer { get; set; }
-
- ///
- /// Gets or sets the transparency threshold.
- ///
- public byte Threshold { get; set; }
+ /// The options for the encoder.
+ public PngEncoderCore(IPngEncoderOptions options)
+ {
+ this.options = options ?? new PngEncoderOptions();
+ }
///
/// Encodes the image to the specified stream from the .
@@ -153,23 +142,25 @@ namespace ImageSharp.Formats
stream.Write(this.chunkDataBuffer, 0, 8);
// Ensure that quality can be set but has a fallback.
- int quality = this.Quality > 0 ? this.Quality : image.MetaData.Quality;
- this.Quality = quality > 0 ? quality.Clamp(1, int.MaxValue) : int.MaxValue;
+ this.quality = this.options.Quality > 0 ? this.options.Quality : image.MetaData.Quality;
+ this.quality = this.quality > 0 ? this.quality.Clamp(1, int.MaxValue) : int.MaxValue;
+
+ this.pngColorType = this.options.PngColorType;
// Set correct color type if the color count is 256 or less.
- if (this.Quality <= 256)
+ if (this.quality <= 256)
{
- this.PngColorType = PngColorType.Palette;
+ this.pngColorType = PngColorType.Palette;
}
- if (this.PngColorType == PngColorType.Palette && this.Quality > 256)
+ if (this.pngColorType == PngColorType.Palette && this.quality > 256)
{
- this.Quality = 256;
+ this.quality = 256;
}
// Set correct bit depth.
- this.bitDepth = this.Quality <= 256
- ? (byte)ImageMaths.GetBitsNeededForColorDepth(this.Quality).Clamp(1, 8)
+ this.bitDepth = this.quality <= 256
+ ? (byte)ImageMaths.GetBitsNeededForColorDepth(this.quality).Clamp(1, 8)
: (byte)8;
// Png only supports in four pixel depths: 1, 2, 4, and 8 bits when using the PLTE chunk
@@ -188,7 +179,7 @@ namespace ImageSharp.Formats
{
Width = image.Width,
Height = image.Height,
- ColorType = (byte)this.PngColorType,
+ ColorType = (byte)this.pngColorType,
BitDepth = this.bitDepth,
FilterMethod = 0, // None
CompressionMethod = 0,
@@ -198,7 +189,7 @@ namespace ImageSharp.Formats
this.WriteHeaderChunk(stream, header);
// Collect the indexed pixel data
- if (this.PngColorType == PngColorType.Palette)
+ if (this.pngColorType == PngColorType.Palette)
{
this.CollectIndexedBytes(image, stream, header);
}
@@ -334,7 +325,7 @@ namespace ImageSharp.Formats
private byte[] EncodePixelRow(PixelAccessor pixels, int row, byte[] previousScanline, byte[] rawScanline, byte[] result)
where TColor : struct, IPixel
{
- switch (this.PngColorType)
+ switch (this.pngColorType)
{
case PngColorType.Palette:
Buffer.BlockCopy(this.palettePixelData, row * rawScanline.Length, rawScanline, 0, rawScanline.Length);
@@ -362,7 +353,7 @@ namespace ImageSharp.Formats
private byte[] GetOptimalFilteredScanline(byte[] rawScanline, byte[] previousScanline, byte[] result)
{
// Palette images don't compress well with adaptive filtering.
- if (this.PngColorType == PngColorType.Palette || this.bitDepth < 8)
+ if (this.pngColorType == PngColorType.Palette || this.bitDepth < 8)
{
NoneFilter.Encode(rawScanline, result);
return result;
@@ -436,7 +427,7 @@ namespace ImageSharp.Formats
/// The
private int CalculateBytesPerPixel()
{
- switch (this.PngColorType)
+ switch (this.pngColorType)
{
case PngColorType.Grayscale:
return 1;
@@ -488,18 +479,18 @@ namespace ImageSharp.Formats
private QuantizedImage WritePaletteChunk(Stream stream, PngHeader header, ImageBase image)
where TColor : struct, IPixel
{
- if (this.Quality > 256)
+ if (this.quality > 256)
{
return null;
}
- if (this.Quantizer == null)
+ if (this.quantizer == null)
{
- this.Quantizer = new OctreeQuantizer();
+ this.quantizer = new OctreeQuantizer();
}
// Quantize the image returning a palette. This boxing is icky.
- QuantizedImage quantized = ((IQuantizer)this.Quantizer).Quantize(image, this.Quality);
+ QuantizedImage quantized = ((IQuantizer)this.quantizer).Quantize(image, this.quality);
// Grab the palette and write it to the stream.
TColor[] palette = quantized.Palette;
@@ -524,7 +515,7 @@ namespace ImageSharp.Formats
colorTable[offset + 1] = bytes[1];
colorTable[offset + 2] = bytes[2];
- if (alpha <= this.Threshold)
+ if (alpha <= this.options.Threshold)
{
transparentPixels.Add((byte)offset);
}
@@ -578,9 +569,9 @@ namespace ImageSharp.Formats
/// The containing image data.
private void WriteGammaChunk(Stream stream)
{
- if (this.WriteGamma)
+ if (this.options.WriteGamma)
{
- int gammaValue = (int)(this.Gamma * 100000F);
+ int gammaValue = (int)(this.options.Gamma * 100000F);
byte[] size = BitConverter.GetBytes(gammaValue);
@@ -608,7 +599,7 @@ namespace ImageSharp.Formats
int resultLength = bytesPerScanline + 1;
byte[] result = new byte[resultLength];
- if (this.PngColorType != PngColorType.Palette)
+ if (this.pngColorType != PngColorType.Palette)
{
this.sub = new byte[resultLength];
this.up = new byte[resultLength];
@@ -622,7 +613,7 @@ namespace ImageSharp.Formats
try
{
memoryStream = new MemoryStream();
- using (ZlibDeflateStream deflateStream = new ZlibDeflateStream(memoryStream, this.CompressionLevel))
+ using (ZlibDeflateStream deflateStream = new ZlibDeflateStream(memoryStream, this.options.CompressionLevel))
{
for (int y = 0; y < this.height; y++)
{
diff --git a/src/ImageSharp.Formats.Png/PngEncoderOptions.cs b/src/ImageSharp.Formats.Png/PngEncoderOptions.cs
new file mode 100644
index 0000000000..9e6e851de1
--- /dev/null
+++ b/src/ImageSharp.Formats.Png/PngEncoderOptions.cs
@@ -0,0 +1,88 @@
+//
+// Copyright (c) James Jackson-South and contributors.
+// Licensed under the Apache License, Version 2.0.
+//
+
+namespace ImageSharp.Formats
+{
+ using Quantizers;
+
+ ///
+ /// Encapsulates the options for the .
+ ///
+ public sealed class PngEncoderOptions : EncoderOptions, IPngEncoderOptions
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public PngEncoderOptions()
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The options for the encoder.
+ private PngEncoderOptions(IEncoderOptions options)
+ : base(options)
+ {
+ }
+
+ ///
+ /// Gets or sets the quality of output for images.
+ ///
+ public int Quality { get; set; }
+
+ ///
+ /// Gets or sets the png color type
+ ///
+ public PngColorType PngColorType { get; set; } = PngColorType.RgbWithAlpha;
+
+ ///
+ /// Gets or sets the compression level 1-9.
+ /// Defaults to 6.
+ ///
+ 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.
+ ///
+ /// The gamma value of the image.
+ public float Gamma { get; set; } = 2.2F;
+
+ ///
+ /// Gets or sets quantizer for reducing the color count.
+ ///
+ public IQuantizer Quantizer { get; set; }
+
+ ///
+ /// Gets or sets the transparency threshold.
+ ///
+ public byte Threshold { get; set; } = 0;
+
+ ///
+ /// Gets or sets a value indicating whether this instance should write
+ /// gamma information to the stream. The default value is false.
+ ///
+ public bool WriteGamma { get; set; }
+
+ ///
+ /// Converts the options to a instance with a
+ /// cast or by creating a new instance with the specfied options.
+ ///
+ /// The options for the encoder.
+ /// The options for the .
+ internal static IPngEncoderOptions Create(IEncoderOptions options)
+ {
+ IPngEncoderOptions pngOptions = options as IPngEncoderOptions;
+ if (pngOptions != null)
+ {
+ return pngOptions;
+ }
+
+ return new PngEncoderOptions(options);
+ }
+ }
+}