<!DOCTYPE html> <html> <body> <canvas id="canvas" width="3" height="2"></canvas> <script src="../../resources/js-test.js"></script> <script> jsTestIsAsync = true; var worker = new Worker('./resources/canvas-ImageBitmap-structured-clone.js'); description("Tests that ImageBitmap supports structured clone and that the pixel data survives the trip between main <--> worker"); function shouldNotBeCalled(e) { testFailed("promise rejected." + e); finishJSTest(); } function compareImageData(data1, data2) { if (data1.length != data2.length) { testFailed("The two image have different dimensions"); return; } for (var i = 0; i < data1.length; i++) { if ((i % 4 != 3 && Math.abs(data1[i] - data2[i]) > 5) || (i % 4 == 3 && data1[i] != data2[i])) { testFailed("The ImageBitmap pixel data did not survive the round trip"); return; } } testPassed("The ImageBitmap pixel data survives the round trip"); } function checkImageBitmap1() { shouldBe("bitmapWidth", "imageWidth1"); shouldBe("bitmapHeight", "imageHeight1"); // newImage is not necessary the same as imageData because of // multiplying and dividing by alpha during the round trip, but // they should be close. // The alpha channel should be exactly the same. compareImageData(newImage.data, image1.data); } function checkImageBitmap2() { shouldBe("bitmapWidth", "imageWidth2"); shouldBe("bitmapHeight", "imageHeight2"); compareImageData(newImage.data, image2.data); } function postToWorker(message, transferable) { return new Promise((resolve, reject) => { function onMessage(e) { resolve(e.data); worker.removeEventListener("message", onMessage); } worker.postMessage(message, transferable); worker.addEventListener("message", onMessage); }); } function getNewImageDataFromWorkerReply(newImageBitmap) { bitmapWidth = newImageBitmap.width; bitmapHeight = newImageBitmap.height; context.clearRect(0, 0, imageWidth1, imageHeight1); context.drawImage(newImageBitmap, 0, 0, bitmapWidth, bitmapHeight); newImage = context.getImageData(0, 0, bitmapWidth, bitmapHeight); } var imageWidth1 = 3; var imageHeight1 = 2; var imageWidth2 = 1; var imageHeight2 = 1; var bitmapWidth; var bitmapHeight; var imageBitmap1; var imageBitmap2; var newImage; var image1 = new ImageData(new Uint8ClampedArray( [255, 0, 0, 255, 0, 255, 0, 255, 255, 255, 255, 127, 0, 0, 0, 64, 12, 34, 56, 64, 12, 34, 56, 127]), imageWidth1, imageHeight1); var image2 = new ImageData(new Uint8ClampedArray([255, 128, 64, 127]), imageWidth2, imageHeight2); var context = document.getElementById("canvas").getContext("2d"); var p1 = createImageBitmap(image1).then(function(image) {imageBitmap1 = image}); var p2 = createImageBitmap(image2).then(function(image) {imageBitmap2 = image}); Promise.all([p1, p2]).then(function() { bitmapWidth = imageBitmap1.width; bitmapHeight = imageBitmap1.height; shouldBe("bitmapWidth", "imageWidth1"); shouldBe("bitmapHeight", "imageHeight1"); var replyPromise = postToWorker(imageBitmap1); // Structured cloning should not neuter the source ImageBitmap bitmapWidth = imageBitmap1.width; bitmapHeight = imageBitmap1.height; shouldBe("bitmapWidth", "imageWidth1"); shouldBe("bitmapHeight", "imageHeight1"); return replyPromise.then(reply => { getNewImageDataFromWorkerReply(reply); checkImageBitmap1(); }); }).then(function() { var replyPromise = postToWorker(imageBitmap1, [imageBitmap1]); // Transfer the ImageBitmap should neuter it bitmapWidth = imageBitmap1.width; bitmapHeight = imageBitmap1.height; shouldBe("bitmapWidth", "0"); shouldBe("bitmapHeight", "0"); return replyPromise.then(reply => { getNewImageDataFromWorkerReply(reply); checkImageBitmap1(); }); }).then(function() { var replyPromise = postToWorker(imageBitmap2); // Structured cloning should not neuter the source ImageBitmap bitmapWidth = imageBitmap2.width; bitmapHeight = imageBitmap2.height; shouldBe("bitmapWidth", "imageWidth2"); shouldBe("bitmapHeight", "imageHeight2"); return replyPromise.then(reply => { getNewImageDataFromWorkerReply(reply); checkImageBitmap2(); }); }).then(finishJSTest, shouldNotBeCalled); </script> </body> </html>