| <!DOCTYPE HTML> |
| <script src="/resources/testharness.js"></script> |
| <script src="/resources/testharnessreport.js"></script> |
| <script> |
| |
| // No matter what is the color space and pixel format of the color managed |
| // canvas, toBlob() and toDataURL() always create the blob in sRGB color |
| // space, and respect the legacy behavior by not including any color space |
| // information in the blob/data url. |
| |
| var opaqueReferencePxiels, transparentReferencePixels; |
| |
| function testPixels(actualPixels, refPixels, testScenario) |
| { |
| // Narrowing down the source of expected error: |
| // - Alpha values should always match. |
| // - Color components should be acceptably close. |
| if (testScenario.canvasColorParam.pixelFormat == 'uint8') { |
| let tolerance_color = 4; |
| for (let i = 0; i < actualPixels.length; i++) { |
| // Alpha channel |
| if (i % 4 == 3) |
| assert_equals(actualPixels[i], refPixels[i]); |
| else |
| assert_approx_equals(actualPixels[i], refPixels[i], tolerance_color); |
| } |
| } else { |
| // For half float backed canvas, we expect the error < 0.01. |
| let tolerance_color = 0.01; |
| for (let i = 0; i < actualPixels.length; i++) { |
| // Alpha channel |
| if (i % 4 == 3) |
| assert_equals(actualPixels[i], refPixels[i]); |
| else |
| assert_approx_equals(actualPixels[i], refPixels[i], tolerance_color); |
| } |
| } |
| } |
| |
| function createCanvas(testScenario) |
| { |
| var canvas = document.createElement("canvas"); |
| canvas.width = 2; |
| canvas.height = 2; |
| return canvas; |
| } |
| |
| function generateFillStyle(red, green, blue, alpha) { |
| return "rgba(" + red + "," + green + "," + blue + "," + alpha + ")"; |
| } |
| |
| function drawPatternOnCanvsa(ctx, alpha, compositeOverBlack) { |
| if (compositeOverBlack) { |
| ctx.fillStyle = generateFillStyle(0, 0, 0, 1); |
| ctx.fillRect(0, 0, 2, 2); |
| } |
| ctx.fillStyle = generateFillStyle(155, 27, 27, alpha); |
| ctx.fillRect(0, 0, 1, 1); |
| ctx.fillStyle = generateFillStyle(27, 155, 27, alpha); |
| ctx.fillRect(1, 0, 1, 1); |
| ctx.fillStyle = generateFillStyle(27, 27, 155, alpha); |
| ctx.fillRect(0, 1, 1, 1); |
| ctx.fillStyle = generateFillStyle(27, 27, 27, alpha); |
| ctx.fillRect(1, 1, 1, 1); |
| } |
| |
| function testScenarioToString(testScenario) { |
| var str = "mimeType: " + testScenario.encodeOptions.type + |
| ", blobPixelFormat: " + testScenario.encodeOptions.pixelFormat + |
| ", source color space: " + testScenario.canvasColorParam.colorSpace + |
| ", pixel format: " + testScenario.canvasColorParam.pixelFormat + |
| ", alpha: " + testScenario.alpha; |
| return str; |
| } |
| |
| function runConvertToBlobTest(testScenario) { |
| var srcCanvas = createCanvas(testScenario); |
| var ctx = srcCanvas.getContext('2d', testScenario.canvasColorParam); |
| var compositeOverBlack = (testScenario.encodeOptions.type == "image/jpeg"); |
| drawPatternOnCanvsa(ctx, testScenario.alpha, compositeOverBlack); |
| var refPixels = ctx.getImageData(0, 0, 2, 2).dataUnion; |
| |
| var t = async_test("Test canvas convertToBlob(): " + |
| testScenarioToString(testScenario)); |
| |
| var image = new Image(); |
| image.onload = t.step_func_done(function() { |
| var dstCanvas = createCanvas(testScenario); |
| var dstCtx = dstCanvas.getContext('2d', testScenario.canvasColorParam); |
| dstCtx.drawImage(image, 0, 0); |
| var actualPixels = dstCtx.getImageData(0, 0, 2, 2).dataUnion; |
| testPixels(actualPixels, refPixels, testScenario); |
| }); |
| |
| srcCanvas.convertToBlob(testScenario.encodeOptions).then( |
| t.step_func(function(blob) { |
| var urlCreator = window.URL || window.webkitURL; |
| image.src = urlCreator.createObjectURL(blob); |
| }), |
| t.step_func_done(function(e) { |
| assert_false("convertToBlob failed."); |
| }) |
| ); |
| } |
| |
| function runAllTests() { |
| |
| var mimeTypes = ['image/png', 'image/jpeg', 'image/webp']; |
| var blobPixelFormats = ['uint8', 'uint16']; |
| |
| var encodeOptionsSet = []; |
| for (var i = 0; i < mimeTypes.length; i++) |
| for (var k = 0; k < blobPixelFormats.length; k++) { |
| var encodeOptions = {}; |
| encodeOptions.quality = 1; |
| encodeOptions.type = mimeTypes[i]; |
| encodeOptions.pixelFormat = blobPixelFormats[k]; |
| encodeOptionsSet.push(encodeOptions); |
| } |
| |
| var canvasColorParams = [ |
| {colorSpace: 'srgb', pixelFormat: 'uint8'}, |
| {colorSpace: 'srgb', pixelFormat: 'float16'}, |
| ]; |
| var alphaValues = [0.5, 1]; |
| |
| // The *correct* way to test convertToBlob() is to directly examine the |
| // image file for the expected color space and pixels. Since this is not |
| // easy to do in javascript, we use a round-trip test here and leave the |
| // more thorough testing to unit tests. |
| |
| var testScenarioSet = []; |
| for (var i = 0; i < encodeOptionsSet.length; i++) |
| for (var j = 0; j < canvasColorParams.length; j++) |
| for (var k = 0; k < alphaValues.length; k++) { |
| var testScenario = {}; |
| testScenario.encodeOptions = encodeOptionsSet[i]; |
| testScenario.canvasColorParam = canvasColorParams[j]; |
| testScenario.alpha = alphaValues[k]; |
| testScenarioSet.push(testScenario); |
| } |
| |
| for (var i = 0; i < testScenarioSet.length; i++) |
| runConvertToBlobTest(testScenarioSet[i]); |
| } |
| |
| test(function() { |
| runAllTests(); |
| }, "Overall test"); |
| |
| </script> |