Browse Source

Bounds check for forward transforms

pull/2633/head
Ynse Hoornenborg 2 years ago
parent
commit
c19d687614
  1. 3
      src/ImageSharp/Formats/Heif/Av1/Av1Math.cs
  2. 32
      src/ImageSharp/Formats/Heif/Av1/Transform/Av1ForwardTransformer.cs
  3. 8
      src/ImageSharp/Formats/Heif/Av1/Transform/Forward/Av1Adst16Forward1dTransformer.cs
  4. 8
      src/ImageSharp/Formats/Heif/Av1/Transform/Forward/Av1Adst32Forward1dTransformer.cs
  5. 8
      src/ImageSharp/Formats/Heif/Av1/Transform/Forward/Av1Adst4Forward1dTransformer.cs
  6. 8
      src/ImageSharp/Formats/Heif/Av1/Transform/Forward/Av1Adst8Forward1dTransformer.cs
  7. 8
      src/ImageSharp/Formats/Heif/Av1/Transform/Forward/Av1Dct16Forward1dTransformer.cs
  8. 8
      src/ImageSharp/Formats/Heif/Av1/Transform/Forward/Av1Dct32Forward1dTransformer.cs
  9. 8
      src/ImageSharp/Formats/Heif/Av1/Transform/Forward/Av1Dct4Forward1dTransformer.cs
  10. 10
      src/ImageSharp/Formats/Heif/Av1/Transform/Forward/Av1Dct64Forward1dTransformer.cs
  11. 8
      src/ImageSharp/Formats/Heif/Av1/Transform/Forward/Av1Dct8Forward1dTransformer.cs
  12. 4
      src/ImageSharp/Formats/Heif/Av1/Transform/Forward/Av1DctDct4Forward2dTransformer.cs
  13. 27
      src/ImageSharp/Formats/Heif/Av1/Transform/Forward/Av1Forward2dTransformerBase.cs
  14. 8
      src/ImageSharp/Formats/Heif/Av1/Transform/Forward/Av1Identity16Forward1dTransformer.cs
  15. 14
      src/ImageSharp/Formats/Heif/Av1/Transform/Forward/Av1Identity32Forward1dTransformer.cs
  16. 8
      src/ImageSharp/Formats/Heif/Av1/Transform/Forward/Av1Identity4Forward1dTransformer.cs
  17. 14
      src/ImageSharp/Formats/Heif/Av1/Transform/Forward/Av1Identity64Forward1dTransformer.cs
  18. 8
      src/ImageSharp/Formats/Heif/Av1/Transform/Forward/Av1Identity8Forward1dTransformer.cs
  19. 2
      src/ImageSharp/Formats/Heif/Av1/Transform/IAv1Forward1dTransformer.cs
  20. 7
      tests/ImageSharp.Tests/Formats/Heif/Av1/Av1ForwardTransformTests.cs

3
src/ImageSharp/Formats/Heif/Av1/Av1Math.cs

@ -144,6 +144,9 @@ internal static class Av1Math
internal static int Clamp(int value, int low, int high) internal static int Clamp(int value, int low, int high)
=> value < low ? low : (value > high ? high : value); => value < low ? low : (value > high ? high : value);
internal static long Clamp(long value, long low, long high)
=> value < low ? low : (value > high ? high : value);
internal static int DivideLog2Floor(int value, int n) internal static int DivideLog2Floor(int value, int n)
=> value >> n; => value >> n;

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

