javascript HTML5 - Canvas, drawImage() 绘制图像模糊
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/31910043/
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
HTML5 - Canvas, drawImage() draws image blurry
提问by Zeng Cheng
I am trying to draw the following image to a canvas but it appears blurry despite defining the size of the canvas. As you can see below, the image is crisp and clear whereas on the canvas, it is blurry and pixelated.
我正在尝试将以下图像绘制到画布上,但尽管定义了画布的大小,但它仍然显得模糊。正如您在下面看到的,图像清晰而清晰,而在画布上,它是模糊和像素化的。
and here is how it looks (the left one being the original and the right one being the drawn-on canvas and blurry.)
这是它的外观(左边的是原始的,右边的是画布上的,模糊的。)
What am I doing wrong?
我究竟做错了什么?
console.log('Hello world')
var c = document.getElementById('canvas')
var ctx = c.getContext('2d')
var playerImg = new Image()
// http://i.imgur.com/ruZv0dl.png sees a CLEAR, CRISP image
playerImg.src = 'http://i.imgur.com/ruZv0dl.png'
playerImg.width = 32
playerImg.height = 32
playerImg.onload = function() {
ctx.drawImage(playerImg, 0, 0, 32, 32);
};
#canvas {
background: #ABABAB;
position: relative;
height: 352px;
width: 512px;
z-index: 1;
}
<canvas id="canvas" height="352" width="521"></canvas>
回答by Canvas
The reason this is happening is because of Anti Aliasing.
Simply set the imageSmoothingEnabled
to false like so
发生这种情况的原因是抗锯齿。imageSmoothingEnabled
像这样简单地设置为 false
context.imageSmoothingEnabled = false;
Here is a jsFiddle verson
这是一个 jsFiddle 版本
jsFiddle : https://jsfiddle.net/mt8sk9cb/
jsFiddle:https://jsfiddle.net/mt8sk9cb/
var c = document.getElementById('canvas')
var ctx = c.getContext('2d')
var playerImg = new Image()
// http://i.imgur.com/ruZv0dl.png sees a CLEAR, CRISP image
playerImg.src = 'http://i.imgur.com/ruZv0dl.png'
playerImg.onload = function() {
ctx.imageSmoothingEnabled = false;
ctx.drawImage(playerImg, 0, 0, 256, 256);
};
回答by Kaiido
Your problem is that your css constraints of canvas{width:512}
vs the canvas property width=521
will make your browser resample the whole canvas.
您的问题是您的canvas{width:512}
vs 画布属性的css 约束width=521
将使您的浏览器重新采样整个画布。
To avoid it, remove those css declarations.
为避免这种情况,请删除那些 css 声明。
var c = document.getElementById('canvas')
var ctx = c.getContext('2d')
var playerImg = new Image()
// http://i.imgur.com/ruZv0dl.png sees a CLEAR, CRISP image
playerImg.src = 'http://i.imgur.com/ruZv0dl.png'
playerImg.width = 32
playerImg.height = 32
playerImg.onload = function() {
ctx.drawImage(playerImg, 0, 0, 32, 32);
};
#canvas {
background: #ABABAB;
position: relative;
z-index: 1;
}
<canvas id="canvas" height="352" width="521"></canvas>
Also, if you were resampling the image (from 32x32 to some other size), @canvas' solution would have been the way to go.
此外,如果您对图像进行重新采样(从 32x32 到其他尺寸),@canvas 的解决方案将是可行的方法。
回答by Diniden
As I encountered this older post for some of my issues, here's even more additional insight to blurry images to layer atop the 'imageSmoothingEnabled' solution.
当我针对我的一些问题遇到这篇较旧的帖子时,这里有更多关于模糊图像的更多见解,以便在“imageSmoothingEnabled”解决方案之上进行分层。
This is more specifically for the use case of monitor specific rendering and only some people will have encountered this issue if they have been trying to render retina quality graphics into their canvas with disappointing results.
这更具体地针对监视器特定渲染的用例,如果他们一直试图将视网膜质量的图形渲染到他们的画布中,结果令人失望,那么只有一些人会遇到这个问题。
Essentially, high density monitors means your canvas needs to accommodate that extra density of pixels. If you do nothing your, canvas will only render enough pixel information into it's context to account for a pixel ratio of 1.
从本质上讲,高密度显示器意味着您的画布需要容纳额外的像素密度。如果你什么都不做,画布只会将足够的像素信息渲染到它的上下文中,以考虑像素比为 1。
So for many modern monitors who have ratios > 1, you should change your canvas context to account for that extra information but keep your canvas the normal width and height.
因此,对于比率 > 1 的许多现代显示器,您应该更改画布上下文以考虑这些额外信息,但保持画布的正常宽度和高度。
To do this you simply set the rendering context width and height to: target width and height * window.devicePixelRatio.
为此,您只需将渲染上下文的宽度和高度设置为:目标宽度和高度 * window.devicePixelRatio。
canvas.width = target width * window.devicePixelRatio;
canvas.height = target height * window.devicePixelRatio;
Then you set the style of the canvas to size the canvas in normal dimensions:
然后设置画布的样式以按正常尺寸调整画布的大小:
canvas.style.width = `${target width}px`;
canvas.style.height = `${target height}px`;
Last you render the image at the maximum context size the image allows. In some cases (such as images rendering svg), you can still get a better image quality by rendering the image at pixelRatio sized dimensions:
最后以图像允许的最大上下文大小渲染图像。在某些情况下(例如图像渲染 svg),您仍然可以通过以 pixelRatio 大小的尺寸渲染图像来获得更好的图像质量:
ctx.drawImage(
img, 0, 0,
img.width * window.devicePixelRatio,
img.height * window.devicePixelRatio
);
So to show off this phenomenon I made a fiddle. You will NOT see a difference in canvas quality if you are on a pixelRatio monitor close to 1.
所以为了炫耀这种现象,我做了一个小提琴。如果您在像素比率接近 1 的显示器上,您将看不到画布质量的差异。
回答by Jeff Tian
The following code works for me:
以下代码对我有用:
img.onload = function () {
canvas.width = img.width;
canvas.height = img.height;
context.drawImage(img, 0, 0, img.width, img.height, 0, 0, img.width, img.height);
};
img.src = e.target.result; // your src
回答by aleha
In addition to @canvas answer.
除了@canvas 的回答。
context.imageSmoothingEnabled = false;
Works perfect. But in my case changing size of canvas resetting this property back to true.
工作完美。但是在我的情况下,更改画布的大小将此属性重置为 true。
window.addEventListener('resize', function(e){
context.imageSmoothingEnabled = false;
}, false)
回答by NeoGriever
Simple tip: draw with .5 in x and y position. like drawImage(, 0.5, 0.5) :D There you get crisp edges :D
简单提示:在 x 和 y 位置用 .5 绘制。像 drawImage(, 0.5, 0.5) :D 你会得到清晰的边缘 :D