Question

I'm working on a simple image crop where the user draws a line with the mouse around an area that they want to keep. When they confirm, the rest of the image will be cropped out. Here's how I'm currently handling said cropping:

var data = c.getImageData(0,0,canvas.width,canvas.height);      
for (var x = 0; x < data.width; x++) {
   for (var y = 0; y < data.height; y++) {
      if (!c.isPointInPath(x,y)) {
         var n = x + (data.width * y);
         var index = n*4; 
         data.data[index+3] = 0;
      }
   }
}

However, this can bog down really quickly. The less of the image you try to retain, the faster it goes, but even saving 30% of the image (canvas is 800x800) causes it to hang for several seconds. Is there a faster way to go about this?

Was it helpful?

Solution 2

There is no real way to speed it up when you have to use a user defined shape, but the bogging down can be handled with a worker.

OTHER TIPS

I don't really understand why you are diving into pixel details to manipulate your cropping image functionality. It's understandable as bigger the image is get as more time is needed for cropping out the rest of the image, because practically with iterating over a two dimensional array of pixels the processing time needed for the operation is exponentially increasing with the increasing in size of the pixels map.

So my suggestion would be to try to remake the function without to even touch the getImageData and putImageData function. It's useless. I would make in the following way:

  1. Obtain the pixel coordinates at the mouse down.
  2. Create an event listener for the mouse move.
  3. Create a semi-transparent image over the original image and use the fillRect function to draw into the created canvas.
  4. Create an event listener for mouse up.
  5. Obtain the pixel coordinates at the mouse up.
  6. Calculate the coordinates of the resulting square.
  7. Draw the resulting image into the canvas using as parameters the square coordinates.
  8. As a final step draw the content of the canvas to an image.

This way you will save a lot of overhead on image cropping processing.

Here is a script for your reference: https://github.com/codepo8/canvascropper/blob/master/canvascrop.js

Some ideas:

Restrict getImageData to the bounding box of the polygon the user draws.

Put data.height, data.width etc. used inside the loop in a variable.

Maybe you can split up inside/outside tests and setting the imagedata alpha value.

Maybe even draw the polygon to a black and white imagedata object, then get the difference between the two?

Can you share the isPointInPath(x,y) function?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top