【问题标题】:canvas.toDataURL() does not alter image quality. How comes?canvas.toDataURL() 不会改变图像质量。怎么会?
【发布时间】:2017-09-26 21:37:32
【问题描述】:

根据docs

HTMLCanvasElement.toDataURL() 方法返回一个数据 URI,其中包含 以类型指定的格式表示的图像 参数(默认为 PNG)。返回的图像的分辨率为 96 dpi

当不涉及打印时,如何引用打印分辨率

我编写了a jsfiddle,它在画布上绘制图像,然后调用toDataURL()。毕竟,结果图像的质量似乎没有受到影响。

我不明白文档中的 96 dpi 是什么意思。有什么想法吗?

var image = new Image();
image.crossOrigin = "Anonymous";
image.src = "...";
// ...
var dataURL = canvas.toDataURL('image/jpeg', 1.0);
window.open(dataURL);

【问题讨论】:

    标签: javascript html canvas printing html5-canvas


    【解决方案1】:

    在不涉及打印的情况下,如何引用打印分辨率?

    MDN 的引用是错误的,因为它将 DPI 称为图像的分辨率

    (旁注:PPI 与 DPI 的物理特性不同 - 但在这种情况下并不重要。你会看到我将 DPI 用于 PPI,因为自从我在 90 年代初开始使用它以来,它已经根深蒂固了)。

    对您的问题的(有点)简短的回答是:

    图像仅以像素为单位,没有实际尺寸的概念。 DPI 纯粹是任意的,当保存为图像中的元数据时,当传输到屏幕或纸张等物理介质(以及整个管道显示图像会考虑其 DPI)。

    至于为什么:96 DPI 指的是“标准”(但不准确且有点过时)屏幕像素密度,因此如果您将图像按原样打印到纸上并保持将纸贴在屏幕上 纸上的内容的大小应该与您在屏幕上看到的大小相匹配(大多数人不会calibrate theirs screens 来获取实际 DPI,并且制造商有时会草率地使用他们的驱动程序,如果不是使用通用驱动程序的话,所以会有一个小的误差范围)。

    浏览器实际上也不会将此信息存储在它生成的图像文件中(不是它需要,见下文)。

    为了记录,让我们先看看 JPEG 文件的二进制文件:


    从 Firefox 保存的 JPEG 的十六进制转储,但 Chrome 的情况相同。

    不,在位置 0x0D 没有定义单位 (0)。这必须是 1(英寸)或 2(厘米)(当然没有 EXIF (0xffe1/APP1),因为没有相机/扫描仪产生图像)。

    那么PNG呢?


    从 Firefox 保存的 PNG 的十六进制转储,但对于 Chrome,情况相同。

    不,这里也没有。没有 pHYs 块,IHDR 只包含实际的像素分辨率。

    这没关系,因为在当今大多数系统上假定图像是 96 DPI,因此它不会产生任何后果(实际上 DPI 用于影响图像,并且没有其他 DPI/ PPI 已定义)。

    在大多数情况下,对于您和我来说,1920x1080 的图像在 15" 和 50" 屏幕上都是 1920x1080。忽略...

    总之:当您通过画布传递图像时,图像可能会嵌入一个提示,例如 300 DPI。这在保存画布时当然会被删除,但它不会改变 图像分辨率(前提是画布与原始图像具有相同的像素分辨率),因此打印质量不会下降(通过 JPEG 压缩当然会影响总体质量,但对于实际分辨率没有变化)。

    【讨论】:

    • 感谢您的详尽回答!这是否也意味着如果一个人使用同一台打印机以高分辨率 (300 DPI) 打印两张图像(原始图像和来自toDataURL() 的图像),那么它们之间应该完全没有区别?
    • @user115202 不一定。如果原件确实嵌入了提示,比如 300 dpi 并且是 300x300 像素,它将以 1x1" 打印在纸上(如果软件打印它认为嵌入的 dpi)。通过画布后,原始 dpi 被忽略,新的默认 dpi 为 96,因此现在图像将在纸上打印为大约 3.1x3.1",但现在更好地匹配它在屏幕上的外观。这也是为什么对图像使用 dpi 部分没有意义的原因。在印刷生产环境中,您通常会将图像放入 DTP 等文件中,然后将其缩放到所需的大小。
    • 谢谢!这意味着在将图像缩放到相同尺寸(打印时)时,它们是等效的。也就是说,toDataURL() 不会降低(打印)质量。如果我的理解是正确的。再次感谢:)
    【解决方案2】:

    这句话中确实有一个错字,因为他们可能应该使用 ppi 而不是 dpi 而 IIRC,EXIF 标签被称为像素密度,但这是一个常见的一。

    jpeg 格式的 ppi 只是为了让软件知道您的 300px * 300px 数字图像打算以 1in*1in 的大小呈现。
    因此,如果渲染器是一台能够以 300dpi 打印的打印机,则每像素一个点。

    此信息写入文件的元数据中,无论原始图像中设置的原始值如何,toDataURL 只会将 JFIF 密度单位元数据设置为 0(无单位),并将 X 和 Y 密度设置为 1(MDN之所以说96dpi,是因为它对应了最标准的屏幕显示比例,也用在CSSpx魔术单元中)。

    【讨论】:

    • "此信息写入文件的元数据中,无论原始图像中设置的原始值如何,toDataURL 都会将此元数据设置为 96" 这是不正确的。没有 DPI 信息与图像格式一起保存。 EXIF 是由相机/扫描仪产生的,但不是由画布产生的。我添加了一个包含更多细节的答案。
    • @K3N 对,它不在EXIF数据中,而是在JFIF数据中(密度单位,X密度Y密度)
    • 正确,但浏览器不使用这些(为 0,表示未定义单位)。并不是说它需要,因为 96 DPI 被假定为默认值。
    • @K3N 是的,只是今天早上快速写下这个答案时,我想到了这个 JFIF 信息,并严重提醒浏览器会保存 EXIF dpi (:confused)
    • @K3N 啊,但是您添加了有价值的信息,无需删除它。 (在upvote之前完成阅读)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-03-07
    • 2012-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多