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;



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



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):



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:






- Code snippet:
// set task basics
memset( &ipuTask, 0, sizeof(ipuTask) );
ipuTask.input.width = inW;
ipuTask.input.height = inH;
ipuTask.input.format = inFmt;
ipuTask.output.width = outW;
ipuTask.output.height = outH;
ipuTask.output.format = outFmt;
// get image file and check for failure
// compute input size in bytes
iInputSize = ipuTask.input.width * ipuTask.input.height *
computeBPP( ipuTask.input.format ) / 8;
// set the amount of memory needed for the task input
ipuTask.input.paddr = iInputSize;
// allocate memory for the input image and check for failure
// (NOTE: input.paddr will be replaced with the physical address)
iRetValue = ioctl( iIPUFD, IPU_ALLOC, &ipuTask.input.paddr );
if( iRetValue < 0 )
{
perror( "ioctl(IPU_ALLOC)" );
Cleanup();
return iRetValue;
}
// map virtual address to input memory
pInputBuff = mmap( 0, iInputSize, PROT_READ | PROT_WRITE,
MAP_SHARED, iIPUFD, ipuTask.input.paddr );
if( !pInputBuff || pInputBuff == MAP_FAILED )
{
perror( "mmap" );
Cleanup();
return -1;
}
// compute output size in bytes
iOutputSize = ipuTask.output.width * ipuTask.output.height *
computeBPP( ipuTask.output.format ) / 8;
// set the amount of memory needed for the task output
ipuTask.output.paddr = iOutputSize;
// allocate memory for the output image and check for failure
// (NOTE: output.paddr will be replaced with the physical address)
iRetValue = ioctl( iIPUFD, IPU_ALLOC, &ipuTask.output.paddr );
if( iRetValue < 0 )
{
perror( "ioctl(IPU_ALLOC)" );
Cleanup();
return iRetValue;
}
// map virtual address to output memory
pOutputBuff = mmap( 0, iOutputSize, PROT_READ | PROT_WRITE,
MAP_SHARED, iIPUFD, ipuTask.output.paddr );
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;
}
// read input image
iRetValue = fread( pInputBuff, 1, iInputSize, fInput );
if( iRetValue < iInputSize )
{
perror( "fread" );
Cleanup();
return -1;
}
// execute the IPU task and check for failure
iRetValue = ioctl( iIPUFD, IPU_QUEUE_TASK, &ipuTask );