Reputation: 1432
I have image data that gets acquired like so:
unsigned char* imageData = NULL;
GetImage(imageData);
The imageData
returns as raw BayerGR8 format: That is to say:
G R G R G R G R ...
B G B G B G B G ...
G R G R G R G R ...
...
where each of those pixels occupies 8 bits.
The images that are being grabbed are 2752x2200 (pixels).
Whenever I set up a bitmap and then create a bitmap using this image data, the bitmap always comes out blank. Here is my bitmap setup:
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;
So far I have tried the following:
HDC hdc = ::GetDC(NULL);
HBITMAP hbit = CreateDIBitmap(hdc, globalinfoheader, CBM_INIT, imageData, pbmi, DIB_RGB_COLORS);
But as I said the bitmap ends up being a blank light-gray image. I have been looking on the wikipedia article on bitmaps and I feel like it may have something to do with the biClrUsed value, but I have no idea what value it should be and have so far just been playing with the numbers.
I have also tried converting the image data directly into a CImage (which I would later convert to an HBITMAP) like so:
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 );
}
}
}
My question is: How do I take my raw Bayer image data and get an rgb color bitmap out of it?
EDIT:
Got it. Here's the function I created that got it working (interpolation method):
/////////////////////////////////////////////////////////////
// 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;
}
Upvotes: 4
Views: 8364
Reputation: 63471
You have to interpolate the components of your Bayer image. Here's a helpful link:
http://www.siliconimaging.com/RGB%20Bayer.htm
Look halfway down to the interpolation section.
As far as the target image goes, just create a stock-standard RGB 24-bit or 32-bit bitmap and set the bits as you interpolate components from your Bayer image.
It seems like half of your question is about the colour conversion and half is about why your Bitmap code is not working. There are countless examples out there that do RGB bitmap creation in Windows, so I won't go into it.
Upvotes: 3