BT709 YUV与RGB 色彩空间的转换
主要渲染能够更加清新没有色差
CIE xyz色彩系统, 480 460这些数字表示波长,越靠近边缘饱和度越高
由于 XYZ 三基色所合成的色光是由他们的比值所决定的,可以设:
⻢蹄形的左右两边的轮廓线代表了波⻓由 380nm-700nm 连续变化的单⾊光;⻢蹄形的底边
代表了紫红⾊光。值得⼀提的是,紫红⾊光并不是单⾊光,⽽是由红⾊(700nm)和紫⾊
(380nm)混合⽽成。
D65的意思是⾊温,,6500K,嗯,冷暖屏就是从这出来的,iPhone基本会⽐6500K⾼⼀点
⽬前⼤多数显示设备所接受并使⽤的是 Rec.709(sRGB),如果⽤PhotoShop RGB的那就
范围更⼤
在⻢蹄形内部,越靠近⻢蹄形边缘的颜⾊饱和度越⾼。
常⻅的601,709的⾊彩空间,包括两种,⼀种是full range的,也就是取值范围在(0,255),⼀种
limited 是取值范围在(16,235),两种的公式有区别
⾸先看YUV转RGB,对于601 limited来说,在计算的时候
需要使⽤Y’U’V”
也就是Y’=Y-16 U’=U-128,5 V’=V-128.5
⽽对于709 imited来说
Y’=Y-0.0625 U’=U-0.5 V’=V-0.5
下列公式⾥的YUV全部是矫正后的
下列是I420与RGB的转换,411,422,444等系数(coeff)是不⼀样的,务必注意
601.6 full range
R = Y + 1.4075 * V;
G = Y - 0.3455 * U - 0.7169*V;
B = Y + 1.779 * U;
Y = 0.299R + 0.587G + 0.114B;
U = -0.169R - 0.331G + 0.5 B ;
V = 0.5 R - 0.419G - 0.081B;
注意,601的的full range不需要做矫正
601.6 的limitied (展开后)
yuv --> rgb
R = 1.164Y + 1.596 * V - 222.9
G = 1.164Y - 0.392 * U - 0.823 * V+ 135.6
B = 1.164Y + 2.017 * U- 276.8
rgb --> yuv
Y = 0.257R’ + 0.504G’ + 0.098B’ + 16
U = -0.148R’ - 0.291G’ + 0.439B’ + 128.5
V = 0.439R’ - 0.368G’ - 0.071*B’ + 128.5
709limited(video range)(未把矫正后的数据带⼊展开)
Y = 16 + 0.183 * R + 0.614 * g + 0.062 * b
U = 128.5 - 0.101 * R - 0.339 * g + 0.439 * b
V = 128.5 + 0.439 * R - 0.399 * g - 0.040 * b
R = 1.164 *Y + 1.792 *V
G = 1.164 *Y - 0.213 *U- 0.534 *V
B = 1.164 *Y + 2.114 U
709full range 没找到
另外,由于浮点数计算的速度没有定点数快,所以在neon汇编优化的时候,会将系数定点化计算,
最后通过位移计算再转回来
在libyuv⾥,由于其RGBA与我们常⻅的RGBA是反的,所以我们使⽤的是libyuv的ABGRToI420
android使⽤的是armv7a,iOS使⽤的是arm64
所以对应的android要改row_neon.cc,iOS需要改row_neon64.cc
由于浮点数计算的速度没有定点数快,所以在neon汇编优化的时候,会将系数定点化计算,最后通
过位移计算再转回来
以709 limited(video range)为例
Y = (4096 + 46 * R + 157 * g + 16 * b )/256
U = (32896 - 26 * R - 87 * g + 112 * b)/256
V = (32896 + 112 * R - 102 * g - 10 b)/256
row_neon.cc⾥,对UV的量化使⽤的是256量化的,对Y使⽤的是128
所以,我们看到的系数变成了23,79,8,并且其没有对16定电话,使⽤的还是16,具体原因我看
了代码也没想明⽩,显⽽易⻅的是32896可以⽤0x8080表示,也就是128.5*256
⽽在row_neon64⾥⾯,YUV的量化系数都是⽤128做的,原因我也没想明⽩
原⽣的CPUImage与libyuv都是使⽤默认的601的⾊彩空间,
libyuv的ABGRToYRow_neon和ABGRToUVRow_neon 已经修改为709 video range的⾊彩空间,把YUV转成纹理时也是使⽤的709 video range的系数
这里改OpenGL的shader,遇到这种问题这样这样解决处理,TB601标准转化的色差