简体   繁体   English

上下文旋转后为什么图像质量下降?

[英]Why do images lose quality after the context has been rotated?

I'm making a top-down shooter game that relies on the avatar always being rotated pointing to the mouse cursor. 我正在制作一个自上而下的射击游戏,依赖于头像始终旋转指向鼠标光标。 I achieve rotation like this: 我像这样实现轮换:

//Rendering.
context.save(); //Save the context state, we're about to change it a lot.

context.translate(position[0] + picture.width/2, position[1] + picture.height/2); //Translate the context to the center of the image.
context.rotate(phi); //Rotate the context by the object's phi.
context.drawImage(picture.image, -picture.width/2, -picture.height/2); //Draw the image at the appropriate position (center of the image = [0, 0]).

context.restore(); //Get the state back.

When the phi is zero, the image is rendered in its normal quality, with sharp edges and detectable pixels. phi为零时,图像以其正常质量渲染,具有锐边和可检测像素。 But, when I set the phi to a nonzero value (actually, when it's not 0 , Pi/2 , Pi , Pi+Pi/2 or 2Pi ), the image looses it's sharpness and the individual pixels can't be seen anymore, because they are blurred out. 但是,当我将phi设置为非零值时(实际上,当它不是0Pi/2PiPi+Pi/22Pi ),图像会失去它的清晰度,并且不再能看到单个像素,因为他们模糊了

Here's a screenshot (sorry about the general bad quality of the screenshot, but I think that the difference is more than noticeable): 这是一个截图(抱歉屏幕截图的一般质量不好,但我认为差异非常明显):

在此输入图像描述

This is, well, a bit unacceptable. 这有点令人无法接受。 I can't have the images always blurred out! 我不能让图像总是模糊不清! Why is this happening and can I solve it? 为什么会这样,我能解决吗?

You could try 你可以试试

context.imageSmoothingEnabled = false;

See docs : 查看文档

context.imageSmoothingEnabled [ = value ] context.imageSmoothingEnabled [= value]

Returns whether pattern fills and the drawImage() method will attempt to smooth images if they have to rescale them (as opposed to just rendering the images with "big pixels"). 返回模式填充和drawImage()方法是否会尝试平滑图像,如果它们必须重新缩放它们(而不是仅使用“大像素”渲染图像)。

Can be set, to change whether images are smoothed (true) or not (false). 可以设置,以更改图像是否平滑(true)与否(false)。

If you want a true pixel-art retro style effect, you'd need to manually create rotated sprite images for several angles, look up the appropriate sprite for the current value of phi , and draw it without rotation. 如果你想要一个真正的像素艺术复古风格效果,你需要手动创建几个角度的旋转精灵图像,查找适当的精灵为phi的当前值,并绘制它而不旋转。 This obviously requires a fair amount of art work! 这显然需要大量的艺术作品!

IF you are rotating images around their center point, make sure the image itself has an even number of pixels. 如果围绕中心点旋转图像,请确保图像本身具有偶数个像素。 Once you end up on odd coordinates the image data needs to be interpolated for the target canvas. 一旦最终得到奇数坐标,就需要为目标画布插入图像数据。 Apple has some nice documentation on translating and rotating the canvas . Apple 在翻译和旋转画布方面有一些很好的文档

So for any image, as suggested above use rounding to snap to full pixels. 因此,对于任何图像,如上所述,使用舍入来捕捉到全像素。

context.translate(Math.floor(img.width/2), Math.floor(img.height/2));

This way every source pixel of your image will always be drawn exactly into a pixel inside the canvas and blurring does not occur. 这样,图像的每个源像素将始终精确地绘制到画布内的像素中,并且不会出现模糊。 This however is only true for multiples of 90 degrees. 然而,这仅适用于90度的倍数。

It seems that all browsers do, to some extend, antialiasing in image drawing so you will probably have to provide rotated images as sprites. 似乎所有浏览器在某种程度上都在图像绘制中进行抗锯齿处理,因此您可能必须提供旋转图像作为精灵。

According to this Chromium bug report you might be lucky there if they haven't fixed it yet. 根据这个Chromium bug报告 ,如果他们尚未修复它,你可能会很幸运。 Read through and you'll learn that Ian Hickson likely opposed making antialiased image drawing optional. 阅读并了解Ian Hickson可能会反对将抗锯齿图像绘制作为可选项。

(picture.width/2, picture.height/2) point won't always work. (picture.width/2, picture.height/2)点并不总是有效。

(Math.floor(picture.width/2) + 0.5, Math.floor(picture.height/2) + 0.5) should help. (Math.floor(picture.width/2) + 0.5, Math.floor(picture.height/2) + 0.5)应该有帮助。

Well, actually it is something you cannot get around 嗯,实际上这是你无法解决的问题

If you rotate an image by a multiple of 90 degrees, your library should smart enough so that no interpolation is applied. 如果将图像旋转90度的倍数,则库应足够智能,以便不应用插值。

But as soon as you rotate an image by an angle different from a multiple of 90 degrees, you need to interpolate. 但是,只要将图像旋转不同于90度的倍数的角度,就需要进行插值。 As a consequence, you get that smoothing. 结果,你得到了平滑。 If you are interested in the theory, you may look for a book on computer graphics or image processing. 如果您对该理论感兴趣,可以查找有关计算机图形或图像处理的书籍。

For the concrete case of image rotation you may have a look at this paper, http://bigwww.epfl.ch/publications/unser9502.html 对于图像旋转的具体情况,您可以查看本文, http://bigwww.epfl.ch/publications/unser9502.html

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM