# RGB color conversion

Page 1/3
| 2 | 3

Does anyone know how to convert a 24 bits rgb color value (e.g. RGB: 255, 153, 0) to a msx2 equivalent?

When I am right it is a 24 bits rgb to 9 bits rgb color conversion. I am looking for a formula.

MSX color component = 24bit color component / 32

wouldn't that be a division by 36.43?
That wat 255 would become 7.

No formula - you just drop (discard) the least significant bits that don't fit in the less-accurate end result.

Say for example you have a 24 bit value containing 8 bits that represent red, and you want to convert to an RGB value that has only 3 bits representing red. Then you take the 3 most significant bits (out of 8), and put 'em in that 3-bit space. The remaining 5 (less significant) bits you throw away.

Yes that means losing image quality, but that's the whole point of such a conversion: represent the same pixels using fewer bits. One could try various dithering and/or rounding methods to improve results (or perhaps an integer divide with a divisor other than a power of 2), but ultimately you will be discarding part of the image information.

Red / Green / Blue channels can be treated as independent, applying the same method to each. Or not. Again: whatever works, but one way or the other you'll be discarding those least significant bits.

Meits wrote:

wouldn't that be a division by 36.43?
That wat 255 would become 7.

No, that would practically leave all the bright colors away as 254 would be already 6 if we are talking about integers. If we start rounding floating points then the brightness problem is not that bad... but anyway... just divide with 32... (This is same as dropping out bits that MSX does not have.)

From 8-bit colour component values to 3-bit values: divide by 255, multiply by 7, and round the result. Other way around: divide by 7, multiply by 255, round the result.

The 7 colour component values: 0, 36, 73, 109, 146, 182, 219, 255

When drawing graphics for screen 5, I try to pick only colours with these component values.

@Meits: and what about value 254? Or 253? You round those down to 6? (from a 3-bit value 0,1,...,7)
If yes, that means values 0-6 each represent ~36 possible values in the original, while 7 represents only 1 value in the original. Probably NOT what you want...
If no (7 represents more values in the original), then you're back to just dropping bits (divide by a power of 2 like NYYRIKKI said) or rounding up/down. Dithering is a better method to preserve a little extra info from the original values.

Grauw wrote:

From 8-bit colour component values to 3-bit values: divide by 255, multiply by 7, and round the result. Other way around: divide by 7, multiply by 255, round the result.

Why is this better than dropping the lowest 5 bits (/32)? Because in a 3-bit palette value 0 is fully off, 7 is fully on, and on a 8-bit palette value 0 is fully off and 255 is fully on. You can convert these to a scale from 0 to 1, by either dividing by 7 or dividing by 255.

Assuming all values are linearly distanced (disregarding things like gamma), you want to pick the 3-bit colour that is closest to the original 8-bit colour. For e.g. 8-bit value 224 (0.88), this should be 3-bit value 6 (0.85), not 7 (1.00). This is why you should divide, multiply and round, rather than just dropping bits with an integer division, as it minimises the error.

For this reason when you convert a 3-bit colour component to 24-bit, you also don’t want to pad the binary values with five 0’s, but rather nc = c << 5 + c << 2 + c >> 1 (integer logic) or nc = round(c / 7 * 255) (floating point logic).

There's probably a better solution : screen 8 with his 256 colors !

Why degrad the colors to fit in screen 5 or 7 ?

From the RuMSX help files :

Quote:

SCREEN 8

The color-value in screen 8 can be 0-255, the color is defined by the following formula:

color-number = 4 x R + 32 x G + B. The values for Red and Green can be 0-7, the values for Blue can be 0-3 (they correspond to 0, 2, 4 and 7).

This means that the bits are representing colors as following: G G G R R R B B.

@Grauw If you want to take that approach then (VALUE+16)/32 is better... The problem is that you think that 255 should become 7 while actually you should think that 256 should become 8.

For screen modes that use a palette, you can choose colors such that the overall results gets closest to the original.

For example if original has many colors that are very similar, and just a few colors that look very different, you could use a few palette colors for those different ones, and fill the rest of the palette with very similar-looking color values. Then for each RGB value pick the best matching palette entry.

Obviously choosing an optimal palette is a much more complicated job than applying the same simple math to each RGB value.

Page 1/3
| 2 | 3