【问题标题】:How to set a resolution/density in JPEG/PNG image in Javascript?如何在 Javascript 中设置 JPEG/PNG 图像的分辨率/密度?
【发布时间】:2021-12-21 20:14:07
【问题描述】:

我需要在 javascript 中更改 JPG/PNG 类型图像的分辨率/密度。我需要这样做的原因是我可以将图像发送到第三方 API,然后它会根据分辨率/密度元数据知道要打印的每英寸像素数 (DPI/PPI)。

javascript中有这样的解决方案吗?

【问题讨论】:

  • 没有。这是通过您的图形编辑器对图像本身完成的。无法通过编程以这种方式更改图像。
  • 此页面上提供了解决方案。 - stackoverflow.com/questions/20379027/…
  • @ScottMarcus 为什么不可能?我看到了软件将分辨率/密度元数据添加到特定文件的图像转换的示例。一个示例是此链接中的 PDF 到 JPEG:filestack.com/docs/document-transformations ...另一个示例是在 SVG 图像中设置密度,然后可以将其转换为 JPEG:sharp.dimens.io/en/stable/api-constructor ...在我的情况下,我已经上传了 JPEG 图像我需要改变密度。我无法将其转换为 SVG 或 PDF,然后再转换回 JPG。
  • 不就是元数据吗?
  • 将 DPI 添加为元数据对实际修改图像没有任何作用。说您的图像具有 128 DPI 并不能做到这一点,图像实际上必须如此密集。只有图形软件可以修改实际的图像密度。正如@guest271314 发布的链接中提到的那样:“DPI 在保存为元数据时纯粹是任意的,当保存为元数据时,当传输到屏幕或纸张等物理介质(以及整个管道)时,DPI 会起到提示的作用显示图像会考虑其 DPI)。”

标签: javascript node.js image jpeg resolution


【解决方案1】:

可以通过withMetadata函数使用JavasCript标准图像处理库sharp轻松设置分辨率/密度。

简单示例:

// Set output metadata to 96 DPI
const data = await sharp(input)
  .withMetadata({ density: 96 })
  .toBuffer();

Npm 模块:sharp

【讨论】:

    【解决方案2】:

    您也可以使用这个最近发布的库,它只对 JPEG ( JFIF ) 和 PNG 进行 dpi 操作

    https://github.com/shutterstock/changeDPI

    【讨论】:

    • 我想支持这一点,但是该库使用 FileReader,这似乎是一种仅限浏览器的实现类型。我一直在努力尝试将其转换为读取简单的缓冲区(并且让这个库与该缓冲区的字节混淆)。如果有人知道如何发送缓冲区,请告诉我。
    • 有一个公开的公关。无论如何,该库都在节点下工作,因为测试是为节点编写的,我可以理解缓冲区更好。该库是为浏览器而生的,因为在 node 中,该解决方案已经可用于其他产品。请在github repo上开一个issue,我们会整理出来的。
    • 在尝试将 changeDPI 和其他人转换为在节点(不仅仅是浏览器)中工作后,我发现 npmjs.com/package/png-dpi-reader-writer 工作。
    • 难以置信,我多年来一直在寻找这样的东西。看看对元数据做这么简单的事情是多么复杂!谢谢!
    • 这个工具完全符合我的需要,而且不需要打后端。非常感谢!!
    【解决方案3】:

    您可以通过添加/更改 PNG 文件的 pHYs 块来做到这一点:

    您可以在https://github.com/murkle/rewrite-png-pHYs-chunk查看我的代码以了解更多信息

    【讨论】:

    • 如果你链接到你的东西并做出一个好的回答,请务必披露,最好在回答中展示它是如何完成的。
    • 抱歉,仅限 PNG
    【解决方案4】:

    对于任何对解决方案感兴趣的人,我最终使用了 graphicsMagic(Image Magick 的节点版本)。因为我使用的是 AWS Lambda(其实例预装了 ImageMagic),所以它变得更容易了,我只需要安装 'gm' npm 包。

    这不是最高效的解决方案,因为我必须在重新采样后调整大小,但它有效!

    const gm = require('gm').subClass({imageMagick: true});
    
    function addResolution(inputBuffer, resizeWidth, resizeHeight) {
      return new Promise((resolve, reject) =>{
    
        gm(inputBuffer)
        .resample(150, 150) // resampled to 150 resolution
        // you have to set the width and height again because resample rearranges those params
        .resize(resizeWidth, resizeHeight, '!')
        .toBuffer('JPEG',function (err, buffer) {
          if (err) reject(err)
          resolve(buffer)
        })
      })
    }
    

    【讨论】:

    • 为什么不直接调整大小然后设置所需的密度?
    • @fmw42 'resample' 除了更改分辨率/密度之外,还会更改图像的高度和宽度,因此之后需要调整大小。 ImageMagic 的“密度”方法仅在将 PDF/SVG/AI 格式转换为 jpeg 时有效。同样,这不是理想的解决方案,但它可以为我的用例完成工作。
    • @AndriyKulak 如果您必须在重新采样后调整大小,那么您不妨只调整大小。您始终可以设置任何光栅格式的密度和单位(用于打印),而不仅仅是使用 -density -units (命令行)的矢量格式。所以不需要重新采样。在您的 Imagemagick 变体中应该有一个与 -density 等效的命令
    • Huh @fmw42 密度(150, 150) 现在工作起来很奇怪。我之前一定做错了什么。它一定是在将 PNG 格式转换为 JPEG。我现在在进行上述转换之前将所有文件转换为 jpeg,并且似乎没有任何错误。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多