如何使用IPP将8位灰度图像转换为NV12色彩空间

时间:2016-06-22 21:22:05

标签: c grayscale yuv intel-ipp

像英特尔®MediaSDK这样的视频编码器不接受8位灰度图像作为输入格式 8位Grayscale格式在范围[0,255]中每像素应用一个字节 在这种情况下,NV12 format是常见的输入格式 NV12格式是YUV 4:2:0格式,在内存中首先排列Y平面,然后是交错UV平面中的打包色度样本:
YYYYYY
YYYYYY
UVUVUV

enter image description here

灰度图像将被称为“I平面”:
IIIIII
IIIIII

enter image description here

设置UV平面很简单:将所有U,V元素设置为128值。

但Y飞机怎么样?

我的同事告诉我只需将“我的飞机”作为Y平面(即Y = I) 但他们错了!
在转换公式中设置R = G = B显示正确的答案是: Y = round(I * 0.859 + 16)。

使用IPP进行上述转化的有效方法是什么?

1 个答案:

答案 0 :(得分:0)

我正在回答我自己的问题 我仍然希望看到更好的答案。

我找到了一个使用两个IPP功能的解决方案:

我选择的函数使用定点数学,以获得更好的性能。

  • 通过扩展,缩放和移位来执行0.859缩放的定点实现。示例:b =(a *标度+(1 <&lt; 7))&gt;&gt; 8; [当比例=(0.859)* 2 ^ 8]。
    “val”参数将ippsMulC_8u_Sfs设置为round(0.859 * 2 ^ 8)= 220.
    ippsMulC_8u_Sfs的“scaleFactor”参数设置为8(将缩放结果除以2 ^ 8)。

代码示例:

void GrayscaleToNV12(const unsigned char I[],
                     int image_width,
                     int image_height,
                     unsigned char J[])
{
    IppStatus ipp_status;
    const int image_size = image_width*image_height;

    unsigned char *UV = &J[image_size]; //In NV12 format, UV plane starts below Y.

    const Ipp8u expanded_scaling = (Ipp8u)(0.859 * 256.0 + 0.5);

    //J[x] = (expanded_scaling * I[x] + 128u) >> 8u;
    ipp_status = ippsMulC_8u_Sfs(I,                 //const Ipp8u* pSrc,
                                 expanded_scaling,  //Ipp8u val,
                                 J,                 //Ipp8u* pDst,
                                 image_size,        //int len,
                                 8);                //int scaleFactor);

    //Check ipp_status, and handle errors...

    //J[x] += 16;
    //ippsAddC_8u_ISfs is deprecated, I used it to keep the code simple.
    ipp_status = ippsAddC_8u_ISfs(16,           //Ipp8u val, 
                                  J,            //Ipp8u* pSrcDst, 
                                  image_size,   //int len, 
                                  0);           //int scaleFactor);

    //Check ipp_status, and handle errors...

    //2. Fill all UV plane with 128 value - "gray color".
    memset(UV, 128, image_width*image_height/2);
}

仍然希望看到更好的答案......