diff --git a/src/ImageSharp/Formats/Jpeg/Port/Components/IDCT.cs b/src/ImageSharp/Formats/Jpeg/Port/Components/IDCT.cs
index 22d787269b..cae1e84344 100644
--- a/src/ImageSharp/Formats/Jpeg/Port/Components/IDCT.cs
+++ b/src/ImageSharp/Formats/Jpeg/Port/Components/IDCT.cs
@@ -1,7 +1,6 @@
namespace ImageSharp.Formats.Jpeg.Port.Components
{
using System;
- using System.Numerics;
using System.Runtime.CompilerServices;
using ImageSharp.Memory;
@@ -69,7 +68,7 @@
Limit[TableOffset + i] = (byte)i;
}
- // End of range limit table: limit[x] = MaxJSample for x > MaxJSample
+ // End of range limit table: Limit[x] = MaxJSample for x > MaxJSample
for (; i < 3 * (MaxJSample + 1); i++)
{
Limit[TableOffset + i] = MaxJSample;
@@ -446,7 +445,7 @@
// Check for all-zero AC coefficients
if ((p1 | p2 | p3 | p4 | p5 | p6 | p7) == 0)
{
- byte dcval = DoLimit(RightShift(z5, Pass1Bits + 3) & RangeMask);
+ byte dcval = Limit[LimitOffset + (RightShift(z5, Pass1Bits + 3) & RangeMask)];
blockData[row] = dcval;
blockData[row + 1] = dcval;
@@ -489,46 +488,55 @@
int tmp5 = tmp11 - tmp6;
int tmp4 = tmp10 - tmp5;
- // Final output stage: scale down by a factor of 8 and range-limit
- blockData[row] = DoLimit(Descale(tmp0 + tmp7, Pass1Bits + 3) & RangeMask);
- blockData[row + 7] = DoLimit(Descale(tmp0 - tmp7, Pass1Bits + 3) & RangeMask);
- blockData[row + 1] = DoLimit(Descale(tmp1 + tmp6, Pass1Bits + 3) & RangeMask);
- blockData[row + 6] = DoLimit(Descale(tmp1 - tmp6, Pass1Bits + 3) & RangeMask);
- blockData[row + 2] = DoLimit(Descale(tmp2 + tmp5, Pass1Bits + 3) & RangeMask);
- blockData[row + 5] = DoLimit(Descale(tmp2 - tmp5, Pass1Bits + 3) & RangeMask);
- blockData[row + 3] = DoLimit(Descale(tmp3 + tmp4, Pass1Bits + 3) & RangeMask);
- blockData[row + 4] = DoLimit(Descale(tmp3 - tmp4, Pass1Bits + 3) & RangeMask);
+ // Final output stage: scale down by a factor of 8, offset, and range-limit
+ blockData[row] = Limit[LimitOffset + (RightShift(tmp0 + tmp7, Pass1Bits + 3) & RangeMask)];
+ blockData[row + 7] = Limit[LimitOffset + (RightShift(tmp0 - tmp7, Pass1Bits + 3) & RangeMask)];
+ blockData[row + 1] = Limit[LimitOffset + (RightShift(tmp1 + tmp6, Pass1Bits + 3) & RangeMask)];
+ blockData[row + 6] = Limit[LimitOffset + (RightShift(tmp1 - tmp6, Pass1Bits + 3) & RangeMask)];
+ blockData[row + 2] = Limit[LimitOffset + (RightShift(tmp2 + tmp5, Pass1Bits + 3) & RangeMask)];
+ blockData[row + 5] = Limit[LimitOffset + (RightShift(tmp2 - tmp5, Pass1Bits + 3) & RangeMask)];
+ blockData[row + 3] = Limit[LimitOffset + (RightShift(tmp3 + tmp4, Pass1Bits + 3) & RangeMask)];
+ blockData[row + 4] = Limit[LimitOffset + (RightShift(tmp3 - tmp4, Pass1Bits + 3) & RangeMask)];
}
}
}
+ ///
+ /// Multiply a variable by an int constant, and immediately descale.
+ ///
+ /// The value
+ /// The multiplier
+ /// The
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static int Multiply(int val, int c)
{
return Descale(val * c, ConstBits);
}
+ ///
+ /// Right-shifts the value by the given amount
+ ///
+ /// The value
+ /// The amount to shift by
+ /// The
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static int RightShift(int x, int shft)
- {
- return x >> shft;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static int Descale(int x, int n)
+ private static int RightShift(int value, int shift)
{
- return RightShift(x + (1 << (n - 1)), n);
+ return value >> shift;
}
///
- /// Offsets the value by 128 and limits it to the 0..255 range
+ /// Descale and correctly round an int value that's scaled by bits.
+ /// We assume rounds towards minus infinity, so adding
+ /// the fudge factor is correct for either sign of .
///
/// The value
- /// The
+ /// The number of bits
+ /// The
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static byte DoLimit(int value)
+ private static int Descale(int value, int n)
{
- return Limit[value + LimitOffset];
+ return RightShift(value + (1 << (n - 1)), n);
}
}
}
\ No newline at end of file