次のように取得される画像データがあります。
unsigned char* imageData = NULL;
GetImage(imageData);
生のimageData
BayerGR8 形式として返されます。
G R G R G R G R ...
B G B G B G B G ...
G R G R G R G R ...
...
これらの各ピクセルは 8 ビットを占有します。
取得されている画像は 2752x2200 (ピクセル) です。
ビットマップを設定し、この画像データを使用してビットマップを作成すると、ビットマップは常に空白になります。これが私のビットマップ設定です:
BITMAPFILEHEADER* bf = new BITMAPFILEHEADER;
bf->bfType = 0x4d42;
bf->bfSize = 6054400 + 54 + sizeof(BITMAPINFO);
bf->bfOffBits = 54;
BITMAPINFOHEADER* bih = new BITMAPINFOHEADER;
bih->biSize = 40;
bih->biWidth = 2752;
bih->biHeight = 2200;
bih->biPlanes = 1;
bih->biBitCount = 8;
bih->biCompression = 0;
bih->biXPelsPerMeter = 2835;
bih->biYPelsPerMeter = 2835;
bih->biClrUsed = 0;
bih->biClrImportant = 0;
これまでのところ、次のことを試しました。
HDC hdc = ::GetDC(NULL);
HBITMAP hbit = CreateDIBitmap(hdc, globalinfoheader, CBM_INIT, imageData, pbmi, DIB_RGB_COLORS);
しかし、私が言ったように、ビットマップは最終的に空のライトグレーのイメージになります。私はビットマップに関するウィキペディアの記事を見てきました.biClrUsed値と関係があるように感じますが、それがどのような値であるべきかわかりません.これまでのところ、数字で遊んでいます.
また、次のように、画像データを直接 CImage (後で HBITMAP に変換します) に変換しようとしました。
void ConvertImageBufferToCImage(unsigned char *pInBuffer, CImage *pOutImage)
{
if ( NULL != *pOutImage )
{
unsigned char *pCursor = (unsigned char*)pOutImage->GetBits();
int nHeight = 2200;
int nWidth = 2752;
int nStride = 0;
if ( 0 < nStride)
{
for ( int y=0; y<nHeight; ++y )
{
for ( int x=0; x<nWidth; ++x )
{
*pCursor = *pInBuffer;
++pCursor;
++pInBuffer;
}
// Consider stride
pCursor += nStride;
}
}
else
{
memcpy( pOutImage->GetBits(), pInBuffer, nWidth * nHeight );
}
}
}
私の質問は 、生のベイヤー画像データを取得して、そこから RGB カラー ビットマップを取得するにはどうすればよいですか?
編集:
とった。これが機能するように作成した関数です(補間法):
/////////////////////////////////////////////////////////////
// ConvertBayer8ToBgr()
// Converts raw BayerGR8 pixels into
// BGR pixels.
//
// G | R | G | R B G R | B G R | B G R | B G R
// --- --- --- --- ------- ------- ------- -------
// B | G | B | G |\ B G R | B G R | B G R | B G R
// --- --- --- --- ----- \ ------- ------- ------- -------
// G | R | G | R ----- / B G R | B G R | B G R | B G R
// --- --- --- --- |/ ------- ------- ------- -------
// B | G | B | G B G R | B G R | B G R | B G R
//
/////////////////////////////////////////////////////////////
void ConvertBayer8ToBGR(VmbUchar_t* bayerImgDat, VmbUchar_t* bgrOutputDat)
{
VmbUchar_t* newimagedata_start = bgrOutputDat;
int currentTempIndex = 0;
int nearestBluesAvg = 0;
int nearestRedsAvg = 0;
int nearestGreensAvg = 0;
for(int j = 0; j < 1100; j++)
{
for(int i = 0; i < 2752; i++) //G R G R G...
{
if(currentTempIndex % 2 == 0 /* even, green */)
{
//avg blue
if(j == 0) //if in the first row, only take next blue
{
nearestBluesAvg = *(bayerImgDat+currentTempIndex+2752);
}
else
{
nearestBluesAvg = (*(bayerImgDat + currentTempIndex + 2752) + *(bayerImgDat+currentTempIndex-2752)) / 2;
}
*bgrOutputDat = nearestBluesAvg; //b
bgrOutputDat++;
*bgrOutputDat = *(bayerImgDat + currentTempIndex); //g
bgrOutputDat++;
//avg red
if(i == 0) //if in first column, only take next red
{
nearestRedsAvg = *(bayerImgDat+currentTempIndex+1);
}
else
{
nearestRedsAvg = ( (*(bayerImgDat+currentTempIndex+1)) + (*(bayerImgDat+currentTempIndex-1)) ) / 2;
}
*bgrOutputDat = nearestRedsAvg; //r
bgrOutputDat++;
currentTempIndex++;
}
else /* odd, red*/
{
//avg blue
if(i == 1099) //if in last column, take just left-down blue pixel
{
nearestBluesAvg = *(bayerImgDat+currentTempIndex-1+2752);
}
else // else take both left-down and right-down
{
nearestBluesAvg = (*(bayerImgDat+currentTempIndex+1+2752) + *(bayerImgDat+currentTempIndex-1+2752)) / 2;
}
*bgrOutputDat = nearestBluesAvg; //b
bgrOutputDat++;
//avg green
nearestGreensAvg = (*(bayerImgDat+currentTempIndex-1) + *(bayerImgDat+currentTempIndex+2752)) / 2;
*bgrOutputDat = nearestGreensAvg; //g
bgrOutputDat++;
*bgrOutputDat = *(bayerImgDat + currentTempIndex); //r
bgrOutputDat++;
currentTempIndex++;
}
}
for(int i = 0; i < 2752; i++)//B G B G B G B....
{
if(currentTempIndex % 2 == 0 /* even, blue */)
{
*bgrOutputDat = *(bayerImgDat + currentTempIndex); //b
bgrOutputDat++;
//avg green
nearestGreensAvg = (*(bayerImgDat + currentTempIndex + 1) + *(bayerImgDat + currentTempIndex -2752)) / 2;
*bgrOutputDat = nearestGreensAvg; //g
bgrOutputDat++;
//avg red
if(i == 0) //if first column, take only right-up pixel
{
nearestRedsAvg = *(bayerImgDat+currentTempIndex+1-2752);
}
else //else take both left-up and right-up pixels
{
nearestRedsAvg = (*(bayerImgDat+currentTempIndex-1-2752) + *(bayerImgDat+currentTempIndex+1-2752)) / 2;
}
*bgrOutputDat = nearestRedsAvg; //r
bgrOutputDat++;
currentTempIndex++;
}
else /* odd, green*/
{
//avg blue
if(i == 2751) //if in last column, only take previous blue (next blue doesnt exist)
{
nearestBluesAvg = *(bayerImgDat + currentTempIndex - 1);
}
else //else take both next and previous
{
nearestBluesAvg = (*(bayerImgDat+currentTempIndex+1) + *(bayerImgDat+currentTempIndex-1)) / 2;
}
*bgrOutputDat = nearestBluesAvg; //b
bgrOutputDat++;
*bgrOutputDat = *(bayerImgDat + currentTempIndex); //g
bgrOutputDat++;
//avg red
if(j == 1099) //if in last row, only take previous red (next red doesn't exist)
{
nearestRedsAvg = *(bayerImgDat+currentTempIndex-2752);
}
else //else take both
{
nearestRedsAvg = (*(bayerImgDat+currentTempIndex+2752) + *(bayerImgDat+currentTempIndex-2752)) / 2;
}
*bgrOutputDat = nearestRedsAvg; //r
bgrOutputDat++;
currentTempIndex++;
}
}
}
bgrOutputDat = newimagedata_start;
}