2

I have got a canvas and I display image using it via the putImageData() method after updating bytes in clamped array got by getImageData.data.

That works nicely, but I need to scale *2 in Y-direction.

Of course I can do it without a question here too by repeating every lines twice, but it requires too much time to render a frame then (I display 25 frames per second). I've read about the ability to scale image with drawImage() method. The only problem that as far as I know, using drawImage() is slower than using putImageData(), and it was required in old browser versions like Firefox/2 (or such).

How can I upscale the image in Y direction twice as fast as possible?

By the way, is it possible to get similar solution to gain full screen resolution somehow (a flash - not JS - example: like what youtube does when you go to fullscreen)?

Darth Hunterix
  • 1,484
  • 5
  • 27
  • 31
LGB
  • 728
  • 1
  • 9
  • 20

2 Answers2

7

If you want the whole canvas to scale, you can do this without any extra javascript. Just set a size in CSS that has twice the width and height specified in the canvas.

<canvas width="200" height="100" style="width:200; height: 200">

See the W3 spec.

Edit:

Looking at the question linked by Alnitak below: If you want nearest-neighbor scaling rather than antialiasing you can do this:

canvas {
    image-rendering: -moz-crisp-edges;
    image-rendering: -o-crisp-edges;
    image-rendering: -webkit-optimize-contrast;
    -ms-interpolation-mode: nearest-neighbor;
}
Russell Zahniser
  • 16,188
  • 39
  • 30
  • but note that this will cause anti-aliasing. That may be a good thing, or it may not... – Alnitak Jul 01 '13 at 14:11
  • Hmm. Is there any anti-aliasing, if I do scale exactly by *2? It can be a nice solution, but I don't know how much CPU time is consumed by the browser then to do it, since I am out of resources already quire heavily. It's good for me if it's still faster than doing it "by hand" in JS. But I will try and compare the result, thanks for your answer! – LGB Jul 01 '13 at 14:14
  • yes, even at exactly *2 it'll anti-alias - see http://stackoverflow.com/a/8597422/6782 – Alnitak Jul 01 '13 at 14:17
  • Thanks. I am curious (but it would be another question) if it can be done better (more control on the method, maybe faster) with WebGL or something similar though. – LGB Jul 01 '13 at 14:30
4

You can achieve vertical scaling (without anti-aliasing) by just grabbing one image row at a time with getImageData and then replicating that row multiple times with putImageData, e.g.:

var oy = 0;
for (var y = 0; y < sh; ++y) {
    var data = src_ctx.getImageData(0, y, sw, 1);
    for (var n = 0; n < scale; ++n) {
        dst_ctx.putImageData(data, 0, oy++);
    }
}

See http://jsfiddle.net/alnitak/hYZ3U/ for a worked example that completes in 3ms on my machine.

Alnitak
  • 334,560
  • 70
  • 407
  • 495
  • 1
    Thanks. Now it's time for me to do some test and benchmark which looks better and which is the faster :) – LGB Jul 01 '13 at 15:52
  • @LGB the CSS scaling method will almost certainly be faster, since it just offloads the work to the rendering system. However the anti-aliasing it produces might well be undesirable. – Alnitak Jul 01 '13 at 15:53