Browse Source

Add IgnoreMetadata to the png encoder options

pull/1574/head
Brian Popow 6 years ago
parent
commit
dde7c1eec5
  1. 8
      src/ImageSharp/Formats/Png/IPngEncoderOptions.cs
  2. 2
      src/ImageSharp/Formats/Png/PngChunkFilter.cs
  3. 15
      src/ImageSharp/Formats/Png/PngEncoder.cs
  4. 8
      src/ImageSharp/Formats/Png/PngEncoderOptions.cs
  5. 5
      src/ImageSharp/Formats/Png/PngEncoderOptionsHelpers.cs
  6. 52
      tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.Chunks.cs

8
src/ImageSharp/Formats/Png/IPngEncoderOptions.cs

@ -59,7 +59,13 @@ namespace SixLabors.ImageSharp.Formats.Png
PngInterlaceMode? InterlaceMethod { get; }
/// <summary>
/// Gets chunk filter method.
/// Gets a value indicating whether the metadata should be ignored when the image is being encoded.
/// When set to true, all ancillary chunks will be skipped.
/// </summary>
bool IgnoreMetadata { get; }
/// <summary>
/// Gets the chunk filter method. This allows to filter ancillary chunks.
/// </summary>
PngChunkFilter? ChunkFilter { get; }

2
src/ImageSharp/Formats/Png/PngChunkFilter.cs

@ -37,7 +37,7 @@ namespace SixLabors.ImageSharp.Formats.Png
ExcludeTextChunks = 1 << 3,
/// <summary>
/// All possible optimizations.
/// All ancillary chunks will be excluded.
/// </summary>
ExcludeAll = ~None
}

15
src/ImageSharp/Formats/Png/PngEncoder.cs

@ -34,22 +34,19 @@ namespace SixLabors.ImageSharp.Formats.Png
/// <inheritdoc/>
public IQuantizer Quantizer { get; set; }
/// <summary>
/// Gets or sets the transparency threshold.
/// </summary>
/// <inheritdoc/>
public byte Threshold { get; set; } = byte.MaxValue;
/// <inheritdoc/>
public PngInterlaceMode? InterlaceMethod { get; set; }
/// <summary>
/// Gets or sets the chunk filter. This can be used to exclude some ancillary chunks from being written.
/// </summary>
/// <inheritdoc/>
public PngChunkFilter? ChunkFilter { get; set; }
/// <summary>
/// Gets or sets a value indicating whether fully transparent pixels should be converted to black pixels.
/// </summary>
/// <inheritdoc/>
public bool IgnoreMetadata { get; set; }
/// <inheritdoc/>
public bool MakeTransparentBlack { get; set; }
/// <summary>

8
src/ImageSharp/Formats/Png/PngEncoderOptions.cs

@ -30,6 +30,7 @@ namespace SixLabors.ImageSharp.Formats.Png
this.Threshold = source.Threshold;
this.InterlaceMethod = source.InterlaceMethod;
this.ChunkFilter = source.ChunkFilter;
this.IgnoreMetadata = source.IgnoreMetadata;
this.MakeTransparentBlack = source.MakeTransparentBlack;
}
@ -60,11 +61,12 @@ namespace SixLabors.ImageSharp.Formats.Png
/// <inheritdoc/>
public PngInterlaceMode? InterlaceMethod { get; set; }
/// <summary>
/// Gets or sets a the optimize method.
/// </summary>
/// <inheritdoc/>
public PngChunkFilter? ChunkFilter { get; set; }
/// <inheritdoc/>
public bool IgnoreMetadata { get; set; }
/// <inheritdoc/>
public bool MakeTransparentBlack { get; set; }
}

5
src/ImageSharp/Formats/Png/PngEncoderOptionsHelpers.cs

@ -40,6 +40,11 @@ namespace SixLabors.ImageSharp.Formats.Png
use16Bit = options.BitDepth == PngBitDepth.Bit16;
bytesPerPixel = CalculateBytesPerPixel(options.ColorType, use16Bit);
if (options.IgnoreMetadata)
{
options.ChunkFilter = PngChunkFilter.ExcludeAll;
}
// Ensure we are not allowing impossible combinations.
if (!PngConstants.ColorTypes.ContainsKey(options.ColorType.Value))
{

52
tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.Chunks.cs

@ -144,6 +144,58 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
}
}
[Fact]
public void IgnoreMetadata_WillExcludeAllAncillaryChunks()
{
// arrange
var testFile = TestFile.Create(TestImages.Png.PngWithMetadata);
using Image<Rgba32> input = testFile.CreateRgba32Image();
using var memStream = new MemoryStream();
var encoder = new PngEncoder() { IgnoreMetadata = true, TextCompressionThreshold = 8 };
var expectedChunkTypes = new Dictionary<PngChunkType, bool>()
{
{ PngChunkType.Header, false },
{ PngChunkType.Palette, false },
{ PngChunkType.Data, false },
{ PngChunkType.End, false }
};
var excludedChunkTypes = new List<PngChunkType>()
{
PngChunkType.Gamma,
PngChunkType.Exif,
PngChunkType.Physical,
PngChunkType.Text,
PngChunkType.InternationalText,
PngChunkType.CompressedText,
};
// act
input.Save(memStream, encoder);
// assert
Assert.True(excludedChunkTypes.Count > 0);
memStream.Position = 0;
Span<byte> bytesSpan = memStream.ToArray().AsSpan(8); // Skip header.
while (bytesSpan.Length > 0)
{
int length = BinaryPrimitives.ReadInt32BigEndian(bytesSpan.Slice(0, 4));
var chunkType = (PngChunkType)BinaryPrimitives.ReadInt32BigEndian(bytesSpan.Slice(4, 4));
Assert.False(excludedChunkTypes.Contains(chunkType), $"{chunkType} chunk should have been excluded");
if (expectedChunkTypes.ContainsKey(chunkType))
{
expectedChunkTypes[chunkType] = true;
}
bytesSpan = bytesSpan.Slice(4 + 4 + length + 4);
}
// all expected chunk types should have been seen at least once.
foreach (PngChunkType chunkType in expectedChunkTypes.Keys)
{
Assert.True(expectedChunkTypes[chunkType], $"We expect {chunkType} chunk to be present at least once");
}
}
[Theory]
[InlineData(PngChunkFilter.ExcludeGammaChunk)]
[InlineData(PngChunkFilter.ExcludeExifChunk)]

Loading…
Cancel
Save