tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

test_imagebitmap_cropping.html (11870B)


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