画布的 drawImage() 不进行亚像素渲染/抗锯齿是不是有技术原因?

Posted

技术标签:

【中文标题】画布的 drawImage() 不进行亚像素渲染/抗锯齿是不是有技术原因?【英文标题】:Is there a technical reason why canvas's drawImage() doesn't do sub-pixel rendering / antialiasing?画布的 drawImage() 不进行亚像素渲染/抗锯齿是否有技术原因? 【发布时间】:2011-09-15 01:45:42 【问题描述】:

Ttl;博士: 我需要在canvas 中非常缓慢地移动图像,而没有明显的逐像素移动。我需要某种抗锯齿功能。


最近我的任务是在网页中水平动画一些“云”图。

很简单,我只是将图像放入 DOM 并使用 CSS3 转换,并为尚不支持 CSS 转换的浏览器使用 jQuery 动画。

一切看起来都不错。我有一些云在页面上平稳移动。

然后,我不断收到设计师的请求,要求我放慢速度……慢下来。

由于浏览器不对 DOM 对象进行亚像素渲染,因此动画似乎以 6 FPS 运行。

所以,我将图像拍到画布上进行一些快速测试,发现它也不会自动进行亚像素渲染。

My quick canvas animation demo (动作时间不准确,处理一下。:-p)

【问题讨论】:

你能做一个ctx.translate(.1 * x, 0) 或类似的东西吗? 在 IE9 和 FF 中看起来很棒。不过在 Chrome 中不太好。 嗯,我一直在 Chrome 中进行测试(认为这将是最好的)。也许这是一个 webkit 问题? 【参考方案1】:

据我了解...没有对反锯齿进行太多浏览器测试。它在 drawImage(img1, x,y,width,height) x 或 y 不是整数时启动。当画布标签 大于 style="width:600; height:600"

将样式设置为画布大小的 1/2 是为了强制抗锯齿。上次我研究了这个主题。我不会假设浏览器会 100% 实现该标准。

绿色筛选视频的注意事项 抗锯齿对于消除伪影很重要。

更新:在您的示例中,我没有使用 chrome 获得抗锯齿功能,而我使用的是 firefox。 用于 Win XP 的两种浏览器的最新版本。 Firefox fps 在您的示例中非常缓慢。

另一个更新 将画布样式大小设置为画布大小的 1/3 [3 个画布像素对应 1 个屏幕像素] 似乎确实可以使亚像素渲染工作......但以这种方式完成它可能会对性能造成很大影响。

Sub-pixel canvas test.<br/>
<canvas id="canvas"   
style="border:solid 1px  #000; width:100px; height:100px"></canvas>

很抱歉不是你真正想要的答案。

【讨论】:

那么抗锯齿不是与亚像素渲染不同的问题吗?也就是说,亚像素渲染是一种进行抗锯齿或增强它的方法,但您可以在没有亚像素渲染的情况下进行抗锯齿。 @Pointy,我不太确定这些术语的正确使用......所以如果你觉得我使用不正确,请随时编辑我的问题。 我认为您的回答很好,但我只是想澄清一下。我不是真正的渲染专家或任何东西,但我已经很老了,而且我知道当 LCD 还是科幻小说时,人们曾经谈论过屏幕图形的抗锯齿 :-)【参考方案2】:

我已经用你的代码示例进行了一些尝试,在我看来,较慢的滚动看起来非常流畅:

ctx.drawImage(img, left -= 0.0025, 0, 633, 417);    

我使用的浏览器是mac上的chrome。

【讨论】:

Chrome 12 在 Windows XP 上仍然卡顿,只是慢了 10 倍。【参考方案3】:

我测试的所有浏览器都支持画布中的抗锯齿,只需将图像放在非整数坐标上即可看到它发生。但是没有子像素渲染(为了澄清,即使用 LCD 排序红色、绿色、蓝色子像素来提高水平分辨率,非常适合文本。)

根据 html5 预标准,由浏览器决定是否要进行抗锯齿处理。

【讨论】:

【参考方案4】:

这是一个已知的 Chrome 问题,记录在 http://code.google.com/p/chromium/issues/detail?id=7508

仍然没有解决方案或解决方法..

【讨论】:

【参考方案5】:

对于较旧的浏览器,您可以为精灵设置动画。创建可能 4 个版本的图像,每个版本都比前一个版本向左移动 0.25 像素。将它们粘贴到一个精灵中,然后为背景位置设置动画。

function moveClouds(n)

    var v = (n % 4) * 417;
    var h = Math.ceil(n / 4);
    clouds.style.backgroundPosition = h + " " + v;

【讨论】:

【参考方案6】:

你可以在这里做一个 hack,但它非常难看。

您将画布元素的分辨率设置为高于实际显示尺寸,然后您的翻译会被浏览器消除锯齿。 Tada,chrome 中的亚像素动画!

【讨论】:

以上是关于画布的 drawImage() 不进行亚像素渲染/抗锯齿是不是有技术原因?的主要内容,如果未能解决你的问题,请参考以下文章

画布:drawImage 方法失败且没有错误

iPad上字体的亚像素渲染

调整画布图像大小而不使其模糊

IE 9 在某些条件下不使用亚像素抗锯齿

ReactJS画布drawImage不显示html5视频元素

缩放图像以适合画布