diff --git a/src/ImageSharp/Formats/Png/IPngEncoderOptions.cs b/src/ImageSharp/Formats/Png/IPngEncoderOptions.cs
index 0f416cb7b0..38c3484c81 100644
--- a/src/ImageSharp/Formats/Png/IPngEncoderOptions.cs
+++ b/src/ImageSharp/Formats/Png/IPngEncoderOptions.cs
@@ -59,8 +59,8 @@ namespace SixLabors.ImageSharp.Formats.Png
PngInterlaceMode? InterlaceMethod { get; }
///
- /// Gets a value indicating whether this instance should skip certain chunks to decrease file size
+ /// Gets the optimize method.
///
- bool Optimized { get; }
+ PngOptimizeMethod? OptimizeMethod { get; }
}
}
diff --git a/src/ImageSharp/Formats/Png/PngEncoder.cs b/src/ImageSharp/Formats/Png/PngEncoder.cs
index 5a79915de1..16bd538c31 100644
--- a/src/ImageSharp/Formats/Png/PngEncoder.cs
+++ b/src/ImageSharp/Formats/Png/PngEncoder.cs
@@ -63,9 +63,9 @@ namespace SixLabors.ImageSharp.Formats.Png
public PngInterlaceMode? InterlaceMethod { get; set; }
///
- /// Gets or sets a value indicating whether this instance should skip certain chunks to decrease file size
+ /// Gets or sets the optimize method.
///
- public bool Optimized { get; set; }
+ public PngOptimizeMethod? OptimizeMethod { get; set; }
///
/// Encodes the image to the specified stream from the .
diff --git a/src/ImageSharp/Formats/Png/PngEncoderCore.cs b/src/ImageSharp/Formats/Png/PngEncoderCore.cs
index 8833389e7c..02bb67c728 100644
--- a/src/ImageSharp/Formats/Png/PngEncoderCore.cs
+++ b/src/ImageSharp/Formats/Png/PngEncoderCore.cs
@@ -153,14 +153,26 @@ namespace SixLabors.ImageSharp.Formats.Png
stream.Write(PngConstants.HeaderBytes, 0, PngConstants.HeaderBytes.Length);
this.WriteHeaderChunk(stream);
- this.WritePaletteChunk(stream, quantized, this.options.Optimized);
+ this.WritePaletteChunk(stream, quantized, this.options.OptimizeMethod);
this.WriteTransparencyChunk(stream, pngMetadata);
- if (!this.options.Optimized)
+ if (((this.options.OptimizeMethod ?? PngOptimizeMethod.None) & PngOptimizeMethod.SuppressPhysicalChunk) != PngOptimizeMethod.SuppressPhysicalChunk)
{
this.WritePhysicalChunk(stream, metadata);
+ }
+
+ if (((this.options.OptimizeMethod ?? PngOptimizeMethod.None) & PngOptimizeMethod.SuppressGammaChunk) != PngOptimizeMethod.SuppressGammaChunk)
+ {
this.WriteGammaChunk(stream);
+ }
+
+ if (((this.options.OptimizeMethod ?? PngOptimizeMethod.None) & PngOptimizeMethod.SuppressExifChunk) != PngOptimizeMethod.SuppressExifChunk)
+ {
this.WriteExifChunk(stream, metadata);
+ }
+
+ if (((this.options.OptimizeMethod ?? PngOptimizeMethod.None) & PngOptimizeMethod.SuppressTextChunks) != PngOptimizeMethod.SuppressTextChunks)
+ {
this.WriteTextChunks(stream, pngMetadata);
}
@@ -552,8 +564,8 @@ namespace SixLabors.ImageSharp.Formats.Png
/// The pixel format.
/// The containing image data.
/// The quantized frame.
- /// If optimized make fully transparent pixels black.
- private void WritePaletteChunk(Stream stream, IQuantizedFrame quantized, bool optimized)
+ /// The optimize method.
+ private void WritePaletteChunk(Stream stream, IQuantizedFrame quantized, PngOptimizeMethod? optimizeMethod)
where TPixel : struct, IPixel
{
if (quantized == null)
@@ -576,6 +588,8 @@ namespace SixLabors.ImageSharp.Formats.Png
Rgba32 rgba = default;
+ bool makeTransparentBlack = ((optimizeMethod ?? PngOptimizeMethod.None) & PngOptimizeMethod.MakeTransparentBlack) == PngOptimizeMethod.MakeTransparentBlack;
+
for (int i = 0; i < paletteLength; i++)
{
if (quantizedSpan.IndexOf((byte)i) > -1)
@@ -585,9 +599,18 @@ namespace SixLabors.ImageSharp.Formats.Png
byte alpha = rgba.A;
- Unsafe.Add(ref colorTableRef, offset) = optimized && alpha == 0 ? (byte)0 : rgba.R;
- Unsafe.Add(ref colorTableRef, offset + 1) = optimized && alpha == 0 ? (byte)0 : rgba.G;
- Unsafe.Add(ref colorTableRef, offset + 2) = optimized && alpha == 0 ? (byte)0 : rgba.B;
+ if (makeTransparentBlack && alpha == 0)
+ {
+ Unsafe.Add(ref colorTableRef, offset) = 0;
+ Unsafe.Add(ref colorTableRef, offset + 1) = 0;
+ Unsafe.Add(ref colorTableRef, offset + 2) = 0;
+ }
+ else
+ {
+ Unsafe.Add(ref colorTableRef, offset) = rgba.R;
+ Unsafe.Add(ref colorTableRef, offset + 1) = rgba.G;
+ Unsafe.Add(ref colorTableRef, offset + 2) = rgba.B;
+ }
if (alpha > this.options.Threshold)
{
diff --git a/src/ImageSharp/Formats/Png/PngEncoderOptions.cs b/src/ImageSharp/Formats/Png/PngEncoderOptions.cs
index 5d4be8f149..89d7b0d5ef 100644
--- a/src/ImageSharp/Formats/Png/PngEncoderOptions.cs
+++ b/src/ImageSharp/Formats/Png/PngEncoderOptions.cs
@@ -29,7 +29,7 @@ namespace SixLabors.ImageSharp.Formats.Png
this.Quantizer = source.Quantizer;
this.Threshold = source.Threshold;
this.InterlaceMethod = source.InterlaceMethod;
- this.Optimized = source.Optimized;
+ this.OptimizeMethod = source.OptimizeMethod;
}
///
@@ -81,8 +81,8 @@ namespace SixLabors.ImageSharp.Formats.Png
public PngInterlaceMode? InterlaceMethod { get; set; }
///
- /// Gets or sets a value indicating whether this instance should skip certain chunks to decrease file size
+ /// Gets or sets a the optimize method.
///
- public bool Optimized { get; set; }
+ public PngOptimizeMethod? OptimizeMethod { get; set; }
}
}
diff --git a/src/ImageSharp/Formats/Png/PngOptimizeMethod.cs b/src/ImageSharp/Formats/Png/PngOptimizeMethod.cs
new file mode 100644
index 0000000000..7ad6646380
--- /dev/null
+++ b/src/ImageSharp/Formats/Png/PngOptimizeMethod.cs
@@ -0,0 +1,49 @@
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
+using System;
+
+namespace SixLabors.ImageSharp.Formats.Png
+{
+ ///
+ /// Provides enumeration of available PNG optimization methods.
+ ///
+ [Flags]
+ public enum PngOptimizeMethod
+ {
+ ///
+ /// With the None filter, the scanline is transmitted unmodified.
+ ///
+ None = 0,
+
+ ///
+ /// Suppress the physical dimension information chunk.
+ ///
+ SuppressPhysicalChunk = 1,
+
+ ///
+ /// Suppress the gamma information chunk.
+ ///
+ SuppressGammaChunk = 2,
+
+ ///
+ /// Suppress the eXIf chunk.
+ ///
+ SuppressExifChunk = 4,
+
+ ///
+ /// Suppress the tTXt, iTXt or zTXt chunk.
+ ///
+ SuppressTextChunks = 8,
+
+ ///
+ /// Make funlly transparent pixels black.
+ ///
+ MakeTransparentBlack = 16,
+
+ ///
+ /// All possible optimizations.
+ ///
+ All = 31,
+ }
+}