Pixel Formats

wuffs_base__pixel_format is a uint32_t that encodes the format of the bytes that constitute an image frame's pixel data. Its bits:

  • bit 31 is reserved.
  • bits 30 .. 28 encodes color (and channel order, in terms of memory).
  • bit 27 is reserved.
  • bits 26 .. 24 encodes transparency.
  • bits 23 .. 21 are reserved.
  • bit 20 indicates big-endian/MSB-first (as opposed to little/LSB).
  • bit 19 indicates floating point (as opposed to integer).
  • bit 18 indicates palette-indexed. The number-of-planes (the next field) will be 0, as the format is considered interleaved, but the 8-bit N-BGRA color data is stored in plane 3.
  • bits 17 .. 16 are the number of planes, minus 1. Zero means interleaved.
  • bits 15 .. 12 encodes the number of bits (depth) in the 3rd channel.
  • bits 11 .. 8 encodes the number of bits (depth) in the 2nd channel.
  • bits 7 .. 4 encodes the number of bits (depth) in the 1st channel.
  • bits 3 .. 0 encodes the number of bits (depth) in the 0th channel.

The bit fields of a wuffs_base__pixel_format are not independent. For example, the number of planes should not be greater than the number of channels. Similarly, bits 15..4 are unused (and should be zero) if bits 31..24 (color and transparency) together imply only 1 channel (gray, no alpha) and floating point samples should mean a bit depth of 16, 32 or 64.

Formats hold between 1 and 4 channels. For example: Y (1 channel: gray), YA (2 channels: gray and alpha), BGR (3 channels: blue, green, red) or CMYK (4 channels: cyan, magenta, yellow, black).

For direct formats with N > 1 channels, those channels can be laid out in either 1 (interleaved) or N (planar) planes. For example, RGBA data is usually interleaved, but YCbCr data is usually planar, due to chroma subsampling.

For indexed formats, the palette (always 256 × 4 bytes) holds 8 bits per channel non-alpha-premultiplied BGRA color data. There is only 1 plane (for the index), as the format is considered interleaved. Plane 0 holds the per-pixel indices. Plane 3 is re-purposed to hold the per-index colors.

The color field is encoded in 3 bits:

  • 0 means A (Alpha).
  • 1 means Y or YA (Gray, Alpha).
  • 2 means YCbCr or YCbCrA (Luma, Chroma-blue, Chroma-red, Alpha).
  • 3 means YCoCg or YCoCgA (Luma, Chroma-orange, Chroma-green, Alpha).
  • 4 means BGR, BGRX or BGRA (Blue, Green, Red, X-padding or Alpha).
  • 5 means RGB, RGBX or RGBA (Red, Green, Blue, X-padding or Alpha).
  • 6 means CMY or CMYK (Cyan, Magenta, Yellow, Black).
  • all other values are reserved.

In Wuffs, channels are given in memory order (also known as byte order), regardless of endianness, since the C type for the pixel data is an array of bytes, not an array of uint32_t. For example, interleaved BGRA with 8 bits per channel means that the bytes in memory are always Blue, Green, Red then Alpha. On big-endian systems, that is the uint32_t 0xBBGGRRAA. On little-endian, 0xAARRGGBB.

When the color field (3 bits) encodes multiple options, the transparency field (3 bits) distinguishes them:

  • 0 means fully opaque, no extra channels
  • 1 means fully opaque, one extra channel (X or K, padding or black).
  • 5 means one extra alpha channel, other channels are non-premultiplied.
  • 6 means one extra alpha channel, other channels are premultiplied.
  • 7 means one extra alpha channel, binary alpha.
  • all other values are reserved.

Binary alpha means that if a color is not completely opaque, it is completely transparent black. As a source pixel format, it can therefore be treated as either non-premultiplied or premultiplied.

The zero wuffs_base__pixel_format value is an invalid pixel format, as it is invalid to combine the zero color (alpha only) with the zero transparency.

Bit depth is encoded in 4 bits:

  • 0 means the channel or index is unused.
  • x means a bit depth of x, for x in the range 1..8.
  • 9 means a bit depth of 10.
  • 10 means a bit depth of 12.
  • 11 means a bit depth of 16.
  • 12 means a bit depth of 24.
  • 13 means a bit depth of 32.
  • 14 means a bit depth of 48.
  • 15 means a bit depth of 64.

For example, the value wuffs_base__pixel_format 0x40000565 means BGR with no alpha or padding, 5/6/5 bits for blue/green/red, interleaved 2 bytes per pixel, laid out LSB-first in memory order:

ptr+0...........  ptr+1...........
MSB          LSB  MSB          LSB
G₂G₁G₀B₄B₃B₂B₁B₀  R₄R₃R₂R₁R₀G₅G₄G₃

On little-endian systems (but not big-endian), this Wuffs pixel format value (0x40000565) corresponds to the Cairo library‘s CAIRO_FORMAT_RGB16_565, the SDL2 (Simple DirectMedia Layer 2) library’s SDL_PIXELFORMAT_RGB565 and the Skia library's kRGB_565_SkColorType. Note BGR in Wuffs versus RGB in the other libraries.

Regardless of endianness, this Wuffs pixel format value (0x40000565) corresponds to the V4L2 (Video For Linux 2) library‘s V4L2_PIX_FMT_RGB565 and the Wayland-DRM library’s WL_DRM_FORMAT_RGB565.

Different software libraries name their pixel formats (and especially their channel order) either according to memory layout or as bits of a native integer type like uint32_t. The two conventions differ because of a system‘s endianness. As mentioned earlier, Wuffs pixel formats are always in memory order. More detail of other software libraries’ naming conventions is in Alexandros Frantzis' Pixel Format Guide.

API Stability

The wuffs_base__pixel_format bit packing is documented for explanation and to assist in debugging (e.g. printfing the bits in %x format). However, do not manipulate its bits directly; they are private implementation details. Use functions such as wuffs_base__pixel_format__num_planes instead.