19

我有一个小图像,我正在画布上渲染,如下所示:

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

我希望它显示一个清晰的放大图像(每个图像像素有 4 个相同的像素)。但是,此代码(在 Mac 上的 Chrome 29 中)会产生模糊的图像。在 Photoshop 术语中,它看起来像是在使用“Bicubic”重采样,而不是“Nearest Neighbour”。

在有用的情况下(例如复古游戏),是否可以生成清晰的放大图像,或者我是否需要在服务器上为每种尺寸的图像创建一个单独的图像文件?

4

2 回答 2

34

只需关闭画布的图像抗锯齿功能 - 不幸的是,这个属性仍然是供应商前缀,所以这里有一些变化:

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

然后绘制图像。

(可选)对于尚未实现此功能的旧版本和浏览器,您可以改用 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)
}

在线测试在这里

于 2013-09-01T07:10:36.327 回答
4

检查这个小提琴: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 顺序存储(红、绿、蓝、alpha,每个值 8 位)。

于 2013-08-31T12:02:40.803 回答