Page 1 of 1
24b color to 16b
Posted: Tue Aug 31, 2010 3:57 am
by lama
hello everyone, how can i recalculate 24bit color (for example 0x545454) to 16 bit color? (that 16bit color should then be the closest possible match of the original, 24 bit color).
thanks.
Re: 24b color to 16b
Posted: Tue Aug 31, 2010 4:33 am
by Combuster
Question shotgun time.
how many values does each color component have in 24 bits? how many in 16 bits? for each red value in 16bits, how many values in 24 bits will have to use that color? What input values (write them out in binary) would result in a red value of 0, which ones would result in 1, which ones in a 2? do you see a pattern yet?
Re: 24b color to 16b
Posted: Tue Aug 31, 2010 8:16 am
by Brendan
Hi,
lama wrote:hello everyone, how can i recalculate 24bit color (for example 0x545454) to 16 bit color? (that 16bit color should then be the closest possible match of the original, 24 bit color).
For 16-bpp you typically get 5-bit red, 6-bit green and 5-bit blue. You'd want the most significant source bits to end up in the destination bits. For example, you might do "
dest = ((source & 0x00F80000) >> 8 ) | ((source & 0x0000FC00) >> 5) | ((source & 0x000000F8) >> 3)". Unfortunately this causes a slight loss of intensity (e.g. a photo will look slightly darker) because you're essentially using "round to lowest".
To avoid the slight loss of intensity, you'd need to round to nearest. For example, "
dest = (((source & 0x00F80000) + 0x00040000) >> 8 ) | (((source & 0x0000FC00) + 0x00000200) >> 5) | (((source & 0x000000F8) + 0x00000002) >> 3)". This causes an extra problem, because values may overflow (e.g. 0xFF becomes 0x00). To work around that you'd need to do something like (for the red only) "
if( (source & 0x00FC0000) == 0x00FC0000) { dest = 0x0000F800; } else { dest = (((source & 0x00F80000) + 0x00040000) >> 8 ); }".
Of course that only really reduces the chance of the problem happening. If you've got large area/s that happens to be the same colour, then you'll end up with either a slight loss of intensity or a slight increase in intensity (depending on if that colour is rounded up or down); and because red, green and blue are handled separately you might (for e.g.) increase red while reducing green and blue, causing slight shifts in hue.
The other problem is something called
posterization or
colour banding.
To avoid all of these problems (intensity shift, hue shift and posterization/colour banding), you need to use
some form of dithering.
Cheers,
Brendan
Re: 24b color to 16b
Posted: Wed Sep 01, 2010 7:41 am
by lama
thanks for your full explanation and example how to do that . it is working now
you may lock this thread.