Especially when dealing with hardware and file formats,
it is common to encode a color in a compact-sized integer.
Here are some examples of such encodings
(-
= unused bit or an alpha bit, R
= red bit, G
= green bit, B
= blue bit):
BBBBBGGG GGGRRRRR
-BBBBBGG GGGRRRRR
-------- BBBBBBBB GGGGGGGG RRRRRRRR
RRRRRRRR BBBBBBBB GGGGGGGG --------
--BBBBB- --GGGGGG GGG---RR RRRRRRR-
Out of these examples given, the first three are very commonly used, while the last two I just came up with. One can come up with a huge amount of variations of such encoding schemes. However, it is probably safe to assume that the bits of a given component are stored sequentially and are in the right order. Under this assumption, all possible encoding schemes can be captured by describing the starting index and length of each component in the integer (in bits). Using some template trickery, the encoding and decoding with a packed color can be made as fast as a hand-written implementation. In Pastel, you do the conversion for the encoding schemes listed above as follows:
Color aColor = Integer_To_Color<uint16, 5, 6, 5>::convert(aPackedColor);
Color bColor = Integer_To_Color<uint16, 5, 5, 5>::convert(bPackedColor);
Color cColor = Integer_To_Color<uint32, 8, 8, 8>::convert(cPackedColor);
Color dColor = Integer_To_Color<uint32, 8, 8, 8, 24, 8, 16>::convert(dPackedColor);
Color eColor = Integer_To_Color<uint32, 9, 9, 5, 1, 13, 25>::convert(ePackedColor);
The Integer_To_Color takes the packed type, the number of bits in each component, and the starting indices of each component. If the positions are not given, the components are assumed to be packed subsequently. The conversion to the other direction is as easy:
uint16 aPackedColor = Integer_To_Color<uint16, 5, 6, 5>::revert(aColor);
uint16 bPackedColor = Integer_To_Color<uint16, 5, 5, 5>::revert(bColor);
uint32 cPackedColor = Integer_To_Color<uint32, 8, 8, 8>::revert(cColor);
uint32 dPackedColor = Integer_To_Color<uint32, 8, 8, 8, 24, 8, 16>::revert(dColor);
uint32 ePackedColor = Integer_To_Color<uint32, 9, 9, 5, 1, 13, 25>::revert(eColor);
Here the encoding scheme must be known in compile time. If this is not the case, then you can use the functions ‘integerToColor’ and ‘colorToInteger’:
Color dColor = integerToColor<uint32>(dPackedColor, 8, 8, 8, 24, 8, 16);
uint32 dPackedColor = colorToInteger<uint32>(dColor, 8, 8, 8, 24, 8, 16);