Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Correct conversion from rec. 709 to sRGB

How do I correctly convert colors stored as Y'CrCb (using rec. 709) to sRGB?

I'm working with HDTV video and I'm extracting the raw data using libavcodec. While I have succeeded in making the conversion, I have yet to be confident that I'm doing it correctly. VLC provides one result, converting in Gimp using 'compose' results in another and using code from the web is not consistent either. So I haven't found a reliable reference to compare to.

My research and current best bet is below. (Values are in floating-point with the range 0.0-1.0) What I'm most uncertain about is the gamma-correction. It makes it a bit lighter than I would expect, but I can't say it looks wrong either...

Studio-swing removal

Y' ranges from 16 to 235 for 8-bit. Cr and Cb ranges from 16 to 240, and centers on 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 it is safe to assume that you will never get values outside the ranges, or if you need to clamp it.

For higher bit-depths the spec says that the LSBs are ignored. What does that mean? I'm also working with material encoded in 10-bit, so this is of interest to me.

From Y'CrCb to RGB

The rec. 709 specification tells 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 provides what appears to be a slightly more accurate definition for Cb and Cr:

Pb = 0.5 * (B' - Y') / (1 - Kb)
Pr = 0.5 * (R' - Y') / (1 - Kr)

where Kb and Kr are the factors for E'b and E'r. The values from the spec. appears to be rounded from these equations.

RGB can be found by reversing the equations (using 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 done using Cr and Cb directly:

double g = y - 2*kr*(1-kr)/kg * v - 2*kb*(1-kb)/kg * u;

(The factor for y is (1-kr-kb)/kg, which is kg/kg as kr+kb+kg=1)

RGB to sRGB

I haven't seen any code examples including this step at all. We need to convert the color space specified by rec. 709 to the one specified in sRGB. AFAIK, the only difference between the two is the transfer function (i.e. gamma). The XY coordinates specified by rec. 709 matches sRGB, but I don't know why sRGB includes the 'Z' coordinate while rec. 709 does not. Does this make a difference? (I know nothing about CIE XYZ.)

The rec. 709 specifies how to gamma-encode linear RGB:

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 reverse it, however the linear cutoff 0.018 does not give the same value for V in both equations. So what are the ranges for the reversed version?:

L = ( ( V + 0.099 ) / 1.099 ) ^ (1/0.45)    for  1 >= V >= ?
L = V / 4.5000                              for  ? >  V >= 0

sRGB had the same issue, but was revised to be 0.0031308 which is more accurate. I remember someone devised a fraction which precisely represented it for sRGB, but I cannot find it again...

I'm 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;
like image 737
Sebastian Wahl Avatar asked Jul 08 '13 21:07

Sebastian Wahl


People also ask

Is Rec 709 the same as sRGB?

709 is the standard camera encoding color space for HDTV with a gamut identical to sRGB. As previously stated, sRGB and Rec. 709 primaries share the same chromaticity values (and therefore the same gamut).

What is a REC 709 conversion?

So think of REC. 709 as this: A common language between your camera and your display. So your camera captures a log footage, then it comes in and gets stretched out and gets converted to a semi-linear conversion and what you say is “presentable.”

What is the white point of Rec 709?

For high definition environment, ITU-R Recommendation BT. 709 defines both encoding and color transformation coefficients. The chromaticity coordinates of the primaries are identical to those defined in sRGB standard. The white point is also D65.

Is sRGB better than BT 709?

The difference between both colour space options is simply down to contrast, with BT. 709 providing darker shadows while sRGB provides brighter dark sections but provides users with a clearer end image, with some details being easier to perceive.


1 Answers

For correct transformation from linear sRGB to non-linear sRGB (companding process) and the reverse process (inverse companding), I use the following functions:

public double Companding(double channel)
{
    double v = channel;
    double V = v <= 0.0031308 ? 12.92 * v : 1.055 * Math.Pow(v, 1 / 2.4d) - 0.055;
    return V;
}

public double InverseCompanding(double channel)
{
    double V = channel;
    double v = V <= 0.04045 ? V / 12.92 : Math.Pow((V + 0.055) / 1.055, 2.4);
    return v;
}

Note: v is linear, V is non-linear.

These functions are based on an equation found here: http://www.brucelindbloom.com/index.html?Eqn_RGB_to_XYZ.html

There is also an option to use simplified sRGB with companding function v = V ^ gamma, where gamma is 2.2, as noted on the website.

like image 164
Tom Pažourek Avatar answered Sep 21 '22 06:09

Tom Pažourek