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

Loading…
Cancel
Save