w3c / ColorWeb-CG

repo for the Color on the Web Community Group
47 stars 21 forks source link

Incorrect TTML Conversions #104

Closed simontWork closed 8 months ago

simontWork commented 11 months ago

The linked TTML conversions were designed for subtitles - i.e. to maintain enough separation between a small number of colours to be visibly different.

The equations there are not colour accurate.

palemieux commented 11 months ago

Can you suggest an alternatives?

simontWork commented 10 months ago

Would prefer to put a code snippet in that implements the ITU conversions. It simplifies as the OOTF adjustment just happens to be unity at 80 cd/m2.

simontWork commented 10 months ago

Further on the TTML conversion, the important design limitation was to be able to undertake the transform in the graphics plane of a television. I don't think either of the TTML conversions are colour accurate.

simontWork commented 10 months ago

Could we use the following from a previous commit

Conversion from sRGB to HLG

Process:

  1. Linearize using the sRGB EOTF
  2. Convert from srgb color space to rec2100-hlg color space
  3. Scale pixel values - See Note 1
  4. Apply HLG Inverse EOTF to convert to HLG from Pseudo-Display Light with Lw = 302 cd/m2 - See Note 1
    • apply HLG Inverse OOTF
    • apply HLG OETF - See Note 2

Note 1: As rec2100-hlg is a relative format, the brightness of the virtual monitor used for mathematical transforms can be chosen to be any level. In this transform it is chosen to be 302 cd/m2 so that the brightness of diffuse white matches the diffuse white of sRGB (80 cd/m2). Using the extended range gamma formula in footnote 2 of BT.2100, this also sets the HLG Inverse OOTF to be unity. The value 0.265 is calculated by taking the inverse OETF of 0.75, the rec2100-hlg diffuse white level.

Note 2: See section 5.3 in ITU-R BT.2408-4 relating to negative transfer functions in format conversions.

function convertSRGBtoREC2100HLG(r, g, b) {
  const systemGamma = 1.0;
  const linearLightScaler = 0.26496256042100724;

  const r1 = srgb_eotf(r);
  const g1 = srgb_eotf(g);
  const b1 = srgb_eotf(b);

  const [r2, g2, b2] = matrixXYZtoBT2020(matrixSRGBtoXYZ(r1,g1,b1));

  const r3 = linearLightScaler * r2;
  const g3 = linearLightScaler * g2;
  const b3 = linearLightScaler * b2;

  const [r4, g4, b4] = hlg_inverse_ootf(r3, g3, b3, systemGamma);  // Can be removed, included for completeness
  const [r5, g5, b5] = hlg_oetf(r4, g4, b4);

  return [r5, g5, b5]
}
palemieux commented 9 months ago

@simontWork

See #107. Step (4) did not have matching lines in the pseudocode and it is not clear the relevance of Lw.