View Javadoc
1   /*
2    * Copyright (c) 2002-2025 Gargoyle Software Inc.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * https://www.apache.org/licenses/LICENSE-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software
10   * distributed under the License is distributed on an "AS IS" BASIS,
11   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   * See the License for the specific language governing permissions and
13   * limitations under the License.
14   */
15  package org.htmlunit.javascript.host.canvas;
16  
17  import org.htmlunit.WebDriverTestCase;
18  import org.htmlunit.junit.BrowserRunner;
19  import org.htmlunit.junit.annotation.Alerts;
20  import org.junit.Test;
21  import org.junit.runner.RunWith;
22  
23  /**
24   * Tests for {@link ImageData}.
25   *
26   * @author Ahmed Ashour
27   * @author Ronald Brill
28   */
29  @RunWith(BrowserRunner.class)
30  public class ImageDataTest extends WebDriverTestCase {
31  
32      /**
33       * @throws Exception if an error occurs
34       */
35      @Test
36      @Alerts({"8", "1", "2",
37               "0", "190", "3", "255", "0", "190", "3", "255",
38               "8", "2", "1",
39               "0", "190", "3", "255", "0", "190", "3", "255"})
40      public void ctorArray() throws Exception {
41          final String html = DOCTYPE_HTML
42              + "<html><head><script>\n"
43              + LOG_TITLE_FUNCTION
44              + "function test() {\n"
45              + "  if (typeof ImageData != 'function') { log('no ctor'); return; }"
46  
47              + "  var arr = new Uint8ClampedArray(8);\n"
48              + "  for (var i = 0; i < arr.length; i += 4) {\n"
49              + "    arr[i + 0] = 0;\n"
50              + "    arr[i + 1] = 190;\n"
51              + "    arr[i + 2] = 3;\n"
52              + "    arr[i + 3] = 255;\n"
53              + "  }\n"
54  
55              + "  var imageData = new ImageData(arr, 1);\n"
56              + "  log(imageData.data.length);\n"
57              + "  log(imageData.width);\n"
58              + "  log(imageData.height);\n"
59  
60              + "  var data = imageData.data;\n"
61              + "  for (var i = 0; i < data.length; i++) {\n"
62              + "    log(data[i]);\n"
63              + "  }\n"
64  
65              + "  var imageData = new ImageData(arr, 2);\n"
66              + "  log(imageData.data.length);\n"
67              + "  log(imageData.width);\n"
68              + "  log(imageData.height);\n"
69  
70              + "  var data = imageData.data;\n"
71              + "  for (var i = 0; i < data.length; i++) {\n"
72              + "    log(data[i]);\n"
73              + "  }\n"
74  
75              + "}\n"
76              + "</script>\n"
77              + "</head>\n"
78              + "<body onload='test()'><canvas id='myCanvas'></canvas></body>\n"
79              + "</html>";
80          loadPageVerifyTitle2(html);
81      }
82  
83      /**
84       * @throws Exception if an error occurs
85       */
86      @Test
87      @Alerts({"8", "1", "2",
88               "0", "190", "3", "255", "0", "190", "3", "255"})
89      public void ctorArrayWidthHeight() throws Exception {
90          final String html = DOCTYPE_HTML
91              + "<html><head><script>\n"
92              + LOG_TITLE_FUNCTION
93              + "function test() {\n"
94              + "  if (typeof ImageData != 'function') { log('no ctor'); return; }"
95  
96              + "  var arr = new Uint8ClampedArray(8);\n"
97              + "  for (var i = 0; i < arr.length; i += 4) {\n"
98              + "    arr[i + 0] = 0;\n"
99              + "    arr[i + 1] = 190;\n"
100             + "    arr[i + 2] = 3;\n"
101             + "    arr[i + 3] = 255;\n"
102             + "  }\n"
103 
104             + "  var imageData = new ImageData(arr, 1, 2);\n"
105             + "  log(imageData.data.length);\n"
106             + "  log(imageData.width);\n"
107             + "  log(imageData.height);\n"
108 
109             + "  var data = imageData.data;\n"
110             + "  for (var i = 0; i < data.length; i++) {\n"
111             + "    log(data[i]);\n"
112             + "  }\n"
113             + "}\n"
114             + "</script>\n"
115             + "</head>\n"
116             + "<body onload='test()'><canvas id='myCanvas'></canvas></body>\n"
117             + "</html>";
118         loadPageVerifyTitle2(html);
119     }
120 
121     /**
122      * @throws Exception if an error occurs
123      */
124     @Test
125     @Alerts({"TypeError", "IndexSizeError/DOMException", "IndexSizeError/DOMException",
126              "IndexSizeError/DOMException", "IndexSizeError/DOMException",
127              "InvalidStateError/DOMException", "IndexSizeError/DOMException"})
128     public void ctorArrayInvalid() throws Exception {
129         final String html = DOCTYPE_HTML
130             + "<html><head><script>\n"
131             + LOG_TITLE_FUNCTION
132             + "function test() {\n"
133 
134             + "  try {\n"
135             + "    var imageData = new ImageData();\n"
136             + "  } catch(e) { logEx(e);}\n"
137 
138             + "  try {\n"
139             + "    var imageData = new ImageData(-2, 1);\n"
140             + "  } catch(e) { logEx(e);}\n"
141 
142             + "  try {\n"
143             + "    var imageData = new ImageData(2, -1);\n"
144             + "  } catch(e) { logEx(e);}\n"
145 
146             + "  try {\n"
147             + "    var imageData = new ImageData(-2, -1);\n"
148             + "  } catch(e) { logEx(e);}\n"
149 
150             + "  var arr = new Uint8ClampedArray(8);\n"
151             + "  try {\n"
152             + "    var imageData = new ImageData(arr, 3);\n"
153             + "  } catch(e) { logEx(e);}\n"
154 
155             + "  arr = new Uint8ClampedArray(11);\n"
156             + "  try {\n"
157             + "    var imageData = new ImageData(arr, 2);\n"
158             + "  } catch(e) { logEx(e);}\n"
159 
160             + "  arr = new Uint8ClampedArray(8);\n"
161             + "  try {\n"
162             + "    var imageData = new ImageData(arr, 2, 2);\n"
163             + "  } catch(e) { logEx(e);}\n"
164 
165             + "}\n"
166             + "</script>\n"
167             + "</head>\n"
168             + "<body onload='test()'><canvas id='myCanvas'></canvas></body>\n"
169             + "</html>";
170         loadPageVerifyTitle2(html);
171     }
172 
173     /**
174      * @throws Exception if an error occurs
175      */
176     @Test
177     @Alerts({"8", "2", "1", "0", "0", "0", "0", "0", "0", "0", "0"})
178     public void ctorWidthHeight() throws Exception {
179         final String html = DOCTYPE_HTML
180             + "<html><head><script>\n"
181             + LOG_TITLE_FUNCTION
182             + "function test() {\n"
183             + "  if (typeof ImageData != 'function') { log('no ctor'); return; }"
184 
185             + "  var imageData = new ImageData(2, 1);\n"
186             + "  log(imageData.data.length);\n"
187             + "  log(imageData.width);\n"
188             + "  log(imageData.height);\n"
189 
190             + "  var data = imageData.data;\n"
191             + "  for (var i = 0; i < data.length; i++) {\n"
192             + "    log(data[i]);\n"
193             + "  }\n"
194             + "}\n"
195             + "</script>\n"
196             + "</head>\n"
197             + "<body onload='test()'><canvas id='myCanvas'></canvas></body>\n"
198             + "</html>";
199         loadPageVerifyTitle2(html);
200     }
201 
202     /**
203      * @throws Exception if an error occurs
204      */
205     @Test
206     @Alerts({"200", "100", "50", "255", "100", "50", "125", "255", "123", "111", "222", "255"})
207     public void getImageData() throws Exception {
208         final String html = DOCTYPE_HTML
209             + "<html><head><script>\n"
210             + LOG_TITLE_FUNCTION
211             + "function test() {\n"
212             + "  var canvas = document.getElementById('myCanvas');\n"
213             + "  if (canvas.getContext) {\n"
214             + "    var ctx = canvas.getContext('2d');\n"
215             + "    ctx.fillStyle = 'rgb(200,100,50)';\n"
216             + "    ctx.fillRect(0, 0, 2, 2);\n"
217             + "    ctx.fillStyle = 'rgba(0, 0, 200, 0.5)';\n"
218             + "    ctx.fillRect(1, 0, 2, 2);\n"
219             + "    ctx.fillStyle = 'rgb(123,111,222)';\n"
220             + "    ctx.fillRect(2, 0, 2, 2);\n"
221             + "    var imageData = ctx.getImageData(0, 0, 3, 1);\n"
222             + "    var data = imageData.data;\n"
223             + "    for (var i = 0; i < data.length; i++) {\n"
224             + "      log(data[i]);\n"
225             + "    }\n"
226             + "  }\n"
227             + "}\n"
228             + "</script>\n"
229             + "</head>\n"
230             + "<body onload='test()'><canvas id='myCanvas'></canvas></body>\n"
231             + "</html>";
232         loadPageVerifyTitle2(html);
233     }
234 
235     /**
236      * @throws Exception if an error occurs
237      */
238     @Test
239     @Alerts({"0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0"})
240     public void getImageDataOutside() throws Exception {
241         final String html = DOCTYPE_HTML
242             + "<html><head><script>\n"
243             + LOG_TITLE_FUNCTION
244             + "function test() {\n"
245             + "  var canvas = document.getElementById('myCanvas');\n"
246             + "  if (canvas.getContext) {\n"
247             + "    var ctx = canvas.getContext('2d');\n"
248             + "    ctx.fillStyle = 'rgb(200,100,50)';\n"
249             + "    ctx.fillRect(0, 0, 2, 2);\n"
250             + "    ctx.fillStyle = 'rgba(0, 0, 200, 0.5)';\n"
251             + "    ctx.fillRect(1, 0, 2, 2);\n"
252             + "    ctx.fillStyle = 'rgb(123,111,222)';\n"
253             + "    ctx.fillRect(2, 0, 2, 2);\n"
254             + "    var imageData = ctx.getImageData(-10, -10, 3, 1);\n"
255             + "    var data = imageData.data;\n"
256             + "    for (var i = 0; i < data.length; i++) {\n"
257             + "      log(data[i]);\n"
258             + "    }\n"
259             + "  }\n"
260             + "}\n"
261             + "</script>\n"
262             + "</head>\n"
263             + "<body onload='test()'><canvas id='myCanvas'></canvas></body>\n"
264             + "</html>";
265         loadPageVerifyTitle2(html);
266     }
267 
268     /**
269      * @throws Exception if an error occurs
270      */
271     @Test
272     @Alerts({"0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0"})
273     public void getImageDataOutside2() throws Exception {
274         final String html = DOCTYPE_HTML
275             + "<html><head><script>\n"
276             + LOG_TITLE_FUNCTION
277             + "function test() {\n"
278             + "  var canvas = document.getElementById('myCanvas');\n"
279             + "  if (canvas.getContext) {\n"
280             + "    var ctx = canvas.getContext('2d');\n"
281             + "    ctx.fillStyle = 'rgb(200,100,50)';\n"
282             + "    ctx.fillRect(0, 0, 2, 2);\n"
283             + "    ctx.fillStyle = 'rgba(0, 0, 200, 0.5)';\n"
284             + "    ctx.fillRect(1, 0, 2, 2);\n"
285             + "    ctx.fillStyle = 'rgb(123,111,222)';\n"
286             + "    ctx.fillRect(2, 0, 2, 2);\n"
287             + "    var imageData = ctx.getImageData(500, 500, 3, 1);\n"
288             + "    var data = imageData.data;\n"
289             + "    for (var i = 0; i < data.length; i++) {\n"
290             + "      log(data[i]);\n"
291             + "    }\n"
292             + "  }\n"
293             + "}\n"
294             + "</script>\n"
295             + "</head>\n"
296             + "<body onload='test()'><canvas id='myCanvas'></canvas></body>\n"
297             + "</html>";
298         loadPageVerifyTitle2(html);
299     }
300 
301     /**
302      * @throws Exception if an error occurs
303      */
304     @Test
305     @Alerts({"0", "0", "0", "0", "200", "100", "50", "255", "100", "50", "125", "255"})
306     public void getImageDataPartlyOutside() throws Exception {
307         final String html = DOCTYPE_HTML
308             + "<html><head><script>\n"
309             + LOG_TITLE_FUNCTION
310             + "function test() {\n"
311             + "  var canvas = document.getElementById('myCanvas');\n"
312             + "  if (canvas.getContext) {\n"
313             + "    var ctx = canvas.getContext('2d');\n"
314             + "    ctx.fillStyle = 'rgb(200,100,50)';\n"
315             + "    ctx.fillRect(0, 0, 2, 2);\n"
316             + "    ctx.fillStyle = 'rgba(0, 0, 200, 0.5)';\n"
317             + "    ctx.fillRect(1, 0, 2, 2);\n"
318             + "    ctx.fillStyle = 'rgb(123,111,222)';\n"
319             + "    ctx.fillRect(2, 0, 2, 2);\n"
320             + "    var imageData = ctx.getImageData(-1, 0, 3, 1);\n"
321             + "    var data = imageData.data;\n"
322             + "    for (var i = 0; i < data.length; i++) {\n"
323             + "      log(data[i]);\n"
324             + "    }\n"
325             + "  }\n"
326             + "}\n"
327             + "</script>\n"
328             + "</head>\n"
329             + "<body onload='test()'><canvas id='myCanvas'></canvas></body>\n"
330             + "</html>";
331         loadPageVerifyTitle2(html);
332     }
333 
334     /**
335      * @throws Exception if an error occurs
336      */
337     @Test
338     @Alerts({"0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0"})
339     public void getImageDataPartlyOutside2() throws Exception {
340         final String html = DOCTYPE_HTML
341             + "<html><head><script>\n"
342             + LOG_TITLE_FUNCTION
343             + "function test() {\n"
344             + "  var canvas = document.getElementById('myCanvas');\n"
345             + "  if (canvas.getContext) {\n"
346             + "    var ctx = canvas.getContext('2d');\n"
347             + "    ctx.fillStyle = 'rgb(200,100,50)';\n"
348             + "    ctx.fillRect(0, 0, 2, 2);\n"
349             + "    ctx.fillStyle = 'rgba(0, 0, 200, 0.5)';\n"
350             + "    ctx.fillRect(1, 0, 2, 2);\n"
351             + "    ctx.fillStyle = 'rgb(123,111,222)';\n"
352             + "    ctx.fillRect(2, 0, 2, 2);\n"
353             + "    var imageData = ctx.getImageData(298, 149, 3, 1);\n"
354             + "    var data = imageData.data;\n"
355             + "    for (var i = 0; i < data.length; i++) {\n"
356             + "      log(data[i]);\n"
357             + "    }\n"
358             + "  }\n"
359             + "}\n"
360             + "</script>\n"
361             + "</head>\n"
362             + "<body onload='test()'><canvas id='myCanvas'></canvas></body>\n"
363             + "</html>";
364         loadPageVerifyTitle2(html);
365     }
366 
367     /**
368      * @throws Exception if an error occurs
369      */
370     @Test
371     @Alerts({"200", "100", "50", "255", "200", "100", "50", "255", "0", "0", "0", "0"})
372     public void getImageDataDrawAfter() throws Exception {
373         final String html = DOCTYPE_HTML
374             + "<html><head><script>\n"
375             + LOG_TITLE_FUNCTION
376             + "function test() {\n"
377             + "  var canvas = document.getElementById('myCanvas');\n"
378             + "  if (canvas.getContext) {\n"
379             + "    var ctx = canvas.getContext('2d');\n"
380             + "    ctx.fillStyle = 'rgb(200,100,50)';\n"
381             + "    ctx.fillRect(0, 0, 2, 2);\n"
382             + "    var imageData = ctx.getImageData(0, 0, 3, 1);\n"
383 
384             + "    ctx.fillStyle = 'rgba(0, 0, 200, 0.5)';\n"
385             + "    ctx.fillRect(1, 0, 2, 2);\n"
386             + "    ctx.fillStyle = 'rgb(123,111,222)';\n"
387             + "    ctx.fillRect(2, 0, 2, 2);\n"
388 
389             + "    var data = imageData.data;\n"
390             + "    for (var i = 0; i < data.length; i++) {\n"
391             + "      log(data[i]);\n"
392             + "    }\n"
393             + "  }\n"
394             + "}\n"
395             + "</script>\n"
396             + "</head>\n"
397             + "<body onload='test()'><canvas id='myCanvas'></canvas></body>\n"
398             + "</html>";
399         loadPageVerifyTitle2(html);
400     }
401 
402     /**
403      * @throws Exception if an error occurs
404      */
405     @Test
406     @Alerts({"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11"})
407     public void data() throws Exception {
408         final String html = DOCTYPE_HTML
409             + "<html><head><script>\n"
410             + LOG_TITLE_FUNCTION
411             + "function test() {\n"
412             + "  var canvas = document.getElementById('myCanvas');\n"
413             + "  if (canvas.getContext) {\n"
414             + "    var ctx = canvas.getContext('2d');\n"
415             + "    ctx.fillStyle = 'rgb(200,100,50)';\n"
416             + "    ctx.fillRect(0, 0, 2, 2);\n"
417             + "    ctx.fillStyle = 'rgba(0, 0, 200, 0.5)';\n"
418             + "    ctx.fillRect(1, 0, 2, 2);\n"
419             + "    ctx.fillStyle = 'rgb(123,111,222)';\n"
420             + "    ctx.fillRect(2, 0, 2, 2);\n"
421             + "    var imageData = ctx.getImageData(0, 0, 3, 1);\n"
422             + "    for (var i = 0; i < imageData.data.length; i++) {\n"
423             + "      imageData.data[i] = i;\n"
424             + "      log(imageData.data[i]);\n"
425             + "    }\n"
426             + "  }\n"
427             + "}\n"
428             + "</script>\n"
429             + "</head>\n"
430             + "<body onload='test()'><canvas id='myCanvas'></canvas></body>\n"
431             + "</html>";
432         loadPageVerifyTitle2(html);
433     }
434 
435     /**
436      * @throws Exception if an error occurs
437      */
438     @Test
439     @Alerts({"8", "1", "2",
440                 "13", "0", "17", "0", "0", "0", "0", "42"})
441     public void setValues() throws Exception {
442         final String html = DOCTYPE_HTML
443             + "<html><head><script>\n"
444             + LOG_TITLE_FUNCTION
445             + "function test() {\n"
446             + "  var canvas = document.getElementById('myCanvas');\n"
447             + "  if (canvas.getContext) {\n"
448             + "    var ctx = canvas.getContext('2d');\n"
449 
450             + "    var imageData = ctx.createImageData(1, 2);\n"
451             + "    log(imageData.data.length);\n"
452             + "    log(imageData.width);\n"
453             + "    log(imageData.height);\n"
454 
455             + "    imageData.data[0] = 13;\n"
456             + "    imageData.data[2] = 17;\n"
457             + "    imageData.data[7] = 42;\n"
458             + "    imageData.data[8] = 43;\n"
459             + "    imageData.data[-5] = 7;\n"
460             + "    imageData.data[100] = 11;\n"
461             + "    for (var i = 0; i < imageData.data.length; i++) {\n"
462             + "      log(imageData.data[i]);\n"
463             + "    }\n"
464             + "  }\n"
465             + "}\n"
466             + "</script>\n"
467             + "</head>\n"
468             + "<body onload='test()'><canvas id='myCanvas'></canvas></body>\n"
469             + "</html>";
470         loadPageVerifyTitle2(html);
471     }
472 
473     /**
474      * @throws Exception if an error occurs
475      */
476     @Test
477     @Alerts({"24", "2", "3",
478                 "0", "0", "17", "0", "0", "0", "0", "0", "0", "0", "0", "0",
479                 "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0"})
480     public void createImageData() throws Exception {
481         final String html = DOCTYPE_HTML
482             + "<html><head><script>\n"
483             + LOG_TITLE_FUNCTION
484             + "function test() {\n"
485             + "  var canvas = document.getElementById('myCanvas');\n"
486             + "  if (canvas.getContext) {\n"
487             + "    var ctx = canvas.getContext('2d');\n"
488             + "    ctx.fillRect(1, 1, 13, 11);\n"
489 
490             + "    var imageData = ctx.createImageData(2, 3);\n"
491             + "    log(imageData.data.length);\n"
492             + "    log(imageData.width);\n"
493             + "    log(imageData.height);\n"
494 
495             + "    imageData.data[2] = 17;\n"
496             + "    for (var i = 0; i < imageData.data.length; i++) {\n"
497             + "      log(imageData.data[i]);\n"
498             + "    }\n"
499             + "  }\n"
500             + "}\n"
501             + "</script>\n"
502             + "</head>\n"
503             + "<body onload='test()'><canvas id='myCanvas'></canvas></body>\n"
504             + "</html>";
505         loadPageVerifyTitle2(html);
506     }
507 
508     /**
509      * @throws Exception if an error occurs
510      */
511     @Test
512     @Alerts({"24", "2", "3",
513                 "0", "0", "17", "0", "0", "0", "0", "0", "0", "0", "0", "0",
514                 "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0"})
515     public void createImageDataFlipped() throws Exception {
516         final String html = DOCTYPE_HTML
517             + "<html><head><script>\n"
518             + LOG_TITLE_FUNCTION
519             + "function test() {\n"
520             + "  var canvas = document.getElementById('myCanvas');\n"
521             + "  if (canvas.getContext) {\n"
522             + "    var ctx = canvas.getContext('2d');\n"
523             + "    ctx.fillRect(1, 1, 13, 11);\n"
524 
525             + "    var imageData = ctx.createImageData(-2, -3);\n"
526             + "    log(imageData.data.length);\n"
527             + "    log(imageData.width);\n"
528             + "    log(imageData.height);\n"
529 
530             + "    imageData.data[2] = 17;\n"
531             + "    for (var i = 0; i < imageData.data.length; i++) {\n"
532             + "      log(imageData.data[i]);\n"
533             + "    }\n"
534             + "  }\n"
535             + "}\n"
536             + "</script>\n"
537             + "</head>\n"
538             + "<body onload='test()'><canvas id='myCanvas'></canvas></body>\n"
539             + "</html>";
540         loadPageVerifyTitle2(html);
541     }
542 
543     /**
544      * @throws Exception if an error occurs
545      */
546     @Test
547     @Alerts({"8",
548                 "0", "0", "17", "0", "0", "0", "0", "0",
549                 "8", "1", "2",
550                 "0", "0", "0", "0", "0", "0", "0", "0"})
551     public void createImageDataFromImageData() throws Exception {
552         final String html = DOCTYPE_HTML
553             + "<html><head><script>\n"
554             + LOG_TITLE_FUNCTION
555             + "function test() {\n"
556             + "  var canvas = document.getElementById('myCanvas');\n"
557             + "  if (canvas.getContext) {\n"
558             + "    var ctx = canvas.getContext('2d');\n"
559             + "    var imageData = ctx.createImageData(1, 2);\n"
560             + "    log(imageData.data.length);\n"
561             + "    imageData.data[2] = 17;\n"
562             + "    for (var i = 0; i < imageData.data.length; i++) {\n"
563             + "      log(imageData.data[i]);\n"
564             + "    }\n"
565 
566             + "    var imageDataCopy = ctx.createImageData(imageData);\n"
567             + "    log(imageDataCopy.data.length);\n"
568             + "    log(imageDataCopy.width);\n"
569             + "    log(imageDataCopy.height);\n"
570             + "    for (var i = 0; i < imageDataCopy.data.length; i++) {\n"
571             + "      log(imageDataCopy.data[i]);\n"
572             + "    }\n"
573             + "  }\n"
574             + "}\n"
575             + "</script>\n"
576             + "</head>\n"
577             + "<body onload='test()'><canvas id='myCanvas'></canvas></body>\n"
578             + "</html>";
579         loadPageVerifyTitle2(html);
580     }
581 }