tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

clli-mdcv-png.html (5060B)


      1 <!DOCTYPE HTML>
      2 <script src="/resources/testharness.js"></script>
      3 <script src="/resources/testharnessreport.js"></script>
      4 <script>
      5 // Render serveral equivalent ISO 21496-1 gainmap images with various values for
      6 // globalHdrHeadroom.
      7 // The test images used by this test have an SDR representation (at headroom 0)
      8 // with pixel values in sRGB of:
      9 //     #C08040, #8040C0, #40C080, #FFFFFF
     10 // They have an HDR representation (at headroom 1) with pixel values in sRGB of
     11 //     #40C080, #C08040,  #8040C0 color(srgb 0x17F/0xFF, 0x17F/0xFF, 0x17F/0xFF)
     12 // The test images vary in:
     13 //  * Some have SDR as the base image (encoded as sRGB) and some have HDR as the
     14 //    base image (encoded as Rec2100 PQ or Rec2100 HLG).
     15 //  * Some use sRGB as the gain application primaries, others use Rec2020
     16 // The tests that use a Rec2100 PQ or HLG base are allowed a higher amount of
     17 // error because of the brutal quantization error in those spaces.
     18 const tests = [
     19  {
     20    filename:'pq-clli_none-mdcv_none.png',
     21    desc:'No CLLI or MDCV',
     22    max_linear_value:1000/203,
     23  },
     24  {
     25    filename:'pq-clli_100-mdcv_p3_5000.png',
     26    desc:'CLLI 100, MDCV 5000',
     27    max_linear_value:203/203,
     28  },
     29  {
     30    filename:'pq-clli_500-mdcv_none.png',
     31    desc:'CLLI 500',
     32    max_linear_value:500/203,
     33  },
     34  {
     35    filename:'pq-clli_none-mdcv_rec2020_5000.png',
     36    desc:'MDCV 5000',
     37    max_linear_value:5000/203,
     38  },
     39 ];
     40 for (const test of tests) {
     41  promise_test(async () => {
     42    filename = test.filename;
     43    const canvas = new OffscreenCanvas(40, 40);
     44    const ctx = canvas.getContext('2d', {colorType:'float16'});
     45    if (ctx.globalHDRHeadroom === undefined) {
     46      return;
     47    }
     48 
     49    const pixelLinearValues = [
     50      100/203,
     51      500/203,
     52      1000/203,
     53      5000/203,
     54    ];
     55    const globalHDRHeadroomValues = [
     56      0,        // log2(1)
     57      1.3045,   // log2(500/203)
     58      4.6224,   // log2(5000/203)
     59      Infinity,
     60    ];
     61    const globalHDRHeadroomLinear = [
     62      203/203,
     63      500/203,
     64      5000/203,
     65      Infinity,
     66    ];
     67 
     68    // Draw the image at the specified headrooms.
     69    const image = new Image;
     70    image.src = 'resources/' + filename;
     71    await new Promise(resolve => image.onload = resolve);
     72    for (let hdrHeadroomIndex = 0; hdrHeadroomIndex < 4; ++hdrHeadroomIndex) {
     73      ctx.globalHDRHeadroom = globalHDRHeadroomValues[hdrHeadroomIndex];
     74      ctx.drawImage(image, 0, 10*hdrHeadroomIndex);
     75    }
     76 
     77    // Read back a pixel in each solid color region.
     78    for (let hdrHeadroomIndex = 0; hdrHeadroomIndex < 4; ++hdrHeadroomIndex) {
     79      for (let pixelIndex = 0; pixelIndex < 4; ++pixelIndex) {
     80        const name = 'globalHDRHeadroom: ' +
     81                     globalHDRHeadroomValues[hdrHeadroomIndex] +
     82                     ', hdrHeadroomIndex:' +
     83                     hdrHeadroomIndex;
     84        const data = ctx.getImageData(
     85            5 + 10*pixelIndex, 5 + 10*hdrHeadroomIndex, 1, 1,
     86            {colorSpace:'rec2100-linear', pixelFormat:'rgba-float16'});
     87        if (test.max_linear_value <= globalHDRHeadroomLinear[hdrHeadroomIndex]) {
     88          // If the test image's (max nits)/203 is <= exp2(globalHDRHeadroom),
     89          // then no tone mapping is performed.
     90          if (pixelLinearValues[pixelIndex] <=
     91              globalHDRHeadroomLinear[hdrHeadroomIndex]) {
     92            // Values below the target will be unchanged.
     93            const kEps = 0.15;
     94            assert_approx_equals(
     95                data.data[0], pixelLinearValues[pixelIndex], kEps,
     96                'No tone mapping');
     97          } else {
     98            // Values above the target may be clamped.
     99            const kEps = 0.05;
    100            assert_greater_than(
    101                data.data[0], globalHDRHeadroomLinear[hdrHeadroomIndex] - kEps,
    102                'Tone map to or above target max');
    103          }
    104        } else {
    105          // If the test image doesn't fit in targeted headroom, then tone
    106          // mapping will happen.
    107          if (pixelLinearValues[pixelIndex] == test.max_linear_value) {
    108            // Pixels equal to the content maximum will map to the target
    109            // maximum.
    110            const kEps = 0.05;
    111            assert_approx_equals(
    112                data.data[0], globalHDRHeadroomLinear[hdrHeadroomIndex], kEps,
    113                'Tone map to target max');
    114          } else if (pixelLinearValues[pixelIndex] > test.max_linear_value) {
    115            // Pixels greater than content maximum will map to be greater or
    116            // equal to the target maximum.
    117            const kEps = 0.05;
    118            assert_greater_than(
    119                data.data[0], globalHDRHeadroomLinear[hdrHeadroomIndex] - kEps,
    120                'Tone map to or above target max');
    121          } else {
    122            // Pixels less than the content maximum will map to a value less
    123            // than the target maximum.
    124            const kEps = 0.05;
    125            assert_less_than(
    126                data.data[0], globalHDRHeadroomLinear[hdrHeadroomIndex],
    127                'Tone map below target max');
    128          }
    129        }
    130      }
    131    }
    132  }, test.desc);
    133 }
    134 </script>