From 486aa58b68fa63ce723cc0c2ea58fc2746e8dd18 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Mon, 24 Aug 2026 21:12:14 +1000 Subject: [PATCH] Document AV1 reference availability tables --- .../Av1BottomRightTopLeftConstants.cs | 241 +++++++++++++++++- 1 file changed, 239 insertions(+), 2 deletions(-) diff --git a/src/ImageSharp/Formats/Heif/Av1/Prediction/Av1BottomRightTopLeftConstants.cs b/src/ImageSharp/Formats/Heif/Av1/Prediction/Av1BottomRightTopLeftConstants.cs index a3a3e0bd8..0591e8522 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Prediction/Av1BottomRightTopLeftConstants.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Prediction/Av1BottomRightTopLeftConstants.cs @@ -3,6 +3,13 @@ namespace SixLabors.ImageSharp.Formats.Heif.Av1.Prediction; +/// +/// Provides packed AV1 top-right and bottom-left reference-availability tables for blocks within a superblock. +/// +/// +/// Each bit describes whether a reference edge has already been reconstructed for one block in the AV1 partition traversal order. +/// Separate tables preserve the alternate visit order used by mixed vertical partitions. +/// internal class Av1BottomRightTopLeftConstants { // Tables to store if the top-right reference pixels are available. The flags @@ -14,6 +21,10 @@ internal class Av1BottomRightTopLeftConstants // . . . . // . . o . // . . . . + + /// + /// Packed top-right availability bits for 4-by-4 blocks. + /// private static readonly byte[] HasTopRight4x4 = [ 255, 255, 255, 255, 85, 85, 85, 85, 119, 119, 119, 119, 85, 85, 85, 85, 127, 127, 127, 127, 85, 85, 85, 85, 119, 119, 119, 119, 85, 85, 85, 85, 255, 127, 255, 127, 85, 85, 85, 85, 119, 119, 119, 119, @@ -23,23 +34,35 @@ internal class Av1BottomRightTopLeftConstants 85, 85, 127, 127, 127, 127, 85, 85, 85, 85, 119, 119, 119, 119, 85, 85, 85, 85, ]; + /// + /// Packed top-right availability bits for 4-by-8 blocks. + /// private static readonly byte[] HasTopRight4x8 = [ 255, 255, 255, 255, 119, 119, 119, 119, 127, 127, 127, 127, 119, 119, 119, 119, 255, 127, 255, 127, 119, 119, 119, 119, 127, 127, 127, 127, 119, 119, 119, 119, 255, 255, 255, 127, 119, 119, 119, 119, 127, 127, 127, 127, 119, 119, 119, 119, 255, 127, 255, 127, 119, 119, 119, 119, 127, 127, 127, 127, 119, 119, 119, 119, ]; + /// + /// Packed top-right availability bits for 8-by-4 blocks. + /// private static readonly byte[] HasTopRight8x4 = [ 255, 255, 0, 0, 85, 85, 0, 0, 119, 119, 0, 0, 85, 85, 0, 0, 127, 127, 0, 0, 85, 85, 0, 0, 119, 119, 0, 0, 85, 85, 0, 0, 255, 127, 0, 0, 85, 85, 0, 0, 119, 119, 0, 0, 85, 85, 0, 0, 127, 127, 0, 0, 85, 85, 0, 0, 119, 119, 0, 0, 85, 85, 0, 0, ]; + /// + /// Packed top-right availability bits for 8-by-8 blocks. + /// private static readonly byte[] HasTopRight8x8 = [ 255, 255, 85, 85, 119, 119, 85, 85, 127, 127, 85, 85, 119, 119, 85, 85, 255, 127, 85, 85, 119, 119, 85, 85, 127, 127, 85, 85, 119, 119, 85, 85, ]; + /// + /// Packed top-right availability bits for 8-by-16 blocks. + /// private static readonly byte[] HasTopRight8x16 = [ 255, 255, @@ -59,6 +82,9 @@ internal class Av1BottomRightTopLeftConstants 119, ]; + /// + /// Packed top-right availability bits for 16-by-8 blocks. + /// private static readonly byte[] HasTopRight16x8 = [ 255, 0, @@ -78,6 +104,9 @@ internal class Av1BottomRightTopLeftConstants 0, ]; + /// + /// Packed top-right availability bits for 16-by-16 blocks. + /// private static readonly byte[] HasTopRight16x16 = [ 255, 85, @@ -89,24 +118,69 @@ internal class Av1BottomRightTopLeftConstants 85, ]; + /// + /// Packed top-right availability bits for 16-by-32 blocks. + /// private static readonly byte[] HasTopRight16x32 = [255, 119, 127, 119]; + + /// + /// Packed top-right availability bits for 32-by-16 blocks. + /// private static readonly byte[] HasTopRight32x16 = [15, 5, 7, 5]; + + /// + /// Packed top-right availability bits for 32-by-32 blocks. + /// private static readonly byte[] HasTopRight32x32 = [95, 87]; + + /// + /// Packed top-right availability bits for 32-by-64 blocks. + /// private static readonly byte[] HasTopRight32x64 = [127]; + + /// + /// Packed top-right availability bits for 64-by-32 blocks. + /// private static readonly byte[] HasTopRight64x32 = [19]; + + /// + /// Packed top-right availability bits for 64-by-64 blocks. + /// private static readonly byte[] HasTopRight64x64 = [7]; + + /// + /// Packed top-right availability bits for 64-by-128 blocks. + /// private static readonly byte[] HasTopRight64x128 = [3]; + + /// + /// Packed top-right availability bits for 128-by-64 blocks. + /// private static readonly byte[] HasTopRight128x64 = [1]; + + /// + /// Packed top-right availability bits for 128-by-128 blocks. + /// private static readonly byte[] HasTopRight128x128 = [1]; + + /// + /// Packed top-right availability bits for 4-by-16 blocks. + /// private static readonly byte[] HasTopRight4x16 = [ 255, 255, 255, 255, 127, 127, 127, 127, 255, 127, 255, 127, 127, 127, 127, 127, 255, 255, 255, 127, 127, 127, 127, 127, 255, 127, 255, 127, 127, 127, 127, 127, ]; + /// + /// Packed top-right availability bits for 16-by-4 blocks. + /// private static readonly byte[] HasTopRight16x4 = [ 255, 0, 0, 0, 85, 0, 0, 0, 119, 0, 0, 0, 85, 0, 0, 0, 127, 0, 0, 0, 85, 0, 0, 0, 119, 0, 0, 0, 85, 0, 0, 0, ]; + /// + /// Packed top-right availability bits for 8-by-32 blocks. + /// private static readonly byte[] HasTopRight8x32 = [ 255, 255, @@ -118,6 +192,9 @@ internal class Av1BottomRightTopLeftConstants 127, ]; + /// + /// Packed top-right availability bits for 32-by-8 blocks. + /// private static readonly byte[] HasTopRight32x8 = [ 15, 0, @@ -129,9 +206,19 @@ internal class Av1BottomRightTopLeftConstants 0, ]; + /// + /// Packed top-right availability bits for 16-by-64 blocks. + /// private static readonly byte[] HasTopRight16x64 = [255, 127]; + + /// + /// Packed top-right availability bits for 64-by-16 blocks. + /// private static readonly byte[] HasTopRight64x16 = [3, 1]; + /// + /// Maps each supported AV1 block-size value to its standard top-right availability table. + /// private static readonly byte[][] HasTopRightTables = [ // 4X4 @@ -173,11 +260,17 @@ internal class Av1BottomRightTopLeftConstants HasTopRight64x16 ]; + /// + /// Packed top-right availability bits for 8-by-8 blocks visited by a mixed vertical partition. + /// private static readonly byte[] HasTopRightVertical8x8 = [ 255, 255, 0, 0, 119, 119, 0, 0, 127, 127, 0, 0, 119, 119, 0, 0, 255, 127, 0, 0, 119, 119, 0, 0, 127, 127, 0, 0, 119, 119, 0, 0, ]; + /// + /// Packed top-right availability bits for 16-by-16 blocks visited by a mixed vertical partition. + /// private static readonly byte[] HasTopRightVertical16x16 = [ 255, 0, @@ -189,7 +282,14 @@ internal class Av1BottomRightTopLeftConstants 0, ]; + /// + /// Packed top-right availability bits for 32-by-32 blocks visited by a mixed vertical partition. + /// private static readonly byte[] HasTopRightVertical32x32 = [15, 7]; + + /// + /// Packed top-right availability bits for 64-by-64 blocks visited by a mixed vertical partition. + /// private static readonly byte[] HasTopRightVertical64x64 = [3]; // The _vert_* tables are like the ordinary tables above, but describe the @@ -201,6 +301,13 @@ internal class Av1BottomRightTopLeftConstants // // There are tables for each of the square sizes. Vertical rectangles (like // BLOCK_16X32) use their respective "non-vert" table + + /// + /// Maps supported block-size values to top-right availability tables for mixed vertical partition traversal. + /// + /// + /// Null entries identify block sizes that cannot use this traversal table; vertical rectangles reuse their standard tables. + /// private static readonly byte[]?[] HasTopRightVerticalTables = [ // 4X4 @@ -234,6 +341,10 @@ internal class Av1BottomRightTopLeftConstants // Similar to the has_tr_* tables, but store if the bottom-left reference // pixels are available. + + /// + /// Packed bottom-left availability bits for 4-by-4 blocks. + /// private static readonly byte[] HasBottomLeft4x4 = [ 84, 85, 85, 85, 16, 17, 17, 17, 84, 85, 85, 85, 0, 1, 1, 1, 84, 85, 85, 85, 16, 17, 17, 17, 84, 85, 85, 85, 0, 0, 1, 0, 84, 85, 85, 85, 16, 17, 17, 17, 84, 85, 85, 85, 0, 1, 1, 1, 84, 85, 85, 85, @@ -242,22 +353,34 @@ internal class Av1BottomRightTopLeftConstants 84, 85, 85, 85, 0, 1, 1, 1, 84, 85, 85, 85, 16, 17, 17, 17, 84, 85, 85, 85, 0, 0, 0, 0, ]; + /// + /// Packed bottom-left availability bits for 4-by-8 blocks. + /// private static readonly byte[] HasBottomLeft4x8 = [ 16, 17, 17, 17, 0, 1, 1, 1, 16, 17, 17, 17, 0, 0, 1, 0, 16, 17, 17, 17, 0, 1, 1, 1, 16, 17, 17, 17, 0, 0, 0, 0, 16, 17, 17, 17, 0, 1, 1, 1, 16, 17, 17, 17, 0, 0, 1, 0, 16, 17, 17, 17, 0, 1, 1, 1, 16, 17, 17, 17, 0, 0, 0, 0, ]; + /// + /// Packed bottom-left availability bits for 8-by-4 blocks. + /// private static readonly byte[] HasBottomLeft8x4 = [ 254, 255, 84, 85, 254, 255, 16, 17, 254, 255, 84, 85, 254, 255, 0, 1, 254, 255, 84, 85, 254, 255, 16, 17, 254, 255, 84, 85, 254, 255, 0, 0, 254, 255, 84, 85, 254, 255, 16, 17, 254, 255, 84, 85, 254, 255, 0, 1, 254, 255, 84, 85, 254, 255, 16, 17, 254, 255, 84, 85, 254, 255, 0, 0, ]; + /// + /// Packed bottom-left availability bits for 8-by-8 blocks. + /// private static readonly byte[] HasBottomLeft8x8 = [ 84, 85, 16, 17, 84, 85, 0, 1, 84, 85, 16, 17, 84, 85, 0, 0, 84, 85, 16, 17, 84, 85, 0, 1, 84, 85, 16, 17, 84, 85, 0, 0, ]; + /// + /// Packed bottom-left availability bits for 8-by-16 blocks. + /// private static readonly byte[] HasBottomLeft8x16 = [ 16, 17, @@ -277,6 +400,9 @@ internal class Av1BottomRightTopLeftConstants 0, ]; + /// + /// Packed bottom-left availability bits for 16-by-8 blocks. + /// private static readonly byte[] HasBottomLeft16x8 = [ 254, 84, @@ -296,6 +422,9 @@ internal class Av1BottomRightTopLeftConstants 0, ]; + /// + /// Packed bottom-left availability bits for 16-by-16 blocks. + /// private static readonly byte[] HasBottomLeft16x16 = [ 84, 16, @@ -307,24 +436,69 @@ internal class Av1BottomRightTopLeftConstants 0, ]; + /// + /// Packed bottom-left availability bits for 16-by-32 blocks. + /// private static readonly byte[] HasBottomLeft16x32 = [16, 0, 16, 0]; + + /// + /// Packed bottom-left availability bits for 32-by-16 blocks. + /// private static readonly byte[] HasBottomLeft32x16 = [78, 14, 78, 14]; + + /// + /// Packed bottom-left availability bits for 32-by-32 blocks. + /// private static readonly byte[] HasBottomLeft32x32 = [4, 4]; + + /// + /// Packed bottom-left availability bits for 32-by-64 blocks. + /// private static readonly byte[] HasBottomLeft32x64 = [0]; + + /// + /// Packed bottom-left availability bits for 64-by-32 blocks. + /// private static readonly byte[] HasBottomLeft64x32 = [34]; + + /// + /// Packed bottom-left availability bits for 64-by-64 blocks. + /// private static readonly byte[] HasBottomLeft64x64 = [0]; + + /// + /// Packed bottom-left availability bits for 64-by-128 blocks. + /// private static readonly byte[] HasBottomLeft64x128 = [0]; + + /// + /// Packed bottom-left availability bits for 128-by-64 blocks. + /// private static readonly byte[] HasBottomLeft128x64 = [0]; + + /// + /// Packed bottom-left availability bits for 128-by-128 blocks. + /// private static readonly byte[] HasBottomLeft128x128 = [0]; + + /// + /// Packed bottom-left availability bits for 4-by-16 blocks. + /// private static readonly byte[] HasBottomLeft4x16 = [ 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, ]; + /// + /// Packed bottom-left availability bits for 16-by-4 blocks. + /// private static readonly byte[] HasBottomLeft16x4 = [ 254, 254, 254, 84, 254, 254, 254, 16, 254, 254, 254, 84, 254, 254, 254, 0, 254, 254, 254, 84, 254, 254, 254, 16, 254, 254, 254, 84, 254, 254, 254, 0, ]; + /// + /// Packed bottom-left availability bits for 8-by-32 blocks. + /// private static readonly byte[] HasBottomLeft8x32 = [ 0, 1, @@ -336,6 +510,9 @@ internal class Av1BottomRightTopLeftConstants 0, ]; + /// + /// Packed bottom-left availability bits for 32-by-8 blocks. + /// private static readonly byte[] HasBottomLeft32x8 = [ 238, 78, @@ -347,9 +524,19 @@ internal class Av1BottomRightTopLeftConstants 14, ]; + /// + /// Packed bottom-left availability bits for 16-by-64 blocks. + /// private static readonly byte[] HasBottomLeft16x64 = [0, 0]; + + /// + /// Packed bottom-left availability bits for 64-by-16 blocks. + /// private static readonly byte[] HasBottomLeft64x16 = [42, 42]; + /// + /// Maps each supported AV1 block-size value to its standard bottom-left availability table. + /// private static readonly byte[][] HasBottomLeftTables = [ // 4X4 @@ -391,11 +578,17 @@ internal class Av1BottomRightTopLeftConstants HasBottomLeft64x16 ]; + /// + /// Packed bottom-left availability bits for 8-by-8 blocks visited by a mixed vertical partition. + /// private static readonly byte[] HasBottomLeftVertical8x8 = [ 254, 255, 16, 17, 254, 255, 0, 1, 254, 255, 16, 17, 254, 255, 0, 0, 254, 255, 16, 17, 254, 255, 0, 1, 254, 255, 16, 17, 254, 255, 0, 0, ]; + /// + /// Packed bottom-left availability bits for 16-by-16 blocks visited by a mixed vertical partition. + /// private static readonly byte[] HasBottomLeftVertical16x16 = [ 254, 16, @@ -407,7 +600,14 @@ internal class Av1BottomRightTopLeftConstants 0, ]; + /// + /// Packed bottom-left availability bits for 32-by-32 blocks visited by a mixed vertical partition. + /// private static readonly byte[] HasBottomLeftVertical32x32 = [14, 14]; + + /// + /// Packed bottom-left availability bits for 64-by-64 blocks visited by a mixed vertical partition. + /// private static readonly byte[] HasBottomLeftVertical64x64 = [2]; // The _vert_* tables are like the ordinary tables above, but describe the @@ -419,6 +619,13 @@ internal class Av1BottomRightTopLeftConstants // // There are tables for each of the square sizes. Vertical rectangles (like // BLOCK_16X32) use their respective "non-vert" table + + /// + /// Maps supported block-size values to bottom-left availability tables for mixed vertical partition traversal. + /// + /// + /// Null entries identify block sizes that cannot use this traversal table; vertical rectangles reuse their standard tables. + /// private static readonly byte[]?[] HasBottomLeftVerticalTables = [ // 4X4 @@ -449,22 +656,46 @@ internal class Av1BottomRightTopLeftConstants null, HasBottomLeft128x128]; + /// + /// Determines whether the top-right reference samples are available for a block at the specified traversal index. + /// + /// The partition type that determines the block traversal order. + /// The size of each block represented by the selected availability table. + /// The block's index in partition traversal order. + /// when the block may use its top-right reference samples; otherwise, . public static bool HasTopRight(Av1PartitionType partitionType, Av1BlockSize blockSize, int blockIndex) { + // Eight block flags share each byte; the quotient selects the byte and the + // remainder selects the bit within that byte. int index1 = blockIndex / 8; int index2 = blockIndex % 8; - Span hasBottomLeftTable = GetHasTopRightTable(partitionType, blockSize); - return ((hasBottomLeftTable[index1] >> index2) & 1) > 0; + Span hasTopRightTable = GetHasTopRightTable(partitionType, blockSize); + return ((hasTopRightTable[index1] >> index2) & 1) > 0; } + /// + /// Determines whether the bottom-left reference samples are available for a block at the specified traversal index. + /// + /// The partition type that determines the block traversal order. + /// The size of each block represented by the selected availability table. + /// The block's index in partition traversal order. + /// when the block may use its bottom-left reference samples; otherwise, . public static bool HasBottomLeft(Av1PartitionType partitionType, Av1BlockSize blockSize, int blockIndex) { + // Eight block flags share each byte; the quotient selects the byte and the + // remainder selects the bit within that byte. int index1 = blockIndex / 8; int index2 = blockIndex % 8; Span hasBottomLeftTable = GetHasBottomLeftTable(partitionType, blockSize); return ((hasBottomLeftTable[index1] >> index2) & 1) > 0; } + /// + /// Selects the top-right availability table for a block size and partition traversal order. + /// + /// The partition type that determines the block traversal order. + /// The block size whose availability table is selected. + /// The packed top-right availability table. private static Span GetHasTopRightTable(Av1PartitionType partition, Av1BlockSize blockSize) { byte[]? ret; @@ -484,6 +715,12 @@ internal class Av1BottomRightTopLeftConstants return ret; } + /// + /// Selects the bottom-left availability table for a block size and partition traversal order. + /// + /// The partition type that determines the block traversal order. + /// The block size whose availability table is selected. + /// The packed bottom-left availability table. private static Span GetHasBottomLeftTable(Av1PartitionType partition, Av1BlockSize blockSize) { byte[]? ret;