diff --git a/src/ImageSharp/Formats/Heif/Av1/Transform/Av1ScanOrderConstants.cs b/src/ImageSharp/Formats/Heif/Av1/Transform/Av1ScanOrderConstants.cs index 5acac18c7f..4f7ea2d2d6 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Transform/Av1ScanOrderConstants.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Transform/Av1ScanOrderConstants.cs @@ -359,7 +359,6 @@ internal static class Av1ScanOrderConstants private static readonly short[] DefaultInverseScan8x8 = []; private static readonly short[] DefaultInverseScan16x16 = []; private static readonly short[] DefaultInverseScan32x32 = []; - private static readonly short[] DefaultInverseScan64x64 = []; private static readonly short[] DefaultInverseScan4x8 = []; private static readonly short[] DefaultInverseScan8x4 = []; private static readonly short[] DefaultInverseScan8x16 = []; @@ -375,7 +374,6 @@ internal static class Av1ScanOrderConstants private static readonly short[] MatrixColumnInverseScan8x8 = []; private static readonly short[] MatrixColumnInverseScan16x16 = []; private static readonly short[] MatrixColumnInverseScan32x32 = []; - private static readonly short[] MatrixColumnInverseScan64x64 = []; private static readonly short[] MatrixColumnInverseScan4x8 = []; private static readonly short[] MatrixColumnInverseScan8x4 = []; private static readonly short[] MatrixColumnInverseScan8x16 = []; @@ -391,7 +389,6 @@ internal static class Av1ScanOrderConstants private static readonly short[] MatrixRowInverseScan8x8 = []; private static readonly short[] MatrixRowInverseScan16x16 = []; private static readonly short[] MatrixRowInverseScan32x32 = []; - private static readonly short[] MatrixRowInverseScan64x64 = []; private static readonly short[] MatrixRowInverseScan4x8 = []; private static readonly short[] MatrixRowInverseScan8x4 = []; private static readonly short[] MatrixRowInverseScan8x16 = []; @@ -403,12 +400,11 @@ internal static class Av1ScanOrderConstants private static readonly short[] MatrixRowInverseScan8x32 = []; private static readonly short[] MatrixRowInverseScan32x8 = []; - // Neighborss are not used (yet) for AVIF coding, leave these arrays empty for now. + // Neighbors are not used (yet) for AVIF coding, leave these arrays empty for now. private static readonly short[] DefaultScan4x4Neighbors = []; private static readonly short[] DefaultScan8x8Neighbors = []; private static readonly short[] DefaultScan16x16Neighbors = []; private static readonly short[] DefaultScan32x32Neighbors = []; - private static readonly short[] DefaultScan64x64Neighbors = []; private static readonly short[] DefaultScan4x8Neighbors = []; private static readonly short[] DefaultScan8x4Neighbors = []; private static readonly short[] DefaultScan8x16Neighbors = []; @@ -424,7 +420,6 @@ internal static class Av1ScanOrderConstants private static readonly short[] MatrixColumnScan8x8Neighbors = []; private static readonly short[] MatrixColumnScan16x16Neighbors = []; private static readonly short[] MatrixColumnScan32x32Neighbors = []; - private static readonly short[] MatrixColumnScan64x64Neighbors = []; private static readonly short[] MatrixColumnScan4x8Neighbors = []; private static readonly short[] MatrixColumnScan8x4Neighbors = []; private static readonly short[] MatrixColumnScan8x16Neighbors = []; @@ -440,7 +435,6 @@ internal static class Av1ScanOrderConstants private static readonly short[] MatrixRowScan8x8Neighbors = []; private static readonly short[] MatrixRowScan16x16Neighbors = []; private static readonly short[] MatrixRowScan32x32Neighbors = []; - private static readonly short[] MatrixRowScan64x64Neighbors = []; private static readonly short[] MatrixRowScan4x8Neighbors = []; private static readonly short[] MatrixRowScan8x4Neighbors = []; private static readonly short[] MatrixRowScan8x16Neighbors = []; diff --git a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1CoefficientsEntropyTests.cs b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1CoefficientsEntropyTests.cs index 8d47cbe9df..866e509a58 100644 --- a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1CoefficientsEntropyTests.cs +++ b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1CoefficientsEntropyTests.cs @@ -101,14 +101,14 @@ public class Av1CoefficientsEntropyTests } [Theory] - [MemberData(nameof(GetBlockSize4x4Data))] - public void RoundTripFullCoefficientsYSize4x4(int bSize, int txSize, int txType) + [MemberData(nameof(GetTransformTypes))] + public void RoundTripFullCoefficientsYSize4x4(int txType) { // Assign const ushort endOfBlock = 16; const Av1ComponentType componentType = Av1ComponentType.Luminance; - Av1BlockSize blockSize = (Av1BlockSize)bSize; - Av1TransformSize transformSize = (Av1TransformSize)txSize; + Av1BlockSize blockSize = Av1BlockSize.Block4x4; + Av1TransformSize transformSize = blockSize.GetMaximumTransformSize(); Av1TransformType transformType = (Av1TransformType)txType; Av1PredictionMode intraDirection = Av1PredictionMode.DC; Av1FilterIntraMode filterIntraMode = Av1FilterIntraMode.DC; @@ -116,14 +116,29 @@ public class Av1CoefficientsEntropyTests } [Theory] - [MemberData(nameof(GetBlockSize4x4Data))] - public void RoundTripFullCoefficientsUvSize4x4(int bSize, int txSize, int txType) + [MemberData(nameof(GetTransformTypes))] + public void RoundTripFullCoefficientsYSize8x8(int txType) + { + // Assign + const ushort endOfBlock = 16; + const Av1ComponentType componentType = Av1ComponentType.Luminance; + Av1BlockSize blockSize = Av1BlockSize.Block8x8; + Av1TransformSize transformSize = blockSize.GetMaximumTransformSize(); + Av1TransformType transformType = (Av1TransformType)txType; + Av1PredictionMode intraDirection = Av1PredictionMode.DC; + Av1FilterIntraMode filterIntraMode = Av1FilterIntraMode.DC; + RoundTripCoefficientsCore(endOfBlock, componentType, blockSize, transformSize, transformType, intraDirection, filterIntraMode); + } + + [Theory] + [MemberData(nameof(GetTransformTypes))] + public void RoundTripFullCoefficientsUvSize4x4(int txType) { // Assign const ushort endOfBlock = 16; const Av1ComponentType componentType = Av1ComponentType.Chroma; - Av1BlockSize blockSize = (Av1BlockSize)bSize; - Av1TransformSize transformSize = (Av1TransformSize)txSize; + Av1BlockSize blockSize = Av1BlockSize.Block4x4; + Av1TransformSize transformSize = blockSize.GetMaxUvTransformSize(true, true); Av1TransformType transformType = (Av1TransformType)txType; Av1PredictionMode intraDirection = Av1PredictionMode.DC; Av1FilterIntraMode filterIntraMode = Av1FilterIntraMode.DC; @@ -155,14 +170,12 @@ public class Av1CoefficientsEntropyTests Assert.Equal(coefficientsBuffer[..endOfBlock], actuals[1..(endOfBlock + 1)]); } - public static TheoryData GetBlockSize4x4Data() + public static TheoryData GetTransformTypes() { - TheoryData result = []; - Av1BlockSize blockSize = Av1BlockSize.Block4x4; - Av1TransformSize transformSize = blockSize.GetMaximumTransformSize(); + TheoryData result = []; for (Av1TransformType transformType = Av1TransformType.DctDct; transformType < Av1TransformType.VerticalDct; transformType++) { - result.Add((int)blockSize, (int)transformSize, (int)transformType); + result.Add((int)transformType); } return result; diff --git a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1ScanOrderTests.cs b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1ScanOrderTests.cs index 9844e2833c..c8c59ce21e 100644 --- a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1ScanOrderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1ScanOrderTests.cs @@ -65,6 +65,45 @@ public class Av1ScanOrderTests Assert.Equal(width * height, scanOrder.Scan.Length); } + [Theory] + [MemberData(nameof(GetCombinations))] + internal void AllIndicesAreInDiagonalOrder(int s, int t) + { + // Assign + Av1TransformSize transformSize = (Av1TransformSize)s; + Av1TransformType transformType = (Av1TransformType)t; + int width = Math.Min(transformSize.GetWidth(), 32); + int height = Math.Min(transformSize.GetHeight(), 32); + + // Act + Av1ScanOrder scanOrder = Av1ScanOrderConstants.GetScanOrder(transformSize, transformType); + + // Assert + HashSet visited = []; + ReadOnlySpan scan = scanOrder.Scan; + + // In reverse order, the indiced used in + // must already be known. + for (int i = scanOrder.Scan.Length - 1; i >= 0; i--) + { + visited.Add(scan[i]); + if (scan.Length > i + 1) + { + Assert.Contains(scan[i + 1], visited); + } + + if (scan.Length > i + width) + { + Assert.Contains(scan[i + width], visited); + } + + if (scan.Length > i + width + 1) + { + Assert.Contains(scan[i + width + 1], visited); + } + } + } + public static TheoryData GetCombinations() { TheoryData combinations = [];