Browse Source

- do not loop trough the entire rented array but only the bytesPerScanline.

- zero out the previousScanline because it might not have zero values all the way trough the array
af/merge-core
luuk 10 years ago
parent
commit
89b4072cf1
  1. 5
      src/ImageSharp/Formats/Png/Filters/AverageFilter.cs
  2. 5
      src/ImageSharp/Formats/Png/Filters/PaethFilter.cs
  3. 5
      src/ImageSharp/Formats/Png/Filters/SubFilter.cs
  4. 5
      src/ImageSharp/Formats/Png/Filters/UpFilter.cs
  5. 25
      src/ImageSharp/Formats/Png/PngDecoderCore.cs

5
src/ImageSharp/Formats/Png/Filters/AverageFilter.cs

@ -19,14 +19,15 @@ namespace ImageSharp.Formats
/// </summary> /// </summary>
/// <param name="scanline">The scanline to decode</param> /// <param name="scanline">The scanline to decode</param>
/// <param name="previousScanline">The previous scanline.</param> /// <param name="previousScanline">The previous scanline.</param>
/// <param name="bytesPerScanline">The number of bytes per scanline</param>
/// <param name="bytesPerPixel">The bytes per pixel.</param> /// <param name="bytesPerPixel">The bytes per pixel.</param>
public static void Decode(byte[] scanline, byte[] previousScanline, int bytesPerPixel) public static void Decode(byte[] scanline, byte[] previousScanline, int bytesPerScanline, int bytesPerPixel)
{ {
// Average(x) + floor((Raw(x-bpp)+Prior(x))/2) // Average(x) + floor((Raw(x-bpp)+Prior(x))/2)
fixed (byte* scan = scanline) fixed (byte* scan = scanline)
fixed (byte* prev = previousScanline) fixed (byte* prev = previousScanline)
{ {
for (int x = 1; x < scanline.Length; x++) for (int x = 1; x < bytesPerScanline; x++)
{ {
byte left = (x - bytesPerPixel < 1) ? (byte)0 : scan[x - bytesPerPixel]; byte left = (x - bytesPerPixel < 1) ? (byte)0 : scan[x - bytesPerPixel];
byte above = prev[x]; byte above = prev[x];

5
src/ImageSharp/Formats/Png/Filters/PaethFilter.cs

@ -20,14 +20,15 @@ namespace ImageSharp.Formats
/// </summary> /// </summary>
/// <param name="scanline">The scanline to decode</param> /// <param name="scanline">The scanline to decode</param>
/// <param name="previousScanline">The previous scanline.</param> /// <param name="previousScanline">The previous scanline.</param>
/// <param name="bytesPerScanline">The number of bytes per scanline</param>
/// <param name="bytesPerPixel">The bytes per pixel.</param> /// <param name="bytesPerPixel">The bytes per pixel.</param>
public static void Decode(byte[] scanline, byte[] previousScanline, int bytesPerPixel) public static void Decode(byte[] scanline, byte[] previousScanline, int bytesPerScanline, int bytesPerPixel)
{ {
// Paeth(x) + PaethPredictor(Raw(x-bpp), Prior(x), Prior(x-bpp)) // Paeth(x) + PaethPredictor(Raw(x-bpp), Prior(x), Prior(x-bpp))
fixed (byte* scan = scanline) fixed (byte* scan = scanline)
fixed (byte* prev = previousScanline) fixed (byte* prev = previousScanline)
{ {
for (int x = 1; x < scanline.Length; x++) for (int x = 1; x < bytesPerScanline; x++)
{ {
byte left = (x - bytesPerPixel < 1) ? (byte)0 : scan[x - bytesPerPixel]; byte left = (x - bytesPerPixel < 1) ? (byte)0 : scan[x - bytesPerPixel];
byte above = prev[x]; byte above = prev[x];

5
src/ImageSharp/Formats/Png/Filters/SubFilter.cs

@ -16,13 +16,14 @@ namespace ImageSharp.Formats
/// Decodes the scanline /// Decodes the scanline
/// </summary> /// </summary>
/// <param name="scanline">The scanline to decode</param> /// <param name="scanline">The scanline to decode</param>
/// <param name="bytesPerScanline">The number of bytes per scanline</param>
/// <param name="bytesPerPixel">The bytes per pixel.</param> /// <param name="bytesPerPixel">The bytes per pixel.</param>
public static void Decode(byte[] scanline, int bytesPerPixel) public static void Decode(byte[] scanline, int bytesPerScanline, int bytesPerPixel)
{ {
// Sub(x) + Raw(x-bpp) // Sub(x) + Raw(x-bpp)
fixed (byte* scan = scanline) fixed (byte* scan = scanline)
{ {
for (int x = 1; x < scanline.Length; x++) for (int x = 1; x < bytesPerScanline; x++)
{ {
byte priorRawByte = (x - bytesPerPixel < 1) ? (byte)0 : scan[x - bytesPerPixel]; byte priorRawByte = (x - bytesPerPixel < 1) ? (byte)0 : scan[x - bytesPerPixel];
scan[x] = (byte)((scan[x] + priorRawByte) % 256); scan[x] = (byte)((scan[x] + priorRawByte) % 256);

5
src/ImageSharp/Formats/Png/Filters/UpFilter.cs

@ -17,13 +17,14 @@ namespace ImageSharp.Formats
/// </summary> /// </summary>
/// <param name="scanline">The scanline to decode</param> /// <param name="scanline">The scanline to decode</param>
/// <param name="previousScanline">The previous scanline.</param> /// <param name="previousScanline">The previous scanline.</param>
public static void Decode(byte[] scanline, byte[] previousScanline) /// <param name="bytesPerScanline">The number of bytes per scanline</param>
public static void Decode(byte[] scanline, byte[] previousScanline, int bytesPerScanline)
{ {
// Up(x) + Prior(x) // Up(x) + Prior(x)
fixed (byte* scan = scanline) fixed (byte* scan = scanline)
fixed (byte* prev = previousScanline) fixed (byte* prev = previousScanline)
{ {
for (int x = 1; x < scanline.Length; x++) for (int x = 1; x < bytesPerScanline; x++)
{ {
byte above = prev[x]; byte above = prev[x];

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

@ -197,11 +197,12 @@ namespace ImageSharp.Formats
/// by a the specified number of bits. /// by a the specified number of bits.
/// </summary> /// </summary>
/// <param name="source">The bytes to convert from. Cannot be null.</param> /// <param name="source">The bytes to convert from. Cannot be null.</param>
/// <param name="bytesPerScanline">The number of bytes per scanline</param>
/// <param name="bits">The number of bits per value.</param> /// <param name="bits">The number of bits per value.</param>
/// <returns>The resulting <see cref="T:byte[]"/> array. Is never null.</returns> /// <returns>The resulting <see cref="T:byte[]"/> array. Is never null.</returns>
/// <exception cref="System.ArgumentNullException"><paramref name="source"/> is null.</exception> /// <exception cref="System.ArgumentNullException"><paramref name="source"/> is null.</exception>
/// <exception cref="System.ArgumentException"><paramref name="bits"/> is less than or equals than zero.</exception> /// <exception cref="System.ArgumentException"><paramref name="bits"/> is less than or equals than zero.</exception>
private static byte[] ToArrayByBitsLength(byte[] source, int bits) private static byte[] ToArrayByBitsLength(byte[] source, int bytesPerScanline, int bits)
{ {
Guard.NotNull(source, nameof(source)); Guard.NotNull(source, nameof(source));
Guard.MustBeGreaterThan(bits, 0, nameof(bits)); Guard.MustBeGreaterThan(bits, 0, nameof(bits));
@ -210,12 +211,12 @@ namespace ImageSharp.Formats
if (bits < 8) if (bits < 8)
{ {
result = new byte[source.Length * 8 / bits]; result = new byte[bytesPerScanline * 8 / bits];
int mask = 0xFF >> (8 - bits); int mask = 0xFF >> (8 - bits);
int resultOffset = 0; int resultOffset = 0;
// ReSharper disable once ForCanBeConvertedToForeach // ReSharper disable once ForCanBeConvertedToForeach
for (int i = 0; i < source.Length; i++) for (int i = 0; i < bytesPerScanline; i++)
{ {
byte b = source[i]; byte b = source[i];
for (int shift = 0; shift < 8; shift += bits) for (int shift = 0; shift < 8; shift += bits)
@ -338,6 +339,12 @@ namespace ImageSharp.Formats
byte[] previousScanline = ArrayPool<byte>.Shared.Rent(this.bytesPerScanline); byte[] previousScanline = ArrayPool<byte>.Shared.Rent(this.bytesPerScanline);
byte[] scanline = ArrayPool<byte>.Shared.Rent(this.bytesPerScanline); byte[] scanline = ArrayPool<byte>.Shared.Rent(this.bytesPerScanline);
// Zero out the previousScanline, because the bytes that are rented from the arraypool may not be zero.
for (var i = 0; i < bytesPerScanline; i++)
{
previousScanline[i] = 0x00;
}
try try
{ {
for (int y = 0; y < this.header.Height; y++) for (int y = 0; y < this.header.Height; y++)
@ -356,25 +363,25 @@ namespace ImageSharp.Formats
case FilterType.Sub: case FilterType.Sub:
SubFilter.Decode(scanline, this.bytesPerPixel); SubFilter.Decode(scanline, this.bytesPerScanline, this.bytesPerPixel);
break; break;
case FilterType.Up: case FilterType.Up:
UpFilter.Decode(scanline, previousScanline); UpFilter.Decode(scanline, previousScanline, this.bytesPerScanline);
break; break;
case FilterType.Average: case FilterType.Average:
AverageFilter.Decode(scanline, previousScanline, this.bytesPerPixel); AverageFilter.Decode(scanline, previousScanline, this.bytesPerScanline, this.bytesPerPixel);
break; break;
case FilterType.Paeth: case FilterType.Paeth:
PaethFilter.Decode(scanline, previousScanline, this.bytesPerPixel); PaethFilter.Decode(scanline, previousScanline, this.bytesPerScanline, this.bytesPerPixel);
break; break;
@ -411,7 +418,7 @@ namespace ImageSharp.Formats
{ {
case PngColorType.Grayscale: case PngColorType.Grayscale:
int factor = 255 / ((int)Math.Pow(2, this.header.BitDepth) - 1); int factor = 255 / ((int)Math.Pow(2, this.header.BitDepth) - 1);
byte[] newScanline1 = ToArrayByBitsLength(defilteredScanline, this.header.BitDepth); byte[] newScanline1 = ToArrayByBitsLength(defilteredScanline, this.bytesPerScanline, this.header.BitDepth);
for (int x = 0; x < this.header.Width; x++) for (int x = 0; x < this.header.Width; x++)
{ {
int offset = 1 + ((x + 1) * this.bytesPerPixel); int offset = 1 + ((x + 1) * this.bytesPerPixel);
@ -439,7 +446,7 @@ namespace ImageSharp.Formats
case PngColorType.Palette: case PngColorType.Palette:
byte[] newScanline = ToArrayByBitsLength(defilteredScanline, this.header.BitDepth); byte[] newScanline = ToArrayByBitsLength(defilteredScanline, this.bytesPerScanline, this.header.BitDepth);
if (this.paletteAlpha != null && this.paletteAlpha.Length > 0) if (this.paletteAlpha != null && this.paletteAlpha.Length > 0)
{ {

Loading…
Cancel
Save