A faster way to copy image data

i has the following script

// copy image data to secondary canvas
var pixelData = contextSource.getImageData(x - (lineWidth/2), y - (lineWidth/2), lineWidth, lineWidth);
var tmpCanvas = document.createElement('canvas');
tmpCanvas.width = tmpCanvas.height = lineWidth;
var tmpContext = tmpCanvas.getContext('2d');

tmpContext.putImageData(pixelData, 0, 0);

contextDest.save();
contextDest.arc(x, y, (lineWidth/2), 0, 2*Math.PI);
contextDest.clip();
contextDest.drawImage(tmpCanvas, x - (lineWidth/2), y - (lineWidth/2));
contextDest.restore();

      

The script is fetching image data from the canvas source as the mouse moves over the source and then copies it to the destination. The script works well, but is slightly slower. here is the result when i move my mouse a little faster.

enter image description here

Is there a faster method than mine? please, help

+3


source to share


1 answer


enter image description here

@ Banana has a good point.

Instead of drawing just the mouse positions, try connecting the positions to one continuous line.

If you want to use the rounded effect on the illustration, you can set:

context.lineCap='round';
context.lineJoin='round';

      

As for cloaking faster ...

A faster way to mask your image:



  • draw one line on the second canvas.
  • Use composition so that all new drawings are visible only where the existing pixels are opaque. This compositing is "native" and is installed with:context.globalCompositeOperation='source-in'

  • Draw the image on the second canvas. The image will only show where the line was.

Using layout is much faster as the layout is hardware accelerated and browser optimizations.

This link code might look like this:

function draw(){
    // clear the second canvas
    ctx1.clearRect(0,0,cw,ch);

    // draw your continuous line 
    ctx1.beginPath();
    ctx1.moveTo(points[0].x,points[0].y);
    for(var i=1;i<points.length;i++){
        p=points[i];
        ctx1.lineTo(p.x,p.y);
    }
    ctx1.stroke();

    // set compositing so new draws only appear in 
    // existing opaque pixels
    ctx1.globalCompositeOperation='source-in';

    // draw the image
    // the image will only be visible in the exising line
    ctx1.drawImage(img,0,0);

    // be tidy! return compositing to its default mode
    ctx1.globalCompositeOperation='source-over';
}

      

Here's an example and demo:

var canvas1=document.getElementById("canvas1");
var ctx1=canvas1.getContext("2d");

var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var $canvas=$("#canvas");
var canvasOffset=$canvas.offset();
var offsetX=canvasOffset.left;
var offsetY=canvasOffset.top;
var scrollX=$canvas.scrollLeft();
var scrollY=$canvas.scrollTop();

var isDown=false;
var startX;
var startY;

var points=[];
var cw,ch;

var img=new Image();
img.onload=start;
img.src="https://dl.dropboxusercontent.com/u/139992952/stackoverflow/tempHouse%201.jpg";
function start(){
  cw=canvas.width=canvas1.width=img.width;
  ch=canvas.height=canvas1.height=img.height;

  ctx1.lineCap = "round";
  ctx1.lineJoin = "round";
  ctx1.lineWidth=20;

  ctx.drawImage(img,0,0);

  $("#canvas").mousedown(function(e){handleMouseDown(e);});
  $("#canvas").mousemove(function(e){handleMouseMove(e);});
  $("#canvas").mouseup(function(e){handleMouseUp(e);});
  $("#canvas").mouseout(function(e){handleMouseOut(e);});
}


function draw(){
  // clear the second canvas
  ctx1.clearRect(0,0,cw,ch);

  // draw your continuous line 
  ctx1.beginPath();
  ctx1.moveTo(points[0].x,points[0].y);
  for(var i=1;i<points.length;i++){
    p=points[i];
    ctx1.lineTo(p.x,p.y);
  }
  ctx1.stroke();

  // set compositing so new draws only appear in 
  // existing opaque pixels
  ctx1.globalCompositeOperation='source-in';

  // draw the image
  // the image will only be visible in the exising line
  ctx1.drawImage(img,0,0);

  // be tidy! return compositing to its default mode
  ctx1.globalCompositeOperation='source-over';
}


function handleMouseDown(e){
  e.preventDefault();
  e.stopPropagation();
  mouseX=parseInt(e.clientX-offsetX);
  mouseY=parseInt(e.clientY-offsetY);
  points.length=0;
  points.push({x:mouseX,y:mouseY});
  isDown=true;
}

function handleMouseUp(e){
  e.preventDefault();
  e.stopPropagation();
  isDown=false;
  draw();
}

function handleMouseOut(e){
  e.preventDefault();
  e.stopPropagation();
  mouseX=parseInt(e.clientX-offsetX);
  mouseY=parseInt(e.clientY-offsetY);
  points.push({x:mouseX,y:mouseY});
  isDown=false;
  draw();
}

function handleMouseMove(e){
  if(!isDown){return;}
  e.preventDefault();
  e.stopPropagation();
  mouseX=parseInt(e.clientX-offsetX);
  mouseY=parseInt(e.clientY-offsetY);
  points.push({x:mouseX,y:mouseY});
  draw();
}
      

body{ background-color: ivory; }
canvas{border:1px solid red;}
      

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<canvas id="canvas" width=300 height=300></canvas><br>
<canvas id="canvas1" width=300 height=300></canvas>
      

Run codeHide result


+3


source







All Articles