BTIC4B - cr88192/bgbtech_misc GitHub Wiki

BTIC4B is meant as a reasonably high-speed codec design.

Table of Contents

General

The image will consist of an array of blocks, each of which will be nominally 8x8 pixels. The actual resolution of a block may be lower than this.

Pixels within a block will be stored as bits interpreting between endpoints.

  • Single axis blocks will interpolate along the luma axis, with a constant chroma.
    • Generally, the colors will be decoded to a pair of endpoints.
  • Multi-axis blocks will interpolate both luma and chroma.
    • Effectively, the YUV vector can be seen as a bounding box.
    • Each pixel then is a point within this bounding box.
Value Ranges:
  • LDR 8, Y values are between 0 and 255.
    • U and V values are in the range of +/- 255.
    • Du and Dv are also in the range of +/- 255.
  • LDR 10/12, Y values are between 0 and 1023 or 4095.
    • U and V values are in the range of +/- 1023 or 4095.
  • HDR 16, YUV values encode 16-bit color points representing half-float values.
    • HDR16 values may be either signed or unsigned.
      • Values are signed, with negatives stored in ones' complement form.
      • Values will be clamped to 16-bit range inside blocks.
The primary colorspace used with this codec will be GDbDr, where:
  • LDR8-Only Blocks:
    • Y=G
    • U=((B-G)>>1)+128
    • V=((R-G)>>1)+128
  • LDR and HDR Blocks:
    • Y=G
    • U=B-G
    • V=R-G
Endpoints will be stored in Center/Diff form:
  • Center=(Min+Max)/2
  • Diff=Max-Min
  • This is done for all components.
Interpolation:
  • 2 bit:
    • 0=Min
    • 1=2/3*Min+1/3Max
    • 2=1/3*Min+2/3Max
    • 3=Max
  • 3 bit:
    • 0=Min
    • 1=6/7*Min+1/7Max
    • 2=5/7*Min+2/7Max
    • 3=4/7*Min+3/7Max
    • 4=3/7*Min+4/7Max
    • 5=2/7*Min+5/7Max
    • 6=1/7*Min+6/7Max
    • 7=Max
  • 4 bit:
    • 0=Min
    • ...
    • 15=Max

TLV

  • 0x00..0x1F XX TT TT
    • 16kB TWOCC
  • 0x20..0x3F XX TT TT TT TT
    • 16kB FOURCC
  • 0x40..0x5F XX XX XX TT TT
    • 512MB TWOCC
  • 0x60..0x7F XX XX XX TT TT TT TT
    • 512MB FOURCC
The size for the marker will include the marker itself.

The length fields are encoded in big-endian order.

A VLI will be a variable length integer. The length of the integer is encoded in the high-order bits.

VLI:

  • 00-7F 0- 127
  • 80-BF XX 128- 16383
  • C0-DF XX XX 16384-2097151
  • ...
SVLI will be a special case, where the sign bit is folded into the LSB.

TWOCC:

  • 'I0'..'I9'
    • Image Data
    • 'I0': Bitstream Format
    • 'I1': Bytestream Format.
    • 'I2': Slice Bitstream
    • 'I3': Slice Bytestream
  • 'AX'
    • Alpha Extension
    • Encoded directly following the 'Ix' lump.
    • Will be encoded using the same format as the 'Ix' lump.
    • For sliced images, required to have the same slice size.
    • If omitted, the image will lack alpha information.
  • 'M0'..'M9', 'Ma'..'Mz'
    • Mipmaps.
  • 'HX'
    • Header (Optional).
The Slice formats will divide the images into a number of slices. Each slice will be prefixed by a VLI giving its size in bytes, and may be encoded or decoded independently.

An SVLI will precede the first slice:

  • Positive values will give the logical size of each slice in blocks.
  • Generally, this is to be a multiple of the size of a scanline.
  • Negative values and 0 are reserved.
Mipmaps:
  • Mipmaps will be a series of images.
  • Each image will be 1/2 the resolution of the preceding image.
    • Each mipmap will contain its associated 'Ix' and 'AX' lumps.
Header (Optional):
  • XSize:VLI
  • YSize:VLI
  • Layout:VLI
    • 3 bits: Image Base Type
      • 0=LDR8 RGB / RGBx
      • 1=LDR8 RGBA
      • 2=LDR10 RGB
      • 3=LDR12 RGB
      • 4=HDR16 RGB
      • 5=HDR16 RGBA
    • 2 bits: Image Block Size
      • 0=256 bit (No AX)
      • 1=384 bit (No AX)
      • 2=512 bit (Opt AX)
      • 3=768 bit (Opt AX)
      • Image data may only encode blocks which fit within the block size.
    • 2 bits: YUV Colorspace
      • 0=GDbDr
      • 1=RCT
      • 2=YCbCr
      • 3=Resv
