[M4IF Technotes] question on YUV2RGB conversion

Robert Bleidt rbleidt hdtv.com
Wed Jan 29 12:15:18 EST 2003


Here is a code fragment that shows how to do this in C integer arithmetic. 
RGB255 mode uses the full dynamic range of the RGB signal for video. (The 
most common display mode) RGB235 makes full white equal 235 decimal and 
full black equal 16 decimal in each RGB component. (very obscure)
Although I used to know what I was doing, that was a long time ago, and 
this work has not been thoroughly checked. Details of clipping errors, 
roundoff noise, overflow, transcoding matrix could be wrong; though it 
seems to work.
You can find a discussion of the theory behind this at 
http://www.inforamp.net/~poynton/ , though it looks like his site is down 
today.
======================================
void convertFrameYUV2RGB(byte *outFrameBuf, byte *inFrameBuf,int pixLine, 
int linesFrm, AviFormatCode aviFormat)
{
         long r,g,b; short y,cr,cb;
         byte *tempp = outFrameBuf;
/*(     //RGB235 mode
         r = (256 * y            + 351 * cr) >> 8 + 16;
         g = (256 * y -  86 * cb - 179 * cr) >> 8 + 16;
         b = (256 * y + 444 * cb           ) >> 8 + 16;
*/
    const int bytesPixYUV = 2;
    int lineLength = pixLine * bytesPixYUV;
    if (aviFormat == RGB255)
    {
                 for (int yy = linesFrm-1; yy >= 0; yy--)
                 {
                    for (int xx = 0; xx <pixLine;  xx += 2)
                    {
                                 cb = inFrameBuf[(xx * 2) +     (yy * 
lineLength)] - 128;
                                 y =  inFrameBuf[(xx * 2) + 1 + (yy * 
lineLength)] - 16;
                                 cr = inFrameBuf[(xx * 2) + 2 + (yy * 
lineLength)] - 128;
                                 //RGB255 mode
                                 r = (298 * y            + 409 * cr) >> 8;
                                 g = (298 * y - 100 * cb - 208 * cr) >> 8;
                                 b = (298 * y + 516 * cb           ) >> 8;
                                 if (r > 255) r = 255;
                                 if (r < 0) r = 0;
                                 if (g > 255) g = 255;
                                 if (g < 0) g = 0;
                                 if (b > 255) b = 255;
                                 if (b < 0) b = 0;
                                 *outFrameBuf++ = (byte) b;
                                 *outFrameBuf++ = (byte) g;
                                 *outFrameBuf++ = (byte) r;
                                 y =  inFrameBuf[(xx * 2) + 3 + (yy * 
lineLength)] - 16;
                                 if (xx < pixLine -2)
                                 { // average chroma for now
                                         cb = ( cb + (inFrameBuf[(xx * 2) + 
4 + (yy * lineLength)] - 128) ) / 2;
                                         cr = ( cr + (inFrameBuf[(xx * 2) + 
6 + (yy * lineLength)] - 128) ) / 2;
                                 }
                                 //RGB255 mode
                                 r = (298 * y            + 409 * cr) >> 8;
                                 g = (298 * y - 100 * cb - 208 * cr) >> 8;
                                 b = (298 * y + 516 * cb           ) >> 8;
                                 if (r > 255) r = 255;
                                 if (r < 0) r = 0;
                                 if (g > 255) g = 255;
                                 if (g < 0) g = 0;
                                 if (b > 255) b = 255;
                                 if (b < 0) b = 0;
                                 *outFrameBuf++ = (byte) b;
                                 *outFrameBuf++ = (byte) g;
                                 *outFrameBuf++ = (byte) r;
                    }
            }
    }
    else
    {
                 for (int yy = linesFrm-1; yy >= 0; yy--)
                 {
                    for (int xx = 0; xx <pixLine; xx += 2)
                    {
                                 cb = inFrameBuf[(xx * 2) +     (yy * 
lineLength)] - 128;
                                 y =  inFrameBuf[(xx * 2) + 1 + (yy * 
lineLength)] - 16;
                                 cr = inFrameBuf[(xx * 2) + 2 + (yy * 
lineLength)] - 128;
                                 //RGB235 mode
                                 r = ((256 * y            + 351 * cr) >> 8) 
+ 16;
                                 g = ((256 * y -  86 * cb - 179 * cr) >> 8) 
+ 16;
                                 b = ((256 * y + 444 * cb           ) >> 8) 
+ 16;
                                 if (r > 255) r = 255;
                                 if (r < 0) r = 0;
                                 if (g > 255) g = 255;
                                 if (g < 0) g = 0;
                                 if (b > 255) b = 255;
                                 if (b < 0) b = 0;
                                 *outFrameBuf++ = (byte) b ;
                                 *outFrameBuf++ = (byte) g;
                                 *outFrameBuf++ = (byte) r;
                                 y =  inFrameBuf[(xx * 2) + 3 + (yy * 
lineLength)] - 16;
                                 if (xx < pixLine -2)
                                 { // average chroma for now
                                         cb = ( cb + (inFrameBuf[(xx * 2) + 
4 + (yy * lineLength)] - 128) ) / 2;
                                         cr = ( cr + (inFrameBuf[(xx * 2) + 
6 + (yy * lineLength)] - 128) ) / 2;
                                 }
                                 //RGB235 mode
                                 r = ((256 * y            + 351 * cr) >> 8) 
+ 16;
                                 g = ((256 * y -  86 * cb - 179 * cr) >> 8) 
+ 16;
                                 b = ((256 * y + 444 * cb           ) >> 8) 
+ 16;
                                 if (r > 255) r = 255;
                                 if (r < 0) r = 0;
                                 if (g > 255) g = 255;
                                 if (g < 0) g = 0;
                                 if (b > 255) b = 255;
                                 if (b < 0) b = 0;
                                 *outFrameBuf++ = (byte) b;
                                 *outFrameBuf++ = (byte) g;
                                 *outFrameBuf++ = (byte) r;
                    }
            }
    }
}
======================================
The following link shows how to do this using an Intel processor's MMX 
instructions:
http://cedar.intel.com/cgi-bin/ids.dll/content/content.jsp?cntKey=Legacy::irtm_AP548_9996&cntType=IDS_EDITORIAL&catCode=0
At 12:56 PM 1/28/2003 -0800, you wrote:
>Hi,
>
>Is there an efficient library or function that I can
>use for YUV2RGB conversion?  It seems the
>float-operation for every pixel is a very high cost
>for the rendering.
>
>Thanks in advance,
>
>Liang
>
>__________________________________________________
>Do you Yahoo!?
>Yahoo! Mail Plus - Powerful. Affordable. Sign up now.
>http://mailplus.yahoo.com
>_______________________________________________
>Technotes mailing list
>Technotes   lists.m4if.org
>http://lists.m4if.org/mailman/listinfo/technotes

Robert Bleidt   - rbleidt   hdtv.com 


More information about the Mp4-tech mailing list