diff --git a/src/ImageSharp/Formats/Heif/Av1/Transform/Av1InverseTransformer.cs b/src/ImageSharp/Formats/Heif/Av1/Transform/Av1InverseTransformer.cs
index 6b36f191fc..49bbdd2e60 100644
--- a/src/ImageSharp/Formats/Heif/Av1/Transform/Av1InverseTransformer.cs
+++ b/src/ImageSharp/Formats/Heif/Av1/Transform/Av1InverseTransformer.cs
@@ -47,4 +47,23 @@ internal class Av1InverseTransformer
Av1InverseTransformerFactory.InverseTransformAdd(
coefficientsBuffer, reconstructionBufferRead, reconstructionReadStride, reconstructionBufferWrite, reconstructionWriteStride, transformFunctionParameters);
}
+
+ ///
+ /// AV1: 7.11.2 Reconstruct.
+ ///
+ public static void ReconstructHighBitDepth(Span coefficientsBuffer, Span reconstructionBuffer, int reconstructionStride, Av1TransformSize transformSize, Av1TransformType transformType, int plane, int numberOfCoefficients, bool isLossless, Av1BitDepth bitDepth)
+ {
+ Av1TransformFunctionParameters transformFunctionParameters = new()
+ {
+ TransformType = transformType,
+ TransformSize = transformSize,
+ EndOfBuffer = numberOfCoefficients,
+ IsLossless = isLossless,
+ BitDepth = bitDepth.GetBitCount(),
+ Is16BitPipeline = true
+ };
+
+ Av1InverseTransformerFactory.InverseTransformAdd(
+ coefficientsBuffer, reconstructionBuffer, reconstructionStride, reconstructionBuffer, reconstructionStride, transformFunctionParameters);
+ }
}
diff --git a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1InverseTransformTests.cs b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1InverseTransformTests.cs
index 31554a94b8..30d50394eb 100644
--- a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1InverseTransformTests.cs
+++ b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1InverseTransformTests.cs
@@ -267,6 +267,56 @@ public class Av1InverseTransformTests
Assert.Equal(expected.Select(value => (byte)value), actual);
}
+ [Theory]
+ [InlineData((int)Av1BitDepth.TenBit, 1023)]
+ [InlineData((int)Av1BitDepth.TwelveBit, 4095)]
+ public void HighBitDepthReconstructionClipsPositiveValues(int bitDepthIndex, short maximum)
+ {
+ const int width = 4;
+ int[] coefficients = new int[width * width];
+ coefficients[0] = 64;
+ short[] reconstruction = new short[width * width];
+ Array.Fill(reconstruction, (short)(maximum - 1));
+
+ Av1InverseTransformer.ReconstructHighBitDepth(
+ coefficients,
+ reconstruction,
+ width,
+ Av1TransformSize.Size4x4,
+ Av1TransformType.DctDct,
+ 0,
+ 1,
+ false,
+ (Av1BitDepth)bitDepthIndex);
+
+ Assert.All(reconstruction, value => Assert.Equal(maximum, value));
+ }
+
+ [Theory]
+ [InlineData((int)Av1BitDepth.TenBit)]
+ [InlineData((int)Av1BitDepth.TwelveBit)]
+ public void HighBitDepthReconstructionClipsNegativeValues(int bitDepthIndex)
+ {
+ const int width = 4;
+ int[] coefficients = new int[width * width];
+ coefficients[0] = -64;
+ short[] reconstruction = new short[width * width];
+ Array.Fill(reconstruction, (short)1);
+
+ Av1InverseTransformer.ReconstructHighBitDepth(
+ coefficients,
+ reconstruction,
+ width,
+ Av1TransformSize.Size4x4,
+ Av1TransformType.DctDct,
+ 0,
+ 1,
+ false,
+ (Av1BitDepth)bitDepthIndex);
+
+ Assert.All(reconstruction, value => Assert.Equal((short)0, value));
+ }
+
private static void AssertAccuracy1d(
Av1TransformType transformType,
Av1TransformSize transformSize,