了解YUV到RGB转换的此着色器

mo49yndu  于 2022-10-18  发布在  其他
关注(0)|答案(1)|浏览(258)

我正在阅读this shader用于YUV平面到RGB的转换。
它处理许多YUV格式。如您所见,它首先对yuv值执行一些操作,然后在最后执行RGB转换:

vec3 yuv;
vec4 rgba;
if(tex_format == 0 || tex_format == 1){
    if(tex_format == 0){
        yuv.r = texture2D(tex_y, textureOut).r - 0.0625;
    }else{
        yuv.r = texture2D(tex_y, textureOut).r;
    }
    yuv.g = texture2D(tex_u, textureOut).r - 0.5;
    yuv.b = texture2D(tex_v, textureOut).r - 0.5;
}else if(tex_format == 2){ // rgb
    yuv = texture2D(tex_y, textureOut).rgb;
}else if(tex_format == 3){ // gray8
    yuv.r = texture2D(tex_y, textureOut).r;
}else if(tex_format == 6){ //BGR
    yuv = texture2D(tex_y, textureOut).bgr;
}else if(tex_format == 10){//yuv420p10le yuv444p10le
    vec3 yuv_l;
    vec3 yuv_h;
    yuv_l.x = texture2D(tex_y, textureOut).r;
    yuv_h.x = texture2D(tex_y, textureOut).a;
    yuv_l.y = texture2D(tex_u, textureOut).r;
    yuv_h.y = texture2D(tex_u, textureOut).a;
    yuv_l.z = texture2D(tex_v, textureOut).r;
    yuv_h.z = texture2D(tex_v, textureOut).a;
    yuv = (yuv_l * 255.0 + yuv_h * 255.0 * 256.0) / (1023.0) - vec3(16.0 / 255.0, 0.5, 0.5);
}else if(tex_format == 8 || tex_format == 9){ //NV12 | NV21
    yuv.r = texture2D(tex_y, textureOut).r - 0.0625;
    vec4 uv = texture2D( tex_u, textureOut);
    if(tex_format == 9){ //NV21
        yuv.g = uv.a - 0.5;
        yuv.b = uv.r - 0.5;
    }else{ //NV12
        yuv.g = uv.r - 0.5;
        yuv.b = uv.a - 0.5;
    }
}else if(tex_format == 16 || tex_format == 17){ //YUV16 YUVJ16
    if(tex_format == 16){
        yuv.r = texture2D(tex_y, textureOut).r - 0.0625;
    }else{
        yuv.r = texture2D(tex_y, textureOut).r;
    }
    yuv.g = texture2D(tex_u, textureOut).r - 0.5;
    yuv.b = texture2D(tex_v, textureOut).r - 0.5;
}

if(tex_format == 0 || tex_format == 10 || tex_format == 16){//yuv | p10le | //YUV16
    rgba.r = yuv.r + 1.596 * yuv.b;
    rgba.g = yuv.r - 0.813 * yuv.b - 0.391 * yuv.g;
    rgba.b = yuv.r + 2.018 * yuv.g;
}else if(tex_format == 1 || tex_format == 17){ //yuy-jpeg || YUVJ16
    rgba.r = yuv.r + 1.402 * yuv.b;
    rgba.g = yuv.r - 0.34413 * yuv.g - 0.71414 * yuv.b;
    rgba.b = yuv.r + 1.772 * yuv.g;
}
else if(tex_format == 2){ //rgb
    rgba.rgb = yuv.rgb;
}else if(tex_format == 3){ //gray8
    rgba.r = yuv.r;
    rgba.g = yuv.r;
    rgba.b = yuv.r;
}else if(tex_format == 6){ //BGR
    rgba.r = yuv.b;
    rgba.g = yuv.g;
    rgba.b = yuv.r;
}else if(tex_format == 19){ // BGGR
    vec2 firstRed = vec2(1,1);
    rgba.r = texture2D(tex_y, textureOut).r;
    rgba.g = texture2D(tex_u, textureOut).r;
    rgba.b = texture2D(tex_v, textureOut).r;
    //        //        BGGR = 19,
    //        //        RGGB = 20 ,
    //        //        GRBG = 21 ,
    //        //        GBRG = 22 ,
}else if(tex_format == 20){ //RGGB
    vec2 firstRed = vec2(0,0);
}else if(tex_format == 21){ //GRBG
    vec2 firstRed = vec2(0,1);
}else if(tex_format == 22){ //GBRG
    vec2 firstRed = vec2(1,0);
}else if(tex_format == 23){//BGR565
    rgba.rgb = texture2D(tex_y, textureOut).bgr;
}else{ //其它
    rgba.r = yuv.r + 1.596 * yuv.b;
    rgba.g = yuv.r - 0.813 * yuv.b - 0.391 * yuv.g;
    rgba.b = yuv.r + 2.018 * yuv.g;
}
rgba.a = alpha;
if(enableHDR){
    rgba.rgb = toHDR(rgba.rgb,1.0);
}
rgba.a = alpha;
gl_FragColor = rgba;

例如,在yuv420p10le格式中,它首先执行以下操作:

vec3 yuv_l;
vec3 yuv_h;
yuv_l.x = texture2D(tex_y, textureOut).r;
yuv_h.x = texture2D(tex_y, textureOut).a;
yuv_l.y = texture2D(tex_u, textureOut).r;
yuv_h.y = texture2D(tex_u, textureOut).a;
yuv_l.z = texture2D(tex_v, textureOut).r;
yuv_h.z = texture2D(tex_v, textureOut).a;
yuv = (yuv_l * 255.0 + yuv_h * 255.0 * 256.0) / (1023.0) - vec3(16.0 / 255.0, 0.5, 0.5);

然后,对于这些yuv值,它执行以下操作:

rgba.r = yuv.r + 1.596 * yuv.b;
rgba.g = yuv.r - 0.813 * yuv.b - 0.391 * yuv.g;
rgba.b = yuv.r + 2.018 * yuv.g;

我在here上面找到了第二个转换,但我不能理解哪个是第一个转换。它在做什么?其他人呢?

kq4fsx7k

kq4fsx7k1#

第一个转换是将有限的YUV数据归一化的转换。在有限的YUV形成中,Y限制在16到240之间。如果我们用16除以256,答案是0.0625。所以,这是一个正常化的步骤。

相关问题