|
|
|
@ -13,7 +13,7 @@ namespace ImageSharp.Formats |
|
|
|
/// This technique is due to Alan W. Paeth.
|
|
|
|
/// <see href="https://www.w3.org/TR/PNG-Filters.html"/>
|
|
|
|
/// </summary>
|
|
|
|
internal static class PaethFilter |
|
|
|
internal static unsafe class PaethFilter |
|
|
|
{ |
|
|
|
/// <summary>
|
|
|
|
/// 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; |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|