Skip to content

Commit

Permalink
Clean up scanline decoding code.
Browse files Browse the repository at this point in the history
  • Loading branch information
JimBobSquarePants committed Sep 10, 2019
1 parent 5d2fe83 commit 221000e
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 38 deletions.
38 changes: 17 additions & 21 deletions src/ImageSharp/Formats/Png/PngDecoderCore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Buffers.Binary;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
Expand Down Expand Up @@ -175,18 +176,7 @@ public Image<TPixel> Decode<TPixel>(Stream stream)
this.InitializeImage(metadata, out image);
}

var deframeStream = new ZlibInflateStream(this.currentStream, this.ReadNextDataChunk);
try
{
deframeStream.AllocateNewBytes(chunk.Length, true);
this.ReadScanlines(deframeStream.CompressedStream, image.Frames.RootFrame, pngMetadata);
}
finally
{
// If an invalid Zlib stream is discovered the decoder will throw an exception
// due to the critical nature of the data chunk.
deframeStream.Dispose();
}
this.ReadScanlines(chunk, image.Frames.RootFrame, pngMetadata);

break;
case PngChunkType.Palette:
Expand Down Expand Up @@ -472,19 +462,25 @@ private int CalculateScanlineLength(int width)
/// Reads the scanlines within the image.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="dataStream">The <see cref="MemoryStream"/> containing data.</param>
/// <param name="chunk">The png chunk containing the compressed scanline data.</param>
/// <param name="image"> The pixel data.</param>
/// <param name="pngMetadata">The png metadata</param>
private void ReadScanlines<TPixel>(Stream dataStream, ImageFrame<TPixel> image, PngMetadata pngMetadata)
private void ReadScanlines<TPixel>(PngChunk chunk, ImageFrame<TPixel> image, PngMetadata pngMetadata)
where TPixel : struct, IPixel<TPixel>
{
if (this.header.InterlaceMethod == PngInterlaceMode.Adam7)
{
this.DecodeInterlacedPixelData(dataStream, image, pngMetadata);
}
else
using (var deframeStream = new ZlibInflateStream(this.currentStream, this.ReadNextDataChunk))
{
this.DecodePixelData(dataStream, image, pngMetadata);
deframeStream.AllocateNewBytes(chunk.Length, true);
DeflateStream dataStream = deframeStream.CompressedStream;

if (this.header.InterlaceMethod == PngInterlaceMode.Adam7)
{
this.DecodeInterlacedPixelData(dataStream, image, pngMetadata);
}
else
{
this.DecodePixelData(dataStream, image, pngMetadata);
}
}
}

Expand Down Expand Up @@ -1021,7 +1017,7 @@ private void ReadInternationalTextChunk(PngMetadata metadata, ReadOnlySpan<byte>
private bool TryUncompressTextData(ReadOnlySpan<byte> compressedData, Encoding encoding, out string value)
{
using (var memoryStream = new MemoryStream(compressedData.ToArray()))
using (var inflateStream = new ZlibInflateStream(memoryStream, () => 0))
using (var inflateStream = new ZlibInflateStream(memoryStream))
{
if (!inflateStream.AllocateNewBytes(compressedData.Length, false))
{
Expand Down
40 changes: 23 additions & 17 deletions src/ImageSharp/Formats/Png/Zlib/ZlibInflateStream.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@ internal sealed class ZlibInflateStream : Stream
private static readonly byte[] ChecksumBuffer = new byte[4];

/// <summary>
/// The inner raw memory stream
/// A default delegate to get more data from the inner stream.
/// </summary>
private readonly Stream innerStream;
private static readonly Func<int> GetDataNoOp = () => 0;

/// <summary>
/// The compressed stream sitting over the top of the deframer
/// The inner raw memory stream
/// </summary>
private DeflateStream compressedStream;
private readonly Stream innerStream;

/// <summary>
/// A value indicating whether this instance of the given entity has been disposed.
Expand Down Expand Up @@ -55,8 +55,17 @@ internal sealed class ZlibInflateStream : Stream
/// <summary>
/// Initializes a new instance of the <see cref="ZlibInflateStream"/> class.
/// </summary>
/// <param name="innerStream">The inner raw stream</param>
/// <param name="getData">A delegate to get more data from the inner stream</param>
/// <param name="innerStream">The inner raw stream.</param>
public ZlibInflateStream(Stream innerStream)
: this(innerStream, GetDataNoOp)
{
}

/// <summary>
/// Initializes a new instance of the <see cref="ZlibInflateStream"/> class.
/// </summary>
/// <param name="innerStream">The inner raw stream.</param>
/// <param name="getData">A delegate to get more data from the inner stream.</param>
public ZlibInflateStream(Stream innerStream, Func<int> getData)
{
this.innerStream = innerStream;
Expand All @@ -76,12 +85,12 @@ public ZlibInflateStream(Stream innerStream, Func<int> getData)
public override long Length => throw new NotSupportedException();

/// <inheritdoc/>
public override long Position { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
public override long Position { get => throw new NotSupportedException(); set => throw new NotSupportedException(); }

/// <summary>
/// Gets the compressed stream over the deframed inner stream
/// </summary>
public DeflateStream CompressedStream => this.compressedStream;
public DeflateStream CompressedStream { get; private set; }

/// <summary>
/// Adds new bytes from a frame found in the original stream
Expand All @@ -92,7 +101,7 @@ public ZlibInflateStream(Stream innerStream, Func<int> getData)
public bool AllocateNewBytes(int bytes, bool isCriticalChunk)
{
this.currentDataRemaining = bytes;
if (this.compressedStream is null)
if (this.CompressedStream is null)
{
return this.InitializeInflateStream(isCriticalChunk);
}
Expand All @@ -101,10 +110,7 @@ public bool AllocateNewBytes(int bytes, bool isCriticalChunk)
}

/// <inheritdoc/>
public override void Flush()
{
throw new NotSupportedException();
}
public override void Flush() => throw new NotSupportedException();

/// <inheritdoc/>
public override int ReadByte()
Expand Down Expand Up @@ -186,10 +192,10 @@ protected override void Dispose(bool disposing)
if (disposing)
{
// dispose managed resources
if (this.compressedStream != null)
if (this.CompressedStream != null)
{
this.compressedStream.Dispose();
this.compressedStream = null;
this.CompressedStream.Dispose();
this.CompressedStream = null;
}
}

Expand Down Expand Up @@ -264,7 +270,7 @@ private bool InitializeInflateStream(bool isCriticalChunk)
}

// Initialize the deflate Stream.
this.compressedStream = new DeflateStream(this, CompressionMode.Decompress, true);
this.CompressedStream = new DeflateStream(this, CompressionMode.Decompress, true);

return true;
}
Expand Down

0 comments on commit 221000e

Please sign in to comment.