Изменение размера изображения холста без его размытия

У меня есть небольшое изображение, которое я рисую на холсте, например:

ctx.drawImage(img, 0, 0, img.width*2, img.height*2);

Я бы хотел, чтобы это показало резкое увеличенное изображение (4 одинаковых пикселя для каждого пикселя изображения). Однако этот код (в Chrome 29 на Mac) создает размытое изображение. В терминах Photoshop это похоже на использование повторной выборки "Bicubic" вместо "Nearest Neighbor".

В ситуации, когда это было бы полезно (например, ретро-игра), возможно ли создать резкое изображение с повышенным разрешением или мне нужно иметь отдельный файл изображения для каждого размера изображения на сервере?

Ответ 1

Просто отключите "сглаживание" холста для изображений - к сожалению, это свойство по-прежнему является префиксом поставщика, поэтому здесь представлены варианты:

context.webkitImageSmoothingEnabled = false;
context.mozImageSmoothingEnabled = false;
context.imageSmoothingEnabled = false; /// future

затем нарисуйте изображение.

При желании для более старых версий и браузеров, которые еще не реализовали это, вы можете использовать CSS:

canvas {
    image-rendering: optimizeSpeed;             // Older versions of FF
    image-rendering: -moz-crisp-edges;          // FF 6.0+
    image-rendering: -webkit-optimize-contrast; // Webkit (non standard naming)
    image-rendering: -o-crisp-edges;            // OS X & Windows Opera (12.02+)
    image-rendering: crisp-edges;               // Possible future browsers.
    -ms-interpolation-mode: nearest-neighbor;   // IE (non standard naming)
}

ПРОВЕРКА ОНЛАЙН ЗДЕСЬ

Ответ 2

Проверьте эту скрипту: http://jsfiddle.net/yPFjg/

Он загружает изображение в холст, затем создает измененную копию и использует это как спрайт.

С небольшими изменениями вы можете реализовать загрузчик изображений, который изменяет размеры изображений на лету.

var ctx = document.getElementById('canvas1').getContext('2d');
var img = new Image();
var original = document.createElement("canvas");
var scaled = document.createElement("canvas");

img.onload = function() {
    var oc = original.getContext('2d');
    var sc = scaled.getContext('2d');
    oc.canvas.width = oc.canvas.height = 16;
    sc.canvas.width = sc.canvas.height = 32;
    oc.drawImage(this, 0, 0);    
    var od = oc.getImageData(0,0,16,16);
    var sd = sc.getImageData(0,0,32,32);
    for (var x=0; x<32; x++) {
        for (var y=0; y<32; y++) {
            for (var c=0; c<4; c++) {        
                // you can improve these calculations, I let them so for clarity        
                sd.data[(y*32+x)*4+c] = od.data[((y>>1)*16+(x>>1))*4+c];
            }
        }
    }
    sc.putImageData(sd, 0, 0);
    ctx.drawImage(scaled, 0, 0);    
}

img.src = document.getElementById('sprite').src;

Некоторые примечания о getImageData: он возвращает объект с массивом. Массив имеет высоту * ширину * 4 размера. Цветовые компоненты хранятся в порядке RGBA (красный, зеленый, синий, альфа, по 8 бит каждое значение).