Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to convert yuy2 to a BITMAP in C++

I'm using a security camera DLL to retreive the image from the camera. The DLL call a function of my program passing the image buffer as a parameter, but the image is in yuy2 format. I need to convert this buffer to RGB, but I tried every formula I found on Internet with no success. Every example I tried (including http://msdn.microsoft.com/en-us/library/aa904813(VS.80).aspx#yuvformats_2) gives me wrong colors.

I'm able to convert the buffer to a BW image using only the Y component of the pixel, but I really need the color picture. I debugged (assembly only) the DLL that shows the image in the screen and it uses DirectDraw to do this.

like image 561
Rodrigo Strauss Avatar asked Dec 20 '10 16:12

Rodrigo Strauss


3 Answers

Using the information from the Microsoft link in the question:

for (int i = 0;  i < width/2;  ++i)
{
    int y0 = ptrIn[0];
    int u0 = ptrIn[1];
    int y1 = ptrIn[2];
    int v0 = ptrIn[3];
    ptrIn += 4;
    int c = y0 - 16;
    int d = u0 - 128;
    int e = v0 - 128;
    ptrOut[0] = clip(( 298 * c + 516 * d + 128) >> 8); // blue
    ptrOut[1] = clip(( 298 * c - 100 * d - 208 * e + 128) >> 8); // green
    ptrOut[2] = clip(( 298 * c + 409 * e + 128) >> 8); // red
    c = y1 - 16;
    ptrOut[3] = clip(( 298 * c + 516 * d + 128) >> 8); // blue
    ptrOut[4] = clip(( 298 * c - 100 * d - 208 * e + 128) >> 8); // green
    ptrOut[5] = clip(( 298 * c + 409 * e + 128) >> 8); // red
    ptrOut += 6;
}
like image 136
Mark Ransom Avatar answered Sep 22 '22 11:09

Mark Ransom


This formula worked:

int C = luma - 16;
int D = cr - 128;
int E = cb - 128;
r = (298*C+409*E+128)/256;
g = (298*C-100*D-208*E+128)/256;
b = (298*C+516*D+128)/256;

I got this from a matlab example.

The gotcha is: in memory, Windows bitmaps aren't RGB, they are BGR. If you are writing to a memory buffer, you need to do something like this:

rgbbuffer[rgbindex] = (char)b;
rgbbuffer[rgbindex + 1] = (char)g;
rgbbuffer[rgbindex + 2] = (char)r;
like image 20
Rodrigo Strauss Avatar answered Sep 20 '22 11:09

Rodrigo Strauss


If you were already using DirectShow to get video data out of the security camera, then you could simply add the "Color Space Converter Filter" to your DirectShow graph. But if you aren't using DirectShow already (it sounds like you're not) then it will be much, much simpler to just convert the data to RGB yourself using the formulas that Daniel linked to. Adding DirectShow to a project is very complicated.

like image 41
Alan Avatar answered Sep 22 '22 11:09

Alan