[转自]http://ffmpeg.blogbus.com/logs/525422.html
lcd显示器是多少位色的啊?俺不知道,人家说都用16位色(rgb565),那俺就学学这个怎么转换来着。如果用公式的话,又是乘法,又是饱和,又是移位,又是或的,会把人累死的:(.不过SDL里有个查表的算法不错,分析一下。
下面是一个表的初始化。
swdata->pixels = (Uint8 *) malloc(width*height*2);
swdata->colortab = (int *)malloc(4*256*sizeof(int));
Cr_r_tab = &swdata->colortab[0*256];
Cr_g_tab = &swdata->colortab[1*256];
Cb_g_tab = &swdata->colortab[2*256];
Cb_b_tab = &swdata->colortab[3*256];
swdata->rgb_2_pix = (Uint32 *)malloc(3*768*sizeof(Uint32));
r_2_pix_alloc = &swdata->rgb_2_pix[0*768];
g_2_pix_alloc = &swdata->rgb_2_pix[1*768];
b_2_pix_alloc = &swdata->rgb_2_pix[2*768];
for (i=0; i<256; i++) {
/* 这里的一个表是为乘法做的一个表*/
CB = CR = (i-128);
Cr_r_tab[i] = (int) ( (0.419/0.299) * CR);
Cr_g_tab[i] = (int) (-(0.299/0.419) * CR);
Cb_g_tab[i] = (int) (-(0.114/0.331) * CB);
Cb_b_tab[i] = (int) ( (0.587/0.331) * CB);
}
Rmask = display->format->Rmask;
Gmask = display->format->Gmask;
Bmask = display->format->Bmask;
for ( i=0; i<256; ++i ) {
/*这个表是为饱和做的,并且已经做好了移位,到查表的时候只要将这几个rgb的值或起来即可,r被饱和到0~0xf800之间(高5位有值),g被饱和到0~0x07e0之间(中间6位有值),b被饱和到0~0x001f之间(低5位有值)*/
r_2_pix_alloc[i+256] = i >> (8 - number_of_bits_set(Rmask));
r_2_pix_alloc[i+256] <<= free_bits_at_bottom(Rmask);
g_2_pix_alloc[i+256] = i >> (8 - number_of_bits_set(Gmask));
g_2_pix_alloc[i+256] <<= free_bits_at_bottom(Gmask);
b_2_pix_alloc[i+256] = i >> (8 - number_of_bits_set(Bmask));
b_2_pix_alloc[i+256] <<= free_bits_at_bottom(Bmask);
}
下面是使用部分代码,也就是查表过程
/*前面那个768的系数其实是算在第二个表的偏移上的,因为y部分数据要使用四次,所以提前到cb,cr里面*/
cr_r = 0*768+256 + colortab[ *cr + 0*256 ];
crb_g = 1*768+256 + colortab[ *cr + 1*256 ]
+ colortab[ *cb + 2*256 ];
cb_b = 2*768+256 + colortab[ *cb + 3*256 ];
++cr; ++cb;
L = *lum++;/*将3个值或起来,构成rgb565,没什么好说的。*/
*row1++ = (rgb_2_pix[ L + cr_r ] |
rgb_2_pix[ L + crb_g ] |
rgb_2_pix[ L + cb_b ]);