|
|
|
@ -30,21 +30,22 @@ namespace SixLabors.ImageSharp.Formats.Png.Filters |
|
|
|
ref byte prevBaseRef = ref MemoryMarshal.GetReference(previousScanline); |
|
|
|
|
|
|
|
// Paeth(x) + PaethPredictor(Raw(x-bpp), Prior(x), Prior(x-bpp))
|
|
|
|
int offset = bytesPerPixel + 1; |
|
|
|
for (int x = 1; x < offset; x++) |
|
|
|
int offset = bytesPerPixel + 1; // Add one bcause x starts at one.
|
|
|
|
int x = 1; |
|
|
|
for (; x < offset; x++) |
|
|
|
{ |
|
|
|
ref byte scan = ref Unsafe.Add(ref scanBaseRef, x); |
|
|
|
byte above = Unsafe.Add(ref prevBaseRef, x); |
|
|
|
scan = (byte)(scan + above); |
|
|
|
} |
|
|
|
|
|
|
|
for (int x = offset; x < scanline.Length; x++) |
|
|
|
for (; x < scanline.Length; x++) |
|
|
|
{ |
|
|
|
ref byte scan = ref Unsafe.Add(ref scanBaseRef, x); |
|
|
|
byte left = Unsafe.Add(ref scanBaseRef, x - bytesPerPixel); |
|
|
|
byte above = Unsafe.Add(ref prevBaseRef, x); |
|
|
|
byte upperLeft = Unsafe.Add(ref prevBaseRef, x - bytesPerPixel); |
|
|
|
scan = (byte)(scan + PaethPredicator(left, above, upperLeft)); |
|
|
|
scan = (byte)(scan + PaethPredictor(left, above, upperLeft)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@ -70,26 +71,25 @@ namespace SixLabors.ImageSharp.Formats.Png.Filters |
|
|
|
// Paeth(x) = Raw(x) - PaethPredictor(Raw(x-bpp), Prior(x), Prior(x - bpp))
|
|
|
|
resultBaseRef = 4; |
|
|
|
|
|
|
|
for (int x = 0; x < scanline.Length; x++) |
|
|
|
{ |
|
|
|
if (x - bytesPerPixel < 0) |
|
|
|
{ |
|
|
|
byte scan = Unsafe.Add(ref scanBaseRef, x); |
|
|
|
byte above = Unsafe.Add(ref prevBaseRef, x); |
|
|
|
ref byte res = ref Unsafe.Add(ref resultBaseRef, x + 1); |
|
|
|
res = (byte)((scan - PaethPredicator(0, above, 0)) % 256); |
|
|
|
sum += res < 128 ? res : 256 - res; |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
byte scan = Unsafe.Add(ref scanBaseRef, x); |
|
|
|
byte left = Unsafe.Add(ref scanBaseRef, x - bytesPerPixel); |
|
|
|
byte above = Unsafe.Add(ref prevBaseRef, x); |
|
|
|
byte upperLeft = Unsafe.Add(ref prevBaseRef, x - bytesPerPixel); |
|
|
|
ref byte res = ref Unsafe.Add(ref resultBaseRef, x + 1); |
|
|
|
res = (byte)((scan - PaethPredicator(left, above, upperLeft)) % 256); |
|
|
|
sum += res < 128 ? res : 256 - res; |
|
|
|
} |
|
|
|
int x = 0; |
|
|
|
for (; x < bytesPerPixel; /* Note: ++x happens in the body to avoid one add operation */) { |
|
|
|
byte scan = Unsafe.Add(ref scanBaseRef, x); |
|
|
|
byte above = Unsafe.Add(ref prevBaseRef, x); |
|
|
|
++x; |
|
|
|
ref byte res = ref Unsafe.Add(ref resultBaseRef, x); |
|
|
|
res = (byte)(scan - PaethPredictor(0, above, 0)); |
|
|
|
sum += ImageMaths.FastAbs(unchecked((sbyte)res)); |
|
|
|
} |
|
|
|
|
|
|
|
for (int xLeft = x - bytesPerPixel; x < scanline.Length; ++xLeft /* Note: ++x happens in the body to avoid one add operation */) { |
|
|
|
byte scan = Unsafe.Add(ref scanBaseRef, x); |
|
|
|
byte left = Unsafe.Add(ref scanBaseRef, xLeft); |
|
|
|
byte above = Unsafe.Add(ref prevBaseRef, x); |
|
|
|
byte upperLeft = Unsafe.Add(ref prevBaseRef, xLeft); |
|
|
|
++x; |
|
|
|
ref byte res = ref Unsafe.Add(ref resultBaseRef, x); |
|
|
|
res = (byte)(scan - PaethPredictor(left, above, upperLeft)); |
|
|
|
sum += ImageMaths.FastAbs(unchecked((sbyte)res)); |
|
|
|
} |
|
|
|
|
|
|
|
sum -= 4; |
|
|
|
@ -106,7 +106,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Filters |
|
|
|
/// The <see cref="byte"/>.
|
|
|
|
/// </returns>
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|
|
|
private static byte PaethPredicator(byte left, byte above, byte upperLeft) |
|
|
|
private static byte PaethPredictor(byte left, byte above, byte upperLeft) |
|
|
|
{ |
|
|
|
int p = left + above - upperLeft; |
|
|
|
int pa = ImageMaths.FastAbs(p - left); |
|
|
|
|