How to correctly convert colors saved as Y'CrCb (using reference 709) to sRGB?
I am working with HDTV video and I am extracting raw data using libavcodec. Although I managed to make the conversion, I’m still not sure if I’m doing it right. VLC provides one result, converting to Gimp using "compose" results in another, and using code from the Internet is also incompatible. Therefore, I did not find a reliable link for comparison.
My research and current best rates are lower. (Values are in a floating point with a range of 0.0-1.0) I most doubt the gamma correction. This makes it a little easier than I expected, but I can’t say that it looks wrong ...
Studio swing removal
Y 'is between 16 and 235 for 8-bits. Cr and Cb ranges from 16 to 240 and is centered at 128.
y = (y - (16 / 255.0)) * ( 1 + 16.0 / 255.0 + (256-235) / 255.0 ); u = (u - (16 / 255.0)) * ( 1 + 16.0 / 255.0 + (256-240) / 255.0 ); v = (v - (16 / 255.0)) * ( 1 + 16.0 / 255.0 + (256-240) / 255.0 ); //Move chroma u -= 0.5; v -= 0.5;
I'm not sure if you can assume that you will never get values out of ranges, or if you need to pinch it.
For higher bit depths, the specification says that LSBs are ignored. What does it mean? I also work with material encoded in 10-bit, so that interests me.
Y'CrCb to RGB
Recommendation. 709 indicates how to convert RGB to Y'CrCb:
E'y = 0.2126 * E'r + 0.7152 * E'g + 0.0722 * E'b E'cb = 0.5389 * ( E'b - E'y ) E'cr = 0.6350 * ( E'r - E'y )
Wikipedia gives what seems like a slightly more precise definition for Cb and Cr:
Pb = 0.5 * (B' - Y') / (1 - Kb) Pr = 0.5 * (R' - Y') / (1 - Kr)
where Kb and Kr are factors for E'b and E'r. Values from the specification. turns out to be rounded off these equations.
RGB can be found by changing the equations (using the Wikipedia version):
double r = y + 2*(1.0-kr) * v; double b = y + 2*(1.0-kb) * u; double g = ( y - kr * rr - kb*rb ) / kg;
G can be performed directly with Cr and Cb:
double g = y - 2*kr*(1-kr)/kg * v - 2*kb*(1-kb)/kg * u;
(The coefficient for y is (1-kr-kb) / kg, which kg / kg at kr + kb + kg = 1)
RGB for sRGB
I have not seen code examples, including this step at all. We need to convert the color space specified in rec. 709 to that specified in sRGB. AFAIK, the only difference between the two is the transfer function (i.e. Gamma). XY coordinates specified in rec. 709 corresponds to sRGB, but I do not know why sRGB includes the "Z" coordinate during rec. 709 no. Does it matter? (I don't know anything about CIE XYZ.)
Recommendation. 709 indicates how to use linear RGB gamma coding:
V = 1.099 * L^0.45 - 0.099 for 1 >= L >= 0.018 V = 4.500 * L for 0.018 > L >= 0
We need to cancel it, however a linear cutoff of 0.018 does not give the same value for V in both equations. So what are the ranges for the reverse version ?:
L = ( ( V + 0.099 ) / 1.099 ) ^ (1/0.45) for 1 >= V >= ? L = V / 4.5000 for ? > V >= 0
sRGB had the same problem, but was changed to 0.0031308, which is more accurate. I remember that someone developed a fraction that accurately represented it for sRGB, but I cannot find it again ...
I am currently using the following:
double cutoff = 1.099 * pow( 0.018, 0.45 ) - 0.099; v = ( v < cutoff ) ? 1.0/4.5 * v : pow( (v+0.099)/1.099, 1.0/0.45 ); v = ( v <= 0.0031308 ) ? 12.92 * v : 1.055*pow( v, 1.0/2.4 ) - 0.055;