image threshold loop vs globalCompositeOperation

JavaScript performance comparison

Test case created by willw1

Preparation code

<canvas id="canvasTest" ></canvas>
      
<script>
Benchmark.prototype.setup = function() {
  //--- on-screen canvas
  var onScreenCanvas=document.getElementById("canvasTest");
  var ctxOnScreen=onScreenCanvas.getContext("2d");
  
  //--- off-screen working canvas
  var drawingCanvas = document.createElement('canvas');
  var ctx=drawingCanvas.getContext("2d");
  
  //--- off-screen canvas to store the greyscale image
  var greyscaleImageCanvas = document.createElement('canvas');
  var ctxGreyscaleImage=greyscaleImageCanvas.getContext("2d");
  
  var image = new Image();
  
  function img2grey(canvasContext) {
      canvasContext.globalCompositeOperation='color';
      canvasContext.fillStyle='white';
      canvasContext.fillRect(0,0,onScreenCanvas.width,onScreenCanvas.height);
  }
  
  function thresholdImage_forloop() {
      var thresh_val = 0.5;
      var imgData = ctxGreyscaleImage.getImageData(0, 0, onScreenCanvas.width, onScreenCanvas.height)
      var d = imgData.data;
      var nv, i
      for (i = 0; i < d.length; i += 4) {
          if (d[i] < thresh_val) {
              nv = 0;
          } else {
              nv = 255;
          }                
          d[i] = nv;
          d[i+1] = nv;
          d[i+2] = nv;
      }
      imgData.data.set(d);
      ctxOnScreen.putImageData(imgData,0,0);
  }
  
  function thresholdImage_globalCompositeOperation() {
  
      thresh_str = '#7f7f7f';
      ctxOnScreen.clearRect(0, 0, onScreenCanvas.width, onScreenCanvas.height);
      ctx.clearRect(0, 0, drawingCanvas.width, drawingCanvas.height);
  
      //----- (1) Threshold the image on the offscreen working canvas, 
      // reducing values above threshold to have threshold value
      ctx.drawImage(greyscaleImageCanvas, 0, 0);
      ctx.globalCompositeOperation='darken';
      ctx.fillStyle=thresh_str;
      ctx.fillRect(0,0,onScreenCanvas.width,onScreenCanvas.height);
      
      //----- (2) Set everything *below* threshold to 0 (black) since that part is unchanged
      // from the original image
      ctx.globalCompositeOperation='difference';
      ctx.drawImage(greyscaleImageCanvas, 0, 0);
  
      //----- (3) Copy the result to the onscreen canvas
      ctxOnScreen.globalCompositeOperation='copy';
      ctxOnScreen.drawImage(drawingCanvas, 0, 0);
  
      //----- (4) Invert the result of step (2) so that it can be 'un-inverted' by color dodge
      ctx.globalCompositeOperation='difference';
      ctx.fillStyle='white';
      ctx.fillRect(0,0,onScreenCanvas.width,onScreenCanvas.height);
      
      //----- (5) 'color-dodge' the results of (2) with it's own inverse (4) 
      //----- This makes use of 0/0 defined as 0 in this globalCompositeOperation,
      //----- so that non-zero (suprathreshold) pixels become 1, zero (sub-threshold) pixels stay zero
      //~ ctxOnScreen.globalCompositeOperation='color-dodge';
      ctxOnScreen.globalCompositeOperation='color-dodge';
      ctxOnScreen.drawImage(drawingCanvas, 0, 0);
  
  }
  
  image.onload = function() {
      onScreenCanvas.width = image.width;
      onScreenCanvas.height = image.height;
      drawingCanvas.width = image.width;
      drawingCanvas.height = image.height;
      greyscaleImageCanvas.width = image.width;
      greyscaleImageCanvas.height = image.height;
      ctxGreyscaleImage.drawImage(image, 0, 0);
      img2grey(ctxGreyscaleImage);
  }
  
  //image.src = "http://i.imgur.com/P40qoSy.jpg";
  //image.src = "https://i.imgur.com/vN0NbVu.jpg";
  image.src = "https://i.imgur.com/UDc9ioj.jpg";
  

};
</script>

Preparation code output

<canvas id="canvasTest" ></canvas>

Test runner

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

Java applet disabled.

Testing in CCBot 2.0.0 / Other 0.0.0
Test Ops/sec
for loop
thresholdImage_forloop();
pending…
globalcompositeoperation
thresholdImage_globalCompositeOperation();
pending…

You can edit these tests or add even more tests to this page by appending /edit to the URL.

0 Comments