YUV422->RGB24 - which conversion formula does IPU use?

Question asked by Smriti Verma on Jul 30, 2014
Latest reply on Jul 30, 2014 by Yuri Muhin

Hi,

I created a 800x600 RGB24 buffer filled with 0x80 i.e; (R, G, B) =  (128, 128, 128) or 0x808080 . I then use  IPU to convert RGB24->YUV422 (see below for the code snippet). As expected the resultant buffer has YUV= 0x808080.

Converting back to RGB24, however, has unexpected result. The resulting RGB buffer has (R, G, B) =  (130, 128, 127) or 0x82807F.

Which conversion does IPU apply?

Based on Wikipedia's YUV page, RGB should either be 0x808080 (ITU-R version) or 0x828282 (if IPU assumes YCbCr format for YUV->RGB conversion).

Any input is greatly appreciated.

Thanks!

YUV - Wikipedia, the free encyclopedia

Excerpt from Wikipedia:

These formulae are based on the NTSC standard;

$Y' = 0.299 \times R + 0.587 \times G + 0.114 \times B$
$U = -0.147 \times R - 0.289 \times G + 0.436 \times B$
$V = 0.615 \times R - 0.515 \times G - 0.100 \times B$

On older, non-SIMD architectures, floating point arithmetic is much slower than using fixed-point arithmetic, so an alternative formulation is:

$C = Y' - 16$
$D = U - 128$
$E = V - 128$

Using the previous coefficients and noting that clamp() denotes clamping a value to the range of 0 to 255, the following formulae provide the conversion from Y'UV to RGB (NTSC version):

$R = \mathrm{clamp}(( 298 \times C + 409 \times E + 128) >> 8)$
$G = \mathrm{clamp}(( 298 \times C - 100 \times D - 208 \times E + 128) >> 8)$
$B = \mathrm{clamp}(( 298 \times C + 516 \times D + 128) >> 8)$

Note: The above formulae are actually implied for YCbCr. Though the term YUV is used here, it should be noted that YUV and YCbCr are not exactly the same in a strict manner.

The ITU-R version of the formulae is different:

$Y = 0.299 \times R + 0.587 \times G + 0.114 \times B + 0$
$Cb = -0.169 \times R - 0.331 \times G + 0.499 \times B + 128$
$Cr = 0.499 \times R - 0.418 \times G - 0.0813 \times B + 128$
$R = \mathrm{clamp}(Y + 1.402 \times (Cr - 128))$
$G = \mathrm{clamp}(Y - 0.344 \times (Cb - 128) - 0.714 \times (Cr - 128))$
$B = \mathrm{clamp}(Y + 1.772 \times (Cb - 128))$
Code snippet:

// get image file and check for failure

// compute input size in bytes

// set the amount of memory needed for the task input

// allocate memory for the input image and check for failure

if( iRetValue < 0 )

{

perror( "ioctl(IPU_ALLOC)" );

Cleanup();

return iRetValue;

}

// map virtual address to input memory

pInputBuff = mmap( 0, iInputSize, PROT_READ | PROT_WRITE,

if( !pInputBuff || pInputBuff == MAP_FAILED )

{

perror( "mmap" );

Cleanup();

return -1;

}

// compute output size in bytes

// set the amount of memory needed for the task output

// allocate memory for the output image and check for failure

if( iRetValue < 0 )

{

perror( "ioctl(IPU_ALLOC)" );

Cleanup();

return iRetValue;

}

// map virtual address to output memory

pOutputBuff = mmap( 0, iOutputSize, PROT_READ | PROT_WRITE,

if( !pOutputBuff || pOutputBuff == MAP_FAILED )

{

perror( "mmap" );

Cleanup();

return -1;

}

// get output file and check for failure

fOutput = fopen( outName.c_str(), "wb" );

if( fOutput < 0 )

{

cerr << "failed to open " << outName.c_str() << endl;

Cleanup();

return -1;

}

iRetValue = fread( pInputBuff, 1, iInputSize, fInput );

if( iRetValue < iInputSize )

{

Cleanup();

return -1;

}

// execute the IPU task and check for failure