C++ sws_标度,YUV到RGB转换

C++ sws_标度,YUV到RGB转换,c++,rgb,yuv,libav,swscale,C++,Rgb,Yuv,Libav,Swscale,我需要将YUV转换为RGB。我还需要RGB值在有限范围内(16-235)。 我尝试使用sws_比例函数来完成此任务 你可以在下面看到我的代码。但在转换后,我得到的黑色像素是(0,0,0),而不是(16,16,16) 也许有一些选项可以告诉sws_比例函数来计算限制范围 AVFrame* frameRGB = avFrameConvertPixelFormat(_decodedBuffer[i].pAVFrame, AV_PIX_FMT_RGB24); 此外,我还尝试了转换YUV像素到RGB像素

我需要将YUV转换为RGB。我还需要RGB值在有限范围内(16-235)。 我尝试使用sws_比例函数来完成此任务

你可以在下面看到我的代码。但在转换后,我得到的黑色像素是(0,0,0),而不是(16,16,16)

也许有一些选项可以告诉sws_比例函数来计算限制范围

AVFrame* frameRGB = avFrameConvertPixelFormat(_decodedBuffer[i].pAVFrame, AV_PIX_FMT_RGB24);
此外,我还尝试了转换YUV像素到RGB像素手动公式,我得到了正确的结果。从YUV(16,128,128)我得到了RGB中的(16,16,16)


您可以将源格式设置为“满刻度”YUVJ

据我所知,sws_scale没有选择作为输出格式的选项。
更改输入格式是我能想到的最好的解决方案

“JPEG:YUV->RGB”的颜色转换与文章中的公式相同

设置源格式的示例:

  • 如果
    src->format
    PIX\u FMT\u YUV420P
    ,则将格式设置为
    PIX\u FMT\u YUVJ420P
  • 如果
    src->format
    PIX\u FMT\u YUV422P
    ,则将格式设置为
    PIX\u FMT\u YUVJ422P
  • 如果
    src->format
    PIX\u FMT\u YUV444P
    ,则将格式设置为
    PIX\u FMT\u YUVJ444P
  • 如果
    PIX\u FMT\u YUV440P
    ,请使用
    PIX\u FMT\u YUV440P

我知道解决方案没有覆盖所有可能列表,并且可能有一些输出像素超出了[16235]的范围,因此这不是最通用的解决方案…

Hello@Rotem,谢谢!这个解决方案似乎对我有效。你能解释一下为什么这个解决方案是有效的吗?它基于什么原则?似乎“AV_PIX_FMT_YUVJ420P”被弃用了“平面YUV4:2:0,12bpp,满标度(JPEG),弃用了AV_PIX_FMT_YUV420P和设置颜色范围”,正如我在我的帖子中提到的,我的解决方案基于你的问题中的转换公式。该公式与JPEG YUV转换(在维基百科中描述)相同。
YUVJ
J
字母应用JPEG转换(JPEG使用全范围YUV,而不是普通的视频转换公式,Y仅限于[16235])。我的解决方案并不理想,部分原因是“AV_PIX_FMT_YUVJ420P”已被弃用。我想你最好用。将
srcRange
设置为
1
。可能有一个更好的解决方案(注意:我从未直接使用sws_scale-只使用FFmpeg命令行)。请发布您找到的解决方案。谢谢回复。我懂你。我接受你的回答作为解决办法。这肯定是可行的,但也许我会尝试手动将公式YUV转换为RGB对话(适用于主要标准BT.601、BT.709和BT.2020,以及8、10和12位深度),以获得更多控制。我遇到了一个有趣的文档,其中以可以理解的形式描述了这些公式的结论
AVFrame* Decoder::avFrameConvertPixelFormat(const AVFrame* src, AVPixelFormat dstFormat) {
    int width = src->width;
    int height = src->height;

    AVFrame* dst = allocPicture(dstFormat, width, height);

    SwsContext* conversion = sws_getContext(width,
                                            height,
                                            (AVPixelFormat)src->format,
                                            width,
                                            height,
                                            dstFormat,
                                            SWS_FAST_BILINEAR,
                                            NULL,
                                            NULL,
                                            NULL);
    sws_scale(conversion, src->data, src->linesize, 0, height, dst->data, dst->linesize);
    sws_freeContext(conversion);

    dst->format = dstFormat;
    dst->width = src->width;
    dst->height = src->height;

    return dst;
}
cmpR = y + 1.402 * (v - 128);
cmpG = y - 0.3441 * (u - 128) - 0.7141 * (v - 128);
cmpB = y + 1.772 * (u - 128);