diff --git a/src/ImageSharp/Formats/Png/PngDecoderCore.cs b/src/ImageSharp/Formats/Png/PngDecoderCore.cs
index 19e8b62fe..b24a5eabd 100644
--- a/src/ImageSharp/Formats/Png/PngDecoderCore.cs
+++ b/src/ImageSharp/Formats/Png/PngDecoderCore.cs
@@ -1159,6 +1159,7 @@ namespace SixLabors.ImageSharp.Formats.Png
///
/// Reads the cycle redundancy chunk from the data.
///
+ [MethodImpl(InliningOptions.ShortMethod)]
private uint ReadChunkCrc()
{
uint crc = 0;
@@ -1174,6 +1175,7 @@ namespace SixLabors.ImageSharp.Formats.Png
/// Skips the chunk data and the cycle redundancy chunk read from the data.
///
/// The image format chunk.
+ [MethodImpl(InliningOptions.ShortMethod)]
private void SkipChunkDataAndCrc(in PngChunk chunk)
{
this.currentStream.Skip(chunk.Length);
@@ -1184,6 +1186,7 @@ namespace SixLabors.ImageSharp.Formats.Png
/// Reads the chunk data from the stream.
///
/// The length of the chunk data to read.
+ [MethodImpl(InliningOptions.ShortMethod)]
private IManagedByteBuffer ReadChunkData(int length)
{
// We rent the buffer here to return it afterwards in Decode()
@@ -1200,6 +1203,7 @@ namespace SixLabors.ImageSharp.Formats.Png
///
/// Thrown if the input stream is not valid.
///
+ [MethodImpl(InliningOptions.ShortMethod)]
private PngChunkType ReadChunkType()
{
if (this.currentStream.Read(this.buffer, 0, 4) == 4)
@@ -1221,6 +1225,7 @@ namespace SixLabors.ImageSharp.Formats.Png
///
/// Whether the length was read.
///
+ [MethodImpl(InliningOptions.ShortMethod)]
private bool TryReadChunkLength(out int result)
{
if (this.currentStream.Read(this.buffer, 0, 4) == 4)
diff --git a/src/ImageSharp/Formats/Png/PngThrowHelper.cs b/src/ImageSharp/Formats/Png/PngThrowHelper.cs
index bc6093948..00b40c50b 100644
--- a/src/ImageSharp/Formats/Png/PngThrowHelper.cs
+++ b/src/ImageSharp/Formats/Png/PngThrowHelper.cs
@@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System;
+using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.Formats.Png
@@ -17,13 +18,16 @@ namespace SixLabors.ImageSharp.Formats.Png
[MethodImpl(InliningOptions.ColdPath)]
public static void ThrowNoData() => throw new ImageFormatException("PNG Image does not contain a data chunk");
+ [MethodImpl(InliningOptions.ColdPath)]
public static void ThrowInvalidChunkType() => throw new ImageFormatException("Invalid PNG data.");
[MethodImpl(InliningOptions.ColdPath)]
public static void ThrowInvalidChunkCrc(string chunkTypeName) => throw new ImageFormatException($"CRC Error. PNG {chunkTypeName} chunk is corrupt!");
+ [MethodImpl(InliningOptions.ColdPath)]
public static void ThrowNotSupportedColor() => new NotSupportedException("Unsupported PNG color type");
+ [MethodImpl(InliningOptions.ColdPath)]
public static void ThrowUnknownFilter() => throw new ImageFormatException("Unknown filter type.");
}
}
diff --git a/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.Chunks.cs b/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.Chunks.cs
index e976d5a76..660d5b724 100644
--- a/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.Chunks.cs
+++ b/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.Chunks.cs
@@ -54,7 +54,6 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
[InlineData((uint)PngChunkType.Header)] // IHDR
[InlineData((uint)PngChunkType.Palette)] // PLTE
// [InlineData(PngChunkTypes.Data)] //TODO: Figure out how to test this
- [InlineData((uint)PngChunkType.End)] // IEND
public void Decode_IncorrectCRCForCriticalChunk_ExceptionIsThrown(uint chunkType)
{
string chunkName = GetChunkTypeName(chunkType);
@@ -74,26 +73,6 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
}
}
- [Theory]
- [InlineData((uint)PngChunkType.Gamma)] // gAMA
- [InlineData((uint)PngChunkType.Transparency)] // tRNS
- [InlineData((uint)PngChunkType.Physical)] // pHYs: It's ok to test physical as we don't throw for duplicate chunks.
- //[InlineData(PngChunkTypes.Text)] //TODO: Figure out how to test this
- public void Decode_IncorrectCRCForNonCriticalChunk_ExceptionIsThrown(uint chunkType)
- {
- string chunkName = GetChunkTypeName(chunkType);
-
- using (var memStream = new MemoryStream())
- {
- WriteHeaderChunk(memStream);
- WriteChunk(memStream, chunkName);
- WriteDataChunk(memStream);
-
- var decoder = new PngDecoder();
- decoder.Decode(null, memStream);
- }
- }
-
private static string GetChunkTypeName(uint value)
{
var data = new byte[4];
diff --git a/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs
index e064c0fb0..1acb4fe2d 100644
--- a/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs
+++ b/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs
@@ -4,11 +4,11 @@
// ReSharper disable InconsistentNaming
using System.IO;
-
+using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Formats.Png;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison;
-
+using SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs;
using Xunit;
namespace SixLabors.ImageSharp.Tests.Formats.Png
@@ -42,6 +42,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
TestImages.Png.Bad.ZlibOverflow,
TestImages.Png.Bad.ZlibOverflow2,
TestImages.Png.Bad.ZlibZtxtBadHeader,
+ TestImages.Png.Bad.Issue1047_BadEndChunk
};
public static readonly string[] TestImages48Bpp =
@@ -90,7 +91,15 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
using (Image image = provider.GetImage(new PngDecoder()))
{
image.DebugSave(provider);
- image.CompareToOriginal(provider, ImageComparer.Exact);
+
+ if (provider.Utility.SourceFileOrDescription == TestImages.Png.Bad.Issue1047_BadEndChunk)
+ {
+ image.CompareToOriginal(provider, ImageComparer.Exact, (IImageDecoder)SystemDrawingReferenceDecoder.Instance);
+ }
+ else
+ {
+ image.CompareToOriginal(provider, ImageComparer.Exact);
+ }
}
}
diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs
index 177749869..d19dbe834 100644
--- a/tests/ImageSharp.Tests/TestImages.cs
+++ b/tests/ImageSharp.Tests/TestImages.cs
@@ -99,6 +99,7 @@ namespace SixLabors.ImageSharp.Tests
public const string ZlibOverflow = "Png/zlib-overflow.png";
public const string ZlibOverflow2 = "Png/zlib-overflow2.png";
public const string ZlibZtxtBadHeader = "Png/zlib-ztxt-bad-header.png";
+ public const string Issue1047_BadEndChunk = "Png/issues/Issue_1047.png";
}
public static readonly string[] All =
diff --git a/tests/Images/Input/Png/issues/Issue_1047.png b/tests/Images/Input/Png/issues/Issue_1047.png
new file mode 100644
index 000000000..0f85dc53c
Binary files /dev/null and b/tests/Images/Input/Png/issues/Issue_1047.png differ