55using System . Buffers . Binary ;
66using System . Collections . Generic ;
77using System . IO ;
8+ using System . IO . Compression ;
89using System . Runtime . CompilerServices ;
910using System . Runtime . InteropServices ;
1011using System . Text ;
@@ -175,11 +176,7 @@ public Image<TPixel> Decode<TPixel>(Stream stream)
175176 this . InitializeImage ( metadata , out image ) ;
176177 }
177178
178- using ( var deframeStream = new ZlibInflateStream ( this . currentStream , this . ReadNextDataChunk ) )
179- {
180- deframeStream . AllocateNewBytes ( chunk . Length ) ;
181- this . ReadScanlines ( deframeStream . CompressedStream , image . Frames . RootFrame , pngMetadata ) ;
182- }
179+ this . ReadScanlines ( chunk , image . Frames . RootFrame , pngMetadata ) ;
183180
184181 break ;
185182 case PngChunkType . Palette :
@@ -465,19 +462,25 @@ private int CalculateScanlineLength(int width)
465462 /// Reads the scanlines within the image.
466463 /// </summary>
467464 /// <typeparam name="TPixel">The pixel format.</typeparam>
468- /// <param name="dataStream ">The <see cref="MemoryStream"/> containing data.</param>
465+ /// <param name="chunk ">The png chunk containing the compressed scanline data.</param>
469466 /// <param name="image"> The pixel data.</param>
470467 /// <param name="pngMetadata">The png metadata</param>
471- private void ReadScanlines < TPixel > ( Stream dataStream , ImageFrame < TPixel > image , PngMetadata pngMetadata )
468+ private void ReadScanlines < TPixel > ( PngChunk chunk , ImageFrame < TPixel > image , PngMetadata pngMetadata )
472469 where TPixel : struct , IPixel < TPixel >
473470 {
474- if ( this . header . InterlaceMethod == PngInterlaceMode . Adam7 )
475- {
476- this . DecodeInterlacedPixelData ( dataStream , image , pngMetadata ) ;
477- }
478- else
471+ using ( var deframeStream = new ZlibInflateStream ( this . currentStream , this . ReadNextDataChunk ) )
479472 {
480- this . DecodePixelData ( dataStream , image , pngMetadata ) ;
473+ deframeStream . AllocateNewBytes ( chunk . Length , true ) ;
474+ DeflateStream dataStream = deframeStream . CompressedStream ;
475+
476+ if ( this . header . InterlaceMethod == PngInterlaceMode . Adam7 )
477+ {
478+ this . DecodeInterlacedPixelData ( dataStream , image , pngMetadata ) ;
479+ }
480+ else
481+ {
482+ this . DecodePixelData ( dataStream , image , pngMetadata ) ;
483+ }
481484 }
482485 }
483486
@@ -924,7 +927,11 @@ private void ReadCompressedTextChunk(PngMetadata metadata, ReadOnlySpan<byte> da
924927 }
925928
926929 ReadOnlySpan < byte > compressedData = data . Slice ( zeroIndex + 2 ) ;
927- metadata . TextData . Add ( new PngTextData ( name , this . UncompressTextData ( compressedData , PngConstants . Encoding ) , string . Empty , string . Empty ) ) ;
930+
931+ if ( this . TryUncompressTextData ( compressedData , PngConstants . Encoding , out string uncompressed ) )
932+ {
933+ metadata . TextData . Add ( new PngTextData ( name , uncompressed , string . Empty , string . Empty ) ) ;
934+ }
928935 }
929936
930937 /// <summary>
@@ -987,7 +994,11 @@ private void ReadInternationalTextChunk(PngMetadata metadata, ReadOnlySpan<byte>
987994 if ( compressionFlag == 1 )
988995 {
989996 ReadOnlySpan < byte > compressedData = data . Slice ( dataStartIdx ) ;
990- metadata . TextData . Add ( new PngTextData ( keyword , this . UncompressTextData ( compressedData , PngConstants . TranslatedEncoding ) , language , translatedKeyword ) ) ;
997+
998+ if ( this . TryUncompressTextData ( compressedData , PngConstants . TranslatedEncoding , out string uncompressed ) )
999+ {
1000+ metadata . TextData . Add ( new PngTextData ( keyword , uncompressed , language , translatedKeyword ) ) ;
1001+ }
9911002 }
9921003 else
9931004 {
@@ -1001,13 +1012,19 @@ private void ReadInternationalTextChunk(PngMetadata metadata, ReadOnlySpan<byte>
10011012 /// </summary>
10021013 /// <param name="compressedData">Compressed text data bytes.</param>
10031014 /// <param name="encoding">The string encoding to use.</param>
1004- /// <returns>A string.</returns>
1005- private string UncompressTextData ( ReadOnlySpan < byte > compressedData , Encoding encoding )
1015+ /// <param name="value">The uncompressed value.</param>
1016+ /// <returns>The <see cref="bool"/>.</returns>
1017+ private bool TryUncompressTextData ( ReadOnlySpan < byte > compressedData , Encoding encoding , out string value )
10061018 {
10071019 using ( var memoryStream = new MemoryStream ( compressedData . ToArray ( ) ) )
1008- using ( var inflateStream = new ZlibInflateStream ( memoryStream , ( ) => 0 ) )
1020+ using ( var inflateStream = new ZlibInflateStream ( memoryStream ) )
10091021 {
1010- inflateStream . AllocateNewBytes ( compressedData . Length ) ;
1022+ if ( ! inflateStream . AllocateNewBytes ( compressedData . Length , false ) )
1023+ {
1024+ value = null ;
1025+ return false ;
1026+ }
1027+
10111028 var uncompressedBytes = new List < byte > ( ) ;
10121029
10131030 // Note: this uses the a buffer which is only 4 bytes long to read the stream, maybe allocating a larger buffer makes sense here.
@@ -1018,7 +1035,8 @@ private string UncompressTextData(ReadOnlySpan<byte> compressedData, Encoding en
10181035 bytesRead = inflateStream . CompressedStream . Read ( this . buffer , 0 , this . buffer . Length ) ;
10191036 }
10201037
1021- return encoding . GetString ( uncompressedBytes . ToArray ( ) ) ;
1038+ value = encoding . GetString ( uncompressedBytes . ToArray ( ) ) ;
1039+ return true ;
10221040 }
10231041 }
10241042
0 commit comments