-
Notifications
You must be signed in to change notification settings - Fork 270
ASTC HDR 6x6 Intermediate File Format (Basis GPU Photo 6x6)
Note: This is a preliminary and in-progress draft specification, and is subject to change.
This document describes the low-level file structure of our custom supercompressed ASTC HDR 6x6 texture "intermediate" format files, first supported by Basis Universal v1.60 (Jan. 2025 release, project internal name "Basis GPU Photo 6x6"). With a strong encoder, the system's compressed bitrate typically ranges between .75 - 3.0 bits/pixel. The actual compressed bitrate depends heavily on the image's content and the amount of Rate-distortion optimization applied. The decoded bitrate is always 3.56 bits/pixel (i.e. standard ASTC HDR 6x6).
This format supports a robust subset of ASTC features: 75 unique ASTC block configurations, solid color (void extent) blocks, single or dual planes, 1-3 subsets, all unique 2- or 3-subset ASTC partition patterns, and weight grid upsampling. It has been developed and heavily tested with both LDR/SDR image and texture content (stored in linear light RGB, typically scaled to 80-100 nits), or positive linear light RGB HDR content.
This format is quite usable on a wide range of LDR/SDR and HDR photographic content with a strong (SSIM-based) encoder using various aggressive block artifact reduction techniques.
This is a relatively simple compressed intermediate format which can be rapidly transcoded into RGB-only standard ASTC HDR 6x6 blocks. No entropy coding is utilized. This intermediate format uses a small number of variable bit length command codes which can output one or more blocks, and which can reuse parts of previously encoded blocks. A deep understanding of the Khronos ASTC format specification and Integer Sequence Encoding is highly recommended to understand this format.
A decoder for this format outputs a 2D array of "physical" (or "transcoded") standard ASTC HDR 6x6 blocks. However, internally a decoder also needs to store the previously decoded four rows of "logical" ASTC HDR 6x6 blocks (or five rows total, including the current row being decoded). Coded logical blocks may use ISE endpoint/weight grid ISE ranges, or smaller weight grid sizes, that are not valid in standard ASTC until the ISE values are requantized and/or the weight grid values are upsampled. An encoder can reference and reuse various ISE encoded values from these previously decoded logical ASTC blocks to greatly increase compression.
This document is a high-level description of the file format. There are some concepts, such as how ISE endpoint/weight grid values are requantized, how weight grids are upsampled, how unique partition pattern identifiers are translated to 10-bit ASTC pattern seeds, or how ISE DPCM deltas are applied, which are not yet fully documented. For these details, please refer to the 6x6 HDR transcoder's open source code in file transcoder/basisu_transcoder.cpp
, function decode_6x6_hdr()
, which serves as the reference implementation. The encoder's source code is in file encoder/basisu_astc_hdr_6x6_enc.cpp
.
This document refers to the ISE tables in the UASTC HDR 4x4 specification. See "Standard ASTC ISE Range Table Reference". Also, this document references the UASTC LDR 4x4 specification, see "UASTC BISE Encoding Example". The way weight grid values are ISE coded in this specification matches the way UASTC LDR 4x4 ISE codes endpoint values.
Variable length bit codes are packed into the output stream starting at the LSB (Least Significant Bit) of each output byte, matching how codes are packed in the ETC1S supercompressed texture format, or zlib (RFC 1951). No entropy coding (such as Huffman coding) is utilized in this format, however Truncated Binary Encoding (also called phase-in codes, or economy codes) are utilized.
The header, which is always at the very beginning of the compressed data stream, contains 3 fields: an ID, width, and height. Each field is 16 bits.
The first code in the header is a 16-bit compression type ID field. It must always be 0xABCD. Therefore, the first byte in the stream will always be 0xCD, and the subsequent byte in the stream will be 0xAB.
The next two codes are also 16 bits each, or totaling 32 bits. These fields are the width and height of the texture, in texels. These values do not need to be a multiple of 6 texels, and can range from [1,32768] texels. These fields must match the expected image's dimensions. Images or textures which are not a multiple of 6 texels in either dimension are typically padded by replicating rows or columns.
The number of unpacked ASTC HDR 6x6 blocks in the file will be floor((width + 5) / 6) * floor((height + 5) / 6).
Immediately following the header are the block commands describing the ASTC HDR 6x6 blocks. There can be, at most, one block command per ASTC HDR 6x6 block, but in practice there will be less due to runs of repeated blocks. The blocks are decoded in simple 2D raster order, starting from the top-left ASTC block and ending at the bottom-right ASTC block. Each row of blocks is decoded in left-to-right order.
There must be at least one command, and the total number of blocks output by all commands must not exceed and must match the number of unpacked ASTC HDR 6x6 blocks, as computed from the header's width and height using the equation above.
There are 4 command types:
- RUN: Code length 3 bits: code value: 0b000
- SOLID: Code length: 3 bits, code value: 0b100
- REUSE: Code length: 2 bits, code value: 0b10
- BLOCK: Code length: 1 bits, code value: 0b1
A run command cannot appear until at least one block has been decoded and written to the output.
The total number of blocks in a run command is stored using a simple 5-bit VLC (Variable Length Code) scheme. The run's length is stored using one or more 6-bit packets. Bits 0-4 of each packet contain additional run length bits, starting from the LSB of the run length. Bit 5 of each packet indicates whether another 6-bit packet follows or not. The total number of decoded run length bits cannot exceed 30-bits (or 6 packets). The actual run length stored will be run_length-1.
The previously decoded block in the output is repeated run length times. This referenced/repeated block may lie on the current row, or at the very end (or the rightmost block) in the previous row of blocks.
This command describes a solid color (or ASTC Void Extent) block. Three 15-bit codes follow, containing the positive half float R, G, and B values to use for all texels in the block. The sign bit, which must always be 0, is not stored. This representation does not permit negative values, and the half float value cannot be infinity or NaN, but may be denormal.
The block's alpha will always be the half float representation of 1.0.
This command reuses the block configuration of a previously emitted block. A 5-bit code is sent which indicates which block's block configuration to reuse. (See Appendix B - Reuse XY "Delta" Codes.) The referenced block cannot be a solid (void extent) block. The referenced block cannot be at an invalid decoded 2D block coordinate (i.e. it must reference a block already decoded, and it cannot refer to a block before the leftmost column or the uppermost row).
The referenced block's block configuration index [0,74] is reused for this block, as well as the endpoint values, and the partition index (if 2-3 subsets). The block's ISE encoded weight values will immediately follow the 5-bit reuse delta code. The block's logical ISE encoded endpoint values may need to be requantized, and the ISE encoded weight grid values may need to be requantized and upsampled, in order to output a valid (standard) physical ASTC block.
BLOCK commands code a single ASTC block. Immediately following the BLOCK command is the block configuration [0,74], which is stored using Truncated Binary Encoding.
Immediately following the block configuration is the Endpoint Mode [0,4], which is also stored using Truncated Binary Encoding. The supported Endpoint Modes are:
- Use Left: Reuse endpoints from the left block (cannot be used on the leftmost column of blocks), followed by ISE encoded weight grid samples. Only 1-subset blocks can use this Endpoint Mode.
- Use Upper: Reuse endpoints from the upper block (cannot be used the first row of blocks), followed by ISE encoded weight grid samples. Only 1-subset blocks can use this Endpoint Mode.
- Use Left Delta: Reuse endpoints from the left block with 5-bit DPCM deltas applied (cannot be used on the leftmost column of blocks), followed by ISE encoded weight grid samples. Only 1-subset blocks can use this Endpoint Mode.
- Use Upper Delta: Reuse endpoints from the upper block with 5-bit DPCM deltas applied (cannot be used the first row of blocks), followed by ISE encoded weight grid samples. Only 1-subset blocks can use this Endpoint Mode.
- Raw: For 2 or 3 subset configurations, the unique partition pattern index is decoded using Truncated Binary Encoding. This unique pattern index is then converted to a standard 10-bit ASTC partition pattern seed value using a table lookup. The full endpoints are decoded using ISE coding, followed by the ISE encoded weight grid samples.
Importantly, the ISE encoded values (for both endpoints and weights) stored in the compressed stream for logical blocks don't always match the ISE encoded endpoints the decompressor must output for physical blocks. The ASTC specification places various limitations on which ISE encoded endpoint/weight grid ranges are valid to use, which are sometimes suboptimal for the purposes of rate-distortion optimization. In these cases, the ISE values must be requantized to the nearest representable quantized ISE values. Additionally, some block configurations store a smaller weight grid than is codable using standard ASTC. In these cases, the weight grid is upsampled.
-
For endpoint modes [0,1] (use left or upper): The left or upper logical (or coded) endpoint values are reused in the current block. The ISE encoded weight grid samples are decoded, potentially requantized, and potentially upsampled.
-
For endpoint modes [2,3] (use left or upper delta): 5-bit codes, representing DPCM deltas ranging between [-16,15], will be applied to the referenced block's logical (or coded) endpoint values. These delta codes are immediately followed by the ISE encoded weight grid samples. The final ISE encoded endpoints may need to be requantized, and the weight grid may need to be requantized and/or upsampled.
-
For endpoint mode 4 (raw), both the endpoints and weight grid values are stored using ISE coding. These values may need to be requantized and potentially upsampled.
There are 75 supported ASTC HDR 6x6 configurations, each assigned an index between [0,74]:
struct block_mode_desc
{
bool m_dp; // Dual plane flag
uint32_t m_cem; // ASTC Color Endpoint Mode
uint32_t m_num_partitions; // Number of partitions, [1,3]
uint32_t m_grid_x; // Grid width: [2,6]
uint32_t m_grid_y; // Grid height: [2,6]
// The logical or coding ISE ranges (which may not be valid ASTC ranges for this configuration):
// See the UASTC LDR 4x4 specification for the array of ISE ranges.
uint32_t m_endpoint_ise_range;
uint32_t m_weight_ise_range;
// The physical/output ASTC decompression ISE ranges (i.e. what the decompressor must output).
uint32_t m_transcode_endpoint_ise_range;
uint32_t m_transcode_weight_ise_range;
uint32_t m_flags; // Flags (see BASIST_HDR_6x6_LEVEL0, etc.)
int m_dp_channel; // Dual plane mode channel
};
// Flags (only used by the encoder, here for reference):
const uint32_t BASIST_HDR_6X6_LEVEL0 = 1;
const uint32_t BASIST_HDR_6X6_LEVEL1 = 2;
const uint32_t BASIST_HDR_6X6_LEVEL2 = 4;
const block_mode_desc g_block_mode_descs[TOTAL_BLOCK_MODE_DECS] =
{
// ------ CEM 11
{ false, 11, 1, 6, 6, BISE_256_LEVELS, BISE_3_LEVELS, BISE_256_LEVELS, BISE_3_LEVELS, BASIST_HDR_6X6_LEVEL0 | BASIST_HDR_6X6_LEVEL1 | BASIST_HDR_6X6_LEVEL2, 0 },
{ false, 11, 1, 6, 6, BISE_80_LEVELS, BISE_4_LEVELS, BISE_80_LEVELS, BISE_4_LEVELS, BASIST_HDR_6X6_LEVEL0 | BASIST_HDR_6X6_LEVEL1 | BASIST_HDR_6X6_LEVEL2, 0 },
{ false, 11, 1, 6, 5, BISE_96_LEVELS, BISE_5_LEVELS, BISE_96_LEVELS, BISE_5_LEVELS, BASIST_HDR_6X6_LEVEL0 | BASIST_HDR_6X6_LEVEL1 | BASIST_HDR_6X6_LEVEL2, 0 },
{ false, 11, 1, 5, 6, BISE_96_LEVELS, BISE_5_LEVELS, BISE_96_LEVELS, BISE_5_LEVELS, BASIST_HDR_6X6_LEVEL0 | BASIST_HDR_6X6_LEVEL1 | BASIST_HDR_6X6_LEVEL2, 0 },
{ false, 11, 1, 6, 4, BISE_80_LEVELS, BISE_8_LEVELS, BISE_80_LEVELS, BISE_8_LEVELS, BASIST_HDR_6X6_LEVEL0 | BASIST_HDR_6X6_LEVEL1 | BASIST_HDR_6X6_LEVEL2, 0 },
{ false, 11, 1, 4, 6, BISE_80_LEVELS, BISE_8_LEVELS, BISE_80_LEVELS, BISE_8_LEVELS, BASIST_HDR_6X6_LEVEL0 | BASIST_HDR_6X6_LEVEL1 | BASIST_HDR_6X6_LEVEL2, 0 },
{ false, 11, 1, 6, 3, BISE_80_LEVELS, BISE_16_LEVELS, BISE_80_LEVELS, BISE_16_LEVELS, BASIST_HDR_6X6_LEVEL0 | BASIST_HDR_6X6_LEVEL1 | BASIST_HDR_6X6_LEVEL2, 0 },
{ false, 11, 1, 3, 6, BISE_80_LEVELS, BISE_16_LEVELS, BISE_80_LEVELS, BISE_16_LEVELS, BASIST_HDR_6X6_LEVEL0 | BASIST_HDR_6X6_LEVEL1 | BASIST_HDR_6X6_LEVEL2, 0 },
{ false, 11, 1, 5, 5, BISE_64_LEVELS, BISE_8_LEVELS, BISE_64_LEVELS, BISE_8_LEVELS, BASIST_HDR_6X6_LEVEL0 | BASIST_HDR_6X6_LEVEL1 | BASIST_HDR_6X6_LEVEL2, 0 },
{ false, 11, 1, 4, 4, BISE_192_LEVELS, BISE_16_LEVELS, BISE_192_LEVELS, BISE_16_LEVELS, BASIST_HDR_6X6_LEVEL0 | BASIST_HDR_6X6_LEVEL1 | BASIST_HDR_6X6_LEVEL2, 0 },
{ false, 11, 1, 3, 3, BISE_256_LEVELS, BISE_16_LEVELS, BISE_256_LEVELS, BISE_16_LEVELS, BASIST_HDR_6X6_LEVEL0 | BASIST_HDR_6X6_LEVEL1 | BASIST_HDR_6X6_LEVEL2, 0 },
// ------ CEM 7
{ false, 7, 1, 6, 6, BISE_96_LEVELS, BISE_5_LEVELS, BISE_96_LEVELS, BISE_5_LEVELS, BASIST_HDR_6X6_LEVEL0 | BASIST_HDR_6X6_LEVEL1 | BASIST_HDR_6X6_LEVEL2, 0 },
{ false, 7, 1, 6, 6, BISE_256_LEVELS, BISE_3_LEVELS, BISE_256_LEVELS, BISE_3_LEVELS, BASIST_HDR_6X6_LEVEL2, 0 },
{ false, 7, 1, 6, 6, BISE_256_LEVELS, BISE_4_LEVELS, BISE_256_LEVELS, BISE_4_LEVELS, BASIST_HDR_6X6_LEVEL2, 0 },
{ false, 7, 1, 5, 6, BISE_256_LEVELS, BISE_6_LEVELS, BISE_256_LEVELS, BISE_6_LEVELS, BASIST_HDR_6X6_LEVEL2, 0 },
{ false, 7, 1, 6, 5, BISE_256_LEVELS, BISE_6_LEVELS, BISE_256_LEVELS, BISE_6_LEVELS, BASIST_HDR_6X6_LEVEL2, 0 },
{ false, 7, 1, 3, 6, BISE_256_LEVELS, BISE_20_LEVELS, BISE_256_LEVELS, BISE_20_LEVELS, BASIST_HDR_6X6_LEVEL1 | BASIST_HDR_6X6_LEVEL2, 0 },
{ false, 7, 1, 6, 3, BISE_256_LEVELS, BISE_20_LEVELS, BISE_256_LEVELS, BISE_20_LEVELS, BASIST_HDR_6X6_LEVEL1 | BASIST_HDR_6X6_LEVEL2, 0 },
// ------ CEM 11, 2 subset
{ false, 11, 2, 6, 6, BISE_32_LEVELS, BISE_2_LEVELS, BISE_32_LEVELS, BISE_2_LEVELS, BASIST_HDR_6X6_LEVEL1 | BASIST_HDR_6X6_LEVEL2, 0 },
// 6x3/3x6
{ false, 11, 2, 6, 3, BISE_48_LEVELS, BISE_3_LEVELS, BISE_48_LEVELS, BISE_3_LEVELS, BASIST_HDR_6X6_LEVEL1 | BASIST_HDR_6X6_LEVEL2, 0 },
{ false, 11, 2, 3, 6, BISE_48_LEVELS, BISE_3_LEVELS, BISE_48_LEVELS, BISE_3_LEVELS, BASIST_HDR_6X6_LEVEL1 | BASIST_HDR_6X6_LEVEL2, 0 },
// 3x6/6x3
{ false, 11, 2, 3, 6, BISE_32_LEVELS, BISE_4_LEVELS, BISE_32_LEVELS, BISE_4_LEVELS, BASIST_HDR_6X6_LEVEL1 | BASIST_HDR_6X6_LEVEL2, 0 },
{ false, 11, 2, 6, 3, BISE_32_LEVELS, BISE_4_LEVELS, BISE_32_LEVELS, BISE_4_LEVELS, BASIST_HDR_6X6_LEVEL1 | BASIST_HDR_6X6_LEVEL2, 0 },
// 3x6/6x3
{ false, 11, 2, 4, 6, BISE_32_LEVELS, BISE_3_LEVELS, BISE_32_LEVELS, BISE_3_LEVELS, 0, 0 },
{ false, 11, 2, 6, 4, BISE_32_LEVELS, BISE_3_LEVELS, BISE_32_LEVELS, BISE_3_LEVELS, 0, 0 },
// ------ CEM 7, 2 subset
// 6x5/5x6
{ false, 7, 2, 5, 6, BISE_80_LEVELS, BISE_3_LEVELS, BISE_80_LEVELS, BISE_3_LEVELS, BASIST_HDR_6X6_LEVEL2, 0 },
{ false, 7, 2, 6, 5, BISE_80_LEVELS, BISE_3_LEVELS, BISE_80_LEVELS, BISE_3_LEVELS, BASIST_HDR_6X6_LEVEL2, 0 },
// 6x4/4x6
{ false, 7, 2, 4, 6, BISE_80_LEVELS, BISE_4_LEVELS, BISE_80_LEVELS, BISE_4_LEVELS, BASIST_HDR_6X6_LEVEL2, 0 },
{ false, 7, 2, 6, 4, BISE_80_LEVELS, BISE_4_LEVELS, BISE_80_LEVELS, BISE_4_LEVELS, BASIST_HDR_6X6_LEVEL2, 0 },
// 6x6
{ false, 7, 2, 6, 6, BISE_32_LEVELS, BISE_3_LEVELS, BISE_32_LEVELS, BISE_3_LEVELS, BASIST_HDR_6X6_LEVEL2, 0 },
// 6x6
{ false, 7, 2, 6, 6, BISE_192_LEVELS, BISE_2_LEVELS, BISE_192_LEVELS, BISE_2_LEVELS, 0, 0 },
// 5x5
{ false, 7, 2, 5, 5, BISE_64_LEVELS, BISE_4_LEVELS, BISE_64_LEVELS, BISE_4_LEVELS, 0, 0 },
// 6x3/3x6
{ false, 7, 2, 3, 6, BISE_48_LEVELS, BISE_8_LEVELS, BISE_48_LEVELS, BISE_8_LEVELS, 0, 0 },
{ false, 7, 2, 6, 3, BISE_48_LEVELS, BISE_8_LEVELS, BISE_48_LEVELS, BISE_8_LEVELS, 0, 0 },
// 6x3/3x6
{ false, 7, 2, 3, 6, BISE_80_LEVELS, BISE_6_LEVELS, BISE_80_LEVELS, BISE_6_LEVELS, 0, 0 },
{ false, 7, 2, 6, 3, BISE_80_LEVELS, BISE_6_LEVELS, BISE_80_LEVELS, BISE_6_LEVELS, 0, 0 },
// ------ Dual Plane
// 3x6
{ true, 11, 1, 3, 6, BISE_64_LEVELS, BISE_4_LEVELS, BISE_64_LEVELS, BISE_4_LEVELS, BASIST_HDR_6X6_LEVEL0 | BASIST_HDR_6X6_LEVEL1 | BASIST_HDR_6X6_LEVEL2, 0 },
{ true, 11, 1, 3, 6, BISE_64_LEVELS, BISE_4_LEVELS, BISE_64_LEVELS, BISE_4_LEVELS, BASIST_HDR_6X6_LEVEL0 | BASIST_HDR_6X6_LEVEL1 | BASIST_HDR_6X6_LEVEL2, 1 },
{ true, 11, 1, 3, 6, BISE_64_LEVELS, BISE_4_LEVELS, BISE_64_LEVELS, BISE_4_LEVELS, BASIST_HDR_6X6_LEVEL0 | BASIST_HDR_6X6_LEVEL1 | BASIST_HDR_6X6_LEVEL2, 2 },
// 6x3
{ true, 11, 1, 6, 3, BISE_64_LEVELS, BISE_4_LEVELS, BISE_64_LEVELS, BISE_4_LEVELS, BASIST_HDR_6X6_LEVEL0 | BASIST_HDR_6X6_LEVEL1 | BASIST_HDR_6X6_LEVEL2, 0 },
{ true, 11, 1, 6, 3, BISE_64_LEVELS, BISE_4_LEVELS, BISE_64_LEVELS, BISE_4_LEVELS, BASIST_HDR_6X6_LEVEL0 | BASIST_HDR_6X6_LEVEL1 | BASIST_HDR_6X6_LEVEL2, 1 },
{ true, 11, 1, 6, 3, BISE_64_LEVELS, BISE_4_LEVELS, BISE_64_LEVELS, BISE_4_LEVELS, BASIST_HDR_6X6_LEVEL0 | BASIST_HDR_6X6_LEVEL1 | BASIST_HDR_6X6_LEVEL2, 2 },
// 3x3
{ true, 11, 1, 3, 3, BISE_64_LEVELS, BISE_16_LEVELS, BISE_64_LEVELS, BISE_16_LEVELS, BASIST_HDR_6X6_LEVEL1 | BASIST_HDR_6X6_LEVEL2, 0 },
{ true, 11, 1, 3, 3, BISE_64_LEVELS, BISE_16_LEVELS, BISE_64_LEVELS, BISE_16_LEVELS, BASIST_HDR_6X6_LEVEL1 | BASIST_HDR_6X6_LEVEL2, 1 },
{ true, 11, 1, 3, 3, BISE_64_LEVELS, BISE_16_LEVELS, BISE_64_LEVELS, BISE_16_LEVELS, BASIST_HDR_6X6_LEVEL1 | BASIST_HDR_6X6_LEVEL2, 2 },
// 4x4
{ true, 11, 1, 4, 4, BISE_48_LEVELS, BISE_5_LEVELS, BISE_48_LEVELS, BISE_5_LEVELS, BASIST_HDR_6X6_LEVEL2, 0 },
{ true, 11, 1, 4, 4, BISE_48_LEVELS, BISE_5_LEVELS, BISE_48_LEVELS, BISE_5_LEVELS, BASIST_HDR_6X6_LEVEL2, 1 },
{ true, 11, 1, 4, 4, BISE_48_LEVELS, BISE_5_LEVELS, BISE_48_LEVELS, BISE_5_LEVELS, BASIST_HDR_6X6_LEVEL2, 2 },
// 5x5
{ true, 11, 1, 5, 5, BISE_256_LEVELS, BISE_2_LEVELS, BISE_256_LEVELS, BISE_2_LEVELS, BASIST_HDR_6X6_LEVEL2, 0 },
{ true, 11, 1, 5, 5, BISE_256_LEVELS, BISE_2_LEVELS, BISE_256_LEVELS, BISE_2_LEVELS, BASIST_HDR_6X6_LEVEL2, 1 },
{ true, 11, 1, 5, 5, BISE_256_LEVELS, BISE_2_LEVELS, BISE_256_LEVELS, BISE_2_LEVELS, BASIST_HDR_6X6_LEVEL2, 2 },
// ------ 2x2 modes for RDO
// note 2x2 modes will be upsampled to 4x4 during transcoding (the min # of weight bits is 7 in ASTC)
{ true, 11, 1, 2, 2, BISE_64_LEVELS, BISE_4_LEVELS, BISE_256_LEVELS, BISE_8_LEVELS, BASIST_HDR_6X6_LEVEL0 | BASIST_HDR_6X6_LEVEL1 | BASIST_HDR_6X6_LEVEL2, 0 },
{ true, 11, 1, 2, 2, BISE_64_LEVELS, BISE_4_LEVELS, BISE_256_LEVELS, BISE_8_LEVELS, BASIST_HDR_6X6_LEVEL0 | BASIST_HDR_6X6_LEVEL1 | BASIST_HDR_6X6_LEVEL2, 1 },
{ true, 11, 1, 2, 2, BISE_64_LEVELS, BISE_4_LEVELS, BISE_256_LEVELS, BISE_8_LEVELS, BASIST_HDR_6X6_LEVEL0 | BASIST_HDR_6X6_LEVEL1 | BASIST_HDR_6X6_LEVEL2, 2 },
{ false, 11, 1, 2, 2, BISE_128_LEVELS, BISE_2_LEVELS, BISE_256_LEVELS, BISE_3_LEVELS, BASIST_HDR_6X6_LEVEL0 | BASIST_HDR_6X6_LEVEL1 | BASIST_HDR_6X6_LEVEL2, 0 },
// ------ 3 subsets
// 6x6
{ false, 7, 3, 6, 6, BISE_32_LEVELS, BISE_2_LEVELS, BISE_32_LEVELS, BISE_2_LEVELS, BASIST_HDR_6X6_LEVEL2, 0 },
// 5x5
{ false, 7, 3, 5, 5, BISE_64_LEVELS, BISE_2_LEVELS, BISE_64_LEVELS, BISE_2_LEVELS, BASIST_HDR_6X6_LEVEL2, 0 },
// 4x4
{ false, 7, 3, 4, 4, BISE_64_LEVELS, BISE_3_LEVELS, BISE_64_LEVELS, BISE_3_LEVELS, BASIST_HDR_6X6_LEVEL2, 0 },
{ false, 7, 3, 4, 4, BISE_40_LEVELS, BISE_4_LEVELS, BISE_40_LEVELS, BISE_4_LEVELS, BASIST_HDR_6X6_LEVEL2, 0 },
{ false, 7, 3, 4, 4, BISE_32_LEVELS, BISE_5_LEVELS, BISE_32_LEVELS, BISE_5_LEVELS, 0, 0 },
// 3x3
{ false, 7, 3, 3, 3, BISE_64_LEVELS, BISE_8_LEVELS, BISE_64_LEVELS, BISE_8_LEVELS, 0, 0 },
// 6x4
{ false, 7, 3, 6, 4, BISE_64_LEVELS, BISE_2_LEVELS, BISE_64_LEVELS, BISE_2_LEVELS, BASIST_HDR_6X6_LEVEL2, 0 },
{ false, 7, 3, 4, 6, BISE_64_LEVELS, BISE_2_LEVELS, BISE_64_LEVELS, BISE_2_LEVELS, BASIST_HDR_6X6_LEVEL2, 0 },
// 6x4
{ false, 7, 3, 6, 4, BISE_32_LEVELS, BISE_3_LEVELS, BISE_32_LEVELS, BISE_3_LEVELS, 0, 0 },
{ false, 7, 3, 4, 6, BISE_32_LEVELS, BISE_3_LEVELS, BISE_32_LEVELS, BISE_3_LEVELS, 0, 0 },
// 6x5
{ false, 7, 3, 6, 5, BISE_48_LEVELS, BISE_2_LEVELS, BISE_48_LEVELS, BISE_2_LEVELS, BASIST_HDR_6X6_LEVEL2, 0 },
{ false, 7, 3, 5, 6, BISE_48_LEVELS, BISE_2_LEVELS, BISE_48_LEVELS, BISE_2_LEVELS, BASIST_HDR_6X6_LEVEL2, 0 },
// 6x3
{ false, 7, 3, 6, 3, BISE_48_LEVELS, BISE_3_LEVELS, BISE_48_LEVELS, BISE_3_LEVELS, 0, 0 },
{ false, 7, 3, 3, 6, BISE_48_LEVELS, BISE_3_LEVELS, BISE_48_LEVELS, BISE_3_LEVELS, 0, 0 },
// 6x3
{ false, 7, 3, 6, 3, BISE_32_LEVELS, BISE_4_LEVELS, BISE_32_LEVELS, BISE_4_LEVELS, BASIST_HDR_6X6_LEVEL2, 0 },
{ false, 7, 3, 3, 6, BISE_32_LEVELS, BISE_4_LEVELS, BISE_32_LEVELS, BISE_4_LEVELS, BASIST_HDR_6X6_LEVEL2, 0 },
// 6x3
{ false, 7, 3, 6, 3, BISE_24_LEVELS, BISE_5_LEVELS, BISE_24_LEVELS, BISE_5_LEVELS, 0, 0 },
{ false, 7, 3, 3, 6, BISE_24_LEVELS, BISE_5_LEVELS, BISE_24_LEVELS, BISE_5_LEVELS, 0, 0 },
// 5x4
{ false, 7, 3, 5, 4, BISE_40_LEVELS, BISE_3_LEVELS, BISE_40_LEVELS, BISE_3_LEVELS, 0, 0 },
{ false, 7, 3, 4, 5, BISE_40_LEVELS, BISE_3_LEVELS, BISE_40_LEVELS, BISE_3_LEVELS, 0, 0 },
};
const uint32_t REUSE_XY_DELTA_BITS = 5;
const uint32_t NUM_REUSE_XY_DELTAS = 1 << REUSE_XY_DELTA_BITS;
struct reuse_xy_delta
{
int8_t m_x, m_y;
};
const reuse_xy_delta g_reuse_xy_deltas[NUM_REUSE_XY_DELTAS] =
{
{ -1, 0 }, { -2, 0 }, { -3, 0 }, { -4, 0 },
{ 3, -1 }, { 2, -1 }, { 1, -1 }, { 0, -1 }, { -1, -1 }, { -2, -1 }, { -3, -1 }, { -4, -1 },
{ 3, -2 }, { 2, -2 }, { 1, -2 }, { 0, -2 }, { -1, -2 }, { -2, -2 }, { -3, -2 }, { -4, -2 },
{ 3, -3 }, { 2, -3 }, { 1, -3 }, { 0, -3 }, { -1, -3 }, { -2, -3 }, { -3, -3 }, { -4, -3 },
{ 3, -4 }, { 2, -4 }, { 1, -4 }, { 0, -4 }
};