Typed arrays for pixel manipulation

JavaScript performance comparison

Test case created

Preparation code

 
<script>
Benchmark.prototype.setup = function() {
    var canvas = document.createElement('canvas');
    var c = canvas.getContext('2d');
    var w = canvas.width = 1000;
    var h = canvas.height = 1000;
    var image = c.getImageData(0, 0, w, h);
   
    for (var y = 0, i = 0; y < h; y++) {
      for (var x = 0; x < w; x++, i += 4) {
        image.data[i] = x & 0xFF;
        image.data[i + 1] = (x ^ y) & 0xFF;
        image.data[i + 2] = 0;
        image.data[i + 3] = 255;
      }
    }
   
    var buffer1 = Array.prototype.slice.call(image.data);
    var buffer2 = Array.prototype.slice.call(image.data);
    var buffer3 = Array.prototype.slice.call(image.data);
   
    var buffer4 = new Uint8Array(image.data);
    var buffer5 = new Uint8Array(image.data);
    var buffer6 = new Uint8Array(image.data);
   
};
</script>

Test runner

Warning! For accurate results, please disable Firebug before running the tests. (Why?)

Java applet disabled.

Testing in unknown unknown
Test Ops/sec
Array
var radius = 100;
var width = image.width;
var height = image.height;
var diameter = 2 * radius + 1;
var x, y, i, r, g, b, a, n;

// Box blur along x
for (y = i = 0; y < height; y++, i -= diameter * 4) {
  for (x = r = g = b = a = n = 0; x < width + diameter; x++, i += 4) {
    if (x < width) {
      r += buffer1[i];
      g += buffer1[i + 1];
      b += buffer1[i + 2];
      a += buffer1[i + 3];
      n++;
    }

    if (x >= radius && x < width + radius) {
      var j = ((x - radius) * height + y) * 4;
      buffer2[j]     = (r / n) & 0xFF;
      buffer2[j + 1] = (g / n) & 0xFF;
      buffer2[j + 2] = (b / n) & 0xFF;
      buffer2[j + 3] = (a / n) & 0xFF;
    }

    if (x >= diameter) {
      var j = i - diameter * 4;
      r -= buffer1[j];
      g -= buffer1[j + 1];
      b -= buffer1[j + 2];
      a -= buffer1[j + 3];
      n--;
    }
  }
}

// Box blur along y
for (x = i = 0; x < width; x++, i -= diameter * 4) {
  for (y = r = g = b = a = n = 0; y < height + diameter; y++, i += 4) {
    if (y < height) {
      r += buffer2[i];
      g += buffer2[i + 1];
      b += buffer2[i + 2];
      a += buffer2[i + 3];
      n++;
    }

    if (y >= radius && y < height + radius) {
      var j = (x + (y - radius) * width) * 4;
      buffer3[j]     = (r / n) & 0xFF;
      buffer3[j + 1] = (g / n) & 0xFF;
      buffer3[j + 2] = (b / n) & 0xFF;
      buffer3[j + 3] = (a / n) & 0xFF;
    }

    if (y >= diameter) {
      var j = i - diameter * 4;
      r -= buffer2[j];
      g -= buffer2[j + 1];
      b -= buffer2[j + 2];
      a -= buffer2[j + 3];
      n--;
    }
  }
}
 
pending…
Uint8Array
var radius = 100;
var width = image.width;
var height = image.height;
var diameter = 2 * radius + 1;
var x, y, i, r, g, b, a, n;

// Box blur along x
for (y = i = 0; y < height; y++, i -= diameter * 4) {
  for (x = r = g = b = a = n = 0; x < width + diameter; x++, i += 4) {
    if (x < width) {
      r += buffer4[i];
      g += buffer4[i + 1];
      b += buffer4[i + 2];
      a += buffer4[i + 3];
      n++;
    }

    if (x >= radius && x < width + radius) {
      var j = ((x - radius) * height + y) * 4;
      buffer5[j]     = (r / n) & 0xFF;
      buffer5[j + 1] = (g / n) & 0xFF;
      buffer5[j + 2] = (b / n) & 0xFF;
      buffer5[j + 3] = (a / n) & 0xFF;
    }

    if (x >= diameter) {
      var j = i - diameter * 4;
      r -= buffer4[j];
      g -= buffer4[j + 1];
      b -= buffer4[j + 2];
      a -= buffer4[j + 3];
      n--;
    }
  }
}

// Box blur along y
for (x = i = 0; x < width; x++, i -= diameter * 4) {
  for (y = r = g = b = a = n = 0; y < height + diameter; y++, i += 4) {
    if (y < height) {
      r += buffer5[i];
      g += buffer5[i + 1];
      b += buffer5[i + 2];
      a += buffer5[i + 3];
      n++;
    }

    if (y >= radius && y < height + radius) {
      var j = (x + (y - radius) * width) * 4;
      buffer6[j]     = (r / n) & 0xFF;
      buffer6[j + 1] = (g / n) & 0xFF;
      buffer6[j + 2] = (b / n) & 0xFF;
      buffer6[j + 3] = (a / n) & 0xFF;
    }

    if (y >= diameter) {
      var j = i - diameter * 4;
      r -= buffer5[j];
      g -= buffer5[j + 1];
      b -= buffer5[j + 2];
      a -= buffer5[j + 3];
      n--;
    }
  }
}
 
pending…

Compare results of other browsers

Revisions

You can edit these tests or add even more tests to this page by appending /edit to the URL. Here’s a list of current revisions for this page:

0 comments

Add a comment