Trying to optimize the algorithm for the percentage of a certain color in the canvas

I have the following small barcode that I use to determine the percentage of color on the canvas, in this case the color is transparent, which returns imageData.data as [0,0,0,0]

Since I return this percentage to mouseove, it is quite expensive to run it, trying to optimize it. Also keep in mind that the color of the canvas is constantly changing, so I need to capture imageData every time and scroll through it.

The bottleneck is all in the scratchPercentage function, of course, I need to optimize this, for example, only get new changes and not run all the image data every time.

scratchFunc: function(e, $this, event) { e.pageX = Math.floor(e.pageX - $this.canvas_offset.left); e.pageY = Math.floor(e.pageY - $this.canvas_offset.top); $this['scratch' + event](e, $this); if($this.settings['scratch' + event]) $this.settings['scratch' + event](e, $this.scratchPercentage($this)); }, scratchPercentage: function($this) { var hits = 0; var imageData = $this.ctx.getImageData(0,0,$this.canvas.width,$this.canvas.height) for(var i=0, ii=imageData.data.length; i<ii; i=i+4) { if( imageData.data[i] == 0 && imageData.data[i+1] == 0 && imageData.data[i+2] == 0 && imageData.data[i+3] == 0 ) hits++; } return hits / ($this.pixels) * 100; }, 
+4
source share
2 answers

Start with this modification:

 scratchPercentage: function($this) { var hits = 0; var imageData = $this.ctx.getImageData(0,0,$this.canvas.width,$this.canvas.height).data var pixels = imageData.length; for(var i=0, ii=pixels; i<ii; i=i+4) { if( imageData[i] == 0 && imageData[i+1] == 0 && imageData[i+2] == 0 && imageData[i+3] == 0 ) hits++; } return hits / ($this.pixels) * 100; } 

I don't have a reference link convenient for this, but saving the handle to your canvas data array saves your loop to allow the location of the pixel data at each iteration. This actually leads to a significant increase in productivity. Similarly, although this is not so important, you can also assign a variable to the size of your array so that you do not have to resolve the value after each iteration of the loop.

Besides these two changes, I don’t think you can make scratchPercentage() any more compact. Without knowing the details of how your canvas changes from frame to frame, I can not offer any optimizations just to calculate the changes. Depending on your exact needs, you can check every other pixel.

I can also think of a crude WebGL solution, but that would not be straightforward. Ultimately, if you do not have consistent information about what has changed between the current and previous frames, you will not be able to pre-calculate this percentage or significantly speed it up.

Edit: Depending on the size of the canvas, you can try resizing the copy in memory by 50% and do your calculations. It will not be perfect, but it should be relatively accurate.

+2
source

1) Reduce the sampling rate.

Do not call calculations every time the mousemove event occurs, but rather save mouseX, mouseY, and then call the sample function in setInterval (experiment with an interval value - where 100% accurate and safe value is the interval of your rendering loop)

or use some throttle function, for example at http://documentcloud.github.com/underscore/#throttle

2) If this function does not have to be highly accurate, skip some pixels

let's say every second for (...; i = i + 8)

+1
source

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


All Articles