RGB颜色转换成16bit颜色
RGB颜色是一个DWORD值,32bit,格式为0x00rrggbb,通过三个宏:GetRValue、GetGValue和GetBValue可以得到三个颜色分量,用8bitBYTE表示。16bit颜色有555和565两种,以565为例,565模式的16bit颜色格式为:rrrrrggggggbbbbb。我们的任务就是将0x00rrggbb转成rrrrrggggggbbbbb。
首先将RGB的三个分量分离出来,将它们分别转成用5bit,6bit,5bit表示的颜色(前3bit,2bit,3bit为0)。因为8bit是256级色度,转成5bit是32级色度,所以每8级色度一组转成1级色度,除以8(右移3位)就行;同样转成6bit只要除以4,因为6bit能表达64级色度。然后再将得到的5bit与上0x1f,6bit与上0x3f,将8bit前面的3bit或2bit清0。这时得到的三个分量为:R=000rrrrr , G=00gggggg , B=000bbbbb 。最后将它们移位相或就可得到一个16bit565模式的颜色了。
运算式如下:
Color16bit =( ( GetRValue(ColorRGB)>>3 ) & 0x1f)<<11 |
( ( GetGValue(ColorRGB)>>2) & 0x3f)<<5 |
( GetBValue(ColorRGB)>>3 ) & 0x1f;
其实并没有必要与上0x1f和0x3f,因为转化后的色度范围是0~31或0~63,前3bit或2bit必为0(从位运算角度看右移后前面空出来的位自动填0);所以去掉上面的与操作,就是(注意移位操作不能合并,否则不能使前3bit,2bit清0):
Color16bit = GetRValue(ColorRGB)>>3<<11 | GetGValue(ColorRGB)>>2<<5 | GetBValue(m_ColorRGB)>>3 ;
挺简单吧,只不过是一堆位运算。只要多动动脑筋,我们可以很容易的写出各种格式之间的转换式。
/*补充贴上我自己的代码里面的转换,可以作为参考*/
static UINT16 *_convertRGB32TORGB1555(UINT32 *data_IN, UINT32 data_Len)
{
UINT32 index = 0;
UINT8 *Tmp_IN = NULL;
UINT16 *data_OUT = NULL;
UINT16 R1555 = 0;
UINT16 G1555 = 0;
UINT16 B1555 = 0;
UINT16 A1555 = 0x8000;
Tmp_IN = (UINT8*)data_IN;
OS_malloc(data_Len/2, (void**)&data_OUT);
if(NULL == data_OUT)
{
printf("os_malloc failed \n");
return NULL;
}
printf("data_Len:%d\n",data_Len);
if(Tmp_IN == NULL || data_Len <= 0 || Tmp_IN == 0)
{
printf("[%s]Param error\n",__FUNCTION__);
return NULL;
}
for(index = 0; index < data_Len/4; index++)
{
R1555 = Tmp_IN[1];
G1555 = Tmp_IN[2];
B1555 = Tmp_IN[3];
if(index < 100)
{
printf("Tmp_IN[0]:%x Tmp_IN[1]:%x Tmp_IN[2]:%x Tmp_IN[3]:%x\n",Tmp_IN[0],Tmp_IN[1],Tmp_IN[2],Tmp_IN[3]);
printf("R1555 :%x G1555 :%x B1555 :%x\n",R1555,G1555,B1555);
}
Tmp_IN += 4;
data_OUT[index] = (A1555)|(((R1555>>3)&0x1f) << 10)|(((G1555>>3)&0x1f) << 5)|((B1555>>3)&0x1f);
}
return data_OUT;
}