0

I have two visible canvases one which uses drawImage and another one where I copy pixels from a hidden (buffer) canvas. Except that everything is the same but when I move the object by some non-integer value the objects starts to stutter. I suspect that flooring while copying pixels is the problem but I'd like to ask how to do this to produce the same result as drawImage?

I set up the jsfiddle.

(object on the right side stutters)

Function which copies pixels.

function draw2()
{
    var canvasData = ctx2.createImageData(canvas2.width, canvas2.height),
        cData = canvasData.data;

        for (var w = 0; w < imgToDraw.width; w++)
        {
            for (var h = 0; h < imgToDraw.height; h++)
            {
                if (elm.x + w < canvas2.width && elm.x + w > 0 &&
                    elm.y + h > 0 && elm.y + h < canvas2.height)
                {
                    var iData = (h * imgToDraw.width + w) * 4;
                    var pData = (Math.floor(elm.x + w) + Math.floor(elm.y + h) * canvas2.width) * 4;

                    cData[pData] = imagePixData[iData];
                    cData[pData + 1] = imagePixData[iData + 1];
                    cData[pData + 2] = imagePixData[iData + 2];
                    cData[pData + 3] = imagePixData[iData + 3];
                }
            }
        }    
    ctx2.putImageData(canvasData, 0, 0);    
}

I suspect line 14 (jsfiddle line 102):

var pData = (~~ (elm.x + w) + ~~ (elm.y + h) * canvas2.width) * 4;

I could use Math.round or Math.ceil instead of ~~ to get the desired result but I don't know which would be better or how drawImage handles this?

Original code by @Loktar - stackoverflow.

Community
  • 1
  • 1
Vico Lemp
  • 133
  • 12
  • You're right that `Math.round` would fix it because the element won't always be positioned on a sub-pixel with a fraction of less than 0.5. As for how `drawImage` handles it, it just copies an image to a canvas so it doesn't really matter to `drawImage` how you write that original image data. – Mike Cluck Mar 22 '16 at 15:53
  • DrawImage doesn't need to decide where to draw when the position is deciaml like 150.5? I thought it does the exactly same thing, I need to lear more :-). If that's so thanks I would select your answer if you want to make one. – Vico Lemp Mar 22 '16 at 16:02
  • drawImage does use anti-aliasing, which becomes really handy when drawing on sub-pixels (non integer coordinates). To do so, it will take the color already present on the implied pixels, and apply some alpha and color manipulations on the pixels concerned so it looks like smaller than a pixel. The calculation is quite complex and made by the GPU. Unfortunately, you're in an edge case where you need to go faster than `drawImage`, so trying to reimplement by your own drawImage's functions is a no-go. For normal cases, `drawImage(canvas,x,y)` would be the solution. – Kaiido Mar 23 '16 at 01:18
  • In the other thread I talked about `Math.ceil` for right part of your image because you do draw a circle, so we could assume that all the left part needs to be floored and all the right part needs to be ceiled. This will produce rough edges, but normally, no transparent pixels. – Kaiido Mar 23 '16 at 01:18

0 Answers0