diff --git a/src/ImageSharp/Formats/Png/Filters/AverageFilter.cs b/src/ImageSharp/Formats/Png/Filters/AverageFilter.cs
index b4ec49946..31d80c586 100644
--- a/src/ImageSharp/Formats/Png/Filters/AverageFilter.cs
+++ b/src/ImageSharp/Formats/Png/Filters/AverageFilter.cs
@@ -22,18 +22,23 @@ namespace ImageSharp.Formats
/// The number of bytes per scanline
/// The bytes per pixel.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static void Decode(byte[] scanline, byte[] previousScanline, int bytesPerScanline, int bytesPerPixel)
+ public static void Decode(ref byte scanline, ref byte previousScanline, int bytesPerScanline, int bytesPerPixel)
{
// Average(x) + floor((Raw(x-bpp)+Prior(x))/2)
- fixed (byte* scan = scanline)
- fixed (byte* prev = previousScanline)
+ for (int x = 1; x < bytesPerScanline; x++)
{
- for (int x = 1; x < bytesPerScanline; x++)
+ if (x - bytesPerPixel < 1)
{
- byte left = (x - bytesPerPixel < 1) ? (byte)0 : scan[x - bytesPerPixel];
- byte above = prev[x];
-
- scan[x] = (byte)((scan[x] + Average(left, above)) % 256);
+ ref byte scan = ref Unsafe.Add(ref scanline, x);
+ ref byte above = ref Unsafe.Add(ref previousScanline, x);
+ scan = (byte)((scan + (above >> 1)) % 256);
+ }
+ else
+ {
+ ref byte scan = ref Unsafe.Add(ref scanline, x);
+ ref byte left = ref Unsafe.Add(ref scanline, x - bytesPerPixel);
+ ref byte above = ref Unsafe.Add(ref previousScanline, x);
+ scan = (byte)((scan + Average(left, above)) % 256);
}
}
}
diff --git a/src/ImageSharp/Formats/Png/Filters/NoneFilter.cs b/src/ImageSharp/Formats/Png/Filters/NoneFilter.cs
index 5abd89296..0f67ba5fb 100644
--- a/src/ImageSharp/Formats/Png/Filters/NoneFilter.cs
+++ b/src/ImageSharp/Formats/Png/Filters/NoneFilter.cs
@@ -15,18 +15,6 @@ namespace ImageSharp.Formats
///
internal static class NoneFilter
{
- ///
- /// Decodes the scanline
- ///
- /// The scanline to decode
- /// The
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static byte[] Decode(byte[] scanline)
- {
- // No change required.
- return scanline;
- }
-
///
/// Encodes the scanline
///
diff --git a/src/ImageSharp/Formats/Png/Filters/PaethFilter.cs b/src/ImageSharp/Formats/Png/Filters/PaethFilter.cs
index a43d4f080..986a291fe 100644
--- a/src/ImageSharp/Formats/Png/Filters/PaethFilter.cs
+++ b/src/ImageSharp/Formats/Png/Filters/PaethFilter.cs
@@ -5,7 +5,6 @@
namespace ImageSharp.Formats
{
- using System;
using System.Runtime.CompilerServices;
///
@@ -24,19 +23,24 @@ namespace ImageSharp.Formats
/// The number of bytes per scanline
/// The bytes per pixel.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static void Decode(byte[] scanline, byte[] previousScanline, int bytesPerScanline, int bytesPerPixel)
+ public static void Decode(ref byte scanline, ref byte previousScanline, int bytesPerScanline, int bytesPerPixel)
{
// Paeth(x) + PaethPredictor(Raw(x-bpp), Prior(x), Prior(x-bpp))
- fixed (byte* scan = scanline)
- fixed (byte* prev = previousScanline)
+ for (int x = 1; x < bytesPerScanline; x++)
{
- for (int x = 1; x < bytesPerScanline; x++)
+ if (x - bytesPerPixel < 1)
{
- byte left = (x - bytesPerPixel < 1) ? (byte)0 : scan[x - bytesPerPixel];
- byte above = prev[x];
- byte upperLeft = (x - bytesPerPixel < 1) ? (byte)0 : prev[x - bytesPerPixel];
-
- scan[x] = (byte)((scan[x] + PaethPredicator(left, above, upperLeft)) % 256);
+ ref byte scan = ref Unsafe.Add(ref scanline, x);
+ ref byte above = ref Unsafe.Add(ref previousScanline, x);
+ scan = (byte)((scan + PaethPredicator(0, above, 0)) % 256);
+ }
+ else
+ {
+ ref byte scan = ref Unsafe.Add(ref scanline, x);
+ ref byte left = ref Unsafe.Add(ref scanline, x - bytesPerPixel);
+ ref byte above = ref Unsafe.Add(ref previousScanline, x);
+ ref byte upperLeft = ref Unsafe.Add(ref previousScanline, x - bytesPerPixel);
+ scan = (byte)((scan + PaethPredicator(left, above, upperLeft)) % 256);
}
}
}
@@ -100,4 +104,4 @@ namespace ImageSharp.Formats
return upperLeft;
}
}
-}
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Png/Filters/SubFilter.cs b/src/ImageSharp/Formats/Png/Filters/SubFilter.cs
index 4610ed0ae..1220dc5fb 100644
--- a/src/ImageSharp/Formats/Png/Filters/SubFilter.cs
+++ b/src/ImageSharp/Formats/Png/Filters/SubFilter.cs
@@ -21,15 +21,21 @@ namespace ImageSharp.Formats
/// The number of bytes per scanline
/// The bytes per pixel.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static void Decode(byte[] scanline, int bytesPerScanline, int bytesPerPixel)
+ public static void Decode(ref byte scanline, int bytesPerScanline, int bytesPerPixel)
{
// Sub(x) + Raw(x-bpp)
- fixed (byte* scan = scanline)
+ for (int x = 1; x < bytesPerScanline; x++)
{
- for (int x = 1; x < bytesPerScanline; x++)
+ if (x - bytesPerPixel < 1)
+ {
+ ref byte scan = ref Unsafe.Add(ref scanline, x);
+ scan = (byte)(scan % 256);
+ }
+ else
{
- byte priorRawByte = (x - bytesPerPixel < 1) ? (byte)0 : scan[x - bytesPerPixel];
- scan[x] = (byte)((scan[x] + priorRawByte) % 256);
+ ref byte scan = ref Unsafe.Add(ref scanline, x);
+ ref byte prev = ref Unsafe.Add(ref scanline, x - bytesPerPixel);
+ scan = (byte)((scan + prev) % 256);
}
}
}
diff --git a/src/ImageSharp/Formats/Png/Filters/UpFilter.cs b/src/ImageSharp/Formats/Png/Filters/UpFilter.cs
index 525f50d0f..ee758f64e 100644
--- a/src/ImageSharp/Formats/Png/Filters/UpFilter.cs
+++ b/src/ImageSharp/Formats/Png/Filters/UpFilter.cs
@@ -21,18 +21,14 @@ namespace ImageSharp.Formats
/// The previous scanline.
/// The number of bytes per scanline
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static void Decode(byte[] scanline, byte[] previousScanline, int bytesPerScanline)
+ public static void Decode(ref byte scanline, ref byte previousScanline, int bytesPerScanline)
{
// Up(x) + Prior(x)
- fixed (byte* scan = scanline)
- fixed (byte* prev = previousScanline)
+ for (int x = 1; x < bytesPerScanline; x++)
{
- for (int x = 1; x < bytesPerScanline; x++)
- {
- byte above = prev[x];
-
- scan[x] = (byte)((scan[x] + above) % 256);
- }
+ ref byte scan = ref Unsafe.Add(ref scanline, x);
+ ref byte above = ref Unsafe.Add(ref previousScanline, x);
+ scan = (byte)((scan + above) % 256);
}
}
diff --git a/src/ImageSharp/Formats/Png/PngDecoderCore.cs b/src/ImageSharp/Formats/Png/PngDecoderCore.cs
index 67a00efef..ae6fd859e 100644
--- a/src/ImageSharp/Formats/Png/PngDecoderCore.cs
+++ b/src/ImageSharp/Formats/Png/PngDecoderCore.cs
@@ -184,14 +184,14 @@ namespace ImageSharp.Formats
public Image Decode(Stream stream)
where TPixel : struct, IPixel
{
- ImageMetaData metadata = new ImageMetaData();
+ var metadata = new ImageMetaData();
this.currentStream = stream;
this.currentStream.Skip(8);
Image image = null;
PixelAccessor pixels = null;
try
{
- using (ZlibInflateStream deframeStream = new ZlibInflateStream(this.currentStream))
+ using (var deframeStream = new ZlibInflateStream(this.currentStream))
{
PngChunk currentChunk;
while (!this.isEndChunkReached && (currentChunk = this.ReadChunk()) != null)
@@ -437,38 +437,36 @@ namespace ImageSharp.Formats
}
this.currentRowBytesRead = 0;
- FilterType filterType = (FilterType)this.scanline[0];
+
+ var filterType = (FilterType)this.scanline[0];
+ var scanBuffer = new BufferSpan(this.scanline);
+ ref byte scanPoint = ref scanBuffer.DangerousGetPinnableReference();
+ var prevBuffer = new BufferSpan(this.previousScanline);
+ ref byte prevPoint = ref prevBuffer.DangerousGetPinnableReference();
switch (filterType)
{
case FilterType.None:
-
- NoneFilter.Decode(this.scanline);
-
break;
case FilterType.Sub:
- SubFilter.Decode(this.scanline, this.bytesPerScanline, this.bytesPerPixel);
-
+ SubFilter.Decode(ref scanPoint, this.bytesPerScanline, this.bytesPerPixel);
break;
case FilterType.Up:
- UpFilter.Decode(this.scanline, this.previousScanline, this.bytesPerScanline);
-
+ UpFilter.Decode(ref scanPoint, ref prevPoint, this.bytesPerScanline);
break;
case FilterType.Average:
- AverageFilter.Decode(this.scanline, this.previousScanline, this.bytesPerScanline, this.bytesPerPixel);
-
+ AverageFilter.Decode(ref scanPoint, ref prevPoint, this.bytesPerScanline, this.bytesPerPixel);
break;
case FilterType.Paeth:
- PaethFilter.Decode(this.scanline, this.previousScanline, this.bytesPerScanline, this.bytesPerPixel);
-
+ PaethFilter.Decode(ref scanPoint, ref prevPoint, this.bytesPerScanline, this.bytesPerPixel);
break;
default:
@@ -517,38 +515,35 @@ namespace ImageSharp.Formats
this.currentRowBytesRead = 0;
- FilterType filterType = (FilterType)this.scanline[0];
+ var filterType = (FilterType)this.scanline[0];
+ var scanBuffer = new BufferSpan(this.scanline);
+ ref byte scanPointer = ref scanBuffer.DangerousGetPinnableReference();
+ var prevBuffer = new BufferSpan(this.previousScanline);
+ ref byte prevPointer = ref prevBuffer.DangerousGetPinnableReference();
switch (filterType)
{
case FilterType.None:
-
- NoneFilter.Decode(this.scanline);
-
break;
case FilterType.Sub:
- SubFilter.Decode(this.scanline, bytesPerInterlaceScanline, this.bytesPerPixel);
-
+ SubFilter.Decode(ref scanPointer, bytesPerInterlaceScanline, this.bytesPerPixel);
break;
case FilterType.Up:
- UpFilter.Decode(this.scanline, this.previousScanline, bytesPerInterlaceScanline);
-
+ UpFilter.Decode(ref scanPointer, ref prevPointer, bytesPerInterlaceScanline);
break;
case FilterType.Average:
- AverageFilter.Decode(this.scanline, this.previousScanline, bytesPerInterlaceScanline, this.bytesPerPixel);
-
+ AverageFilter.Decode(ref scanPointer, ref prevPointer, bytesPerInterlaceScanline, this.bytesPerPixel);
break;
case FilterType.Paeth:
- PaethFilter.Decode(this.scanline, this.previousScanline, bytesPerInterlaceScanline, this.bytesPerPixel);
-
+ PaethFilter.Decode(ref scanPointer, ref prevPointer, bytesPerInterlaceScanline, this.bytesPerPixel);
break;
default:
@@ -583,9 +578,10 @@ namespace ImageSharp.Formats
private void ProcessDefilteredScanline(byte[] defilteredScanline, PixelAccessor pixels)
where TPixel : struct, IPixel
{
- TPixel color = default(TPixel);
+ var color = default(TPixel);
BufferSpan pixelBuffer = pixels.GetRowSpan(this.currentRow);
- BufferSpan scanlineBuffer = new BufferSpan(defilteredScanline, 1);
+ var scanlineBuffer = new BufferSpan(defilteredScanline, 1);
+
switch (this.PngColorType)
{
case PngColorType.Grayscale:
@@ -646,7 +642,7 @@ namespace ImageSharp.Formats
{
byte[] newScanline = ToArrayByBitsLength(defilteredScanline, this.bytesPerScanline, this.header.BitDepth);
byte[] palette = this.palette;
- TPixel color = default(TPixel);
+ var color = default(TPixel);
if (this.paletteAlpha != null && this.paletteAlpha.Length > 0)
{
@@ -703,7 +699,7 @@ namespace ImageSharp.Formats
private void ProcessInterlacedDefilteredScanline(byte[] defilteredScanline, int row, PixelAccessor pixels, int pixelOffset = 0, int increment = 1)
where TPixel : struct, IPixel
{
- TPixel color = default(TPixel);
+ var color = default(TPixel);
switch (this.PngColorType)
{
@@ -901,7 +897,7 @@ namespace ImageSharp.Formats
///
private PngChunk ReadChunk()
{
- PngChunk chunk = new PngChunk();
+ var chunk = new PngChunk();
this.ReadChunkLength(chunk);
if (chunk.Length < 0)
{