Grayscale in Fabric.js is slow

I don’t think Fabric.js is an intruder here, because when I add time warnings, it only takes 2-3 seconds. However, the code used here is:

applyTo: function(canvasEl) { var context = canvasEl.getContext('2d'), imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), data = imageData.data, len = imageData.width * imageData.height * 4, index = 0, average; while (index < len) { average = (data[index] + data[index + 1] + data[index + 2]) / 3; data[index] = average; data[index + 1] = average; data[index + 2] = average; index += 4; } context.putImageData(imageData, 0, 0); }, 

So, if it is not an intruder, then the intruder is the putImageData function.

Is there a way to increase / optimize this function so that it works with a 5000x5000 image, of course, in less than 15 seconds?

If not, is there a way to set a “working” icon, which is deleted only after putImageData is completed via jQuery, because at the moment it is deleted after 2 seconds, because the Fabric.js code ends faster?

+4
source share
2 answers

If putImageData takes the most time, you cannot do much to improve your speed, as this is a low-level feature offered by the browser.

What you can do is gradually process the image and display it to the user without blocking the browser for 15 seconds.

Tip. Instead of synchronizing script execution with time warnings, I suggest using only the Chrome developer tools. They have a great javascript profiling tool and more specifically canvas drawing.

Google Developer Tools Flame Chart

+1
source

I am not very familiar with fabric.js, but your possibilities for optimization are very limited by the canvas. Putting your variables right after each other, rather than creating an average variable, will save you a little time:

 data[index] = data[index+1] = data[index+2] = (data[index] + data[index + 1] + data[index + 2]) / 3; index+=4; 

You can also try putting data on the canvas in rows. This will not speed up the work, but if you have such a large canvas, it will be useful to show the user some progress. In the following example, I did this and changed the while loop to two for loops, because I like it better for loops :)

 for(var i=0;i<imageData.height;i++) { var row = context.getImageData(0, i, canvasEl.width, 1); for(var j=0;j<imageData.width*4;j+=4) { row.data[index] = row.data[index+1] = row.data[index+2] = (row.data[index] + row.data[index + 1] + row.data[index + 2]) / 3; context.putImageData(row, 0, i); } } 
0
source

Source: https://habr.com/ru/post/1496187/


All Articles