| # 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](/doc/note/pixel-subsampling.md). |
| |
| 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](https://afrantzis.github.io/pixel-format-guide/). |
| |
| |
| ## API Stability |
| |
| The `wuffs_base__pixel_format` bit packing is documented for explanation and to |
| assist in debugging (e.g. `printf`'ing 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. |