steve steve - 10 months ago 49
Javascript Question

Resize image with javascript canvas (smoothly)

I'm trying to resize some images with canvas but I'm clueless on how to smoothen them.
On photoshop, browsers etc.. there are a few algorithms they use (e.g. bicubic, bilinear) but I don't know if these are built into canvas or not.

Here's my fiddle:

var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0, 300, 234);

The first one is a normal resized image tag, and the second one is canvas. Notice how the canvas one is not as smooth. How can I achieve 'smoothness'?

Answer Source

You can use down-stepping to achive better results. Most browsers seem to use linear interpolation rather than bicubic when resizing images.

Unless one chooses no smoothing or nearest neighbor the browser will always interpolate the image after down-scaling it as this function as a low-pass filter to avoid aliasing.

Bilinear uses 2x2 pixels to do the interpolation while bi-cubic uses 4x4 so by doing it in steps you can get close to bi-cubic result while using bi-linear interpolation as seen in the resulting images.


/// when image is loaded:
img.onload = function () {

    /// set size proportional to image
    canvas.height = canvas.width * (img.height / img.width);

    /// step 1 - resize to 50%
    var oc = document.createElement('canvas'),
        octx = oc.getContext('2d');

    oc.width = img.width * 0.5;
    oc.height = img.height * 0.5;
    octx.drawImage(img, 0, 0, oc.width, oc.height);

    /// step 2 - resize 50% of step 1
    octx.drawImage(oc, 0, 0, oc.width * 0.5, oc.height * 0.5);

    /// step 3, resize to final size
    ctx.drawImage(oc, 0, 0, oc.width * 0.5, oc.height * 0.5,
    0, 0, canvas.width, canvas.height);
img.src = "";

Depending on how drastic your resize is you can might skip step 2 if the difference is less.

In the demo you can see the new result is now much similar to the image element.