为什么 html canvas 会破坏这个源图像?

问题描述

我正在尝试制作一个超级简单的 HTML Canvas 裁剪工具。我测试的第一件事是查看输出图像是否与输入图像在感知上相同。

使用 this image 作为源,canvas 无法保持平滑的渐变,正如您在我在此处发布的图像比较中所看到的(尽管进行了 imgur 压缩,但仍然可见)。您还可以在任何在线照片编辑器中复制它,例如 https://pixlr.com

有什么办法可以解决这个问题吗?

Left: Original,Right: After Canvas

我正在使用的代码片段:

const loadImagetoCanvas = (file) => { // file is from input.files
    const img = new Image();
    img.onload = () => {
        const { width,height } = img;
        canvas.width = width;
        canvas.height = height;
        ctx.clearRect(0,width,height);
        ctx.drawImage(img,0);
    }
    img.src = URL.createObjectURL(file);
};

解决方法

两个字:伽马校正。您的 PNG 文件有一个 1.0000 的 gAMA 块。 Web 浏览器(正确)使用此信息来调整具有 2.2 标准 sRGB 伽玛的输出设备的显示像素。此行为对于 元素是相同的。[1]

我不知道您使用什么查看器或转换工具来生成您的 imgur 图像,但它要么剥离要么忽略伽马块。

如果您的图像实际上使用 2.2 的 gamma 编码(因此 gamma 块是错误的),您可以使用以下方法删除块:

pngcrush -rem gAMA 1024.png 1024.nogamma.png


[1] spec 要求这种一致性。你真的看到你的(正确的,虽然使用 createObjectURL 是不必要的和一个坏主意)代码和 标记之间的不同行为?