@ -36,12 +36,11 @@ internal class Av1ForwardTransformer
internal static void Transform2d(Span<short> input, Span<int> coefficients, uint stride, Av1TransformType transformType, Av1TransformSize transformSize, int bitDepth) internal static void Transform2d(Span<short> input, Span<int> coefficients, uint stride, Av1TransformType transformType, Av1TransformSize transformSize, int bitDepth)
{ {
Av1Transform2dFlipConfiguration config = new(transformType, transformSize); Av1Transform2dFlipConfiguration config = new(transformType, transformSize);
ref int buffer = ref TemporaryCoefficientsBuffer[0];
IAv1Forward1dTransformer? columnTransformer = GetTransformer(config.TransformFunctionTypeColumn); IAv1Forward1dTransformer? columnTransformer = GetTransformer(config.TransformFunctionTypeColumn);
IAv1Forward1dTransformer? rowTransformer = GetTransformer(config.TransformFunctionTypeRow); IAv1Forward1dTransformer? rowTransformer = GetTransformer(config.TransformFunctionTypeRow);
if (columnTransformer != null && rowTransformer != null) if (columnTransformer != null && rowTransformer != null)
{ {
Transform2dCore(columnTransformer, rowTransformer, ref input[0], stride, ref coefficients[0], config, ref buffer, bitDepth); Transform2dCore(columnTransformer, rowTransformer, input, stride, coefficients, config, TemporaryCoefficientsBuffer, bitDepth);
} }
else else
{ {
@ -55,7 +54,7 @@ internal class Av1ForwardTransformer
/// <summary> /// <summary>
/// SVT: av1_tranform_two_d_core_c /// SVT: av1_tranform_two_d_core_c
/// </summary> /// </summary>
private static void Transform2dCore<TColumn, TRow>(TColumn transformFunctionColumn, TRow transformFunctionRow, ref short input, uint inputStride, ref int output, Av1Transform2dFlipConfiguration config, ref int buf, int bitDepth) private static void Transform2dCore<TColumn, TRow>(TColumn transformFunctionColumn, TRow transformFunctionRow, Span<short> input, uint inputStride, Span<int> output, Av1Transform2dFlipConfiguration config, Span<int> buf, int bitDepth)
where TColumn : IAv1Forward1dTransformer where TColumn : IAv1Forward1dTransformer
where TRow : IAv1Forward1dTransformer where TRow : IAv1Forward1dTransformer
{ {
@ -87,8 +86,13 @@ internal class Av1ForwardTransformer
// ASSERT(txfm_func_col != NULL); // ASSERT(txfm_func_col != NULL);
// ASSERT(txfm_func_row != NULL); // ASSERT(txfm_func_row != NULL);
// use output buffer as temp buffer // use output buffer as temp buffer
ref int tempIn = ref output; Span<int> tempInSpan = output[..transformRowCount];
ref int tempOut = ref Unsafe.Add(ref output, transformRowCount); Span<int> tempOutSpan = output.Slice(transformRowCount, transformRowCount);
ref int tempIn = ref tempInSpan[0];
ref int tempOut = ref tempOutSpan[0];
ref short inputRef = ref input[0];
ref int outputRef = ref output[0];
ref int bufRef = ref buf[0];
// Columns // Columns
for (c = 0; c < transformColumnCount; ++c) for (c = 0; c < transformColumnCount; ++c)
@ -98,7 +102,7 @@ internal class Av1ForwardTransformer
uint t = (uint)c; uint t = (uint)c;
for (r = 0; r < transformRowCount; ++r) for (r = 0; r < transformRowCount; ++r)
{ {
Unsafe.Add(ref tempIn, r) = Unsafe.Add(ref input, t); Unsafe.Add(ref tempIn, r) = Unsafe.Add(ref inputRef, t);
t += inputStride; t += inputStride;
} }
} }
@ -108,20 +112,20 @@ internal class Av1ForwardTransformer
for (r = 0; r < transformRowCount; ++r) for (r = 0; r < transformRowCount; ++r)
{ {
// Flip upside down // Flip upside down
Unsafe.Add(ref tempIn, r) = Unsafe.Add(ref input, t); Unsafe.Add(ref tempIn, r) = Unsafe.Add(ref inputRef, t);
t -= inputStride; t -= inputStride;
} }
} }
RoundShiftArray(ref tempIn, transformRowCount, -shift[0]); // NM svt_av1_round_shift_array_c RoundShiftArray(ref tempIn, transformRowCount, -shift[0]); // NM svt_av1_round_shift_array_c
transformFunctionColumn.Transform(ref tempIn, ref tempOut, cosBitColumn, stageRangeColumn); transformFunctionColumn.Transform(tempInSpan, tempOutSpan, cosBitColumn, stageRangeColumn);
RoundShiftArray(ref tempOut, transformRowCount, -shift[1]); // NM svt_av1_round_shift_array_c RoundShiftArray(ref tempOut, transformRowCount, -shift[1]); // NM svt_av1_round_shift_array_c
if (!config.FlipLeftToRight) if (!config.FlipLeftToRight)
{ {
int t = c; int t = c;
for (r = 0; r < transformRowCount; ++r) for (r = 0; r < transformRowCount; ++r)
{ {
Unsafe.Add(ref buf, t) = Unsafe.Add(ref tempOut, r); Unsafe.Add(ref bufRef, t) = Unsafe.Add(ref tempOut, r);
t += transformColumnCount; t += transformColumnCount;
} }
} }
@ -131,7 +135,7 @@ internal class Av1ForwardTransformer
for (r = 0; r < transformRowCount; ++r) for (r = 0; r < transformRowCount; ++r)
{ {
// flip from left to right // flip from left to right
Unsafe.Add(ref buf, t) = Unsafe.Add(ref tempOut, r); Unsafe.Add(ref bufRef, t) = Unsafe.Add(ref tempOut, r);
t += transformColumnCount; t += transformColumnCount;
} }
} }
@ -141,11 +145,11 @@ internal class Av1ForwardTransformer
for (r = 0; r < transformRowCount; ++r) for (r = 0; r < transformRowCount; ++r)
{ {
transformFunctionRow.Transform( transformFunctionRow.Transform(
ref Unsafe.Add(ref buf, r * transformColumnCount), buf.Slice(r * transformColumnCount, transformColumnCount),
ref Unsafe.Add(ref output, r * transformColumnCount), output.Slice(r * transformColumnCount, transformColumnCount),
cosBitRow, cosBitRow,
stageRangeRow); stageRangeRow);
RoundShiftArray(ref Unsafe.Add(ref output, r * transformColumnCount), transformColumnCount, -shift[2]); RoundShiftArray(ref Unsafe.Add(ref outputRef, r * transformColumnCount), transformColumnCount, -shift[2]);
if (Math.Abs(rectangleType) == 1) if (Math.Abs(rectangleType) == 1)
{ {
@ -154,7 +158,7 @@ internal class Av1ForwardTransformer
int t = r * transformColumnCount; int t = r * transformColumnCount;
for (c = 0; c < transformColumnCount; ++c) for (c = 0; c < transformColumnCount; ++c)
{ {
ref int current = ref Unsafe.Add(ref output, t); ref int current = ref Unsafe.Add(ref outputRef, t);
current = Av1Math.RoundShift((long)current * NewSqrt, NewSqrtBitCount); current = Av1Math.RoundShift((long)current * NewSqrt, NewSqrtBitCount);
t++; t++;
} }

8
src/ImageSharp/Formats/Heif/Av1/Transform/Forward/Av1Adst16Forward1dTransformer.cs

@ -7,8 +7,12 @@ namespace SixLabors.ImageSharp.Formats.Heif.Av1.Transform.Forward;
internal class Av1Adst16Forward1dTransformer : IAv1Forward1dTransformer internal class Av1Adst16Forward1dTransformer : IAv1Forward1dTransformer
{ {
public void Transform(ref int input, ref int output, int cosBit, Span<byte> stageRange) public void Transform(Span<int> input, Span<int> output, int cosBit, Span<byte> stageRange)
=> TransformScalar(ref input, ref output, cosBit); {
Guard.MustBeSizedAtLeast(input, 16, nameof(input));
Guard.MustBeSizedAtLeast(output, 16, nameof(output));
TransformScalar(ref input[0], ref output[0], cosBit);
}
private static void TransformScalar(ref int input, ref int output, int cosBit) private static void TransformScalar(ref int input, ref int output, int cosBit)
{ {

8
src/ImageSharp/Formats/Heif/Av1/Transform/Forward/Av1Adst32Forward1dTransformer.cs

@ -7,8 +7,12 @@ namespace SixLabors.ImageSharp.Formats.Heif.Av1.Transform.Forward;
internal class Av1Adst32Forward1dTransformer : IAv1Forward1dTransformer internal class Av1Adst32Forward1dTransformer : IAv1Forward1dTransformer
{ {
public void Transform(ref int input, ref int output, int cosBit, Span<byte> stageRange) public void Transform(Span<int> input, Span<int> output, int cosBit, Span<byte> stageRange)
=> TransformScalar(ref input, ref output, cosBit); {
Guard.MustBeSizedAtLeast(input, 32, nameof(input));
Guard.MustBeSizedAtLeast(output, 32, nameof(output));
TransformScalar(ref input[0], ref output[0], cosBit);
}
private static void TransformScalar(ref int input, ref int outputRef, int cosBit) private static void TransformScalar(ref int input, ref int outputRef, int cosBit)
{ {

8
src/ImageSharp/Formats/Heif/Av1/Transform/Forward/Av1Adst4Forward1dTransformer.cs

@ -7,8 +7,12 @@ namespace SixLabors.ImageSharp.Formats.Heif.Av1.Transform.Forward;
internal class Av1Adst4Forward1dTransformer : IAv1Forward1dTransformer internal class Av1Adst4Forward1dTransformer : IAv1Forward1dTransformer
{ {
public void Transform(ref int input, ref int output, int cosBit, Span<byte> stageRange) public void Transform(Span<int> input, Span<int> output, int cosBit, Span<byte> stageRange)
=> TransformScalar(ref input, ref output, cosBit); {
Guard.MustBeSizedAtLeast(input, 4, nameof(input));
Guard.MustBeSizedAtLeast(output, 4, nameof(output));
TransformScalar(ref input[0], ref output[0], cosBit);
}
private static void TransformScalar(ref int input, ref int output, int cosBit) private static void TransformScalar(ref int input, ref int output, int cosBit)
{ {

8
src/ImageSharp/Formats/Heif/Av1/Transform/Forward/Av1Adst8Forward1dTransformer.cs

@ -7,8 +7,12 @@ namespace SixLabors.ImageSharp.Formats.Heif.Av1.Transform.Forward;
internal class Av1Adst8Forward1dTransformer : IAv1Forward1dTransformer internal class Av1Adst8Forward1dTransformer : IAv1Forward1dTransformer
{ {
public void Transform(ref int input, ref int output, int cosBit, Span<byte> stageRange) public void Transform(Span<int> input, Span<int> output, int cosBit, Span<byte> stageRange)
=> TransformScalar(ref input, ref output, cosBit); {
Guard.MustBeSizedAtLeast(input, 8, nameof(input));
Guard.MustBeSizedAtLeast(output, 8, nameof(output));
TransformScalar(ref input[0], ref output[0], cosBit);
}
private static void TransformScalar(ref int input, ref int output, int cosBit) private static void TransformScalar(ref int input, ref int output, int cosBit)
{ {

8
src/ImageSharp/Formats/Heif/Av1/Transform/Forward/Av1Dct16Forward1dTransformer.cs

@ -7,8 +7,12 @@ namespace SixLabors.ImageSharp.Formats.Heif.Av1.Transform.Forward;
internal class Av1Dct16Forward1dTransformer : IAv1Forward1dTransformer internal class Av1Dct16Forward1dTransformer : IAv1Forward1dTransformer
{ {
public void Transform(ref int input, ref int output, int cosBit, Span<byte> stageRange) public void Transform(Span<int> input, Span<int> output, int cosBit, Span<byte> stageRange)
=> TransformScalar(ref input, ref output, cosBit); {
Guard.MustBeSizedAtLeast(input, 16, nameof(input));
Guard.MustBeSizedAtLeast(output, 16, nameof(output));
TransformScalar(ref input[0], ref output[0], cosBit);
}
private static void TransformScalar(ref int input, ref int output, int cosBit) private static void TransformScalar(ref int input, ref int output, int cosBit)
{ {

8
src/ImageSharp/Formats/Heif/Av1/Transform/Forward/Av1Dct32Forward1dTransformer.cs

@ -7,8 +7,12 @@ namespace SixLabors.ImageSharp.Formats.Heif.Av1.Transform.Forward;
internal class Av1Dct32Forward1dTransformer : IAv1Forward1dTransformer internal class Av1Dct32Forward1dTransformer : IAv1Forward1dTransformer
{ {
public void Transform(ref int input, ref int output, int cosBit, Span<byte> stageRange) public void Transform(Span<int> input, Span<int> output, int cosBit, Span<byte> stageRange)
=> TransformScalar(ref input, ref output, cosBit); {
Guard.MustBeSizedAtLeast(input, 32, nameof(input));
Guard.MustBeSizedAtLeast(output, 32, nameof(output));
TransformScalar(ref input[0], ref output[0], cosBit);
}
private static void TransformScalar(ref int input, ref int output, int cosBit) private static void TransformScalar(ref int input, ref int output, int cosBit)
{ {

8
src/ImageSharp/Formats/Heif/Av1/Transform/Forward/Av1Dct4Forward1dTransformer.cs

@ -7,8 +7,12 @@ namespace SixLabors.ImageSharp.Formats.Heif.Av1.Transform.Forward;
internal class Av1Dct4Forward1dTransformer : IAv1Forward1dTransformer internal class Av1Dct4Forward1dTransformer : IAv1Forward1dTransformer
{ {
public void Transform(ref int input, ref int output, int cosBit, Span<byte> stageRange) public void Transform(Span<int> input, Span<int> output, int cosBit, Span<byte> stageRange)
=> TransformScalar(ref input, ref output, cosBit); {
Guard.MustBeSizedAtLeast(input, 4, nameof(input));
Guard.MustBeSizedAtLeast(output, 4, nameof(output));
TransformScalar(ref input[0], ref output[0], cosBit);
}
private static void TransformScalar(ref int input, ref int output, int cosBit) private static void TransformScalar(ref int input, ref int output, int cosBit)
{ {

10
src/ImageSharp/Formats/Heif/Av1/Transform/Forward/Av1Dct64Forward1dTransformer.cs

@ -7,10 +7,14 @@ namespace SixLabors.ImageSharp.Formats.Heif.Av1.Transform.Forward;
internal class Av1Dct64Forward1dTransformer : IAv1Forward1dTransformer internal class Av1Dct64Forward1dTransformer : IAv1Forward1dTransformer
{ {
public void Transform(ref int input, ref int output, int cosBit, Span<byte> stageRange) public void Transform(Span<int> input, Span<int> output, int cosBit, Span<byte> stageRange)
=> TransforScalar(ref input, ref output, cosBit); {
Guard.MustBeSizedAtLeast(input, 64, nameof(input));
Guard.MustBeSizedAtLeast(output, 64, nameof(output));
TransformScalar(ref input[0], ref output[0], cosBit);
}
private static void TransforScalar(ref int input, ref int output, int cosBit) private static void TransformScalar(ref int input, ref int output, int cosBit)
{ {
Span<int> temp0 = stackalloc int[64]; Span<int> temp0 = stackalloc int[64];
Span<int> temp1 = stackalloc int[64]; Span<int> temp1 = stackalloc int[64];

8
src/ImageSharp/Formats/Heif/Av1/Transform/Forward/Av1Dct8Forward1dTransformer.cs

@ -7,8 +7,12 @@ namespace SixLabors.ImageSharp.Formats.Heif.Av1.Transform.Forward;
internal class Av1Dct8Forward1dTransformer : IAv1Forward1dTransformer internal class Av1Dct8Forward1dTransformer : IAv1Forward1dTransformer
{ {
public void Transform(ref int input, ref int output, int cosBit, Span<byte> stageRange) public void Transform(Span<int> input, Span<int> output, int cosBit, Span<byte> stageRange)
=> TransformScalar(ref input, ref output, cosBit); {
Guard.MustBeSizedAtLeast(input, 8, nameof(input));
Guard.MustBeSizedAtLeast(output, 8, nameof(output));
TransformScalar(ref input[0], ref output[0], cosBit);
}
private static void TransformScalar(ref int input, ref int output, int cosBit) private static void TransformScalar(ref int input, ref int output, int cosBit)
{ {

4
src/ImageSharp/Formats/Heif/Av1/Transform/Forward/Av1DctDct4Forward2dTransformer.cs

@ -12,7 +12,7 @@ internal class Av1DctDct4Forward2dTransformer : Av1Forward2dTransformerBase
private readonly Av1Dct4Forward1dTransformer transformer = new(); private readonly Av1Dct4Forward1dTransformer transformer = new();
private readonly int[] temp = new int[Av1Constants.MaxTransformSize * Av1Constants.MaxTransformSize]; private readonly int[] temp = new int[Av1Constants.MaxTransformSize * Av1Constants.MaxTransformSize];
public void Transform(ref short input, ref int output, int cosBit, int columnNumber) public void Transform(Span<short> input, Span<int> output, int cosBit, int columnNumber)
{ {
/*if (Vector256.IsHardwareAccelerated) /*if (Vector256.IsHardwareAccelerated)
{ {
@ -22,7 +22,7 @@ internal class Av1DctDct4Forward2dTransformer : Av1Forward2dTransformerBase
} }
else*/ else*/
{ {
Transform2dCore(this.transformer, this.transformer, ref input, 4, ref output, this.config, ref this.temp[0], 8); Transform2dCore(this.transformer, this.transformer, input, 4, output, this.config, this.temp, 8);
} }
} }

27
src/ImageSharp/Formats/Heif/Av1/Transform/Forward/Av1Forward2dTransformerBase.cs

@ -13,7 +13,7 @@ internal abstract class Av1Forward2dTransformerBase
/// <summary> /// <summary>
/// SVT: av1_tranform_two_d_core_c /// SVT: av1_tranform_two_d_core_c
/// </summary> /// </summary>
protected static void Transform2dCore<TColumn, TRow>(TColumn transformFunctionColumn, TRow transformFunctionRow, ref short input, uint inputStride, ref int output, Av1Transform2dFlipConfiguration config, ref int buf, int bitDepth) protected static void Transform2dCore<TColumn, TRow>(TColumn transformFunctionColumn, TRow transformFunctionRow, Span<short> input, uint inputStride, Span<int> output, Av1Transform2dFlipConfiguration config, Span<int> buf, int bitDepth)
where TColumn : IAv1Forward1dTransformer where TColumn : IAv1Forward1dTransformer
where TRow : IAv1Forward1dTransformer where TRow : IAv1Forward1dTransformer
{ {
@ -45,8 +45,13 @@ internal abstract class Av1Forward2dTransformerBase
// ASSERT(txfm_func_col != NULL); // ASSERT(txfm_func_col != NULL);
// ASSERT(txfm_func_row != NULL); // ASSERT(txfm_func_row != NULL);
// use output buffer as temp buffer // use output buffer as temp buffer
ref int tempIn = ref output; ref short inputRef = ref input[0];
ref int tempOut = ref Unsafe.Add(ref output, transformRowCount); ref int outputRef = ref output[0];
ref int bufRef = ref buf[0];
Span<int> tempInSpan = output.Slice(0, transformRowCount);
Span<int> tempOutSpan = output.Slice(transformRowCount, transformRowCount);
ref int tempIn = ref tempInSpan[0];
ref int tempOut = ref tempOutSpan[0];
// Columns // Columns
for (c = 0; c < transformColumnCount; ++c) for (c = 0; c < transformColumnCount; ++c)
@ -56,7 +61,7 @@ internal abstract class Av1Forward2dTransformerBase
uint t = (uint)c; uint t = (uint)c;
for (r = 0; r < transformRowCount; ++r) for (r = 0; r < transformRowCount; ++r)
{ {
Unsafe.Add(ref tempIn, r) = Unsafe.Add(ref input, t); Unsafe.Add(ref tempIn, r) = Unsafe.Add(ref inputRef, t);
t += inputStride; t += inputStride;
} }
} }
@ -66,20 +71,20 @@ internal abstract class Av1Forward2dTransformerBase
for (r = 0; r < transformRowCount; ++r) for (r = 0; r < transformRowCount; ++r)
{ {
// flip upside down // flip upside down
Unsafe.Add(ref tempIn, r) = Unsafe.Add(ref input, t); Unsafe.Add(ref tempIn, r) = Unsafe.Add(ref inputRef, t);
t -= inputStride; t -= inputStride;
} }
} }
RoundShiftArray(ref tempIn, transformRowCount, -shift[0]); // NM svt_av1_round_shift_array_c RoundShiftArray(ref tempIn, transformRowCount, -shift[0]); // NM svt_av1_round_shift_array_c
transformFunctionColumn.Transform(ref tempIn, ref tempOut, cosBitColumn, stageRangeColumn); transformFunctionColumn.Transform(tempInSpan, tempOutSpan, cosBitColumn, stageRangeColumn);
RoundShiftArray(ref tempOut, transformRowCount, -shift[1]); // NM svt_av1_round_shift_array_c RoundShiftArray(ref tempOut, transformRowCount, -shift[1]); // NM svt_av1_round_shift_array_c
if (!config.FlipLeftToRight) if (!config.FlipLeftToRight)
{ {
int t = c; int t = c;
for (r = 0; r < transformRowCount; ++r) for (r = 0; r < transformRowCount; ++r)
{ {
Unsafe.Add(ref buf, t) = Unsafe.Add(ref tempOut, r); Unsafe.Add(ref bufRef, t) = Unsafe.Add(ref tempOut, r);
t += transformColumnCount; t += transformColumnCount;
} }
} }
@ -89,7 +94,7 @@ internal abstract class Av1Forward2dTransformerBase
for (r = 0; r < transformRowCount; ++r) for (r = 0; r < transformRowCount; ++r)
{ {
// flip from left to right // flip from left to right
Unsafe.Add(ref buf, t) = Unsafe.Add(ref tempOut, r); Unsafe.Add(ref bufRef, t) = Unsafe.Add(ref tempOut, r);
t += transformColumnCount; t += transformColumnCount;
} }
} }
@ -98,8 +103,8 @@ internal abstract class Av1Forward2dTransformerBase
// Rows // Rows
for (r = 0; r < transformRowCount; ++r) for (r = 0; r < transformRowCount; ++r)
{ {
transformFunctionRow.Transform(ref Unsafe.Add(ref buf, r * transformColumnCount), ref Unsafe.Add(ref output, r * transformColumnCount), cosBitRow, stageRangeRow); transformFunctionRow.Transform(buf.Slice(r * transformColumnCount, transformColumnCount), output.Slice(r * transformColumnCount, transformColumnCount), cosBitRow, stageRangeRow);
RoundShiftArray(ref Unsafe.Add(ref output, r * transformColumnCount), transformColumnCount, -shift[2]); RoundShiftArray(ref Unsafe.Add(ref outputRef, r * transformColumnCount), transformColumnCount, -shift[2]);
if (Math.Abs(rectangleType) == 1) if (Math.Abs(rectangleType) == 1)
{ {
@ -107,7 +112,7 @@ internal abstract class Av1Forward2dTransformerBase
// size difference is a factor of 2. // size difference is a factor of 2.
for (c = 0; c < transformColumnCount; ++c) for (c = 0; c < transformColumnCount; ++c)
{ {
ref int current = ref Unsafe.Add(ref output, (r * transformColumnCount) + c); ref int current = ref Unsafe.Add(ref outputRef, (r * transformColumnCount) + c);
current = Av1Math.RoundShift((long)current * NewSqrt2, NewSqrt2BitCount); current = Av1Math.RoundShift((long)current * NewSqrt2, NewSqrt2BitCount);
} }
} }

8
src/ImageSharp/Formats/Heif/Av1/Transform/Forward/Av1Identity16Forward1dTransformer.cs

@ -9,8 +9,12 @@ internal class Av1Identity16Forward1dTransformer : IAv1Forward1dTransformer
{ {
private const int TwiceNewSqrt2 = 2 * 5793; private const int TwiceNewSqrt2 = 2 * 5793;
public void Transform(ref int input, ref int output, int cosBit, Span<byte> stageRange) public void Transform(Span<int> input, Span<int> output, int cosBit, Span<byte> stageRange)
=> TransformScalar(ref input, ref output); {
Guard.MustBeSizedAtLeast(input, 16, nameof(input));
Guard.MustBeSizedAtLeast(output, 16, nameof(output));
TransformScalar(ref input[0], ref output[0]);
}
private static void TransformScalar(ref int input, ref int output) private static void TransformScalar(ref int input, ref int output)
{ {

14
src/ImageSharp/Formats/Heif/Av1/Transform/Forward/Av1Identity32Forward1dTransformer.cs

@ -7,12 +7,16 @@ namespace SixLabors.ImageSharp.Formats.Heif.Av1.Transform.Forward;
internal class Av1Identity32Forward1dTransformer : IAv1Forward1dTransformer internal class Av1Identity32Forward1dTransformer : IAv1Forward1dTransformer
{ {
public void Transform(ref int input, ref int output, int cosBit, Span<byte> stageRange) public void Transform(Span<int> input, Span<int> output, int cosBit, Span<byte> stageRange)
{ {
TransformScalar(ref input, ref output); Guard.MustBeSizedAtLeast(input, 32, nameof(input));
TransformScalar(ref Unsafe.Add(ref input, 8), ref Unsafe.Add(ref output, 8)); Guard.MustBeSizedAtLeast(output, 32, nameof(output));
TransformScalar(ref Unsafe.Add(ref input, 16), ref Unsafe.Add(ref output, 16)); ref int inputRef = ref input[0];
TransformScalar(ref Unsafe.Add(ref input, 24), ref Unsafe.Add(ref output, 24)); ref int outputRef = ref output[0];
TransformScalar(ref inputRef, ref outputRef);
TransformScalar(ref Unsafe.Add(ref inputRef, 8), ref Unsafe.Add(ref outputRef, 8));
TransformScalar(ref Unsafe.Add(ref inputRef, 16), ref Unsafe.Add(ref outputRef, 16));
TransformScalar(ref Unsafe.Add(ref inputRef, 24), ref Unsafe.Add(ref outputRef, 24));
} }
private static void TransformScalar(ref int input, ref int output) private static void TransformScalar(ref int input, ref int output)

8
src/ImageSharp/Formats/Heif/Av1/Transform/Forward/Av1Identity4Forward1dTransformer.cs

@ -7,8 +7,12 @@ namespace SixLabors.ImageSharp.Formats.Heif.Av1.Transform.Forward;
internal class Av1Identity4Forward1dTransformer : IAv1Forward1dTransformer internal class Av1Identity4Forward1dTransformer : IAv1Forward1dTransformer
{ {
public void Transform(ref int input, ref int output, int cosBit, Span<byte> stageRange) public void Transform(Span<int> input, Span<int> output, int cosBit, Span<byte> stageRange)
=> TransformScalar(ref input, ref output); {
Guard.MustBeSizedAtLeast(input, 4, nameof(input));
Guard.MustBeSizedAtLeast(output, 4, nameof(output));
TransformScalar(ref input[0], ref output[0]);
}
private static void TransformScalar(ref int input, ref int output) private static void TransformScalar(ref int input, ref int output)
{ {

14
src/ImageSharp/Formats/Heif/Av1/Transform/Forward/Av1Identity64Forward1dTransformer.cs

@ -9,12 +9,16 @@ internal class Av1Identity64Forward1dTransformer : IAv1Forward1dTransformer
{ {
private const int QuadNewSqrt2 = 4 * 5793; private const int QuadNewSqrt2 = 4 * 5793;
public void Transform(ref int input, ref int output, int cosBit, Span<byte> stageRange) public void Transform(Span<int> input, Span<int> output, int cosBit, Span<byte> stageRange)
{ {
TransformScalar(ref input, ref output); Guard.MustBeSizedAtLeast(input, 64, nameof(input));
TransformScalar(ref Unsafe.Add(ref input, 16), ref Unsafe.Add(ref output, 16)); Guard.MustBeSizedAtLeast(output, 64, nameof(output));
TransformScalar(ref Unsafe.Add(ref input, 32), ref Unsafe.Add(ref output, 32)); ref int inputRef = ref input[0];
TransformScalar(ref Unsafe.Add(ref input, 48), ref Unsafe.Add(ref output, 48)); ref int outputRef = ref output[0];
TransformScalar(ref inputRef, ref outputRef);
TransformScalar(ref Unsafe.Add(ref inputRef, 16), ref Unsafe.Add(ref outputRef, 16));
TransformScalar(ref Unsafe.Add(ref inputRef, 32), ref Unsafe.Add(ref outputRef, 32));
TransformScalar(ref Unsafe.Add(ref inputRef, 48), ref Unsafe.Add(ref outputRef, 48));
} }
private static void TransformScalar(ref int input, ref int output) private static void TransformScalar(ref int input, ref int output)

8
src/ImageSharp/Formats/Heif/Av1/Transform/Forward/Av1Identity8Forward1dTransformer.cs

@ -7,8 +7,12 @@ namespace SixLabors.ImageSharp.Formats.Heif.Av1.Transform.Forward;
internal class Av1Identity8Forward1dTransformer : IAv1Forward1dTransformer internal class Av1Identity8Forward1dTransformer : IAv1Forward1dTransformer
{ {
public void Transform(ref int input, ref int output, int cosBit, Span<byte> stageRange) public void Transform(Span<int> input, Span<int> output, int cosBit, Span<byte> stageRange)
=> TransformScalar(ref input, ref output); {
Guard.MustBeSizedAtLeast(input, 8, nameof(input));
Guard.MustBeSizedAtLeast(output, 8, nameof(output));
TransformScalar(ref input[0], ref output[0]);
}
private static void TransformScalar(ref int input, ref int output) private static void TransformScalar(ref int input, ref int output)
{ {

2
src/ImageSharp/Formats/Heif/Av1/Transform/IAv1Forward1dTransformer.cs

@ -15,5 +15,5 @@ internal interface IAv1Forward1dTransformer
/// <param name="output">Output coefficients.</param> /// <param name="output">Output coefficients.</param>
/// <param name="cosBit">The cosinus bit.</param> /// <param name="cosBit">The cosinus bit.</param>
/// <param name="stageRange">Stage ranges.</param> /// <param name="stageRange">Stage ranges.</param>
void Transform(ref int input, ref int output, int cosBit, Span<byte> stageRange); void Transform(Span<int> input, Span<int> output, int cosBit, Span<byte> stageRange);
} }

7
tests/ImageSharp.Tests/Formats/Heif/Av1/Av1ForwardTransformTests.cs

@ -8,7 +8,8 @@ using SixLabors.ImageSharp.Formats.Heif.Av1.Transform.Forward;
namespace SixLabors.ImageSharp.Tests.Formats.Heif.Av1; namespace SixLabors.ImageSharp.Tests.Formats.Heif.Av1;
/// <summary> /// <summary>
/// SVY: test/FwdTxfm2dTest.cc /// SVY: test/FwdTxfm1dTest.cc
/// SVY: test/FwdTxfm2dAsmTest.cc
/// </summary> /// </summary>
[Trait("Format", "Avif")] [Trait("Format", "Avif")]
public class Av1ForwardTransformTests public class Av1ForwardTransformTests
@ -256,8 +257,8 @@ public class Av1ForwardTransformTests
// calculate in forward transform functions // calculate in forward transform functions
transformerUnderTest.Transform( transformerUnderTest.Transform(
ref inputOfTest[0], inputOfTest,
ref outputOfTest[0], outputOfTest,
config.CosBitColumn, config.CosBitColumn,
config.StageRangeColumn); config.StageRangeColumn);

Loading…
Cancel
Save