From 502fa2c6f4c1d1f77bd0a81de76894ceab50dec4 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Thu, 10 Nov 2016 12:14:54 +1100 Subject: [PATCH] Use fixed on filter loops --- Settings.StyleCop | 1 + .../Formats/Png/Filters/AverageFilter.cs | 41 +++++++++++-------- .../Formats/Png/Filters/NoneFilter.cs | 8 ++-- .../Formats/Png/Filters/PaethFilter.cs | 39 +++++++++++------- .../Formats/Png/Filters/SubFilter.cs | 29 ++++++++----- .../Formats/Png/Filters/UpFilter.cs | 31 +++++++++----- 6 files changed, 95 insertions(+), 54 deletions(-) diff --git a/Settings.StyleCop b/Settings.StyleCop index b7a5355e0..4403974d3 100644 --- a/Settings.StyleCop +++ b/Settings.StyleCop @@ -32,6 +32,7 @@ Vol pp cmyk + Paeth diff --git a/src/ImageSharp/Formats/Png/Filters/AverageFilter.cs b/src/ImageSharp/Formats/Png/Filters/AverageFilter.cs index bef124541..6fe2175d9 100644 --- a/src/ImageSharp/Formats/Png/Filters/AverageFilter.cs +++ b/src/ImageSharp/Formats/Png/Filters/AverageFilter.cs @@ -12,7 +12,7 @@ namespace ImageSharp.Formats /// the value of a pixel. /// /// - internal static class AverageFilter + internal static unsafe class AverageFilter { /// /// Decodes the scanline @@ -28,12 +28,17 @@ namespace ImageSharp.Formats // Average(x) + floor((Raw(x-bpp)+Prior(x))/2) byte[] result = new byte[scanline.Length]; - for (int x = 1; x < scanline.Length; x++) + fixed (byte* scan = scanline) + fixed (byte* prev = previousScanline) + fixed (byte* res = result) { - byte left = (x - bytesPerPixel < 1) ? (byte)0 : result[x - bytesPerPixel]; - byte above = previousScanline[x]; + for (int x = 1; x < scanline.Length; x++) + { + byte left = (x - bytesPerPixel < 1) ? (byte)0 : res[x - bytesPerPixel]; + byte above = prev[x]; - result[x] = (byte)((scanline[x] + Average(left, above)) % 256); + res[x] = (byte)((scan[x] + Average(left, above)) % 256); + } } return result; @@ -50,19 +55,23 @@ namespace ImageSharp.Formats 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[bytesPerScanline + 1]; - - encodedScanline[0] = (byte)FilterType.Average; - - for (int x = 0; x < bytesPerScanline; x++) + byte[] result = new byte[bytesPerScanline + 1]; + fixed (byte* scan = scanline) + fixed (byte* prev = previousScanline) + fixed (byte* res = result) { - byte left = (x - bytesPerPixel < 0) ? (byte)0 : scanline[x - bytesPerPixel]; - byte above = previousScanline[x]; + res[0] = 3; - encodedScanline[x + 1] = (byte)((scanline[x] - Average(left, above)) % 256); + for (int x = 0; x < bytesPerScanline; x++) + { + byte left = (x - bytesPerPixel < 0) ? (byte)0 : scan[x - bytesPerPixel]; + byte above = prev[x]; + + res[x + 1] = (byte)((scan[x] - Average(left, above)) % 256); + } } - return encodedScanline; + return result; } /// @@ -73,7 +82,7 @@ namespace ImageSharp.Formats /// The private static int Average(byte left, byte above) { - return Convert.ToInt32(Math.Floor((left + above) / 2.0D)); + return (left + above) >> 1; } } -} +} \ No newline at end of file diff --git a/src/ImageSharp/Formats/Png/Filters/NoneFilter.cs b/src/ImageSharp/Formats/Png/Filters/NoneFilter.cs index 175e5affa..068e57ad0 100644 --- a/src/ImageSharp/Formats/Png/Filters/NoneFilter.cs +++ b/src/ImageSharp/Formats/Png/Filters/NoneFilter.cs @@ -34,11 +34,11 @@ namespace ImageSharp.Formats public static byte[] Encode(byte[] scanline, int bytesPerScanline) { // Insert a byte before the data. - byte[] encodedScanline = new byte[bytesPerScanline + 1]; - encodedScanline[0] = (byte)FilterType.None; - Buffer.BlockCopy(scanline, 0, encodedScanline, 1, bytesPerScanline); + byte[] result = new byte[bytesPerScanline + 1]; + result[0] = 0; + Buffer.BlockCopy(scanline, 0, result, 1, bytesPerScanline); - return encodedScanline; + return result; } } } diff --git a/src/ImageSharp/Formats/Png/Filters/PaethFilter.cs b/src/ImageSharp/Formats/Png/Filters/PaethFilter.cs index 232d7cc3d..55f7a36b0 100644 --- a/src/ImageSharp/Formats/Png/Filters/PaethFilter.cs +++ b/src/ImageSharp/Formats/Png/Filters/PaethFilter.cs @@ -13,7 +13,7 @@ namespace ImageSharp.Formats /// This technique is due to Alan W. Paeth. /// /// - internal static class PaethFilter + internal static unsafe class PaethFilter { /// /// Decodes the scanline @@ -27,13 +27,18 @@ namespace ImageSharp.Formats // Paeth(x) + PaethPredictor(Raw(x-bpp), Prior(x), Prior(x-bpp)) byte[] result = new byte[scanline.Length]; - for (int x = 1; x < scanline.Length; x++) + fixed (byte* scan = scanline) + fixed (byte* prev = previousScanline) + fixed (byte* res = result) { - byte left = (x - bytesPerPixel < 1) ? (byte)0 : result[x - bytesPerPixel]; - byte above = previousScanline[x]; - byte upperLeft = (x - bytesPerPixel < 1) ? (byte)0 : previousScanline[x - bytesPerPixel]; + for (int x = 1; x < scanline.Length; x++) + { + byte left = (x - bytesPerPixel < 1) ? (byte)0 : res[x - bytesPerPixel]; + byte above = prev[x]; + byte upperLeft = (x - bytesPerPixel < 1) ? (byte)0 : prev[x - bytesPerPixel]; - result[x] = (byte)((scanline[x] + PaethPredicator(left, above, upperLeft)) % 256); + res[x] = (byte)((scan[x] + PaethPredicator(left, above, upperLeft)) % 256); + } } return result; @@ -50,19 +55,25 @@ namespace ImageSharp.Formats 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[bytesPerScanline + 1]; - encodedScanline[0] = (byte)FilterType.Paeth; + byte[] result = new byte[bytesPerScanline + 1]; - for (int x = 0; x < bytesPerScanline; x++) + fixed (byte* scan = scanline) + fixed (byte* prev = previousScanline) + fixed (byte* res = result) { - byte left = (x - bytesPerPixel < 0) ? (byte)0 : scanline[x - bytesPerPixel]; - byte above = previousScanline[x]; - byte upperLeft = (x - bytesPerPixel < 0) ? (byte)0 : previousScanline[x - bytesPerPixel]; + res[0] = 4; - encodedScanline[x + 1] = (byte)((scanline[x] - PaethPredicator(left, above, upperLeft)) % 256); + for (int x = 0; x < bytesPerScanline; x++) + { + byte left = (x - bytesPerPixel < 0) ? (byte)0 : scan[x - bytesPerPixel]; + byte above = prev[x]; + byte upperLeft = (x - bytesPerPixel < 0) ? (byte)0 : prev[x - bytesPerPixel]; + + res[x + 1] = (byte)((scan[x] - PaethPredicator(left, above, upperLeft)) % 256); + } } - return encodedScanline; + return result; } /// diff --git a/src/ImageSharp/Formats/Png/Filters/SubFilter.cs b/src/ImageSharp/Formats/Png/Filters/SubFilter.cs index c4fbe3e51..79ebcf835 100644 --- a/src/ImageSharp/Formats/Png/Filters/SubFilter.cs +++ b/src/ImageSharp/Formats/Png/Filters/SubFilter.cs @@ -10,7 +10,7 @@ namespace ImageSharp.Formats /// of the prior pixel. /// /// - internal static class SubFilter + internal static unsafe class SubFilter { /// /// Decodes the scanline @@ -23,11 +23,15 @@ namespace ImageSharp.Formats // Sub(x) + Raw(x-bpp) byte[] result = new byte[scanline.Length]; - for (int x = 1; x < scanline.Length; x++) + fixed (byte* scan = scanline) + fixed (byte* res = result) { - byte priorRawByte = (x - bytesPerPixel < 1) ? (byte)0 : result[x - bytesPerPixel]; + for (int x = 1; x < scanline.Length; x++) + { + byte priorRawByte = (x - bytesPerPixel < 1) ? (byte)0 : res[x - bytesPerPixel]; - result[x] = (byte)((scanline[x] + priorRawByte) % 256); + res[x] = (byte)((scan[x] + priorRawByte) % 256); + } } return result; @@ -43,17 +47,22 @@ namespace ImageSharp.Formats public static byte[] Encode(byte[] scanline, int bytesPerPixel, int bytesPerScanline) { // Sub(x) = Raw(x) - Raw(x-bpp) - byte[] encodedScanline = new byte[bytesPerScanline + 1]; - encodedScanline[0] = (byte)FilterType.Sub; + byte[] result = new byte[bytesPerScanline + 1]; - for (int x = 0; x < bytesPerScanline; x++) + fixed (byte* scan = scanline) + fixed (byte* res = result) { - byte priorRawByte = (x - bytesPerPixel < 0) ? (byte)0 : scanline[x - bytesPerPixel]; + res[0] = 1; - encodedScanline[x + 1] = (byte)((scanline[x] - priorRawByte) % 256); + for (int x = 0; x < bytesPerScanline; x++) + { + byte priorRawByte = (x - bytesPerPixel < 0) ? (byte)0 : scan[x - bytesPerPixel]; + + res[x + 1] = (byte)((scan[x] - priorRawByte) % 256); + } } - return encodedScanline; + return result; } } } diff --git a/src/ImageSharp/Formats/Png/Filters/UpFilter.cs b/src/ImageSharp/Formats/Png/Filters/UpFilter.cs index 026070421..7f162fae1 100644 --- a/src/ImageSharp/Formats/Png/Filters/UpFilter.cs +++ b/src/ImageSharp/Formats/Png/Filters/UpFilter.cs @@ -10,7 +10,7 @@ namespace ImageSharp.Formats /// rather than just to its left, is used as the predictor. /// /// - internal static class UpFilter + internal static unsafe class UpFilter { /// /// Decodes the scanline @@ -23,11 +23,16 @@ namespace ImageSharp.Formats // Up(x) + Prior(x) byte[] result = new byte[scanline.Length]; - for (int x = 1; x < scanline.Length; x++) + fixed (byte* scan = scanline) + fixed (byte* prev = previousScanline) + fixed (byte* res = result) { - byte above = previousScanline[x]; + for (int x = 1; x < scanline.Length; x++) + { + byte above = prev[x]; - result[x] = (byte)((scanline[x] + above) % 256); + res[x] = (byte)((scan[x] + above) % 256); + } } return result; @@ -43,17 +48,23 @@ namespace ImageSharp.Formats public static byte[] Encode(byte[] scanline, int bytesPerScanline, byte[] previousScanline) { // Up(x) = Raw(x) - Prior(x) - byte[] encodedScanline = new byte[bytesPerScanline + 1]; - encodedScanline[0] = (byte)FilterType.Up; + byte[] result = new byte[bytesPerScanline + 1]; - for (int x = 0; x < bytesPerScanline; x++) + fixed (byte* scan = scanline) + fixed (byte* prev = previousScanline) + fixed (byte* res = result) { - byte above = previousScanline[x]; + res[0] = 2; - encodedScanline[x + 1] = (byte)((scanline[x] - above) % 256); + for (int x = 0; x < bytesPerScanline; x++) + { + byte above = prev[x]; + + res[x + 1] = (byte)((scan[x] - above) % 256); + } } - return encodedScanline; + return result; } } }