diff --git a/src/ImageSharp/Formats/Png/Filters/AverageFilter.cs b/src/ImageSharp/Formats/Png/Filters/AverageFilter.cs
index 97ded289c4..bef124541c 100644
--- a/src/ImageSharp/Formats/Png/Filters/AverageFilter.cs
+++ b/src/ImageSharp/Formats/Png/Filters/AverageFilter.cs
@@ -45,15 +45,16 @@ namespace ImageSharp.Formats
/// The scanline to encode
/// The previous scanline.
/// The bytes per pixel.
+ /// The number of bytes per scanline
/// The
- public static byte[] Encode(byte[] scanline, byte[] previousScanline, int bytesPerPixel)
+ public static byte[] Encode(byte[] scanline, byte[] previousScanline, int bytesPerPixel, int bytesPerScanline)
{
// Average(x) = Raw(x) - floor((Raw(x-bpp)+Prior(x))/2)
- byte[] encodedScanline = new byte[scanline.Length + 1];
+ byte[] encodedScanline = new byte[bytesPerScanline + 1];
encodedScanline[0] = (byte)FilterType.Average;
- for (int x = 0; x < scanline.Length; x++)
+ for (int x = 0; x < bytesPerScanline; x++)
{
byte left = (x - bytesPerPixel < 0) ? (byte)0 : scanline[x - bytesPerPixel];
byte above = previousScanline[x];
diff --git a/src/ImageSharp/Formats/Png/Filters/PaethFilter.cs b/src/ImageSharp/Formats/Png/Filters/PaethFilter.cs
index 1234cb6efe..232d7cc3df 100644
--- a/src/ImageSharp/Formats/Png/Filters/PaethFilter.cs
+++ b/src/ImageSharp/Formats/Png/Filters/PaethFilter.cs
@@ -45,14 +45,15 @@ namespace ImageSharp.Formats
/// The scanline to encode
/// The previous scanline.
/// The bytes per pixel.
+ /// The number of bytes per scanline
/// The
- public static byte[] Encode(byte[] scanline, byte[] previousScanline, int bytesPerPixel)
+ public static byte[] Encode(byte[] scanline, byte[] previousScanline, int bytesPerPixel, int bytesPerScanline)
{
// Paeth(x) = Raw(x) - PaethPredictor(Raw(x-bpp), Prior(x), Prior(x - bpp))
- byte[] encodedScanline = new byte[scanline.Length + 1];
+ byte[] encodedScanline = new byte[bytesPerScanline + 1];
encodedScanline[0] = (byte)FilterType.Paeth;
- for (int x = 0; x < scanline.Length; x++)
+ for (int x = 0; x < bytesPerScanline; x++)
{
byte left = (x - bytesPerPixel < 0) ? (byte)0 : scanline[x - bytesPerPixel];
byte above = previousScanline[x];
diff --git a/src/ImageSharp/Formats/Png/Filters/SubFilter.cs b/src/ImageSharp/Formats/Png/Filters/SubFilter.cs
index eb5bd9bfd4..c4fbe3e518 100644
--- a/src/ImageSharp/Formats/Png/Filters/SubFilter.cs
+++ b/src/ImageSharp/Formats/Png/Filters/SubFilter.cs
@@ -38,14 +38,15 @@ namespace ImageSharp.Formats
///
/// The scanline to encode
/// The bytes per pixel.
+ /// The number of bytes per scanline
/// The
- public static byte[] Encode(byte[] scanline, int bytesPerPixel)
+ public static byte[] Encode(byte[] scanline, int bytesPerPixel, int bytesPerScanline)
{
// Sub(x) = Raw(x) - Raw(x-bpp)
- byte[] encodedScanline = new byte[scanline.Length + 1];
+ byte[] encodedScanline = new byte[bytesPerScanline + 1];
encodedScanline[0] = (byte)FilterType.Sub;
- for (int x = 0; x < scanline.Length; x++)
+ for (int x = 0; x < bytesPerScanline; x++)
{
byte priorRawByte = (x - bytesPerPixel < 0) ? (byte)0 : scanline[x - bytesPerPixel];
diff --git a/src/ImageSharp/Formats/Png/Filters/UpFilter.cs b/src/ImageSharp/Formats/Png/Filters/UpFilter.cs
index ebb5e3b54c..026070421b 100644
--- a/src/ImageSharp/Formats/Png/Filters/UpFilter.cs
+++ b/src/ImageSharp/Formats/Png/Filters/UpFilter.cs
@@ -37,15 +37,16 @@ namespace ImageSharp.Formats
/// Encodes the scanline
///
/// The scanline to encode
+ /// The number of bytes per scanline
/// The previous scanline.
/// The
- public static byte[] Encode(byte[] scanline, byte[] previousScanline)
+ public static byte[] Encode(byte[] scanline, int bytesPerScanline, byte[] previousScanline)
{
// Up(x) = Raw(x) - Prior(x)
- byte[] encodedScanline = new byte[scanline.Length + 1];
+ byte[] encodedScanline = new byte[bytesPerScanline + 1];
encodedScanline[0] = (byte)FilterType.Up;
- for (int x = 0; x < scanline.Length; x++)
+ for (int x = 0; x < bytesPerScanline; x++)
{
byte above = previousScanline[x];
diff --git a/src/ImageSharp/Formats/Png/PngEncoderCore.cs b/src/ImageSharp/Formats/Png/PngEncoderCore.cs
index 05fd4c4409..9d68ba84a4 100644
--- a/src/ImageSharp/Formats/Png/PngEncoderCore.cs
+++ b/src/ImageSharp/Formats/Png/PngEncoderCore.cs
@@ -331,18 +331,24 @@ namespace ImageSharp.Formats
/// The
private byte[] EncodePixelData()
{
- // TODO: Use pointers
byte[][] filteredScanlines = new byte[this.height][];
- byte[] previousScanline = new byte[this.width * this.bytesPerPixel];
+ int bytesPerScanline = this.width * this.bytesPerPixel;
int length = 0;
+
+ byte[] previousScanline = new byte[bytesPerScanline];
+ byte[] rawScanline = new byte[bytesPerScanline];
+
for (int y = 0; y < this.height; y++)
{
- byte[] rawScanline = this.GetRawScanline(y);
- byte[] filteredScanline = this.GetOptimalFilteredScanline(rawScanline, previousScanline, this.bytesPerPixel);
+ Buffer.BlockCopy(this.pixelData, y * bytesPerScanline, rawScanline, 0, bytesPerScanline);
+ byte[] filteredScanline = this.GetOptimalFilteredScanline(rawScanline, previousScanline, bytesPerScanline, this.bytesPerPixel);
length += filteredScanline.Length;
filteredScanlines[y] = filteredScanline;
- previousScanline = rawScanline;
+ // Do a bit of shuffling;
+ byte[] tmp = rawScanline;
+ rawScanline = previousScanline;
+ previousScanline = tmp;
}
// Flatten the jagged array
@@ -362,22 +368,23 @@ namespace ImageSharp.Formats
///
/// The raw scanline
/// The previous scanline
- /// The number of bytes per pixel
+ /// The number of bytes per scanline
+ /// The number of bytes per pixel
/// The
- private byte[] GetOptimalFilteredScanline(byte[] rawScanline, byte[] previousScanline, int byteCount)
+ private byte[] GetOptimalFilteredScanline(byte[] rawScanline, byte[] previousScanline, int bytesPerScanline, int bytesPerPixel)
{
Tuple[] candidates = new Tuple[4];
- byte[] sub = SubFilter.Encode(rawScanline, byteCount);
+ byte[] sub = SubFilter.Encode(rawScanline, bytesPerPixel, bytesPerScanline);
candidates[0] = new Tuple(sub, this.CalculateTotalVariation(sub));
- byte[] up = UpFilter.Encode(rawScanline, previousScanline);
+ byte[] up = UpFilter.Encode(rawScanline, bytesPerScanline, previousScanline);
candidates[1] = new Tuple(up, this.CalculateTotalVariation(up));
- byte[] average = AverageFilter.Encode(rawScanline, previousScanline, byteCount);
+ byte[] average = AverageFilter.Encode(rawScanline, previousScanline, bytesPerPixel, bytesPerScanline);
candidates[2] = new Tuple(average, this.CalculateTotalVariation(average));
- byte[] paeth = PaethFilter.Encode(rawScanline, previousScanline, byteCount);
+ byte[] paeth = PaethFilter.Encode(rawScanline, previousScanline, bytesPerPixel, bytesPerScanline);
candidates[3] = new Tuple(paeth, this.CalculateTotalVariation(paeth));
int lowestTotalVariation = int.MaxValue;
@@ -413,19 +420,6 @@ namespace ImageSharp.Formats
return totalVariation;
}
- ///
- /// Get the raw scanline data from the pixel data
- ///
- /// The row number
- /// The
- private byte[] GetRawScanline(int y)
- {
- int stride = this.bytesPerPixel * this.width;
- byte[] rawScanline = new byte[stride];
- Buffer.BlockCopy(this.pixelData, y * stride, rawScanline, 0, stride);
- return rawScanline;
- }
-
///
/// Calculates the correct number of bytes per pixel for the given color type.
///