Browse Source

Rent the scanlines

af/merge-core
James Jackson-South 9 years ago
parent
commit
fdfbca3b28
  1. 93
      src/ImageSharp/Formats/Png/PngDecoderCore.cs

93
src/ImageSharp/Formats/Png/PngDecoderCore.cs

@ -6,11 +6,12 @@
namespace ImageSharp.Formats namespace ImageSharp.Formats
{ {
using System; using System;
using System.Buffers;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
/// <summary> /// <summary>
/// Performs the png decoding operation. /// Performs the png decoding operation.
/// </summary> /// </summary>
@ -111,8 +112,7 @@ namespace ImageSharp.Formats
/// Thrown if the image is larger than the maximum allowable size. /// Thrown if the image is larger than the maximum allowable size.
/// </exception> /// </exception>
public void Decode<TColor, TPacked>(Image<TColor, TPacked> image, Stream stream) public void Decode<TColor, TPacked>(Image<TColor, TPacked> image, Stream stream)
where TColor : struct, IPackedPixel<TPacked> where TColor : struct, IPackedPixel<TPacked> where TPacked : struct
where TPacked : struct
{ {
Image<TColor, TPacked> currentImage = image; Image<TColor, TPacked> currentImage = image;
this.currentStream = stream; this.currentStream = stream;
@ -161,8 +161,8 @@ namespace ImageSharp.Formats
if (this.header.Width > image.MaxWidth || this.header.Height > image.MaxHeight) if (this.header.Width > image.MaxWidth || this.header.Height > image.MaxHeight)
{ {
throw new ArgumentOutOfRangeException( throw new ArgumentOutOfRangeException(
$"The input png '{this.header.Width}x{this.header.Height}' is bigger than the " $"The input png '{this.header.Width}x{this.header.Height}' is bigger than the "
+ $"max allowed size '{image.MaxWidth}x{image.MaxHeight}'"); + $"max allowed size '{image.MaxWidth}x{image.MaxHeight}'");
} }
image.InitPixels(this.header.Width, this.header.Height); image.InitPixels(this.header.Width, this.header.Height);
@ -182,8 +182,7 @@ namespace ImageSharp.Formats
/// <param name="image">The image to read to.</param> /// <param name="image">The image to read to.</param>
/// <param name="data">The data containing physical data.</param> /// <param name="data">The data containing physical data.</param>
private void ReadPhysicalChunk<TColor, TPacked>(Image<TColor, TPacked> image, byte[] data) private void ReadPhysicalChunk<TColor, TPacked>(Image<TColor, TPacked> image, byte[] data)
where TColor : struct, IPackedPixel<TPacked> where TColor : struct, IPackedPixel<TPacked> where TPacked : struct
where TPacked : struct
{ {
data.ReverseBytes(0, 4); data.ReverseBytes(0, 4);
data.ReverseBytes(4, 4); data.ReverseBytes(4, 4);
@ -244,8 +243,7 @@ namespace ImageSharp.Formats
/// <param name="dataStream">The <see cref="MemoryStream"/> containing data.</param> /// <param name="dataStream">The <see cref="MemoryStream"/> containing data.</param>
/// <param name="pixels"> The pixel data.</param> /// <param name="pixels"> The pixel data.</param>
private void ReadScanlines<TColor, TPacked>(MemoryStream dataStream, PixelAccessor<TColor, TPacked> pixels) private void ReadScanlines<TColor, TPacked>(MemoryStream dataStream, PixelAccessor<TColor, TPacked> pixels)
where TColor : struct, IPackedPixel<TPacked> where TColor : struct, IPackedPixel<TPacked> where TPacked : struct
where TPacked : struct
{ {
this.bytesPerPixel = this.CalculateBytesPerPixel(); this.bytesPerPixel = this.CalculateBytesPerPixel();
this.bytesPerScanline = this.CalculateScanlineLength() + 1; this.bytesPerScanline = this.CalculateScanlineLength() + 1;
@ -270,60 +268,66 @@ namespace ImageSharp.Formats
/// <param name="compressedStream">The compressed pixel data stream.</param> /// <param name="compressedStream">The compressed pixel data stream.</param>
/// <param name="pixels">The image pixel accessor.</param> /// <param name="pixels">The image pixel accessor.</param>
private void DecodePixelData<TColor, TPacked>(Stream compressedStream, PixelAccessor<TColor, TPacked> pixels) private void DecodePixelData<TColor, TPacked>(Stream compressedStream, PixelAccessor<TColor, TPacked> pixels)
where TColor : struct, IPackedPixel<TPacked> where TColor : struct, IPackedPixel<TPacked> where TPacked : struct
where TPacked : struct
{ {
// TODO: ArrayPool<byte>.Shared.Rent(this.bytesPerScanline) byte[] previousScanline = ArrayPool<byte>.Shared.Rent(this.bytesPerScanline);
byte[] previousScanline = new byte[this.bytesPerScanline]; byte[] scanline = ArrayPool<byte>.Shared.Rent(this.bytesPerScanline);
byte[] scanline = new byte[this.bytesPerScanline];
try
for (int y = 0; y < this.header.Height; y++)
{ {
compressedStream.Read(scanline, 0, this.bytesPerScanline); for (int y = 0; y < this.header.Height; y++)
{
compressedStream.Read(scanline, 0, this.bytesPerScanline);
FilterType filterType = (FilterType)scanline[0]; FilterType filterType = (FilterType)scanline[0];
switch (filterType) switch (filterType)
{ {
case FilterType.None: case FilterType.None:
NoneFilter.Decode(scanline); NoneFilter.Decode(scanline);
break; break;
case FilterType.Sub: case FilterType.Sub:
SubFilter.Decode(scanline, this.bytesPerPixel); SubFilter.Decode(scanline, this.bytesPerPixel);
break; break;
case FilterType.Up: case FilterType.Up:
UpFilter.Decode(scanline, previousScanline); UpFilter.Decode(scanline, previousScanline);
break; break;
case FilterType.Average: case FilterType.Average:
AverageFilter.Decode(scanline, previousScanline, this.bytesPerPixel); AverageFilter.Decode(scanline, previousScanline, this.bytesPerPixel);
break; break;
case FilterType.Paeth: case FilterType.Paeth:
PaethFilter.Decode(scanline, previousScanline, this.bytesPerPixel); PaethFilter.Decode(scanline, previousScanline, this.bytesPerPixel);
break; break;
default: default:
throw new ImageFormatException("Unknown filter type."); throw new ImageFormatException("Unknown filter type.");
} }
this.ProcessDefilteredScanline(scanline, y, pixels); this.ProcessDefilteredScanline(scanline, y, pixels);
byte[] temp = previousScanline; byte[] temp = previousScanline;
previousScanline = scanline; previousScanline = scanline;
scanline = temp; scanline = temp;
}
}
finally
{
ArrayPool<byte>.Shared.Return(previousScanline);
ArrayPool<byte>.Shared.Return(scanline);
} }
} }
@ -618,10 +622,7 @@ namespace ImageSharp.Formats
/// <summary> /// <summary>
/// Calculates the length of the given chunk. /// Calculates the length of the given chunk.
/// </summary> /// </summary>
/// <param name="chunk">he chunk.</param> /// <param name="chunk">The chunk.</param>
/// <returns>
/// The <see cref="int"/> representing the chunk length.
/// </returns>
/// <exception cref="ImageFormatException"> /// <exception cref="ImageFormatException">
/// Thrown if the input stream is not valid. /// Thrown if the input stream is not valid.
/// </exception> /// </exception>

Loading…
Cancel
Save