冰法昨天修复了Vive Media Decoder解析mp4图像颜色错误的问题,并且写了博客。
读了一下,有几点补充说明,因为我喜欢把数算一遍,以确定其正确性。
主要内容在这几个公式上
将ycbcr重新映射到全范围0-255: y=(255/(235-16))*(y-16) cb=(255/(240-16))*(cb-16) cr=(255/(240-16))*(cr-16) 根据u和v的取值范围,将ycbcr映射到yuv(整数): y=y u=0.872*(cb-128) v=1.230*(cr-128) 应用矩阵叉乘展开: r=y+1.28033*v g=y-0.21482*u-0.38059*v b=y+2.12798*u 整合公式: r=(255/(235-16))*(y-16)+(255/(240-16))*1.28033*(1.230*(cr-128)) g=(255/(235-16))*(y-16)-(255/(240-16))*0.21482*(0.872*(cb-128))-(255/(240-16))*0.38059*(1.230*(cr-128)) b=(255/(235-16))*(y-16)+(255/(240-16))*2.12798*(0.872*(cb-128))
这些公式对应的是RGB888格式的,其中
y=y u=0.872*(cb-128) v=1.230*(cr-128)
这个系数的由来是这里
https://en.wikipedia.org/wiki/YUV#Numerical_approximations
也就是
umax = 0.436 vmax = 0.615 y = [0, 1] u = [-umax, umax] v = [-vmax, vmax] rangeY = 1 - 0 = 1 rangeU = umax - (-umax) = 2 * umax = 0.872 rangeV = vmax - (-vmax) = 2 * vmax = 1.230
YUV转RGB,应用BT.709矩阵
应用矩阵叉乘展开: r=y+1.28033*v g=y-0.21482*u-0.38059*v b=y+2.12798*u
r = 1 * y + 0 * u + 1.28033 * v g = 1 * y - 0.21482 * u - 0.38059 * v b = 1 * y + 2.12798 * u + 0 * v
然后就是单纯的算数展开与合并
r=(255/(235-16))*(y-16)+(255/(240-16))*1.28033*(1.230*(cr-128)) g=(255/(235-16))*(y-16)-(255/(240-16))*0.21482*(0.872*(cb-128))-(255/(240-16))*0.38059*(1.230*(cr-128)) b=(255/(235-16))*(y-16)+(255/(240-16))*2.12798*(0.872*(cb-128))
定义个变量简化一下
float facY = (255/(235-16)) = 1.1643835616438356164383561643836 float facCBCR = (255/(240-16)) = 1.1383928571428571428571428571429
于是上式可以写为
r = facY * (y-16) + facCBCR * 1.28033 * (1.230*(cr-128)) g = facY * (y-16) - facCBCR * 0.21482 * (0.872*(cb-128)) - facCBCR * 0.38059 * (1.230*(cr-128)) b = facY * (y-16) + facCBCR* 2.12798 * (0.872*(cb-128))
因为目前是RGB888,范围是[0-255],变成Shader范围是[0,1],所以
y-16要变成y-0.0627451
cb-128要变成cb-0.5019608
因为
16/255 = 0.062745098039215686274509803921569 约 0.0627451
128/255 = 0.50196078431372549019607843137255 约 0.5019608
接着替换
r = facY * (y-0.0627451) + facCBCR * 1.28033 * (1.230*(cr-0.5019608)) g = facY * (y-0.0627451) - facCBCR * 0.21482 * (0.872*(cb-0.5019608)) - facCBCR * 0.38059 * (1.230*(cr-0.5019608)) b = facY * (y-0.0627451) + facCBCR * 2.12798 * (0.872*(cb-0.5019608))
合并常量
facCBCR * 1.28033 * 1.230 = 1.792748 facCBCR * 0.21482 * 0.872 = 0.2132472 facCBCR * 0.38059 * 1.230 = 0.5329109 facCBCR* 2.12798 * 0.872 = 2.1124
最后rgb结果近似为
r = 1.164384 * (y-0.0627451) + 1.792748 * (cr-0.5019608) g = 1.164384 * (y-0.0627451) - 0.2132472 * (cb-0.5019608) - 0.5329109 * (cr-0.5019608) b = 1.164384 * (y-0.0627451) + 2.1124 * (cb-0.5019608)