Browse Source

Inline AV1 inverse transform clamping

pull/2633/head
James Jackson-South 1 week ago
parent
commit
e6043e7429
  1. 9
      src/ImageSharp/Formats/Heif/Av1/Transform/Av1Inverse2dTransformer.cs
  2. 32
      src/ImageSharp/Formats/Heif/Av1/Transform/Av1InverseTransformMath.cs

9
src/ImageSharp/Formats/Heif/Av1/Transform/Av1Inverse2dTransformer.cs

@ -542,6 +542,8 @@ internal static class Av1Inverse2dTransformer
int shift0 = config.Shift0; int shift0 = config.Shift0;
int shift1 = config.Shift1; int shift1 = config.Shift1;
bool normalizeRectangle = Math.Abs(config.TransformSize.GetRectangleLogRatio()) == 1; bool normalizeRectangle = Math.Abs(config.TransformSize.GetRectangleLogRatio()) == 1;
byte rowClampBits = (byte)(bitDepth + 8);
byte columnClampBits = (byte)Math.Max(bitDepth + 6, 16);
Span<int> tempIn = workspace[..vectorLength]; Span<int> tempIn = workspace[..vectorLength];
Span<int> tempOut = workspace.Slice(vectorLength, vectorLength); Span<int> tempOut = workspace.Slice(vectorLength, vectorLength);
Span<int> step = workspace.Slice(2 * vectorLength, vectorLength); Span<int> step = workspace.Slice(2 * vectorLength, vectorLength);
@ -554,12 +556,12 @@ internal static class Av1Inverse2dTransformer
for (int column = 0; column < width; column++) for (int column = 0; column < width; column++)
{ {
int value = input[rowOffset + column]; int value = input[rowOffset + column];
tempIn[column] = normalizeRectangle value = normalizeRectangle
? Av1Math.RoundShift((long)value * Av1InverseTransformMath.NewInverseSqrt2, Av1InverseTransformMath.NewSqrt2BitCount) ? Av1Math.RoundShift((long)value * Av1InverseTransformMath.NewInverseSqrt2, Av1InverseTransformMath.NewSqrt2BitCount)
: value; : value;
tempIn[column] = Av1Transform1dMath.Clamp(value, rowClampBits);
} }
Av1InverseTransformMath.ClampBuffer(tempIn, width, (byte)(bitDepth + 8));
TRowOperator.Transform(tempIn, tempOut, step, config.CosBitRow, config.StageRangeRow); TRowOperator.Transform(tempIn, tempOut, step, config.CosBitRow, config.StageRangeRow);
Av1InverseTransformMath.RoundShiftArray(tempOut, width, -shift0); Av1InverseTransformMath.RoundShiftArray(tempOut, width, -shift0);
tempOut[..width].CopyTo(buffer.Slice(rowOffset, width)); tempOut[..width].CopyTo(buffer.Slice(rowOffset, width));
@ -571,10 +573,9 @@ internal static class Av1Inverse2dTransformer
for (int row = 0; row < height; row++) for (int row = 0; row < height; row++)
{ {
tempIn[row] = buffer[(row * width) + sourceColumn]; tempIn[row] = Av1Transform1dMath.Clamp(buffer[(row * width) + sourceColumn], columnClampBits);
} }
Av1InverseTransformMath.ClampBuffer(tempIn, height, (byte)Math.Max(bitDepth + 6, 16));
TColumnOperator.Transform(tempIn, tempOut, step, config.CosBitColumn, config.StageRangeColumn); TColumnOperator.Transform(tempIn, tempOut, step, config.CosBitColumn, config.StageRangeColumn);
Av1InverseTransformMath.RoundShiftArray(tempOut, height, -shift1); Av1InverseTransformMath.RoundShiftArray(tempOut, height, -shift1);

32
src/ImageSharp/Formats/Heif/Av1/Transform/Av1InverseTransformMath.cs

@ -261,38 +261,6 @@ internal static class Av1InverseTransformMath
} }
} }
/// <summary>
/// Clamps a transform-stage buffer to a signed range of the specified bit width.
/// </summary>
/// <param name="buffer">The transform-stage values.</param>
/// <param name="size">The number of values to clamp.</param>
/// <param name="bit">The signed range width in bits.</param>
internal static void ClampBuffer(Span<int> buffer, int size, byte bit)
{
for (int i = 0; i < size; i++)
{
buffer[i] = ClampValue(buffer[i], bit);
}
}
/// <summary>
/// Clamps one transform-stage value to a signed range of the specified bit width.
/// </summary>
/// <param name="value">The value to clamp.</param>
/// <param name="bit">The signed range width in bits.</param>
/// <returns>The clamped value.</returns>
private static int ClampValue(int value, byte bit)
{
if (bit <= 0)
{
return value; // Do nothing for invalid clamp bit.
}
long maximum = (1L << (bit - 1)) - 1;
long minimum = -(1L << (bit - 1));
return (int)Av1Math.Clamp(value, minimum, maximum);
}
/// <summary> /// <summary>
/// Restricts an inverse-transform residual to the intermediate range permitted for the sample bit depth. /// Restricts an inverse-transform residual to the intermediate range permitted for the sample bit depth.
/// </summary> /// </summary>

Loading…
Cancel
Save