Skip to content
Brendan G Bohannon edited this page Feb 23, 2016 · 27 revisions

BTIC2E is similar in premise to the original JPEG format except:

  • A byte-based block serialization is used rather than Huffman coded VLC;
  • A blocky version of the Haar Wavelet is used in place of the DCT;
  • A cheaper colorspace is used.
  • Image will be encoded in terms of rows of macroblocks.
    • Each row will start with a VLI encoding the number of bytes used by this row.
    • Each row will be encoded independently with predictors reset to default values.
    • An encoder may produce row VLIs with overlong values.
  • Different header structure.
  • ...

Table of Contents

VLI

VLI (prefix, suffix bytes, nominal range):

  • 0x00..0x7F, x0, 0x00000000..0x0000007F
  • 0x80..0xBF, x1, 0x00000080..0x00003FFF
  • 0xC0..0xDF, x2, 0x00004000..0x001FFFFF
  • 0xE0..0xEF, x3, 0x00200000..0x0FFFFFFF
  • 0xF0 , x4, 0x10000000..0xFFFFFFFF
VLI, 64 Bit:
  • 0xF0..0xF7, x4, 0x0000000010000000..0x00000007FFFFFFFF
  • 0xF8..0xFB, x5, 0x0000000800000000..0x000003FFFFFFFFFF
  • 0xFC..0xFD, x6, 0x0000040000000000..0x0001FFFFFFFFFFFF
  • 0xFE , x7, 0x0002000000000000..0x00FFFFFFFFFFFFFF
  • 0xFF , x8, 0x0100000000000000..0xFFFFFFFFFFFFFFFF
SVLI: Signed VLI, which consists of a VLI with the sign folded into the LSB.

Headers

Headers:

  • Prior to the start of the image data, there will be a series of headers
  • The headers will consist of a tag, which will be a signed VLI
    • Negative tags will consist of a raw tag followed by data.
      • These are implicitly must-understand.
    • Positive tags will be followed by a signed length and data.
      • Positive lengths mean data which may be safely ignored.
      • Negative lengths mean the data is must-understand (The absolute value is used as the length).
  • A tag value of 0 will be a special case, encoding the end of the header list and the start of the image data.
Header -1: Image Size
  • Followed by UVLIs encoding the X and Y resolution.
Header -2: Frame Type
  • VLI encodes type:
    • Bits 0-2: Macroblock Layout
    • Bits 3/4:
      • 0=LDR 8
      • 1=LDR 12
      • 2=HDR 16 (Half-Float)
    • Bits 5/6:
      • 0=Default Colorspace (Below)
      • 1=YCbCr
      • 2=RCT
Header -4: Y Quantization Table
  • Consist of a series of SVLI values, representing coefficients 0..63 in zigzag order.
  • Values greater than 0 will encode the quantization factor for a coefficient.
  • Values less than 0 will repeat the prior value N times.
Header -5: UV Quantization Table
  • Same format as the Y quantization table.

Macroblock

Each macroblock will be 8x8, 16x8, or 16x16. Several Layouts will be defined:

  • 0=4:2:0 (Default)
    • 4x Y block, U block, V block
    • Chroma will be reduced by 1/2 horizontally and vertically.
    • Macroblock is 16x16
  • 1=Mono
    • Y blocks only
    • Image will be monochromatic.
    • Macroblock is 8x8
  • 2=4:4:4
    • Y block, U block, V block
    • Each pixel has its own chroma values.
    • Macroblock is 8x8
  • 3=4:2:2
    • 2x Y block, U block, V block
    • Chroma will be reduced by 1/2 horizontally.
    • Macroblock is 16x8
A header will encode the layout.

The image data will consist of individually coded rows of macroblocks each with their own length prefix.

  • The VLI for a row may be longer than that needed to encode a given number of bytes for the row.
  • A row may contain more bytes than that needed for the coded blocks within the row.
    • Any bytes following the end of the last macroblock in a row are to be ignored.

Colorspace

RGB to YUV:

  • Y=(3R+4G+B)/8
  • U=(B-Y)/2+Bias
  • V=(R-Y)/2+Bias
YUV to RGB:
  • B=Y+((U-Bias)*2)
  • R=Y+((V-Bias)*2)
  • G=(8Y-3R-B)/4
Bias will be 128 for LDR 8, 2048 for LDR 12, and 0x4000 for HDR 16.

With HDR 16, values will map between -32768 and 32767. Negative Half-Float values will be stored sign extended and with the low 15 bits inverted.

Blocky Haar

Nominally, a pair of values (A, B) is transformed into a new pair (C, D) as C=A+B, D=(C/2)-B.

This will be applied over 8 pixels (A0 .. A7):

  • B0=A0+A1, B1=A2+A3, B2=A4+A5, B3=A6+A7, B4=(B0/2)-A1, B5=(B1/2)-A3, B6=(B2/2)-A5, B7=(B3/2)-A7
  • C0=B0+B1, C1=B2+B3, C2=(C0/2)-B1, C5=(C1/2)-B3
  • D0=C0+C1, D1=(D0/2)-C1
  • Output: D0, D1, C2, C3, B4, B5, B6, B7
This will be applied both to every row, and then to every column, in order to transform an 8x8 block.

Block Serialization

Will consist of a DC coefficient, followed by a list of AC coefficients. The AC coefficients will use RLE compression to eliminate any runs of zeroes. They will be encoded in the block in zigzag order.

The DC coefficient will be stored as the difference from the prior DC coefficient for the same component.

AC Coefficients:

  • 0zzz-vvvv
    • 0-7 zeroes, value -8 .. 7
    • AC: The value 0x00 will be special and will signal the end of a block (EOB).
    • DC: 0x10 Will signal an empty block.
  • 100z-zzvv
    • AC: 8-15 zeroes, values: -1, 1, -2, 2
    • DC: Invalid
  • 101z-zzzz
    • AC: 1-32 zeroes
  • 110v-vvvv
    • Values -24..23 (V=16..47)
  • 1110-zzvv vvvv-vvvv
    • 0-3 zeroes, value -512..511 (BE)
  • 1111-00zz vvvv-vvvv vvvv-vvvv
    • 0-3 zeroes, Value -32768..32767 (LE)
  • 1111-01zz vvvv-vvvv vvvv-vvvv vvvv-vvvv
    • 0-3 zeroes, Value -8M..8M (LE)
  • 1111-1000 vvvv-vvvv vvvv-vvvv vvvv-vvvv vvvv-vvvv
    • Value -2G..2G (LE)
Value will be sign-folded in 0, -1, 1, -2, 2, ... order.

DC coefficients will use the same basic coding, except:

  • A zero run values of 0 will indicate a normal block (DC+AC coeffs).
  • Zero run value of 1 will indicate a block with only a DC coefficient (Implicit EOB).
  • Other zero values are reserved.
  • 0xA0..0xBF will be reserved for block-level commands:
    • 0xA0 will encode an absent (single color) block (DC difference will be 0, no AC coefficients are encoded).
      • Replaced with 0x10.
    • 0xA1, At the start of a macroblock, will indicate that the macroblock should be skipped.
      • Any pixels in the block will be left unchanged from the previous frame.
    • 0xAF, Ignored at the start of a block. Intended as a debugging command.
      • Not to be used outside of debugging.
      • Its purpose is to help detect if blocks start and end at the expected location.
Clone this wiki locally