Commit eec72142 authored by noel's avatar noel Committed by Commit bot

Add new media image layout tests for video color profiles

  media/color-profile-munsell-bt601-smpte-to-srgb.html
  media/color-profile-munsell-bt709-to-srgb.html

The tests transform a test chart image from source color profile
(bt601, bt709) to sRGB and compares the output with the expected
Munsell colors [1] and studio video range black and white colors
and some proportions of them, SG Black 2x for example. Note: all
the expected colors are in sRGB color space.

The tests (one each for bt601 & bt709) are designed to be run in
the test harness automatically, but also manually to help detect
color changes should that happen in future.

The tabulated color results of these tests are correct and don't
change or need to be rebaselined. If the test colors changed, it
is a colorimetric error: the offending CL should be reverted.

[1] For more details on Munsell colors and gamuts, see
http://www.brucelindbloom.com/index.html?ColorCheckerRGB.html

TBR=kbr@chomium.org
BUG=570150

Review URL: https://codereview.chromium.org/1629963005

Cr-Commit-Position: refs/heads/master@{#371589}
parent e05e92d6
......@@ -98,6 +98,9 @@ crbug.com/527242 virtual/spv2/paint/invalidation/spv2/cached-change-row-border-w
crbug.com/527242 virtual/spv2/paint/invalidation/spv2/cached-change-table-border-width.html [ Failure ]
crbug.com/527242 virtual/spv2/paint/invalidation/spv2/cached-change-tbody-border-width.html [ Failure ]
crbug.com/524134 media/color-profile-munsell-bt601-smpte-to-srgb.html [ NeedsRebaseline ]
crbug.com/524134 media/color-profile-munsell-bt709-to-srgb.html [ NeedsRebaseline ]
crbug.com/536138 virtual/spv2/paint/invalidation/repaint-subsequence-on-ancestor-clip-change.html [ Failure ]
crbug.com/537172 [ Mac10.6 XP Win10 ] virtual/spv2/paint/invalidation/spv2/background-image-paint-invalidation.html [ Failure ]
......
<!DOCTYPE html>
<html>
<script src="../resources/run-after-layout-and-paint.js"></script>
<script src="resources/munsell-video-chart.js"></script>
<style>
div { position: relative; top: -390px; left: 475px }
</style>
<!-- Color accuracy test case: you should not rebaseline this test. -->
<body style="overflow: hidden">
<img><p><canvas style="display:none;"></canvas></p>
<div>
<pre id="log" style="font-size: 8.9pt"></pre>
<div>
</body>
<script>
if (window.testRunner) {
testRunner.dumpAsTextWithPixelResults();
testRunner.waitUntilDone();
}
window.onload = function() {
if (window.internals)
internals.settings.setImageColorProfilesEnabled(true);
var cyanInTargetGamut = false; // BT.601 Cyan is outside the sRGB gamut.
testImageColors('resources/munsell-bt601-smpte-c.png', cyanInTargetGamut);
};
</script>
</html>
<!DOCTYPE html>
<html>
<script src="../resources/run-after-layout-and-paint.js"></script>
<script src="resources/munsell-video-chart.js"></script>
<style>
div { position: relative; top: -390px; left: 475px }
</style>
<!-- Color accuracy test case: you should not rebaseline this test. -->
<body style="overflow: hidden">
<img><p><canvas style="display:none;"></canvas></p>
<div>
<pre id="log" style="font-size: 8.9pt"></pre>
<div>
</body>
<script>
if (window.testRunner) {
testRunner.dumpAsTextWithPixelResults();
testRunner.waitUntilDone();
}
window.onload = function() {
if (window.internals)
internals.settings.setImageColorProfilesEnabled(true);
var cyanInTargetGamut = true; // BT.709 and sRGB have the same gamut.
testImageColors('resources/munsell-bt709-hdtv-itu.png', cyanInTargetGamut);
};
</script>
</html>
window.ignoreCyan = false;
function testImageColors(source, cyanInTargetGamut) {
window.ignoreCyan = !cyanInTargetGamut;
var image = document.querySelector('img');
image.onload = function() {
runAfterLayoutAndPaint(window.testRunner ? changeColorProfile : profileChanged);
};
image.src = source;
}
function changeColorProfile() {
/* The test image contains the Munsell colors in a known color space. Convert
* the colors to sRGB color space and test the transformed color accuracy.
*/
window.testRunner.setColorProfile('sRGB', profileChanged);
}
function profileChanged() {
setTimeout(drawImageToCanvas, 0);
}
function drawImageToCanvas() {
var image = document.querySelector('img');
var canvas = document.querySelector('canvas');
canvas.width = image.width;
canvas.height = image.height;
canvas.getContext('2d').drawImage(image, 0, 0, canvas.width, canvas.height);
chartColorTransform(canvas);
}
function log(message) {
document.getElementById('log').textContent += message + '\n';
}
function getCanvasColor(canvas, i) {
var x = 40 + (i % 6) * (canvas.width / 6);
var y = 40 + Math.floor(i / 6) * (canvas.height / 4 - 40);
try {
var data = canvas.getContext('2d').getImageData(x, y, 1, 1).data;
if (data[3] == 255)
return { rgb: [data[0], data[1], data[2]] };
return { rgb: [0, 0, 0] };
} catch (error) {
console.error(error);
return { rgb: [255, 255, 255] };
}
}
function getMunsellColor(i) {
if (!window.munsell_srgb_colors) {
window.munsell_srgb_colors = new Array( // Munsell colors in sRGB space.
{ color: 'Dark Skin', rgb: [ 115, 80, 64 ] },
{ color: 'Light Skin', rgb: [ 195, 151, 130 ] },
{ color: 'Blue Sky', rgb: [ 94, 123, 156 ] },
{ color: 'Foliage', rgb: [ 88, 108, 65 ] },
{ color: 'Blue Flower', rgb: [ 130, 129, 177 ] },
{ color: 'Bluish Green', rgb: [ 100, 190, 171 ] },
{ color: 'Orange', rgb: [ 217, 122, 37 ] },
{ color: 'Purplish Blue', rgb: [ 72, 91, 165 ] },
{ color: 'Moderate Red', rgb: [ 194, 84, 98 ] },
{ color: 'Purple', rgb: [ 91, 59, 107 ] },
{ color: 'Yellow Green', rgb: [ 160, 188, 60 ] },
{ color: 'Orange Yellow', rgb: [ 230, 163, 42 ] },
{ color: 'Blue', rgb: [ 46, 60, 153 ] },
{ color: 'Green', rgb: [ 71, 150, 69 ] },
{ color: 'Red', rgb: [ 177, 44, 56 ] },
{ color: 'Yellow', rgb: [ 238, 200, 27 ] },
{ color: 'Magenta', rgb: [ 187, 82, 148 ] },
{ color: 'Cyan (*)', rgb: [ /* -49 */ 0, 135, 166 ] },
{ color: 'White', rgb: [ 243, 242, 237 ] },
{ color: 'Neutral 8', rgb: [ 201, 201, 201 ] },
{ color: 'Neutral 6.5', rgb: [ 161, 161, 161 ] },
{ color: 'Neutral 5', rgb: [ 122, 122, 121 ] },
{ color: 'Neutral 3.5', rgb: [ 83, 83, 83 ] },
{ color: 'Black', rgb: [ 50, 49, 50 ] }
);
}
if (i < 0 && i >= munsell_srgb_colors.length)
return { color: 'invalid-color', rgb: [ 0, 0, 0 ] };
return munsell_srgb_colors[i];
}
function getStudioColor(i) {
if (!window.studio_srgb_colors) {
// Studio video range white & black and proportions thereof, in sRGB space.
window.studio_srgb_colors = new Array(
{ color: 'SG White', rgb: [ 237, 237, 237 ] },
{ color: 'SG White 1/2', rgb: [ 130, 130, 130 ] },
{ color: 'SG White 1/4', rgb: [ 74, 74, 74 ] },
{ color: 'SG Black 4x', rgb: [ 79, 79, 79 ] },
{ color: 'SG Black 2x', rgb: [ 48, 48, 48 ] },
{ color: 'SG Black', rgb: [ 31, 31, 31 ] }
);
}
if (i < 0 && i >= studio_srgb_colors.length)
return { color: 'invalid-color', rgb: [ 0, 0, 0 ] };
return studio_srgb_colors[i];
}
function getColorError(cx, cy) {
var dr = (cx[0] - cy[0]);
var dg = (cx[1] - cy[1]);
var db = (cx[2] - cy[2]);
return Math.round(Math.sqrt((dr * dr) + (dg * dg) + (db * db)));
}
function pad(string, size) {
size = size || 14;
if (string.length < size)
string += ' '.repeat(size - string.length);
return string;
}
function drawRule(size) {
log('-'.repeat(size || 44));
}
function chartColorTransform(canvas) {
/*
* Add header over table of color names, actual and expected values, and the
* per color error (Euclidean distance).
*/
log(pad('Color') + pad('Actual') + pad('Expected') + 'dE');
drawRule();
var totalSquaredError = 0.0;
/*
* Report per color error dE, by comparing with the expected Munsell & Studio colors.
*/
for (var i = 0; i < 30;) {
var expected = (i < 24) ? getMunsellColor(i) : getStudioColor(i - 24);
var actual = getCanvasColor(canvas, i);
var dE = getColorError(actual.rgb, expected.rgb);
log(pad(expected.color) + pad(actual.rgb.join(',')) + pad(expected.rgb.join(',')) + dE);
if (ignoreCyan && (i + 1) == 18)
; // Do not include the Munsell Cyan (out-of-srgb-gamut) color error.
else
totalSquaredError += dE * dE;
if (++i % 6 == 0 && i <= 24)
drawRule();
}
/*
* Report the total RMS color error: lower is better, and should be << 2, which is the
* JND (Just Noticable Difference) perception threshold. Above a JND, the color error
* is noticable to the human eye.
*/
drawRule();
log('\nResult: total RMS color error: ' + Math.sqrt(totalSquaredError / 30.0).toFixed(2));
if (window.testRunner)
window.testRunner.notifyDone();
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment