VFW采集到视频帧时
1. 如果摄像头采用的是RGB24输出的时候,在buffer中RGB三分量的排列顺序是 [B0,G0,R0,B1,G1,R1....Bn,Gn,Rn] ,可以直接采用StretchDIBits来画图,但是在画图前必须填充BITMAPINFO 信息结构体。该结构体中的内容可以从 VFW函数库中capCaptureGetSetup函数来取得一部分信息。
2. 如果摄像头采用的是YUY2输出的话,因为StretchDIBits函数只能采用RGB的色彩空间,所以必须首先转换成RGB的数据。此时vfw回调所得buffer中的数据排列如下 [Y0 U0 Y1 V0 Y2 U1 Y3 V1] 转换函数如下
/*
每连续的4个YUV,代表2个像素 UV是共享的
1. Y0 U0 Y1 V0 ===> [Y0 U0 V0][Y1 U0 V0] 代表两个像素
*/
void YUY2_RGB2(BYTE *YUY2buff,BYTE *RGBbuff,DWORD dwSize)
{
//
//C = Y - 16
//D = U - 128
//E = V - 128
//R = clip(( 298 * C + 409 * E + 128) >> 8)
//G = clip(( 298 * C - 100 * D - 208 * E + 128) >> 8)
//B = clip(( 298 * C + 516 * D + 128) >> 8)
BYTE *orgRGBbuff = RGBbuff;
for( DWORD count = 0; count < dwSize; count += 4 )
{
//Y0 U0 Y1 V0
BYTE Y0 = *YUY2buff;
BYTE U = *(++YUY2buff);
BYTE Y1 = *(++YUY2buff);
BYTE V = *(++YUY2buff);
++YUY2buff;
LONG Y,C,D,E;
BYTE R,G,B;
Y = Y0;
C = Y - 16;
D = U - 128;
E = V - 128;
R = clip255(( 298 * C + 409 * E + 128) >> 8);
G = clip255(( 298 * C - 100 * D - 208 * E + 128) >> 8);
B = clip255(( 298 * C + 516 * D + 128) >> 8);
*(RGBbuff) = B;
*(++RGBbuff) = G;
*(++RGBbuff) = R;
Y = Y1;
C = Y-16;
D = U-128;
E = V-128;
R = clip255(( 298 * C + 409 * E + 128) >> 8);
G = clip255(( 298 * C - 100 * D - 208 * E + 128) >> 8);
B = clip255(( 298 * C + 516 * D + 128) >> 8);
*(++RGBbuff) = B;
*(++RGBbuff) = G;
*(++RGBbuff) = R;
++RGBbuff;
}
}
BYTE clip255(LONG v)
{
if(v < 0) v=0;
else if( v > 255) v=255;
return (BYTE)v;
}
YUV转换后,如果要调用StretchDIBits来画图的话,传入的buffer中的RGB分量的排列顺序也必须按照BGR的顺序,否则就会看到色彩颠倒的情况,所以上面的转换函数也采用BGR的排列顺序来排列顺序。
3.如果摄像头输出的是RGB16的数据,我们只要StretchDIBits画图的时候设置位图属性和输出属性一致就OK
如果要实现自己通过SetPiexel来画像素的话,就必须把RGB16(RGB555,RGB565)扩大到RGB24(RGB888)
扩展公式如下
这里的source就是RGB16(RGB555)
void CDib::ConvertLine16To24_555(BYTE *target, BYTE *source, int width_in_pixels)
{
WORD *bits = (WORD *)source;
for (int cols = 0; cols < width_in_pixels; cols++)
{
target[0] = (((bits[cols] & 0x7C00) >> 10) * 0xFF) / 0x1F;
target[1] = (((bits[cols] & 0x03E0) >> 5) * 0xFF) / 0x1F;
target[2] = (((bits[cols] & 0x001F) >> 0) * 0xFF) / 0x1F;
target += 3;
}
}