@@ -38,7 +38,7 @@ internal sealed class PngDecoderCore : IImageDecoderInternals
3838 private readonly bool ignoreMetadata ;
3939
4040 /// <summary>
41- /// Gets or sets a value indicating whether to read the header and trns chunks only.
41+ /// Gets or sets a value indicating whether to read the IHDR and tRNS chunks only.
4242 /// </summary>
4343 private readonly bool colorMetadataOnly ;
4444
@@ -82,16 +82,6 @@ internal sealed class PngDecoderCore : IImageDecoderInternals
8282 /// </summary>
8383 private byte [ ] paletteAlpha ;
8484
85- /// <summary>
86- /// A value indicating whether the header chunk has been reached.
87- /// </summary>
88- private bool isHeaderChunkReached ;
89-
90- /// <summary>
91- /// A value indicating whether the end chunk has been reached.
92- /// </summary>
93- private bool isEndChunkReached ;
94-
9585 /// <summary>
9686 /// Previous scanline processed.
9787 /// </summary>
@@ -161,7 +151,7 @@ public Image<TPixel> Decode<TPixel>(BufferedReadStream stream, CancellationToken
161151 Image < TPixel > image = null ;
162152 try
163153 {
164- while ( ! this . isEndChunkReached && this . TryReadChunk ( out PngChunk chunk ) )
154+ while ( this . TryReadChunk ( out PngChunk chunk ) )
165155 {
166156 try
167157 {
@@ -215,8 +205,7 @@ public Image<TPixel> Decode<TPixel>(BufferedReadStream stream, CancellationToken
215205
216206 break ;
217207 case PngChunkType . End :
218- this . isEndChunkReached = true ;
219- break ;
208+ goto EOF ;
220209 case PngChunkType . ProprietaryApple :
221210 PngThrowHelper . ThrowInvalidChunkType ( "Proprietary Apple PNG detected! This PNG file is not conform to the specification and cannot be decoded." ) ;
222211 break ;
@@ -228,6 +217,7 @@ public Image<TPixel> Decode<TPixel>(BufferedReadStream stream, CancellationToken
228217 }
229218 }
230219
220+ EOF :
231221 if ( image is null )
232222 {
233223 PngThrowHelper . ThrowNoData ( ) ;
@@ -251,15 +241,14 @@ public IImageInfo Identify(BufferedReadStream stream, CancellationToken cancella
251241 this . currentStream . Skip ( 8 ) ;
252242 try
253243 {
254- while ( ! this . isEndChunkReached && this . TryReadChunk ( out PngChunk chunk ) )
244+ while ( this . TryReadChunk ( out PngChunk chunk ) )
255245 {
256246 try
257247 {
258248 switch ( chunk . Type )
259249 {
260250 case PngChunkType . Header :
261251 this . ReadHeaderChunk ( pngMetadata , chunk . Data . GetSpan ( ) ) ;
262- this . isHeaderChunkReached = true ;
263252 break ;
264253 case PngChunkType . Physical :
265254 if ( this . colorMetadataOnly )
@@ -280,6 +269,13 @@ public IImageInfo Identify(BufferedReadStream stream, CancellationToken cancella
280269 this . ReadGammaChunk ( pngMetadata , chunk . Data . GetSpan ( ) ) ;
281270 break ;
282271 case PngChunkType . Data :
272+
273+ // Spec says tRNS must be before IDAT so safe to exit.
274+ if ( this . colorMetadataOnly )
275+ {
276+ goto EOF ;
277+ }
278+
283279 this . SkipChunkDataAndCrc ( chunk ) ;
284280 break ;
285281 case PngChunkType . Transparency :
@@ -288,10 +284,9 @@ public IImageInfo Identify(BufferedReadStream stream, CancellationToken cancella
288284 this . paletteAlpha = alpha ;
289285 this . AssignTransparentMarkers ( alpha , pngMetadata ) ;
290286
291- if ( this . colorMetadataOnly && this . isHeaderChunkReached )
287+ if ( this . colorMetadataOnly )
292288 {
293- // Quick exit
294- this . isEndChunkReached = true ;
289+ goto EOF ;
295290 }
296291
297292 break ;
@@ -338,28 +333,28 @@ public IImageInfo Identify(BufferedReadStream stream, CancellationToken cancella
338333
339334 break ;
340335 case PngChunkType . End :
341- this . isEndChunkReached = true ;
342- break ;
336+ goto EOF ;
343337 }
344338 }
345339 finally
346340 {
347341 chunk . Data ? . Dispose ( ) ; // Data is rented in ReadChunkData()
348342 }
349343 }
344+
345+ EOF :
346+ if ( this . header . Width == 0 && this . header . Height == 0 )
347+ {
348+ PngThrowHelper . ThrowNoHeader ( ) ;
349+ }
350+
351+ return new ImageInfo ( new PixelTypeInfo ( this . CalculateBitsPerPixel ( ) ) , this . header . Width , this . header . Height , metadata ) ;
350352 }
351353 finally
352354 {
353355 this . scanline ? . Dispose ( ) ;
354356 this . previousScanline ? . Dispose ( ) ;
355357 }
356-
357- if ( this . header . Width == 0 && this . header . Height == 0 )
358- {
359- PngThrowHelper . ThrowNoHeader ( ) ;
360- }
361-
362- return new ImageInfo ( new PixelTypeInfo ( this . CalculateBitsPerPixel ( ) ) , this . header . Width , this . header . Height , metadata ) ;
363358 }
364359
365360 /// <summary>
@@ -1212,7 +1207,7 @@ private bool TryReadChunk(out PngChunk chunk)
12121207 PngChunkType type = this . ReadChunkType ( ) ;
12131208
12141209 // NOTE: Reading the Data chunk is the responsible of the caller
1215- // If we're reading color metadata only we're only interested in the Header and Transparancy chunks.
1210+ // If we're reading color metadata only we're only interested in the IHDR and tRNS chunks.
12161211 // We can skip all other chunk data in the stream for better performance.
12171212 if ( type == PngChunkType . Data || ( this . colorMetadataOnly && type != PngChunkType . Header && type != PngChunkType . Transparency ) )
12181213 {
0 commit comments