How to stretch images with no antialiasing

Solution 1:

The Canvas documentation explicitly does not specify a scaling method - in my own tests it did indeed anti-alias the image quite badly in Firefox.

The code below copies pixel by pixel from a source image (which must be from the same Origin or from a Data URI) and scales it by the specified factor.

An extra off-screen canvas (src_canvas) is required to receive the original source image, and its image data is then copied pixel by pixel into an on-screen canvas.

var img = new Image();
img.src = ...;
img.onload = function() {

    var scale = 8;

    var src_canvas = document.createElement('canvas');
    src_canvas.width = this.width;
    src_canvas.height = this.height;

    var src_ctx = src_canvas.getContext('2d');
    src_ctx.drawImage(this, 0, 0);
    var src_data = src_ctx.getImageData(0, 0, this.width, this.height).data;

    var dst_canvas = document.getElementById('canvas');
    dst_canvas.width = this.width * scale;
    dst_canvas.height = this.height * scale;
    var dst_ctx = dst_canvas.getContext('2d');

    var offset = 0;
    for (var y = 0; y < this.height; ++y) {
        for (var x = 0; x < this.width; ++x) {
            var r = src_data[offset++];
            var g = src_data[offset++];
            var b = src_data[offset++];
            var a = src_data[offset++] / 100.0;
            dst_ctx.fillStyle = 'rgba(' + [r, g, b, a].join(',') + ')';
            dst_ctx.fillRect(x * scale, y * scale, scale, scale);
        }
    }
};

Working demo at http://jsfiddle.net/alnitak/LwJJR/

EDIT a more optimal demo is available at http://jsfiddle.net/alnitak/j8YTe/ that also uses a raw image data array for the destination canvas.

Solution 2:

I've gotten this to work for canvas

var canvas = document.getElementById("canvas"),
    context = canvas.getContext('2d');
context.webkitImageSmoothingEnabled = context.imageSmoothingEnabled = context.mozImageSmoothingEnabled = context.oImageSmoothingEnabled = false;

Solution 3:

The only way I can think of is via canvas. You can try simply drawing the image to a canvas and then scaling the canvas -- I think that you won't get anti-aliasing this way. If you still do, you can try either scaling the image in the draw call or if that doesn't work, you could use getImageData and putImageData to scale the image "by hand"

update: first method works: http://jsfiddle.net/nUVJt/3/