7

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.

Rodrigo Strauss
  • 2,064
  • 2
  • 14
  • 14
  • I'm just guessing -> isn't this for example bit-order issue? – nothrow Dec 20 '10 at 16:43
  • 2
    To anybody who got confused like I did. YUY2 is a macropixel format in the form Y0 | U0 | Y1 | V0. Every 4 byte represents two RGB pixels. `Y` is known as Luma, `U` is known as Cb and `V` is known as Cr. – Maghoumi Mar 28 '16 at 06:04

4 Answers4

13

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;
}
Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
  • Hi I'm new on this topic, how do you declare the output buffer, and how do you save it to a file. You already have my vote. thx. – Delta May 27 '13 at 21:59
  • @Delta, you could use a `vector` e.g. `vector buffer(width*height*3); ptrOut = &buffer[0];`. As for saving to a file that has been answered elsewhere e.g. http://stackoverflow.com/questions/2654480/writing-bmp-image-in-pure-c-c-without-other-libraries – Mark Ransom May 28 '13 at 04:03
  • Why divide by 256 (>> 8) and not 255? Is this output normalized to [0, 1] or [0, 255]? – PixelArtDragon Jun 01 '22 at 16:35
  • @PixelArtDragon it's been a long time since I wrote this, forgive me for not remembering precisely. I almost certainly was going for [0, 255] because that's 99% what is used for RGB. It's difficult for me now to relate this answer to the source material, it could be that the reference has changed over the years. – Mark Ransom Jun 01 '22 at 17:40
3

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;
Rodrigo Strauss
  • 2,064
  • 2
  • 14
  • 14
  • My answer had the correct ordering for BGR, see the code comments. Sorry I didn't make the point explicitly. It's always the first gotcha for someone working with Windows bitmaps, the second being that the rows are upside down. – Mark Ransom Dec 30 '10 at 16:43
1

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.

Alan
  • 4,897
  • 2
  • 24
  • 17
0

You will have to write your own converter. GDI+ doesn't know how to deal with YUY2 bitmaps.

Look here.

Please note that 2 pixels share same color values and have different luminance values.

Here are some formulas to help you write your converter.

Daniel Mošmondor
  • 19,718
  • 12
  • 58
  • 99