像英特尔®MediaSDK这样的视频编码器不接受8位灰度图像作为输入格式
8位Grayscale格式在范围[0,255]中每像素应用一个字节
在这种情况下,NV12 format是常见的输入格式
NV12格式是YUV 4:2:0格式,在内存中首先排列Y平面,然后是交错UV平面中的打包色度样本:
YYYYYY
YYYYYY
UVUVUV
灰度图像将被称为“I平面”:
IIIIII
IIIIII
设置UV平面很简单:将所有U,V元素设置为128值。
但Y飞机怎么样?
我的同事告诉我只需将“我的飞机”作为Y平面(即Y = I)
但他们错了!
在转换公式中设置R = G = B显示正确的答案是: Y = round(I * 0.859 + 16)。
使用IPP进行上述转化的有效方法是什么?
答案 0 :(得分:0)
我正在回答我自己的问题 我仍然希望看到更好的答案。
我找到了一个使用两个IPP功能的解决方案:
我选择的函数使用定点数学,以获得更好的性能。
代码示例:
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);
}
仍然希望看到更好的答案......