Header may be located either in the image (preceding image-data or mipmap lumps), or appended onto BITMAPINFOHEADER within the relevant file-formats.

If XSize and YSize are 0, then the resolution is taken from the BITMAPINFOHEADER. If they are non-zero and a bitmap header is used, then they are required to match.

Defaults (No Header):

  • LDR8 RGBA with 512-bit blocks and GDbDr.

Bitstream Serialization

Will be similar to the bytestream serialization, except using an entropy-coded bitstream.

The bitstream will be encoded in LSB-first order, with values encoded with the LSB first in the bitstream.

Adaptive Rice with Length Limiting (AdRiceLL) will be used for commands and values. This consists of a unary coded Q value followed by Rk suffix bits. The Rk value is updated after every symbol depending on the value of Q.

  • Q=0..7: Encoded as a normal AdRice value.
    • Q=0: Rk=Rk-1;
    • Q=1: Rk=Rk;
    • Q=2|3: Rk=Rk+1;
    • Q=4..7: Rk=Rk+2;
  • Q>=8: Encoded as 5+(Q-8)*3 bits. Rk=Rk+3+(Q-8);
  • Rk is kept in the range of 0 to 15.
AdSRiceLL will be a signed variant used for signed values. These will have the sign folded into the LSB (0, -1, 1, -2, 2, -3, 3, ...).

Rk Values:

  • RkCy(AdSRice)=2: Center Y
  • RkCuv(AdSRice)=2: Center U and V
  • RkDy(AdSRice)=2: Diff Y
  • RkDuv(AdSRice)=2: Diff U and V
  • RkCmd(SmtfRice)=2: Command
  • RkMask(SmtfRice2)=2: Masks
  • RkCnt(AdRice)=2: Counts
  • RkMisc(AdSRice)=2: Misc Values.
SMTF (Old):
  • Values are encoded as a AdRiceLL encoded index(I).
  • 0: Returns the value in position 0.
  • 1-31: Swap I with I-1, returning the value which was previously in I.
  • 32-255: Rotate the table back 1 position, swapping the new 0 with the old I, returning the value previously at I.
SMTF/STF2 (New):
  • Values are encoded as a AdRiceLL encoded index(I).
  • Swap I with (I*7)/8, returning the value that was at I.

Masks

Masks will be encoded with a variant of SMTF:

  • 0: Use current mask.
  • 1..256: SMTF coded mask symbol.
  • LSB of the mask symbol's value indicates whether the selected mask should replace the currently active mask.
    • 0x00: The mask is only used for the current color vector.
    • 0x01: The mask replaces the currently active mask.
Masks will be optional, and will default to being disabled.
  • If the mask is disabled, all then delta components always will be coded.
    • This will depend on the type of color vector used by the block.
    • YUV: Encodes delta Cy, Cu, and Cv
    • YUVD: Encodes delta Cy, Cu, Cv, and Dy
    • YUVDyuv: Encodes delta Cy, Cu, Cv, Dy, Du, and Dv
  • Enabling feature -1 will enable masks.
    • If enabled, a mask symbol will be encoded prior to each color vector.
    • Only values normally encoded by this color vector will be encoded.
    • Other bits in the mask will be ignored if not encoded in the vector.
For the alpha channel, a subset of the vectors will be used:
  • Y: Encodes Cy
  • YD: Ecodes Cy and Dy.
  • Likewise, only the Cy and Dy quantizers will be encoded.
  • Mask state will be the same as in the normal case.
Mask Value Bits:
  • 0x02=Has Cy
  • 0x04=Has Cu
  • 0x08=Has Cv
  • 0x10=Has Dy
  • 0x20=Has Du
  • 0x40=Has Dv
  • 0x80=YUVD/YUVDyuv
Initially, the mask SMTF table will have values in descending order, with the initial starting value of 0xFF (all components enabled).

Bit 7 will indicate whether to use YUVD or YUVDyuv interpolation. If set, YUVD vectors will be decoded as YUVD, and single-axis interpolation will be Luma-only. Clearing this bit will cause YUVD endpoints to be decoded as YUVDyuv, and single-axis blocks will also interpolate chroma.

Color Prediction

