This document describes a format string spec to comprehensively and compactly describe RGB colour spaces.
Complete description data should be encoded in a human-readable/writable string, which may drive the correct rendering of RGB images.
Complete set of properties relating to an RGB colour:
- Components
- Encoding
- Block compression/chroma subsampling strategy
- Gamma compression strategy
- Colour space
- Dynamic range
- Other encoding options
- Swizzling, Endian, user data, etc
"components_[format]_[colourspace]_["BE" big-endian]_[swizzle parameters]_[userdata]"
A set of single character component names:
r
g
b
- red, green, bluel
- luma/luminance (r = g = b
)a
- alpha (exempt from colourspace)e
- shared exponentx
- unused bits (may appear multiple times)
Component names are lower-case. (or should they be upper case? they could be case-insensitive, but then we halve the namespace for future expansion)
Description of the format for each channel, underscore separated for each component
Eg: rgb_8_8_8
, bgra_10_10_10_2
, rgbe_9_9_9_5
, rgba_s6_f11_4.8_u3
Encoding options:
- Omitted: 8 bit normalised integer for each component
- Unsigned normalised integer:
8
,10
- Signed normalised integer:
s8
- Floating point:
f32
,f11
- Unsigned fixed point:
1.7
,8.8
- Signed fixed point:
s2.6
,s4.4
- Unsigned integer:
u16
- Signed integer:
i16
- Block compression format:
DXT5
,ETC1
,ASTC6x6
- TODO: chroma subsampling strategy...
Open question: Is a more compact grammar possible? Without separating underscores?
Colour space name or description.
- Omitted: Assume sRGB
- Typical names:
sRGB
,DCI-P3
,BT.709
, (documented set) - Adapted whitepoint using
'@'
:sRGB@D50
- Custom gamma using
'^'
:- gamma 2.2:
[colourspace]^2.2
- Linear:
[colourspace]^1
- Use sRGB hybrid gamma ramp:
[colourspace]^sRGB
- gamma 2.2:
- Use xyY vectors:
{0.312,0.329[,1.0]}
- Custom whitepoint:
sRGB@{0.312,0.329}
- Custom primaries:
R{0.64,0.33}G{0.3,0.6}B{0.15,0.06}
- Custom whitepoint:
- Completely custom colourspace:
- Eg:
R{0.64,0.33}G{0.3,0.6}B{0.15,0.06}@D50^sRGB
- Eg:
Currently there is no spec to describe the encoded dynamic range beyond implicit parameters according to a specific colour space (ie, HDR10
, etc).
TODO: the industry hasn't really settled on standard expressions. We'll need to do a little more research to decide on a good strategy.
All formats should be read in bit-order, and encoded as little-endian bit-streams. This marker says to emit the bitstream as big-endian.
It should be noted that this will have the effect of reversing the order of the components when they are byte-aligned, and may appear contrary to a struct with separate element members.
While rgb_8_8_8
is equivalent to bgr_8_8_8_BE
, formats where elements straddle byte boundaries require the BE
specifier to be expressed correctly.
Eg:
rrrrrggg gggbbbbb
- rgb_565
bbbbbggg gggrrrrr
- bgr_565
gggbbbbb rrrrrggg
- rgb_565_BE
gggrrrrr bbbbbggg
- bgr_565_BE
TODO: develop an expression for swizzling parameters that cover known hardware.
I think there's no hardware that will fail to be expressed by [bytes-in-row]:[num-rows]
.
We could use something like Z32:16
to specify eg: swizzle tiles of 16 rows of 32bytes.
A string of user data starting with #
, eg: #userdata-string
.
May not contain _
characters.
I like rgb_8_8_8
because it's very readable, and the 8_8_8
can be omitted and inferred for the most common colour formats.
An alternative strategy that eliminates the underscores would be to have the encoding follow the channel immediately, eg: R8G8B8
I feel this becomes very difficult to read with longer formats, eg: R10fG10fB10fA2
, but it is gramatically sound.