提高CSS缩小元素的图像质量
Improving image quality of CSS-downscaled elements
我正在使用transform: scale(x)
缩小我出色的图形编辑器的内容。当缩小时,比例向0
(不包括)下降,当放大时,比例上升,最高可达1
(包括),这意味着完全缩放或初始比例。
然而,当大幅缩小时,图像质量开始变得非常嘈杂——请考虑以下示例,并注意缩小将如何使图像外观变得嘈杂:
var graphContainer = document.getElementById("graph-container");
var zoomInButton = document.getElementById("zoom-in-button");
var zoomOutButton = document.getElementById("zoom-out-button");
var zoomLevel = 1;
zoomInButton.addEventListener("click", function () {
zoomLevel = Math.max(1, zoomLevel - 0.25);
graphContainer.style.transform = "scale(" + (1 / zoomLevel) + ")";
});
zoomOutButton.addEventListener("click", function () {
zoomLevel = zoomLevel + 0.25;
graphContainer.style.transform = "scale(" + (1 / zoomLevel) + ")";
});
#editor-container {
background-color: #001723;
}
#graph-container { transform-origin: top center; }
<div id="editor-container">
<button id="zoom-in-button">Zoom in</button>
<button id="zoom-out-button">Zoom out</button>
<div id="graph-container">
<img class="shape" src="http://i.imgur.com/zsWkcGz.png" />
</div>
</div>
也在JSFiddle 上演示
此图像是一个画布绘制的形状,以交互方式可视化两个图形节点之间的连接,并导出为png
请缩小,看看这条线有多吵,即使缩放是在0.25
和CSS的步骤中完成的如何消除此像素噪声该问题发生在最新的谷歌Chrome和微软Edge中,未在其他浏览器中测试。无论是否使用3D GPU加速,都会出现此问题。
注意:显然,这是一个最小、完整和可验证的例子,实际工作要复杂得多。
成群的线条形状按程序绘制在画布上(每行<1ms),然后在空闲时使用toDataUrl异步缓存到
img
元素(每行约40ms),这样屏幕平移(这也是一项必需的功能)工作得更顺利,因为在屏幕上移动img
元素比移动canvas
元素(或在单个画布上重新绘制所有行)便宜得多,无论是元素本身、容器,还是转换为给定方向的浏览器视口。因此,生成mipmaps并不是一个真正的选项,或者只是作为最后的手段,因为它将带来显著的性能损失(每个mip级别都必须缓存到一个单独的图像上,至少会将性能减半)。不过,我相信这是可以避免的。幸运的是,在每一个缩放步骤上重新绘制线条形状都会抹杀幻灯片的性能。
以下是我尝试过的事情的列表,没有效果:
- 通过在形状元素本身或容器上定义以下CSS属性值来提示更好的图像质量:
image-rendering: pixelated | optimizeSpeed | optimizeQuality
- 使用伪
transform
强制提升渲染层到GPU加速 - 用
scale3d
代替scale
- 将
img.width
和img.height
减半,然后通过加倍img.style.width
和img.style.height
进行补偿 - 不将画布结果缓存到
img
中,而是直接显示canvas
元素(性能较慢,质量较差)
我也尝试过在缩小时使用filter: blur
,但它并没有产生更好的质量,因为模糊效果本身是在屏幕上渲染给定形状后应用的。
除了创建每个形状的下采样版本,有效地创建软件渲染的mipmap(LOD)系统之外,我还能做些什么来消除这种像素噪声(正如我所写,它希望强烈避免)
这个问题与一系列类似的问题有什么不同,这些问题都是通过缩小尺度来调查糟糕的图像质量的
- 在这里,容器被缩小了(并进行了CSS转换),而不是单独的图像元素。没有对实际的图像数据进行任何操作,这是类似主题中讨论的内容
使用SVG图像而不是PNG可以获得更好的结果,而且它们也很容易生成并嵌入到代码中,甚至不需要托管它们。
正如你在这个演示中看到的,SVG不会像素化或变得模糊,你会在像Retina这样的高分辨率屏幕上得到更好的结果。
SVG代码:
<svg class="shape" width="440px" height="319px" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<path d="M1,316.040132 C1,316.040132 241.5837,339.680482 241.5837,163.497447 C241.5837,-12.6855883 439,2.31775322 439,2.31775322" id="Path" stroke="#50E3C2" stroke-width="2"></path>
</g>
</svg>
显然不是完美的。
对具有尖锐边缘的图像进行插值将不可避免地产生伪影。即使它是抗锯齿的,即使它是模糊的。你可以在Photoshop中测试这个,你会得到同样的结果。
即使是mipmap方法也不起作用。
固有的问题是像素无法保留复杂矢量形状的所有信息;当你挤压像素时,形状就会丢失。有两种提高质量的解决方案:
- 要么在缩放图片之前以更高的分辨率渲染图片,这样就有更多的像素来存储形状的意图
- 或者直接按照目标比例渲染矢量形状
- 如何使用css动画/javascript使具有背景图像的元素出现
- CSS3动画图像质量按比例
- fabric.js:使用 Image.set() 调整图像大小是否会降低图像质量
- JavaScript裁剪(裁剪)的图像质量差
- 如何获取内部动态加载图像的元素的高度
- 如何使用THree.js和webGL将交互式图像或元素嵌入到全景图像查看器中
- Uploadcare:如何防止图像质量下降
- 输入类型='文件'如何控制图像质量
- nodejs改变图像质量
- HTML5 文件阅读器 API - 图像质量
- 没有图像的元素上的CSS掩码
- 缩小图像质量损失
- 图像/DIV 元素切换全屏
- 使用 pdf .js 的 pdf 图像质量很差
- 如何使用量角器比较视频/图像质量
- 获取包含图像的元素的 $.height() 当图像可能尚未加载时
- 是否可以在放大野生动物园手机时逐步提高图像质量
- 如何将要附加图像的元素传递到image.onload()函数中
- 与页面交互时,图像质量每秒下降
- 提高CSS缩小元素的图像质量