Parameter -2 will be a predictor. This predictor may be applied at each block command to predict the color vector.

If this parameter is 0, then the prediction will be whatever is in the color vector.

Prediction will be based on blocks in the pattern:

 C B
 A p

Where p is the block being predicted, A is the preceding block, with C and B being the blocks in the preceding scanline. Near the start of the image, if C falls outside of the image buffer, then prediction will not be used, and it will behave as if the predictor were 0.

If one of the blocks is the result of a skip or skip+translate operation, its values will ignored be copied from the current contents of the color vector.

If the predictor is 1, then a Paeth predictor will be used to predict the block color:

p will be predicted as whichever value is closest to A+B-C.

Commands

Commands will be encoded using SMTF.

For each coded bitstream, all bitstream state will be reset to default values prior to beginning decoding.

Command Coded:

  • 0x00-0x1F: Block Command
    • Folowed by a delta color-vector and pixel-bits for that block type. Blocks are identified by their subtype.
  • 0x20-0x3F: Run of Blocks (Reusing prior color vector).
    • Command gives the block type, followed by a byte with giving the number of blocks (1-64).
    • High order 2 bits of run length are reserved.
    • Flat color blocks have no data, and merely repeat the previous color.
  • 0x40: End Of Image Data
  • 0x41: Skip Blocks
    • Followed by a count giving the number of skipped blocks.
  • 0x42: Move+Skip Blocks
    • Followed by a count giving the number of skipped blocks, and bytes for the X and Y offsets.
  • 0x43: Set Parameter
  • 0x44: Set parameter vector
  • 0x45: Set delta quantization factors
  • 0x46: Enable Feature, following misc-value gives feature.
  • 0x47: Disable Feature, misc-value gives feature.
  • 0x48: Run of flat color blocks.
    • Followed by byte count, and a YUV color vector for each block.
  • 0x49: Absolute Color (YUVD)
  • 0x4A: Absolute Color (YUVDyuv)
    • Encodes a YUVDyuv color vector, though the vector is interpreted as an absolute color.
Color Vector:
  • YUV, YUVD, or YUVDyuv
  • YUV will be used for flat-color blocks.
  • The single axis blocks will use YUVD (rather than YUVDyuv).
  • Chroma subsampled blocks will use YUVDyuv.
The values are stored as a quantized differences from the preceding values.

Alpha images will use the same basic format as the main image, however:

  • Color Vectors will be Y (Flat) and YD (Other).
  • Block types will be those for the alpha channel.
  • Alpha blocks will be directly tied to those of the main image.
    • In the main image, skip/skip+translate will naturally copy the alpha data.
    • Skip in the alpha image will simply leave this intact.
    • New blocks in the main image will default to being opaque.
    • Skipping a new block from the main image will leave it as an opaque block.
  • If the block may not have alpha, it is required to be skipped.

Bytestream (Alternate Coding)

Commands will be encoded as raw bytes.

Masks will be encoded as VLI values.

Blocks will be encoded as raw blobs of bytes.

If the LSB is 1, then the value is a bit-packed color vector. Each component delta will be 5 bits.

  • YUV will use 15 bits:
    • 11-15=Cv, 6-10=Cu, 1-5=Cy, 0=1
  • YUVD or YUVDyuv will use 23 or 32 bits:
    • 21=0, 16-20=Dy, 11-15=Cv, 6-10=Cu, 1-5=Cy, 0=1
    • 27-31=Dv, 22-26=Du, 21=1, 16-20=Dy, 11-15=Cv, 6-10=Cu, 1-5=Cy, 0=1
    • If bit 21 is set, an additional byte will be present, and the vector is extended to include Du and Dv.
    • If bit 21 is clear, Du and Dv are assumed to be zero.
    • YUVD and YUVDyuv are basically the same, differing slightly in interpretation.
  • These values will be stored using sign folding.

Canonical Meta-Block

Metablocks are an intermediate representation for blocks inside the codec. The specifics of the metablock format need not apply to its serialized form, but they are related.

The metablocks may be 256, 384, 512, or 768 bits in the current form.

