diff --git a/src/ImageSharp/Formats/Png/PngDecoderCore.cs b/src/ImageSharp/Formats/Png/PngDecoderCore.cs
index bc2bb95298..ffaa9d567f 100644
--- a/src/ImageSharp/Formats/Png/PngDecoderCore.cs
+++ b/src/ImageSharp/Formats/Png/PngDecoderCore.cs
@@ -38,7 +38,7 @@ namespace SixLabors.ImageSharp.Formats.Png
private readonly bool ignoreMetadata;
///
- /// Gets or sets a value indicating whether to read the header and trns chunks only.
+ /// Gets or sets a value indicating whether to read the IHDR and tRNS chunks only.
///
private readonly bool colorMetadataOnly;
@@ -82,16 +82,6 @@ namespace SixLabors.ImageSharp.Formats.Png
///
private byte[] paletteAlpha;
- ///
- /// A value indicating whether the header chunk has been reached.
- ///
- private bool isHeaderChunkReached;
-
- ///
- /// A value indicating whether the end chunk has been reached.
- ///
- private bool isEndChunkReached;
-
///
/// Previous scanline processed.
///
@@ -161,7 +151,7 @@ namespace SixLabors.ImageSharp.Formats.Png
Image image = null;
try
{
- while (!this.isEndChunkReached && this.TryReadChunk(out PngChunk chunk))
+ while (this.TryReadChunk(out PngChunk chunk))
{
try
{
@@ -215,8 +205,7 @@ namespace SixLabors.ImageSharp.Formats.Png
break;
case PngChunkType.End:
- this.isEndChunkReached = true;
- break;
+ goto EOF;
case PngChunkType.ProprietaryApple:
PngThrowHelper.ThrowInvalidChunkType("Proprietary Apple PNG detected! This PNG file is not conform to the specification and cannot be decoded.");
break;
@@ -228,6 +217,7 @@ namespace SixLabors.ImageSharp.Formats.Png
}
}
+ EOF:
if (image is null)
{
PngThrowHelper.ThrowNoData();
@@ -251,7 +241,7 @@ namespace SixLabors.ImageSharp.Formats.Png
this.currentStream.Skip(8);
try
{
- while (!this.isEndChunkReached && this.TryReadChunk(out PngChunk chunk))
+ while (this.TryReadChunk(out PngChunk chunk))
{
try
{
@@ -259,7 +249,6 @@ namespace SixLabors.ImageSharp.Formats.Png
{
case PngChunkType.Header:
this.ReadHeaderChunk(pngMetadata, chunk.Data.GetSpan());
- this.isHeaderChunkReached = true;
break;
case PngChunkType.Physical:
if (this.colorMetadataOnly)
@@ -280,6 +269,13 @@ namespace SixLabors.ImageSharp.Formats.Png
this.ReadGammaChunk(pngMetadata, chunk.Data.GetSpan());
break;
case PngChunkType.Data:
+
+ // Spec says tRNS must be before IDAT so safe to exit.
+ if (this.colorMetadataOnly)
+ {
+ goto EOF;
+ }
+
this.SkipChunkDataAndCrc(chunk);
break;
case PngChunkType.Transparency:
@@ -288,10 +284,9 @@ namespace SixLabors.ImageSharp.Formats.Png
this.paletteAlpha = alpha;
this.AssignTransparentMarkers(alpha, pngMetadata);
- if (this.colorMetadataOnly && this.isHeaderChunkReached)
+ if (this.colorMetadataOnly)
{
- // Quick exit
- this.isEndChunkReached = true;
+ goto EOF;
}
break;
@@ -338,8 +333,7 @@ namespace SixLabors.ImageSharp.Formats.Png
break;
case PngChunkType.End:
- this.isEndChunkReached = true;
- break;
+ goto EOF;
}
}
finally
@@ -347,19 +341,20 @@ namespace SixLabors.ImageSharp.Formats.Png
chunk.Data?.Dispose(); // Data is rented in ReadChunkData()
}
}
+
+ EOF:
+ if (this.header.Width == 0 && this.header.Height == 0)
+ {
+ PngThrowHelper.ThrowNoHeader();
+ }
+
+ return new ImageInfo(new PixelTypeInfo(this.CalculateBitsPerPixel()), this.header.Width, this.header.Height, metadata);
}
finally
{
this.scanline?.Dispose();
this.previousScanline?.Dispose();
}
-
- if (this.header.Width == 0 && this.header.Height == 0)
- {
- PngThrowHelper.ThrowNoHeader();
- }
-
- return new ImageInfo(new PixelTypeInfo(this.CalculateBitsPerPixel()), this.header.Width, this.header.Height, metadata);
}
///
@@ -1212,7 +1207,7 @@ namespace SixLabors.ImageSharp.Formats.Png
PngChunkType type = this.ReadChunkType();
// NOTE: Reading the Data chunk is the responsible of the caller
- // If we're reading color metadata only we're only interested in the Header and Transparancy chunks.
+ // If we're reading color metadata only we're only interested in the IHDR and tRNS chunks.
// We can skip all other chunk data in the stream for better performance.
if (type == PngChunkType.Data || (this.colorMetadataOnly && type != PngChunkType.Header && type != PngChunkType.Transparency))
{