diff --git a/src/ImageSharp/Formats/Png/PngDecoderCore.cs b/src/ImageSharp/Formats/Png/PngDecoderCore.cs
index 76162eacb..ef2f22655 100644
--- a/src/ImageSharp/Formats/Png/PngDecoderCore.cs
+++ b/src/ImageSharp/Formats/Png/PngDecoderCore.cs
@@ -252,9 +252,10 @@ namespace SixLabors.ImageSharp.Formats.Png
using (var deframeStream = new ZlibInflateStream(this.currentStream, this.ReadNextDataChunk))
{
- deframeStream.AllocateNewBytes(chunk.Length);
+ deframeStream.AllocateNewBytes(chunk.Length);
this.ReadScanlines(deframeStream.CompressedStream, image.Frames.RootFrame);
}
+
break;
case PngChunkType.Palette:
byte[] pal = new byte[chunk.Length];
@@ -1376,16 +1377,23 @@ namespace SixLabors.ImageSharp.Formats.Png
/// Count of bytes in the next data chunk, or 0 if there are no more data chunks left.
private int ReadNextDataChunk()
{
- this.currentStream.Read(this.crcBuffer, 0, 4);
+ if (this.nextChunk != null)
+ {
+ return 0;
+ }
- this.TryReadChunk(out PngChunk chunk);
+ this.currentStream.Read(this.crcBuffer, 0, 4);
- if (chunk.Type == PngChunkType.Data)
+ if (this.TryReadChunk(out PngChunk chunk))
{
- return chunk.Length;
+ if (chunk.Type == PngChunkType.Data)
+ {
+ return chunk.Length;
+ }
+
+ this.nextChunk = chunk;
}
- this.nextChunk = chunk;
return 0;
}
@@ -1401,6 +1409,9 @@ namespace SixLabors.ImageSharp.Formats.Png
if (this.nextChunk != null)
{
chunk = this.nextChunk.Value;
+
+ this.nextChunk = null;
+
return true;
}
diff --git a/src/ImageSharp/Formats/Png/Zlib/ZlibInflateStream.cs b/src/ImageSharp/Formats/Png/Zlib/ZlibInflateStream.cs
index c2f6d6d88..a92220a59 100644
--- a/src/ImageSharp/Formats/Png/Zlib/ZlibInflateStream.cs
+++ b/src/ImageSharp/Formats/Png/Zlib/ZlibInflateStream.cs
@@ -42,11 +42,6 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
///
private bool isDisposed;
- ///
- /// Whether the crc value has been read.
- ///
- private bool crcRead;
-
///
/// The current data remaining to be read
///
@@ -119,17 +114,36 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
{
if (this.currentDataRemaining == 0)
{
- this.currentDataRemaining = this.getData();
+ // last buffer was read in its entirety, let's make sure we don't actually have more
+ this.currentDataRemaining = this.getData();
- if (this.currentDataRemaining == 0)
- {
- return 0;
- }
+ if (this.currentDataRemaining == 0)
+ {
+ return 0;
+ }
}
int bytesToRead = Math.Min(count, this.currentDataRemaining);
this.currentDataRemaining -= bytesToRead;
- return this.innerStream.Read(buffer, offset, bytesToRead);
+ int bytesRead = this.innerStream.Read(buffer, offset, bytesToRead);
+
+ // keep reading data until we've reached the end of the stream or filled the buffer
+ while (this.currentDataRemaining == 0 && bytesRead < count)
+ {
+ this.currentDataRemaining = this.getData();
+
+ if (this.currentDataRemaining == 0)
+ {
+ return bytesRead;
+ }
+
+ offset += bytesRead;
+ bytesToRead = Math.Min(count - bytesRead, this.currentDataRemaining);
+ this.currentDataRemaining -= bytesToRead;
+ bytesRead += this.innerStream.Read(buffer, offset, bytesToRead);
+ }
+
+ return bytesRead;
}
///
@@ -165,14 +179,6 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
{
this.compressedStream.Dispose();
this.compressedStream = null;
-
- if (!this.crcRead)
- {
- // Consume the trailing 4 bytes
- this.innerStream.Read(ChecksumBuffer, 0, 4);
- this.currentDataRemaining -= 4;
- this.crcRead = true;
- }
}
}