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.
Speeding up a canvas image crop
-
11-12-2021 - |
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?
Solution 2
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:
- Obtain the pixel coordinates at the
mouse down
. - Create an event listener for the
mouse move
. - Create a semi-transparent image over the original image and use the
fillRect
function to draw into the created canvas. - Create an event listener for
mouse up
. - Obtain the pixel coordinates at the
mouse up
. - Calculate the coordinates of the resulting square.
- Draw the resulting image into the canvas using as parameters the square coordinates.
- 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?