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.
source share