Commit 22d98b41 authored by Philip Jägenstedt's avatar Philip Jägenstedt Committed by Commit Bot

Make canvas-createImageBitmap-e_srgb.html run cross-browser

There were harness errors in Edge, Firefox and Safari:
https://wpt.fyi/results/html/canvas/element/manual/wide-gamut-canvas/canvas-createImageBitmap-e_srgb.html?run_id=657990001&run_id=659880001&run_id=633480001&run_id=663850001

The cause for that was the convertToBlob call not correctly wrapped in a
step in testCreateImageBitmapFromColorManagedBlob.

That was only the first of multiple errors fixed here:
 - not handling image or video decode failures, causing timeouts
 - failures at the end of testCreateImageBitmapFromColorManagedBlob
   would not have failed the test because promise rejections were
   not handled
 - failing in cryptic ways if ImageData dataUnion isn't supported

These issues were fixed while also modernizing the tests to use more
modern APIs where available, like img.decode() and fetch().

Change-Id: Ia8d0086a2d216dd291c9429460f8a79f8f4fd1c6
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2359991Reviewed-by: default avatarWan-Teh Chang <wtc@google.com>
Reviewed-by: default avatarFernando Serboncini <fserb@chromium.org>
Commit-Queue: Philip Jägenstedt <foolip@chromium.org>
Cr-Commit-Position: refs/heads/master@{#798674}
parent afe7d924
...@@ -44,8 +44,9 @@ function testPixels(ctx, tests, sourceType) ...@@ -44,8 +44,9 @@ function testPixels(ctx, tests, sourceType)
tolerance = 0.03; tolerance = 0.03;
for (var i = 0; i < tests.length; i++) { for (var i = 0; i < tests.length; i++) {
actual = ctx.getImageData(tests[i][0], tests[i][1], 1, 1).dataUnion; actual = ctx.getImageData(tests[i][0], tests[i][1], 1, 1).dataUnion;
assert_implements(actual, 'ImageData dataUnion not supported');
expected = tests[i][2]; expected = tests[i][2];
assert_true(actual.length === expected.length); assert_equals(actual.length, expected.length);
for (var j = 0; j < actual.length; j++) for (var j = 0; j < actual.length; j++)
assert_approx_equals(actual[j], expected[j], tolerance, tests[i][3]); assert_approx_equals(actual[j], expected[j], tolerance, tests[i][3]);
} }
...@@ -171,7 +172,9 @@ function compareBitmaps(bitmap1, bitmap2) ...@@ -171,7 +172,9 @@ function compareBitmaps(bitmap1, bitmap2)
ctx1.drawImage(bitmap1, 0, 0); ctx1.drawImage(bitmap1, 0, 0);
ctx2.drawImage(bitmap2, 0, 0); ctx2.drawImage(bitmap2, 0, 0);
var data1 = ctx1.getImageData(0, 0, 50, 50).dataUnion; var data1 = ctx1.getImageData(0, 0, 50, 50).dataUnion;
assert_implements(data1, 'ImageData dataUnion not supported');
var data2 = ctx2.getImageData(0, 0, 50, 50).dataUnion; var data2 = ctx2.getImageData(0, 0, 50, 50).dataUnion;
assert_implements(data2, 'ImageData dataUnion not supported');
var dataMatched = true; var dataMatched = true;
for (var i = 0; i < data1.length; i++) { for (var i = 0; i < data1.length; i++) {
if (data1[i] != data2[i]) { if (data1[i] != data2[i]) {
...@@ -286,14 +289,11 @@ function initializeTestCanvasTransparent(canvasColorSpace, canvasPixelFormat) ...@@ -286,14 +289,11 @@ function initializeTestCanvasTransparent(canvasColorSpace, canvasPixelFormat)
// HTMLImageElement - Opaque sRGB // HTMLImageElement - Opaque sRGB
// File formats: AVIF, Bitmap, GIF, ICO, JPEG, PNG, WEBP // File formats: AVIF, Bitmap, GIF, ICO, JPEG, PNG, WEBP
['avif', 'bmp', 'gif', 'ico', 'jpg', 'png', 'webp'].forEach(ext => { ['avif', 'bmp', 'gif', 'ico', 'jpg', 'png', 'webp'].forEach(ext => {
promise_test(function() { promise_test(async () => {
return new Promise((resolve,reject) => { const image = new Image();
var image = new Image();
image.onload = function() {
resolve(image);
}
image.src = 'resources/pattern-srgb.' + ext; image.src = 'resources/pattern-srgb.' + ext;
}).then(testImageBitmapOpaque); await image.decode();
await testImageBitmapOpaque(image);
}, 'createImageBitmap in e-sRGB from an opaque sRGB HTMLImageElement (' + ext + }, 'createImageBitmap in e-sRGB from an opaque sRGB HTMLImageElement (' + ext +
') with resize.'); ') with resize.');
}); });
...@@ -301,14 +301,11 @@ function initializeTestCanvasTransparent(canvasColorSpace, canvasPixelFormat) ...@@ -301,14 +301,11 @@ function initializeTestCanvasTransparent(canvasColorSpace, canvasPixelFormat)
// HTMLImageElement - Transparent sRGB // HTMLImageElement - Transparent sRGB
// File formats: AVIF, Bitmap, ICO, PNG, WEBP // File formats: AVIF, Bitmap, ICO, PNG, WEBP
['avif', 'bmp', 'ico', 'png', 'webp'].forEach(ext => { ['avif', 'bmp', 'ico', 'png', 'webp'].forEach(ext => {
promise_test(function() { promise_test(async () => {
return new Promise((resolve,reject) => { const image = new Image();
var image = new Image();
image.onload = function() {
resolve(image);
}
image.src = 'resources/pattern-srgb-transparent.' + ext; image.src = 'resources/pattern-srgb-transparent.' + ext;
}).then(testImageBitmapFromTransparentImage); await image.decode();
await testImageBitmapFromTransparentImage(image);
}, 'createImageBitmap in e-sRGB from a transparent sRGB HTMLImageElement (' + ext + }, 'createImageBitmap in e-sRGB from a transparent sRGB HTMLImageElement (' + ext +
') with resize.'); ') with resize.');
}); });
...@@ -316,56 +313,54 @@ function initializeTestCanvasTransparent(canvasColorSpace, canvasPixelFormat) ...@@ -316,56 +313,54 @@ function initializeTestCanvasTransparent(canvasColorSpace, canvasPixelFormat)
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// SVG Image - sRGB // SVG Image - sRGB
promise_test(function() { promise_test(async () => {
return new Promise((resolve, reject) => { const image = new Image();
var image = new Image();
image.onload = function() {
resolve(image);
}
image.src = 'resources/pattern-srgb.svg' image.src = 'resources/pattern-srgb.svg'
}).then(testImageBitmapFromSVG); await image.decode();
await testImageBitmapFromSVG(image);
}, 'createImageBitmap in e-sRGB from a sRGB SVG image with resize.'); }, 'createImageBitmap in e-sRGB from a sRGB SVG image with resize.');
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// HTMLVideoElement - sRGB // HTMLVideoElement - sRGB
promise_test(function() { promise_test(async () => {
return new Promise((resolve, reject) => {
var video = document.createElement("video"); var video = document.createElement("video");
video.oncanplaythrough = function() { assert_implements_optional(video.canPlayType("video/ogg"), "video/ogg not supported");
resolve(video);
}
video.preload = "auto"; video.preload = "auto";
video.src = 'resources/pattern-srgb-fullcolor.ogv' video.src = 'resources/pattern-srgb-fullcolor.ogv'
}).then(testImageBitmapVideoSource); await new Promise((resolve, reject) => {
video.onloadeddata = resolve;
video.onerror = reject;
});
await testImageBitmapVideoSource(video);
}, 'createImageBitmap in e-sRGB from a sRGB HTMLVideoElement with resize.'); }, 'createImageBitmap in e-sRGB from a sRGB HTMLVideoElement with resize.');
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// HTMLCanvasElement - Opaque sRGB // HTMLCanvasElement - Opaque sRGB
promise_test(function() { promise_test(async () => {
var testCanvas = initializeTestCanvas('srgb', 'uint8'); var testCanvas = initializeTestCanvas('srgb', 'uint8');
return testImageBitmapOpaque(testCanvas); await testImageBitmapOpaque(testCanvas);
}, 'createImageBitmap in e-sRGB from an opaque sRGB HTMLCanvasElement with resize.'); }, 'createImageBitmap in e-sRGB from an opaque sRGB HTMLCanvasElement with resize.');
// HTMLCanvasElement - Opaque e-sRGB // HTMLCanvasElement - Opaque e-sRGB
promise_test(function() { promise_test(async () => {
var testCanvas = initializeTestCanvas('srgb', 'float16'); var testCanvas = initializeTestCanvas('srgb', 'float16');
return testImageBitmapOpaque(testCanvas); await testImageBitmapOpaque(testCanvas);
}, 'createImageBitmap in e-sRGB from an opaque e-sRGB HTMLCanvasElement with resize.'); }, 'createImageBitmap in e-sRGB from an opaque e-sRGB HTMLCanvasElement with resize.');
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// HTMLCanvasElement - Transparent sRGB // HTMLCanvasElement - Transparent sRGB
promise_test(function() { promise_test(async () => {
var testCanvas = initializeTestCanvasTransparent('srgb', 'uint8'); var testCanvas = initializeTestCanvasTransparent('srgb', 'uint8');
return testImageBitmapTransparent(testCanvas); await testImageBitmapTransparent(testCanvas);
}, 'createImageBitmap in e-sRGB from a transparent sRGB HTMLCanvasElement with resize.'); }, 'createImageBitmap in e-sRGB from a transparent sRGB HTMLCanvasElement with resize.');
// HTMLCanvasElement - Transparent e-sRGB // HTMLCanvasElement - Transparent e-sRGB
promise_test(function() { promise_test(async () => {
var testCanvas = initializeTestCanvasTransparent('srgb', 'float16'); var testCanvas = initializeTestCanvasTransparent('srgb', 'float16');
return testImageBitmapTransparent(testCanvas); await testImageBitmapTransparent(testCanvas);
}, 'createImageBitmap in e-sRGB from a transparent e-sRGB HTMLCanvasElement with resize.'); }, 'createImageBitmap in e-sRGB from a transparent e-sRGB HTMLCanvasElement with resize.');
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
...@@ -373,60 +368,48 @@ promise_test(function() { ...@@ -373,60 +368,48 @@ promise_test(function() {
// Blob from file - Opaque sRGB // Blob from file - Opaque sRGB
// File formats: AVIF, Bitmap, GIF, ICO, JPEG, PNG, WEBP // File formats: AVIF, Bitmap, GIF, ICO, JPEG, PNG, WEBP
['avif', 'bmp', 'gif', 'ico', 'jpg', 'png', 'webp'].forEach(ext => { ['avif', 'bmp', 'gif', 'ico', 'jpg', 'png', 'webp'].forEach(ext => {
promise_test(function() { promise_test(async () => {
return new Promise((resolve, reject) => { const response = await fetch('resources/pattern-srgb.' + ext);
var xhr = new XMLHttpRequest(); assert_true(response.ok);
xhr.open("GET", 'resources/pattern-srgb.' + ext); const blob = await response.blob();
xhr.responseType = 'blob'; await testImageBitmapOpaque(blob);
xhr.send();
xhr.onload = function() {
resolve(xhr.response);
};
}).then(testImageBitmapOpaque);
}, 'createImageBitmap in e-sRGB from an opaque sRGB Blob (' + ext + ') with resize.'); }, 'createImageBitmap in e-sRGB from an opaque sRGB Blob (' + ext + ') with resize.');
}); });
// Blob form file - Transparent sRGB // Blob form file - Transparent sRGB
// File formats: AVIF, Bitmap, ICO, PNG, WEBP // File formats: AVIF, Bitmap, ICO, PNG, WEBP
['avif', 'bmp', 'ico', 'png', 'webp'].forEach(ext => { ['avif', 'bmp', 'ico', 'png', 'webp'].forEach(ext => {
promise_test(function() { promise_test(async () => {
return new Promise((resolve, reject) => { const response = await fetch('resources/pattern-srgb-transparent.' + ext);
var xhr = new XMLHttpRequest(); assert_true(response.ok);
xhr.open("GET", 'resources/pattern-srgb-transparent.' + ext); const blob = await response.blob();
xhr.responseType = 'blob'; await testImageBitmapFromTransparentImage(blob);
xhr.send();
xhr.onload = function() {
resolve(xhr.response);
};
}).then(testImageBitmapFromTransparentImage);
}, 'createImageBitmap in e-sRGB from a transparent sRGB Blob (' + ext + ') with resize.'); }, 'createImageBitmap in e-sRGB from a transparent sRGB Blob (' + ext + ') with resize.');
}); });
// Color managed blob from canvas // Color managed blob from canvas
function testCreateImageBitmapFromColorManagedBlob(pixelFormat, isTransparent) { function testCreateImageBitmapFromColorManagedBlob(pixelFormat, isTransparent) {
promise_test(async () => {
let canvasPixelFormat = 'uint8'; let canvasPixelFormat = 'uint8';
if (pixelFormat == 'uint16') if (pixelFormat == 'uint16')
canvasPixelFormat = 'float16'; canvasPixelFormat = 'float16';
var testCanvas; let testCanvas;
if (isTransparent) if (isTransparent)
testCanvas = initializeTestCanvasTransparent('srgb', canvasPixelFormat); testCanvas = initializeTestCanvasTransparent('srgb', canvasPixelFormat);
else else
testCanvas = initializeTestCanvas('srgb', canvasPixelFormat); testCanvas = initializeTestCanvas('srgb', canvasPixelFormat);
var encodeOptions = {}; const blob = await testCanvas.convertToBlob({
encodeOptions.quality = 1; quality: 1,
encodeOptions.type = 'image/png'; type: 'image/png',
encodeOptions.pixelFormat = pixelFormat; pixelFormat,
});
var t = async_test('createImageBitmap in e-sRGB from color managed Blob' +
' with resize. blobPixelFormat: ' + pixelFormat +
', transparency: ' + isTransparent);
testCanvas.convertToBlob(encodeOptions).then(
t.step_func_done(function(blob) {
if (isTransparent) if (isTransparent)
testImageBitmapTransparent(blob); await testImageBitmapTransparent(blob);
else else
testImageBitmapOpaque(blob); await testImageBitmapOpaque(blob);
})); }, 'createImageBitmap in e-sRGB from color managed Blob' +
' with resize. blobPixelFormat: ' + pixelFormat +
', transparency: ' + isTransparent);
} }
function runAllCreateImageBitmapFromColorManagedBlobTests() { function runAllCreateImageBitmapFromColorManagedBlobTests() {
...@@ -444,67 +427,67 @@ runAllCreateImageBitmapFromColorManagedBlobTests(); ...@@ -444,67 +427,67 @@ runAllCreateImageBitmapFromColorManagedBlobTests();
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// ImageData - Opaque sRGB // ImageData - Opaque sRGB
promise_test(function() { promise_test(async () => {
var canvas = initializeTestCanvas('srgb', 'uint8'); var canvas = initializeTestCanvas('srgb', 'uint8');
var ctx = canvas.getContext('2d'); var ctx = canvas.getContext('2d');
var data = ctx.getImageData(0, 0, 20, 20); var data = ctx.getImageData(0, 0, 20, 20);
return testImageBitmapOpaque(data); await testImageBitmapOpaque(data);
}, 'createImageBitmap in e-sRGB from an opaque sRGB ImageData with resize.'); }, 'createImageBitmap in e-sRGB from an opaque sRGB ImageData with resize.');
// ImageData - Opaque e-sRGB // ImageData - Opaque e-sRGB
promise_test(function() { promise_test(async () => {
var canvas = initializeTestCanvas('srgb', 'float16'); var canvas = initializeTestCanvas('srgb', 'float16');
var ctx = canvas.getContext('2d', var ctx = canvas.getContext('2d',
{colorSpace: 'srgb', pixelFormat:'float16'}); {colorSpace: 'srgb', pixelFormat:'float16'});
var data = ctx.getImageData(0, 0, 20, 20); var data = ctx.getImageData(0, 0, 20, 20);
return testImageBitmapOpaque(data); await testImageBitmapOpaque(data);
}, 'createImageBitmap in e-sRGB from an opaque e-sRGB ImageData with resize.'); }, 'createImageBitmap in e-sRGB from an opaque e-sRGB ImageData with resize.');
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// ImageData - Transparent sRGB // ImageData - Transparent sRGB
promise_test(function() { promise_test(async () => {
var canvas = initializeTestCanvasTransparent('srgb', 'uint8'); var canvas = initializeTestCanvasTransparent('srgb', 'uint8');
var ctx = canvas.getContext('2d'); var ctx = canvas.getContext('2d');
var data = ctx.getImageData(0, 0, 20, 20); var data = ctx.getImageData(0, 0, 20, 20);
return testImageBitmapTransparent(data); await testImageBitmapTransparent(data);
}, 'createImageBitmap in e-sRGB from a transparent sRGB ImageData with resize.'); }, 'createImageBitmap in e-sRGB from a transparent sRGB ImageData with resize.');
// ImageData - Transparent e-sRGB // ImageData - Transparent e-sRGB
promise_test(function() { promise_test(async () => {
var canvas = initializeTestCanvasTransparent('srgb', 'float16'); var canvas = initializeTestCanvasTransparent('srgb', 'float16');
var ctx = canvas.getContext('2d', var ctx = canvas.getContext('2d',
{colorSpace: 'srgb', pixelFormat:'float16'}); {colorSpace: 'srgb', pixelFormat:'float16'});
var data = ctx.getImageData(0, 0, 20, 20); var data = ctx.getImageData(0, 0, 20, 20);
return testImageBitmapTransparent(data); await testImageBitmapTransparent(data);
}, 'createImageBitmap in e-sRGB from a transparent e-sRGB ImageData with resize.'); }, 'createImageBitmap in e-sRGB from a transparent e-sRGB ImageData with resize.');
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// ImageBitmap - Opaque sRGB // ImageBitmap - Opaque sRGB
promise_test(function() { promise_test(async () => {
var testCanvas = initializeTestCanvas('srgb', 'uint8'); var testCanvas = initializeTestCanvas('srgb', 'uint8');
return createImageBitmap(testCanvas).then(testImageBitmapOpaque); await createImageBitmap(testCanvas).then(testImageBitmapOpaque);
}, 'createImageBitmap in e-sRGB from an opaque sRGB ImageBitmap with resize.'); }, 'createImageBitmap in e-sRGB from an opaque sRGB ImageBitmap with resize.');
// ImageBitmap - Opaque e-sRGB // ImageBitmap - Opaque e-sRGB
promise_test(function() { promise_test(async () => {
var testCanvas = initializeTestCanvas('srgb', 'float16'); var testCanvas = initializeTestCanvas('srgb', 'float16');
return createImageBitmap(testCanvas).then(testImageBitmapOpaque); await createImageBitmap(testCanvas).then(testImageBitmapOpaque);
}, 'createImageBitmap in e-sRGB from an opaque e-sRGB ImageBitmap with resize.'); }, 'createImageBitmap in e-sRGB from an opaque e-sRGB ImageBitmap with resize.');
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// ImageBitmap - Transparent sRGB // ImageBitmap - Transparent sRGB
promise_test(function() { promise_test(async () => {
var testCanvas = initializeTestCanvasTransparent('srgb', 'uint8'); var testCanvas = initializeTestCanvasTransparent('srgb', 'uint8');
return createImageBitmap(testCanvas).then(testImageBitmapTransparent); await createImageBitmap(testCanvas).then(testImageBitmapTransparent);
}, 'createImageBitmap in e-sRGB from a transparent sRGB ImageBitmap with resize.'); }, 'createImageBitmap in e-sRGB from a transparent sRGB ImageBitmap with resize.');
// ImageBitmap - Transparent e-sRGB // ImageBitmap - Transparent e-sRGB
promise_test(function() { promise_test(async () => {
var testCanvas = initializeTestCanvasTransparent('srgb', 'float16'); var testCanvas = initializeTestCanvasTransparent('srgb', 'float16');
return createImageBitmap(testCanvas).then(testImageBitmapTransparent); await createImageBitmap(testCanvas).then(testImageBitmapTransparent);
}, 'createImageBitmap in e-sRGB from a transparent e-sRGB ImageBitmap with resize.'); }, 'createImageBitmap in e-sRGB from a transparent e-sRGB ImageBitmap with resize.');
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
...@@ -529,15 +512,15 @@ function initializeOffscreenCanvas(canvasColorSpace, canvasPixelFormat) ...@@ -529,15 +512,15 @@ function initializeOffscreenCanvas(canvasColorSpace, canvasPixelFormat)
} }
//OffscreenCanvas - Opaque sRGB //OffscreenCanvas - Opaque sRGB
promise_test(function() { promise_test(async () => {
var offscreen = initializeOffscreenCanvas('srgb', 'uint8'); var offscreen = initializeOffscreenCanvas('srgb', 'uint8');
return testImageBitmapOpaque(offscreen); await testImageBitmapOpaque(offscreen);
}, 'createImageBitmap in e-sRGB from an opaque sRGB OffscreenCanvas with resize.'); }, 'createImageBitmap in e-sRGB from an opaque sRGB OffscreenCanvas with resize.');
//OffscreenCanvas - Opaque e-sRGB //OffscreenCanvas - Opaque e-sRGB
promise_test(function() { promise_test(async () => {
var offscreen = initializeOffscreenCanvas('srgb', 'float16'); var offscreen = initializeOffscreenCanvas('srgb', 'float16');
return testImageBitmapOpaque(offscreen); await testImageBitmapOpaque(offscreen);
}, 'createImageBitmap in e-sRGB from an opaque e-sRGB OffscreenCanvas with resize.'); }, 'createImageBitmap in e-sRGB from an opaque e-sRGB OffscreenCanvas with resize.');
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
...@@ -562,15 +545,15 @@ function initializeOffscreenCanvasTransparent(canvasColorSpace, canvasPixelForma ...@@ -562,15 +545,15 @@ function initializeOffscreenCanvasTransparent(canvasColorSpace, canvasPixelForma
} }
//OffscreenCanvas - Transparent sRGB //OffscreenCanvas - Transparent sRGB
promise_test(function() { promise_test(async () => {
var offscreen = initializeOffscreenCanvasTransparent('srgb', 'uint8'); var offscreen = initializeOffscreenCanvasTransparent('srgb', 'uint8');
return testImageBitmapTransparent(offscreen); await testImageBitmapTransparent(offscreen);
}, 'createImageBitmap in e-sRGB from a transparent sRGB OffscreenCanvas with resize.'); }, 'createImageBitmap in e-sRGB from a transparent sRGB OffscreenCanvas with resize.');
//OffscreenCanvas - Transparent e-sRGB //OffscreenCanvas - Transparent e-sRGB
promise_test(function() { promise_test(async () => {
var offscreen = initializeOffscreenCanvasTransparent('srgb', 'float16'); var offscreen = initializeOffscreenCanvasTransparent('srgb', 'float16');
return testImageBitmapTransparent(offscreen); await testImageBitmapTransparent(offscreen);
}, 'createImageBitmap in e-sRGB from a transparent e-sRGB OffscreenCanvas with resize.'); }, 'createImageBitmap in e-sRGB from a transparent e-sRGB OffscreenCanvas with resize.');
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
......
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