8x8 blocks: Nominal=384 Bits, Ext=512 bits

 Bytes 0-15: Color Vector
    0: BlockType:BYTE
    1: AlphaType:BYTE
    2: Ca:BYTE (Center Alpha, 8-bit)
    3: Da:BYTE (Diff Alpha, 8-bit)
    4: Cy:S16 (Center Y, 16-bit)
    6: Cu:S16 (Center U, 16-bit)
    8: Cv:S16 (Center V, 16-bit)
   10: Dy:S16 (Diff Y, 16-bit)
   12: Du:S16 (Diff U, 16-bit)
   14: Dv:S16 (Diff V, 16-bit)
 Bytes 16-47: YUV Data (384 bit block)
 Bytes 48-63: YUV Data (512 bit block)
 Bytes 0-7: Color Vector (LDR8-Only Blocks, No Alpha)
    0: BlockType:BYTE
    1: Reserved:BYTE
    2: Cy:BYTE (Center Y, 8-bit)
    3: Cu:BYTE (Center U, 8-bit)
    4: Cv:BYTE (Center V, 8-bit)
    5: Dy:BYTE (Diff Y, 8-bit)
    6: Du:BYTE (Diff U, 8-bit)
    7: Dv:BYTE (Diff V, 8-bit)
 8x8x3+4x4x2 (4:2:0, 384 bit)
 Bytes 16-39: Y Data (8x8x3 bpp)
 Bytes 40-43: U Data (4x4x2 bpp)
 Bytes 44-47: V Data (4x4x2 bpp)
 8x8x3+4x8x3 (4:2:2, 512 bit)
 Bytes 16-39: Y Data (8x8x3 bpp)
 Bytes 40-51: U Data (4x8x3 bpp)
 Bytes 52-63: V Data (4x8x3 bpp)
 8x8x2+8x8x2 (4:4:4, 512 bit)
 Bytes 16-31: Y Data (8x8x2)
 Bytes 32-47: U Data (8x8x2)
 Bytes 48-63: V Data (8x8x2)
 8x8x4+4x4x4 (4:2:0, 512 bit)
 Bytes 16-47: Y Data (8x8x4 bpp)
 Bytes 48-55: U Data (4x4x4 bpp)
 Bytes 56-63: V Data (4x4x4 bpp)
 8x8x3+8x8x2 (4:4:4, 512 bit)
 Bytes  0- 7: Color Vector LDR8
 Bytes  8-31: Y Data (8x8x3)
 Bytes 32-47: U Data (8x8x2)
 Bytes 48-63: V Data (8x8x2)
 8x8x4+8x8x3 (4:4:4, 768 bit)
 Bytes 16-47: Y Data (8x8x4)
 Bytes 48-71: U Data (8x8x3)
 Bytes 72-95: V Data (8x8x3)

Block Type (Hex):

  • 00=Flat (0 bit, Bs=256b)
  • 01=2x2x1 (4 bit, Bs=256b)
  • 02=4x2x1 (8 bit, Bs=256b)
  • 03=2x4x1 (8 bit, Bs=256b)
  • 04=4x4x1 (16 bit, Bs=256b)
  • 05=8x4x1 (32 bit, Bs=256b)
  • 06=4x8x1 (32 bit, Bs=256b)
  • 07=8x8x1 (64 bit, Bs=256b)
  • 08=Grad4 (4 bit, Bs=256b)
  • 09=2x2x2 (8 bit, Bs=256b)
  • 0A=4x2x2 (16 bit, Bs=256b)
  • 0B=2x4x2 (16 bit, Bs=256b)
  • 0C=4x4x2 (32 bit, Bs=256b)
  • 0D=8x4x2 (64 bit, Bs=256b)
  • 0E=4x8x2 (64 bit, Bs=256b)
  • 0F=8x8x2 (128 bit, Bs=256b)
  • 10=8x8x3 (192 bit, Bs=384b)
  • 11=8x8x4 (256 bit, Bs=384b)
  • 12=Escape (Tag, Reserved)
  • 13=Y8x8x2+UV4x4x2 (192 bit, 4:2:0, LDR8, Bs=256b)
  • 14=Y2x2x2+UV2x2x1 (16 bit, 4:1:0, Bs=256b)
  • 15=Y4x4x2+UV2x2x2 (48 bit, 4:1:0, Bs=256b)
  • 16=Y4x4x2+UV4x4x2 (96 bit, 4:2:0, Bs=256b)
  • 17=Y8x8x2+UV2x2x2 (144 bit, 4:1:0, Bs=384b)
  • 18=Y8x8x2+UV4x4x2 (192 bit, 4:2:0, Bs=384b)
  • 19=Y8x8x3+UV8x8x2 (448 bit, 4:4:4, LDR8, Bs=512b)
  • 1A=Y8x8x2+UV4x8x2 (256 bit, 4:2:2, Bs=384b)
  • 1B=Y8x8x2+UV8x8x2 (384 bit, 4:4:4, Bs=512b, BsA=768b)
  • 1C=Y8x8x3+UV4x4x2 (256 bit, 4:2:0, Bs=384b)
  • 1D=Y8x8x4+UV4x4x4 (384 bit, 4:2:0, Bs=512b, BsA=768b)
  • 1E=Y8x8x3+UV4x8x3 (384 bit, 4:2:2, Bs=512b, BsA=768b)
  • 1F=Y8x8x4+UV8x8x3 (640 bit, 4:4:4, Bs=768b, BsA=N/A)
    • Bs: Minimum blocksize needed to encode this format.
    • BsA: Minimum blocksize needed to encode an alpha channel.
    • LDR8: Block uses LDR8 Header format.
Bit 6 in BlockType will indicate the use of YUVDyuv for single-axis blocks.

Pixel data will be laid out in raster order starting in the low-order bits.

If read from the LSB, the pixels will seem to be in left-to-right, nominally bottom-to-top order. Note that the image may be stored with the raster ordering starting in either the lower-left or upper-left corner.

In examples given here, for convinience, they will be shown starting in the upper-left, though the definitions will be equivalent (if flipped) in the bottom-to-top case.

Single axis blocks will generally interpolate only along Y, assuming U and V to be flat. Blocks with Y and UV will interpolate each axis independently.

YUV data will be packed end-to-end in blocks if less than the normal amount of bits is used. Ex: 4.10 will have the UV data start at byte 32 rather than 40.

Grad4: 4-bit tag encodes gradient direction

  • Bit 3: Hard/Soft, 0=Hard, 1=Soft
    • Hard will jump directly between the colors
    • Soft will transistion smoothly
  • Bit 2: Diagonal
  • Bit 0/1: Direction (0 to 1)
    • 0=L-R / UL-LR
    • 1=U-D / UR-LL
    • 2=R-L / LR-UL
    • 3=D-U / LL-UR

Alpha Blocks

If an alpha block is used, then the metablock format will be 512 or 768 bits, but only 384 or 512 bits may be used for the pixel data for blocks with alpha. The remaining 128 or 256 bits will be used for the alpha channel.

The AlphaType will indicate whether the Alpha from the main header is used (DA) or if a secondary Alpha Header is used (SA).

Bit 5 in the AlphaType field will be set for 768 blocks and clear for 512 bit blocks. Note that 512 bit block layouts may be used with 768 bit blocks.

The Ca/Da fields will map linearly to alpha values between 0 and 1.

If a separate Alpha Block header is used:

 0/1: Ca2:S16 (Center Alpha, Alternate)
 2/3: Da2:S16 (Diff Alpha, Alternate)
 4-7: Reserved
 8-15 | 8-31: Alpha Bits

AlphaType:

  • Tag=00: Flat (DA)
  • Tag=01: 2x2x1 (4 bits, Bs=512b, SA)
  • Tag=02: 4x4x1 (16 bits, Bs=512b, SA)
  • Tag=03: 8x8x1 (64 bits, Bs=512b, SA)
  • Tag=04: 2x2x2 (8 bits, Bs=512b, SA)
  • Tag=05: 4x4x2 (32 bits, Bs=512b, SA)
  • Tag=06: 4x4x3 (48 bits, Bs=512b, SA)
  • Tag=07: 4x8x2 (64 bits, Bs=512b, SA)
    • Even/Odd Pixel Average
  • Tag=08: Flat (SA)
  • Tag=09: Reserved
  • Tag=0A: 4x8x2 (64 bits, Bs=512b, SA)
    • Alpha is encoded at 1/2 horizontal resolution.
  • Tag=0B: 8x4x2 (64 bits, Bs=512b, SA)
    • Alpha is encoded at 1/2 vertical resolution.
  • Tag=0C: 8x8x2 (128 bits, Bs=512b, DA)
  • Tag=0D: 8x8x2 (128 bits, Bs=768b, SA)
  • Tag=0E: 8x8x3 (192 bits, Bs=768b, SA)
  • Tag=0F: 8x8x4 (256 bits, Bs=768b, DA)
  • Tag=16..31: Reserved
Even/Odd Average:
 A b C d E f G h
 i J k L m N o P
 Q r S t U v W x
 y Z ...

Alternating even and odd pixels are encoded. The remaining pixels are to be interpolated as averages of the adjacent pixels. The way in which averaging is performed is implementation defined.

⚠️ **GitHub.com Fallback** ⚠️