Source code
Revision control
Copy as Markdown
Other Tools
<!DOCTYPE HTML>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
// Render serveral equivalent ISO 21496-1 gainmap images with various values for
// globalHdrHeadroom.
// The test images used by this test have an SDR representation (at headroom 0)
// with pixel values in sRGB of:
// #C08040, #8040C0, #40C080, #FFFFFF
// They have an HDR representation (at headroom 1) with pixel values in sRGB of
// #40C080, #C08040, #8040C0 color(srgb 0x17F/0xFF, 0x17F/0xFF, 0x17F/0xFF)
// The test images vary in:
// * Some have SDR as the base image (encoded as sRGB) and some have HDR as the
// base image (encoded as Rec2100 PQ or Rec2100 HLG).
// * Some use sRGB as the gain application primaries, others use Rec2020
// The tests that use a Rec2100 PQ or HLG base are allowed a higher amount of
// error because of the brutal quantization error in those spaces.
promise_test(async () => {
const tests = [
{
filename:'iso21496-1-base_srgb-altr_none-use_base.jpg',
workingSpace:'srgb',
epsilon:0x4/255
},
{
filename:'iso21496-1-base_srgb-altr_rec2020-use_altr.jpg',
workingSpace:'rec2020',
epsilon:0x4/255
},
/*
// Enable these when passing on at least one browser.
{
filename:'iso21496-1-base_rec2100pq-altr_none-use_base.jpg',
workingSpace:'rec2020',
epsilon:0x8/255
},
{
filename:'iso21496-1-base_rec2100pq-altr_none-use_altr.jpg',
workingSpace:'rec2020',
epsilon:0x8/255
},
{
filename:'iso21496-1-base_rec2100hlg-altr_none-use_base.jpg',
workingSpace:'rec2020',
epsilon:0x8/255
},
*/
];
for (const test of tests) {
filename = test.filename;
const canvas = new OffscreenCanvas(64, 64);
const ctx = canvas.getContext('2d', {colorType:'float16'});
if (ctx.globalHDRHeadroom === undefined) {
break;
}
// All test images evaluate to these sRGB values at headroom 0
const sdrExpected = [
[ 0xC0/0xFF, 0x80/0xFF, 0x40/0xFF],
[ 0x80/0xFF, 0x40/0xFF, 0xC0/0xFF],
[ 0x40/0xFF, 0xC0/0xFF, 0x80/0xFF],
[ 0xFF/0xFF, 0xFF/0xFF, 0xFF/0xFF]];
// All test images evaluate to these sRGB values at headroom 1
const hdrExpected = [
[ 0x40/0xFF, 0xC0/0xFF, 0x80/0xFF],
[ 0xC0/0xFF, 0x80/0xFF, 0x40/0xFF],
[ 0x80/0xFF, 0x40/0xFF, 0xC0/0xFF],
[0x17F/0xFF, 0x17F/0xFF, 0x17F/0xFF]];
const globalHDRHeadroomValues = [
0, 1, Infinity, 0.75,
]
const expectedPixelValues = [
sdrExpected, hdrExpected, hdrExpected, null,
];
// The interpolated values at HDR headroom 0.75 depend on the gain
// application color space primaries.
if (test.workingSpace === 'srgb') {
expectedPixelValues[3] = [
[ 0.335045, 0.681192, 0.424504, ],
[ 0.681192, 0.424504, 0.335045, ],
[ 0.424504, 0.335045, 0.681192, ],
[ 1.357607, 1.357607, 1.357607, ],];
}
if (test.workingSpace === 'rec2020') {
expectedPixelValues[3] = [
[ 0.443076, 0.687104, 0.429474, ],
[ 0.690319, 0.428588, 0.362702, ],
[ 0.496921, 0.349176, 0.692474, ],
[ 1.357607, 1.357607, 1.357607, ],];
}
// Draw the image at the specified headrooms.
const image = new Image;
image.src = 'resources/' + filename;
await new Promise(resolve => image.onload = resolve);
for (let x = 0; x < 4; ++x) {
ctx.globalHDRHeadroom = globalHDRHeadroomValues[x];
ctx.drawImage(image, 16*x, 0);
}
// Read back a pixel in each solid color region.
for (let x = 0; x < 4; ++x) {
for (let y = 0; y < 4; ++y) {
const name = 'filename:' + filename + ', ' +
'globalHDRHeadroom: ' + globalHDRHeadroomValues[x] + ', ' +
'x:' + x + ', ' +
'y:' + y;
const data = ctx.getImageData(
8 + 16*x, 8 + 16*y, 1, 1,
{colorSpace:'srgb', pixelFormat:'rgba-float16'});
const actual = data.data;
const expected = expectedPixelValues[x][y];
for (let c = 0; c < 3; ++c) {
const kEpsilon = 0x08 / 255;
assert_approx_equals(
actual[c], expected[c], kEpsilon, name);
}
}
}
}
});
</script>