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;
}
}