We recently faced the problem of RGB → YUV conversion described on (OpenCV mat to NvJPEGEncoder jpg limited range)
As the thread shows, OpenCV conversion abides to the I420 convention, which constrains the pixel intensities Y (16 to 235) and UV (16 to 240).
LibYUV (libyuv/libyuv - Git at Google) can be used as a safe way to convert a RGB CvMat to NvBuffer.
Given that the parameters were properly allocated, the function libyuv::RGB24ToJ420 can be used to perform the conversion.
bool convertRGBtoYUV(const cv::Mat& rgb, NvBuffer& nvbuf)
{
NvBuffer::NvBufferPlane &planeY = nvbuf.planes[0];
NvBuffer::NvBufferPlane &planeU = nvbuf.planes[1];
NvBuffer::NvBufferPlane &planeV = nvbuf.planes[2];
const int strideY = planeY.fmt.stride;
const int strideU = planeU.fmt.stride;
const int strideV = planeV.fmt.stride;
uint8_t* dst_y = planeY.data;
uint8_t* dst_u = planeU.data;
uint8_t* dst_v = planeV.data;
return libyuv::RGB24ToJ420(rgb.data,
rgb.step,
dst_y,
strideY,
dst_u,
strideU,
dst_v,
strideV,
rgb.cols,
rgb.rows);
}
Differently from I420, RGB → J420 conversion leads to images that use the full 0 to 255 intensity range.
So, when the NvBuffer is used as argument of the method encodeFromBuffer, the JPEG will be encoded with the full intensity range.
Cheers,
Diego Carvalho - Fugro (http://fugro.com/)