【问题标题】:Why is HTML5 canvas svg filter lossy?为什么 HTML5 canvas svg 过滤器有损?
【发布时间】:2020-08-08 05:18:27
【问题描述】:

以下是您应该能够在浏览器中运行的示例代码。它应该首先加载图像。图片显示后,您可以点击查看原始图片与带有 identitdy svg 滤镜的图片之间的差异。

可能很难直接在浏览器上查看,但您可以将结果下载为图像并在任何图像查看器中打开。结果并不奇怪。它具有类似于某种压缩伪影的斑点区域。

所以我的问题是:

  1. 应用任何 svg 过滤器会导致质量损失吗?
  2. 为什么会这样? (也许我错过了,但文件中没有提到)
  3. 如何实现无损 svg 滤镜?

<body>
    <canvas id='canvas' width=850 height=850></canvas>
    <svg width="0" height="0" style="position:absolute;z-index:-1;">
        <defs>
            <filter id="identity" x="0" y="0" width="100%" height="100%">
                <feComponentTransfer></feComponentTransfer>
            </filter>
        </defs>
    </svg>
</body>


<script>
    canvas = document.getElementById('canvas')
    image = new Image()
    image.src = 'https://cms-assets.tutsplus.com/uploads/users/127/posts/31341/final_image/1_10.png'
    image.onload = function() {
        let ctx = canvas.getContext('2d')
        ctx.drawImage(this, 0, 0)
        canvas.image = this
    }

    canvas.onclick = function() {
        let ctx = this.getContext('2d')
        ctx.clearRect(0, 0, this.width, this.height)
        ctx.filter = 'none'
        ctx.drawImage(this.image, 0, 0)
        ctx.globalCompositeOperation = 'difference'
        ctx.filter = 'url(#identity)'
        ctx.drawImage(this.image, 0, 0)
        // 20x the difference
        ctx.filter = 'brightness(20)'
        ctx.drawImage(canvas, 0, 0)
    }
</script>

【问题讨论】:

  • 简单地说,是一个等待标准化的experimental feature。你可以说它就像一个“测试版”功能,所以不要指望它在所有兄弟上都能正常运行。顺便说一句,我不确定问题是什么。我看到结果是 png 图像的像素完美副本,没有任何过滤器或其他任何东西。你能上传你看到的结果吗?最新的 Chrome 在这里运行。 (这是我看到的结果:femto.pw/5rsj.png
  • 感谢您的回复。加载后请点击图片。您会看到计算出的放大 20 倍的差异图像。如果两张图片相同。我们应该看到全黑。但至少在我的浏览器中,我可以看到一些不同。
  • 哦该死的,没注意到onclick。我的错。 面部护理.

标签: javascript html5-canvas svg-filters


【解决方案1】:

线性 RGB V sRGB(对数)

使用线性颜色模型通常会导致颜色精度下降。始终使用 sRGB 以获得最佳效果。

默认颜色插值滤镜是线性 RGB

feComponentTransfer 的默认颜色模型是线性 RGB,可能会导致一些伪影。

要强制过滤器使用 sRGB 使用属性color-interpolation-filters="sRGB"

下面的示例 sn-p 显示使用 sRGB 时没有损失。当您看到图像时,单击它以查看结果。应该全黑不亏。

<body>
    <canvas id='canvas' width=850 height=850></canvas>
    <svg width="0" height="0" style="position:absolute;z-index:-1;">
        <defs>
            <filter id="identity" x="0" y="0" width="100%" height="100%">
                <feComponentTransfer color-interpolation-filters="sRGB"></feComponentTransfer>
            </filter>
        </defs>
    </svg>
</body>


<script>
    canvas = document.getElementById('canvas')
    image = new Image()
    const ctx = canvas.getContext('2d')
    image.src = 'https://cms-assets.tutsplus.com/uploads/users/127/posts/31341/final_image/1_10.png'
    image.onload = () => ctx.drawImage(image, 0, 0);

    canvas.onclick = function() {
        ctx.globalCompositeOperation = 'source-over'
        ctx.filter = 'none'
        ctx.drawImage(image, 0, 0)
        ctx.globalCompositeOperation = 'difference'
        ctx.filter = 'url(#identity)'
        ctx.drawImage(image, 0, 0)

        ctx.filter = 'brightness(20)'
        ctx.drawImage(canvas, 0, 0)
    }
</script>

【讨论】:

    猜你喜欢
    • 2011-06-27
    • 2012-06-22
    • 2016-07-11
    • 2011-04-02
    • 1970-01-01
    • 2016-12-03
    • 2011-08-18
    • 2012-07-29
    • 2012-06-01
    相关资源
    最近更新 更多