提高CSS缩小尺寸元素的图像质量

时间:2016-08-03 12:30:26

标签: javascript css canvas

我使用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>
&#13;
&#13;
&#13;

Demo also on JSFiddle

此图像是画布绘制的形状,以交互方式显示两个图形节点之间的连接,导出到png。

请缩小并查看该线的噪音,即使以0.25和CSS的步长进行缩放也是如此。 如何摆脱这种像素噪音?最新的Google Chrome和Microsoft Edge都存在问题,而在其他浏览器中未经测试。无论有没有3D GPU加速,都会出现问题。

  

注意:显然,这是一个Minimal, Complete, and Verifiable example,真正的工作量更复杂。

     

线条形状的渐变在程序上绘制到画布上(每行<1ms),然后在空闲时使用toDataUrl(每行约40ms)异步缓存到img个元素,以便屏幕平移 - 这也是必需的功能 - 工作更顺利,因为在屏幕上移动img元素比移动canvas元素(或重绘单个画布上的所有线条)便宜得多,无论是它是转换为给定方向的元素本身,容器或浏览器视口。

     

因此,生成mipmap实际上不是一种选择,或仅作为最后的手段,因为它会带来重要的性能损失(每个mip级别会必须将其缓存到单独的图像上,至少将性能降低一半)。不过,我想相信它可以避免。在每个缩放步骤中重新绘制线条形状将巧妙地消除性能直至幻灯片放映。

以下是我尝试过的事情清单,没有效果:

  • 通过在形状元素本身或容器上定义以下CSS属性值来提示更好的图像质量:
image-rendering: pixelated | optimizeSpeed | optimizeQuality
  • 强制使用虚拟transform
  • 将渲染层提升为GPU加速
  • 使用scale3d代替scale
  • img.widthimg.height减半,然后加倍img.style.widthimg.style.height
  • 进行补偿
  • 不将画布结果缓存到img,而是直接显示canvas元素(效果较差,质量相同)

我在缩小时也尝试使用filter: blur,但是did not yield a better quality,因为在已经在屏幕上呈现给定的形状后,应用了模糊效果本身。

除了创建每个形状的缩减采样版本,还能有效地创建一个软件渲染的mipmap(LOD)系统,我还能做些什么才能摆脱这种像素噪声?(正如我所写的那样) ,希望强烈避免)

这个问题与similar questions从缩小尺度调查不良图像质量的数组有什么不同?

  • 这里,它是缩小尺寸的容器(并使用CSS转换),而不是单个图像元素。没有对实际图像数据进行任何操作,这是在类似主题中讨论的内容。

2 个答案:

答案 0 :(得分:3)

使用SVG图像而不是PNG可以获得更好的效果,并且它们也很容易生成并嵌入到您的代码中,您甚至不需要托管它们。

正如你在demo中看到的那样,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>

显然不完美。

答案 1 :(得分:2)

具有锐边的图像的插值将不可避免地产生伪影。即使它是抗污染的,即使它是模糊的。你可以在Photoshop中测试它,你会得到相同的结果。

即使是mipmap方法也行不通。

固有的问题是像素无法保留复杂矢量形状的所有信息;当你挤压像素时,形状会丢失。有两种解决方案可以提高质量:

  • 在缩放之前以更高的分辨率渲染图片,以便存储更多像素来存储形状的意图
  • 或直接在您瞄准的比例下渲染矢量形状