c++rgbyuvlibavswscale

sws_scale, YUV to RGB conversion


I need convert YUV to RGB. I also need the RGB values to be in the limited range (16-235). I try to use sws_scale function for this task.

My code you can see below. But after conversion I got the black pixel is (0, 0, 0) instead of (16, 16, 16).

Maybe there are some options to tell sws_scale function to calculate the limited range.

AVFrame* frameRGB = avFrameConvertPixelFormat(_decodedBuffer[i].pAVFrame, AV_PIX_FMT_RGB24);
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;
}

Also I tried convert YUV pixel to RGB pixel manualy with formula and I got correct result. From YUV (16, 128, 128) I got (16, 16, 16) in RGB.

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

Solution

  • You may the source format to "full scale" YUVJ.

    As far as I know, sws_scale has no option for selecting Studio RGB as output format.
    Changing the input format is the best solution I can think of.

    The color conversion formula of "JPEG: YUV -> RGB" is the same as the formula in your post.

    Examples for setting the source format:

    I know the solution is not covering all the possibilists, and there might be some output pixels exceeding the range of [16, 235], so it's not the most general solution...