Function to convert YCbCr to RGB?

38.1k Views Asked by At

I have Y, Cb and Cr values, each with a size of 8 bits. What would be a simple C function which can convert these values to R,G,B (each with a size of 8 bits)?

Here is a prototype of the function I am looking for:

void convertYCbCrToRGB(
    unsigned char Y,
    unsigned char cg,
    unsigned char cb,
    unsigned char &r,
    unsigned char &g,
    unsigned char &b);

P.S. I am looking for the correct conversion formula only, since I have found different versions of it everywhere. I am very well-versed in C/C++.

4

There are 4 best solutions below

2
On BEST ANSWER

The problem comes that nearly everybody confuses YCbCr YUV and YPbPr. So literature you can find is often crappy. First you have to know if you really have YCbCr or if someone lies to you :-).

  • YUV coded data comes from analog sources (PAL video decoder, S-Video, ...)
  • YPbPr coded data also comes from analog sources but produces better color results as YUV (Component Video)
  • YCbCr coded data comes from digital sources (DVB, HDMI, ...)

YPbPr and YCbCr are related. Here are the right formulae:

https://web.archive.org/web/20180421030430/http://www.equasys.de/colorconversion.html

(the archive.org has been added to fix the old, broken link).

1
On

Integer operation of ITU-R standard for YCbCr is (from Wikipedia)

Cr = Cr - 128 ;
Cb = Cb - 128 ;
r = Y + ( Cr >> 2 + Cr >> 3 + Cr >> 5 ) ;
g = Y - ( Cb >> 2 + Cb >> 4 + Cb >> 5) - ( Cr >> 1 + Cr >> 3 + Cr >> 4 + Cr >> 5) ;
b = Y + ( Cb + Cb >> 1 + Cb >> 2 + Cb >> 6) ;

or equivalently but more concisely to :

Cr = Cr - 128 ;
Cb = Cb - 128 ;
r = Y + 45 * Cr / 32 ;
g = Y - (11 * Cb + 23 * Cr) / 32 ;
b = Y + 113 * Cb / 64 ;

do not forget to clamp values of r, g and b within [0,255].

2
On

Check out this page. It contains useful information on conversion formulae.

As an aside, you could return a unsigned int with the values for RGBA encoded from the most significant byte to least significant byte, i.e.

unsigned int YCbCrToRGBA(unsigned char Y, unsigned char Cb, unsigned char Cb) {
   unsigned char R = // conversion;
   unsigned char G = // conversion;
   unsigned char B = // conversion;

   return (R << 3) + (G << 2) + (B << 1) + 255;
}
1
On

Here is my solution to my question.
This one is Full Range YCbCr to RGB conversion routine.

Color GetColorFromYCbCr(int y, int cb, int cr, int a)
{
 double Y = (double) y;
 double Cb = (double) cb;
 double Cr = (double) cr;

 int r = (int) (Y + 1.40200 * (Cr - 0x80));
 int g = (int) (Y - 0.34414 * (Cb - 0x80) - 0.71414 * (Cr - 0x80));
 int b = (int) (Y + 1.77200 * (Cb - 0x80));

 r = Max(0, Min(255, r));
 g = Max(0, Min(255, g));
 b = Max(0, Min(255, b));

 return Color.FromArgb(a, r, g, b);
}