exif-orientation.html (5762B)
1 <!-- 2 Copyright (c) 2020 The Khronos Group Inc. 3 Use of this source code is governed by an MIT-style license that can be 4 found in the LICENSE.txt file. 5 --> 6 7 <!DOCTYPE html> 8 <html> 9 <head> 10 <meta charset="utf-8"> 11 <title>Verifies EXIF orientation is respected when uploading images to WebGL textures</title> 12 <link rel="stylesheet" href="../../../resources/js-test-style.css"/> 13 <script src="../../../js/js-test-pre.js"></script> 14 <script src="../../../js/webgl-test-utils.js"></script> 15 <script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script> 16 </head> 17 <body onload="run()"> 18 <canvas id="c" width="256" height="256"></canvas> 19 <div id="description"></div> 20 <div id="console"></div> 21 <script> 22 "use strict"; 23 description(); 24 let wtu = WebGLTestUtils; 25 let tiu = TexImageUtils; 26 let canvas = document.getElementById("c"); 27 let gl = wtu.create3DContext(canvas); 28 let program = tiu.setupTexturedQuad(gl, gl.RGBA); 29 const resourcePath = "../../../resources/"; 30 const tolerance = 5; 31 32 // The locations are written assuming flipY = false. For flipY = true, y = 1.0-y. 33 const expectedColors = { 34 top: { location: [ 0.5, 0.25 ], color: [ 255, 0, 0 ] }, 35 left: { location: [ 0.4, 0.5 ], color: [ 0, 0, 255 ] }, 36 right: { location: [ 0.6, 0.5 ], color: [ 255, 255, 0 ] }, 37 bottom: { location: [ 0.5, 0.75 ], color: [ 0, 255, 0 ] }, 38 } 39 40 function output(str) 41 { 42 debug(str); 43 bufferedLogToConsole(str); 44 } 45 46 function checkPixels(flipY) 47 { 48 for (let place in expectedColors) { 49 let color = expectedColors[place]; 50 let loc = color.location; 51 let x = loc[0]; 52 let y = (flipY ? 1.0 - loc[1] : loc[1]); 53 output(" Checking " + place); 54 wtu.checkCanvasRect(gl, Math.floor(canvas.width * x), Math.floor(canvas.height * y), 1, 1, 55 color.color, "shouldBe " + color.color + " +/-" + tolerance, tolerance); 56 } 57 } 58 59 async function testImageBitmapWithFlipY(source, flipY) 60 { 61 const bitmap = await createImageBitmap(source, flipY ? {imageOrientation: flipY} : undefined); 62 63 output(" Testing texImage2D, flipY = " + flipY); 64 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, bitmap); 65 wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]); 66 checkPixels(flipY == "flipY"); 67 68 output(" Testing texSubImage2D, flipY = " + flipY); 69 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, bitmap.width, bitmap.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); 70 gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, bitmap); 71 wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]); 72 checkPixels(flipY == "flipY"); 73 } 74 75 async function testImageBitmapFromBlob(filename) 76 { 77 let response = await fetch(resourcePath + filename); 78 let blob = await response.blob(); 79 output("----------------------------------------------------------------"); 80 output("Testing " + filename + " via ImageBitmap from Blob"); 81 await testImageBitmapWithFlipY(blob, "flipY"); 82 await testImageBitmapWithFlipY(blob, "none"); 83 await testImageBitmapWithFlipY(blob, undefined); 84 } 85 86 async function testImageBitmapFromImage(image) 87 { 88 await testImageBitmapWithFlipY(image, "flipY"); 89 await testImageBitmapWithFlipY(image, "none"); 90 await testImageBitmapWithFlipY(image, undefined); 91 } 92 93 async function testImageElementWithFlipY(image, flipY) 94 { 95 output(" Testing texImage2D, flipY = " + flipY); 96 gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY); 97 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image); 98 wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]); 99 checkPixels(flipY); 100 101 output(" Testing texSubImage2D, flipY = " + flipY); 102 gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY); 103 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, image.width, image.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); 104 gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, image); 105 wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]); 106 checkPixels(flipY); 107 } 108 109 async function testImageElement(filename) 110 { 111 let image = new Image(); 112 image.src = resourcePath + filename; 113 await image.decode(); 114 115 output("----------------------------------------------------------------"); 116 output("Testing " + filename + " via HTMLImageElement"); 117 118 await testImageElementWithFlipY(image, true); 119 await testImageElementWithFlipY(image, false); 120 121 output("----------------------------------------------------------------"); 122 output("Testing " + filename + " via ImageBitmap from HTMLImageElement"); 123 124 await testImageBitmapFromImage(image); 125 } 126 127 async function testSingleImage(filename) 128 { 129 await testImageBitmapFromBlob(filename); 130 await testImageElement(filename); 131 } 132 133 async function run() 134 { 135 let tex = gl.createTexture(); 136 // Bind the texture to the default texture unit 0 137 gl.bindTexture(gl.TEXTURE_2D, tex); 138 // Set up texture parameters 139 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); 140 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); 141 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); 142 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); 143 144 const filenames = [ 145 "exif-orientation-test-1-normal.jpg", 146 "exif-orientation-test-2-mirror-horizontal.jpg", 147 "exif-orientation-test-3-rotate-180.jpg", 148 "exif-orientation-test-4-mirror-vertical.jpg", 149 "exif-orientation-test-5-mirror-horizontal-90-ccw.jpg", 150 "exif-orientation-test-6-90-cw.jpg", 151 "exif-orientation-test-7-mirror-horizontal-90-cw.jpg", 152 "exif-orientation-test-8-90-ccw.jpg", 153 ]; 154 155 for (let fn of filenames) { 156 await testSingleImage(fn); 157 } 158 159 finishTest(); 160 } 161 162 var successfullyParsed = true; 163 </script> 164 </body> 165 </html>