javascript 在不模糊的情况下调整画布图像的大小
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18547042/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Resizing a canvas image without blurring it
提问by JJJollyjim
I have a small image, which I am rendering on a canvas, like this:
我有一个小图像,正在画布上渲染,如下所示:
ctx.drawImage(img, 0, 0, img.width*2, img.height*2);
I would like this to show a sharp upsized image (4 identical pixels for each image pixel). However, this code (in Chrome 29 on Mac) makes a blurry image. In Photoshop terms, it looks like it's using "Bicubic" resampling, instead of "Nearest Neighbour".
我希望这能显示一个清晰的放大图像(每个图像像素有 4 个相同的像素)。但是,此代码(在 Mac 上的 Chrome 29 中)会产生模糊的图像。在 Photoshop 术语中,它看起来像是在使用“双三次”重采样,而不是“最近邻”。
In a situation where it would be useful (eg. a retro game), Is it possible to produce a sharp upsized image, or do I need to have a seperate image file for each size of the image on the server?
在它有用的情况下(例如复古游戏),是否可以生成清晰的放大图像,或者我是否需要为服务器上的每种尺寸的图像提供单独的图像文件?
回答by
Simply turn off canvas' anti-aliasing for images - unfortunately this property is still vendor prefixed so here are the variations:
只需关闭画布对图像的抗锯齿 - 不幸的是,此属性仍然是供应商前缀,因此这里是变体:
context.webkitImageSmoothingEnabled = false;
context.mozImageSmoothingEnabled = false;
context.imageSmoothingEnabled = false;
then draw the image.
然后绘制图像。
Optionally for older versions and browsers which hasn't implemented this yet, you can use CSS instead:
对于尚未实现此功能的旧版本和浏览器(可选),您可以改用 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)
}
回答by Pedro L.
Check this fiddle: http://jsfiddle.net/yPFjg/
检查这个小提琴:http: //jsfiddle.net/yPFjg/
It loads the image into a canvas, then creates a resized copy and uses that as sprite.
它将图像加载到画布中,然后创建一个调整大小的副本并将其用作精灵。
With few modifications, you can implement an image loader that resizes images on the fly.
只需稍加修改,您就可以实现动态调整图像大小的图像加载器。
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;
Some notes about getImageData: it returns an object with an array. The array has a height*width*4 size. The color components are stored in RGBA order (red, green, blue, alpha, 8 bits each value).
关于 getImageData 的一些注意事项:它返回一个带有数组的对象。该数组具有高度*宽度*4 大小。颜色分量按 RGBA 顺序存储(红色、绿色、蓝色、alpha,每个值 8 位)。