2 <title>Test ImageBitmap Cropping (Bug
1190210)
</title>
4 <script src=
"/tests/SimpleTest/SimpleTest.js"></script>
5 <link rel=
"stylesheet" href=
"/tests/SimpleTest/test.css">
7 <script type=
"text/javascript">
9 SimpleTest
.waitForExplicitFinish();
12 * [isPixel description]
13 * @param {[type]} ctx : canvas context
14 * @param {[type]} x : pixel x coordinate
15 * @param {[type]} y : pixel y coordinate
16 * @param {[type]} c : a rgba color code
17 * @param {[type]} d : error duration
20 function isPixel(ctx
, x
, y
, c
, d
) {
21 var pos
= x
+ "," + y
;
22 var color
= c
[0] + "," + c
[1] + "," + c
[2] + "," + c
[3];
23 var pixel
= ctx
.getImageData(x
, y
, 1, 1);
24 var pr
= pixel
.data
[0],
28 ok(c
[0]-d
<= pr
&& pr
<= c
[0]+d
&&
29 c
[1]-d
<= pg
&& pg
<= c
[1]+d
&&
30 c
[2]-d
<= pb
&& pb
<= c
[2]+d
&&
31 c
[3]-d
<= pa
&& pa
<= c
[3]+d
,
32 "pixel "+pos
+" of "+ctx
.canvas
.id
+" is "+pr
+","+pg
+","+pb
+","+pa
+"; expected "+color
+" +/- "+d
);
36 // The pattern of the 320x240.webm video.
37 // .------------------------------------------------.
38 // | 255 | 255 | 0 | 0 | 255 | 255 | 0 |
39 // | 255 | 255 | 255 | 255 | 0 | 0 | 0 |
40 // | 255 | 0 | 255 | 0 | 255 | 0 | 255 |
43 // 0 46 92 138 184 230 276 319
46 // TEST_BITMAPS is a collection of test cases.
47 // Each object in the TEST_BITMAPS array is a test case with the following
49 // 1) croppingArea: indicating the cropping area in format (x, y, width, height).
50 // 2) testedPixels: an array of pixels that is going to be checked.
51 // Each item in the testedPixels array contains:
52 // 2.1) "pixel": the coordinate of this pixel (x, y).
53 // 2.2) "expectedColor": the expected color of this pixel (r, g, b, a).
54 // 2.3) "tolerance": the acceptable tolerance of pixel values.
57 // Cropping area is exactly the same as source surface.
58 {'croppingArea': [0, 0, 320, 240],
59 'testedPixels': [{"pixel": [0, 0], "expectedColor": [255, 255, 255, 255], "tolerance": 5},
60 {"pixel": [50, 0], "expectedColor": [255, 255, 0, 255], "tolerance": 5}]},
61 // Cropping area completely covers the source surface.
62 {'croppingArea': [-100, -100, 520, 440],
63 'testedPixels': [{"pixel": [0, 0], "expectedColor": [0, 0, 0, 0], "tolerance": 5},
64 {"pixel": [519, 0], "expectedColor": [0, 0, 0, 0], "tolerance": 5},
65 {"pixel": [0, 439], "expectedColor": [0, 0, 0, 0], "tolerance": 5},
66 {"pixel": [519, 439], "expectedColor": [0, 0, 0, 0], "tolerance": 5},
67 {"pixel": [100, 100], "expectedColor": [255, 255, 255, 255], "tolerance": 5},
68 {"pixel": [150, 120], "expectedColor": [255, 255, 0, 255], "tolerance": 5},
69 {"pixel": [200, 140], "expectedColor": [0, 255, 255, 255], "tolerance": 5}]},
70 // Cropping area partially covers the left-upper part of the source surface.
71 {'croppingArea': [-100, -100, 320, 240],
72 'testedPixels': [{"pixel": [0, 0], "expectedColor": [0, 0, 0, 0 ], "tolerance": 5},
73 {"pixel": [100, 100], "expectedColor": [255, 255, 255, 255], "tolerance": 5},
74 {"pixel": [150, 100], "expectedColor": [255, 255, 0, 255], "tolerance": 5}]},
75 // Cropping area partially covers the middle-upper part of the source surface.
76 {'croppingArea': [ 100, -100, 220, 240],
77 'testedPixels': [{"pixel": [0, 0], "expectedColor": [0, 0, 0, 0 ], "tolerance": 5},
78 {"pixel": [0, 100], "expectedColor": [0, 255, 255, 255], "tolerance": 5},
79 {"pixel": [150, 100], "expectedColor": [255, 0, 0, 255], "tolerance": 5}]},
80 // Cropping area partially covers the right-upper part of the source surface.
81 {'croppingArea': [ 200, -100, 320, 240],
82 'testedPixels': [{"pixel": [0, 0], "expectedColor": [0, 0, 0, 0 ], "tolerance": 5},
83 {"pixel": [0, 100], "expectedColor": [255, 0, 255, 255], "tolerance": 5},
84 {"pixel": [100, 100], "expectedColor": [0, 0, 255, 255], "tolerance": 5}]},
85 // Cropping area partially covers the left-center part of the source surface.
86 {'croppingArea': [-100, 100, 320, 120],
87 'testedPixels': [{"pixel": [0, 0], "expectedColor": [0, 0, 0, 0 ], "tolerance": 5},
88 {"pixel": [200, 0], "expectedColor": [0, 255, 255, 255], "tolerance": 5},
89 {"pixel": [250, 10], "expectedColor": [0, 255, 0, 255], "tolerance": 5}]},
90 // Cropping area partially covers the left-bottom part of the source surface.
91 {'croppingArea': [-100, 200, 320, 240],
92 'testedPixels': [{"pixel": [0, 0], "expectedColor": [0, 0, 0, 0 ], "tolerance": 5},
93 {"pixel": [100, 0], "expectedColor": [0, 60, 136, 255], "tolerance": 5},
94 {"pixel": [180, 10], "expectedColor": [255, 255, 255, 255], "tolerance": 5}]},
95 // Cropping area partially covers the middle-bottom part of the source surface.
96 {'croppingArea': [ 40, 200, 200, 100],
97 'testedPixels': [{"pixel": [0, 0], "expectedColor": [0, 60, 136, 255], "tolerance": 5},
98 {"pixel": [100, 20], "expectedColor": [107, 0, 210, 255], "tolerance": 5},
99 {"pixel": [80, 150], "expectedColor": [0, 0, 0, 0 ], "tolerance": 5}]},
100 // Cropping area partially covers the right-bottom part of the source surface.
101 {'croppingArea': [ 160, 100, 300, 300],
102 'testedPixels': [{"pixel": [0, 0], "expectedColor": [0, 255, 0, 255], "tolerance": 5},
103 {"pixel": [120, 20], "expectedColor": [0, 0, 255, 255], "tolerance": 5},
104 {"pixel": [299, 299], "expectedColor": [0, 0, 0, 0 ], "tolerance": 5}]},
105 // Cropping area is completely outside the source surface. (upper-left)
106 {'croppingArea': [-500, -500, 20, 20],
107 'testedPixels': [{"pixel": [0, 0], "expectedColor": [0, 0, 0, 0], "tolerance": 5},
108 {"pixel": [19, 19], "expectedColor": [0, 0, 0, 0], "tolerance": 5}]},
109 // Cropping area is completely outside the source surface. (upper-right)
110 {'croppingArea': [ 500, -500, 20, 20],
111 'testedPixels': [{"pixel": [0, 0], "expectedColor": [0, 0, 0, 0], "tolerance": 5},
112 {"pixel": [19, 19], "expectedColor": [0, 0, 0, 0], "tolerance": 5}]},
113 // Cropping area is completely outside the source surface. (bottom-left)
114 {'croppingArea': [-200, 500, 20, 20],
115 'testedPixels': [{"pixel": [0, 0], "expectedColor": [0, 0, 0, 0], "tolerance": 5},
116 {"pixel": [19, 19], "expectedColor": [0, 0, 0, 0], "tolerance": 5}]},
117 // Cropping area is completely outside the source surface. (bottom-right)
118 {'croppingArea': [ 500, 200, 20, 20],
119 'testedPixels': [{"pixel": [0, 0], "expectedColor": [0, 0, 0, 0], "tolerance": 5},
120 {"pixel": [19, 19], "expectedColor": [0, 0, 0, 0], "tolerance": 5}]},
123 function failed(ex
) {
124 ok(false, "Promise failure: " + ex
);
136 function prepareSources() {
137 gVideo
= document
.createElement("video");
138 gVideo
.src
= "http://example.com/tests/dom/canvas/test/crossorigin/video.sjs?name=tests/dom/canvas/test/320x240.webm&type=video/webm&cors=anonymous";
139 gVideo
.crossOrigin
= "anonymous";
140 gVideo
.autoplay
= "true"
143 gCanvas
= document
.createElement("canvas");
144 gCtx
= gCanvas
.getContext("2d");
147 var promise
= new Promise(function(resolve
, reject
) {
152 gVideo
.onloadeddata = function() {
153 ok(gVideo
, "[Prepare Sources] gVideo is ok.");
156 gCanvas
.width
= gVideo
.videoWidth
;
157 gCanvas
.height
= gVideo
.videoHeight
;
158 gCtx
.drawImage(gVideo
, 0, 0);
159 ok(gCanvas
, "[Prepare Sources] gCanvas is ok.");
160 ok(gCtx
, "[Prepare Sources] gCtx is ok.");
163 gImage
= document
.createElement("img");
164 gImage
.src
= gCanvas
.toDataURL();
166 var promiseImage
= new Promise(function(resolve
, reject
) {
167 resolverImage
= resolve
;
169 gImage
.onload = function() {
173 // Prepare ImageData.
174 gImageData
= gCtx
.getImageData(0, 0, gCanvas
.width
, gCanvas
.height
);
175 ok(gImageData
, "[Prepare Sources] gImageData is ok.");
177 // Prepapre PNG Blob.
178 var promisePNGBlob
= new Promise(function(resolve
, reject
) {
179 gCanvas
.toBlob(function(blob
) {
181 ok(gPNGBlob
, "[Prepare Sources] gPNGBlob is ok.");
186 // Prepare JPEG Blob.
187 var promiseJPEGBlob
= new Promise(function(resolve
, reject
) {
188 gCanvas
.toBlob(function(blob
) {
190 ok(gJPEGBlob
, "[Prepare Sources] gJPEGBlob is ok.");
192 }, "image/jpeg", 0.95);
195 // Prepare ImageBitmap.
196 var promiseImageBitmap
= new Promise(function(resolve
, reject
) {
197 var p
= createImageBitmap(gVideo
);
198 p
.then(function(bitmap
) {
199 gImageBitmap
= bitmap
;
200 ok(gImageBitmap
, "[Prepare Sources] gImageBitmap is ok.");
205 resolver(Promise
.all([
216 function testCropping_randomTest(source
) {
217 var canvasSrouce
= document
.createElement("canvas");
218 var ctxSource
= canvasSrouce
.getContext("2d");
220 var p
= createImageBitmap(source
);
221 p
.then(function(bitmap
) {
222 canvasSrouce
.width
= bitmap
.width
;
223 canvasSrouce
.height
= bitmap
.height
;
227 function testCropping(source
) {
228 var canvas
= document
.createElement("canvas");
229 var ctx
= canvas
.getContext("2d");
230 document
.body
.appendChild(canvas
);
232 function createBitmap(def
) {
233 return createImageBitmap(source
, def
.croppingArea
[0], def
.croppingArea
[1], def
.croppingArea
[2], def
.croppingArea
[3])
234 .then(function (bitmap
) { def
.bitmap
= bitmap
; }, failed
);
237 var promise
= new Promise(function(resolve
, reject
) {
238 resolve(Promise
.all(TEST_BITMAPS
.map(createBitmap
)))
241 function testPixel(testedPixel
) {
242 isPixel(ctx
, testedPixel
.pixel
[0], testedPixel
.pixel
[1], testedPixel
.expectedColor
, testedPixel
.tolerance
);
245 return promise
.then(function() {
246 TEST_BITMAPS
.forEach(function (testCase
) {
247 if (!testCase
.bitmap
) { return; }
248 ctx
.clearRect(0, 0, canvas
.width
, canvas
.height
);
249 canvas
.width
= testCase
.bitmap
.width
;
250 canvas
.height
= testCase
.bitmap
.height
;
251 ctx
.drawImage(testCase
.bitmap
, 0, 0);
252 testCase
.testedPixels
.forEach(testPixel
);
257 function runTests() {
260 then( function() { return Promise
.all([testCropping(gImage
),
261 testCropping(gVideo
),
262 testCropping(gCanvas
),
264 testCropping(gImageData
),
265 testCropping(gImageBitmap
),
266 testCropping(gPNGBlob
),
267 testCropping(gJPEGBlob
)]); }).
268 then(SimpleTest
.finish
, function(ev
) { failed(ev
); SimpleTest
.finish(); });
271 addLoadEvent(runTests
);