如何在Javascript中设置JPEG/PNG图像的分辨率/密度?

5

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

是否有任何javascript解决方案?


不可以。这需要使用图像编辑器对图像本身进行处理,而无法通过编程以此方式更改图像。 - Scott Marcus
1
@ScottMarcus为什么不可能呢?我看到有些软件可以从特定文件的图像转换中添加分辨率/密度元数据的示例。一个例子是将PDF转换为JPEG,链接在这里:https://www.filestack.com/docs/document-transformations ... 另一个例子是在SVG图像中设置密度,然后可以将其转换为JPEG:http://sharp.dimens.io/en/stable/api-constructor/ ... 在我的情况下,我已经上传了一个JPEG图像,我需要更改其密度。我无法将其转换为SVG或PDF,然后再转换回JPG。 - andre
1
这不仅仅是元数据吗? - andre
请看《canvas.toDataURL()不会改变图像质量,为什么?》(原文链接:https://dev59.com/9qXja4cB1Zd3GeqPR37u)。 - guest271314
1
将DPI作为元数据添加并不会实际修改图像。说你的图像有128 DPI并不能使它变得如此密集,图像必须实际上是那么密集的。只有图形软件才能修改实际图像密度。正如@guest271314发布的链接中所提到的:“当保存为图像的元数据时,DPI纯粹是任意的,并且在传输到物理介质(如屏幕或纸张)时作为提示(整个显示图像的管道都考虑其DPI)。" - Scott Marcus
显示剩余6条评论
4个回答

5

如果你对解决方案有疑问,我最终使用了graphicMagic(node的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
@fmw42的 'resample' 会改变图像的高度和宽度,同时也会改变分辨率/密度,因此之后需要进行调整大小的操作。ImageMagic的 'density' 方法仅适用于将PDF/SVG/AI格式转换为jpeg时使用。再次强调,这不是理想的解决方案,但对于我的使用情况来说,它可以完成任务。 - andre
如果您在重新采样后需要调整大小,那么最好直接调整大小。您可以始终使用-density -units(命令行)设置任何光栅格式的密度和单位(用于打印),而不仅仅是矢量格式。因此,重新采样是不必要的。在您的Imagemagick变体中应该有一个等效的-density命令。@AndriyKulak - fmw42
哎呀,@fmw42,密度(150, 150)现在奇怪地可以工作了。我之前一定做错了什么。可能是将PNG格式转换为JPEG时出了问题。现在,在进行上述转换之前,我会将所有文件都转换为JPEG格式,似乎没有出现任何错误。谢谢! - andre

5

我想赞同这个观点,但该库使用FileReader,这似乎是一种仅适用于浏览器的实现。我一直在试图将其转换为读取简单缓冲区(并且让该库干扰该缓冲区的字节),这让我头痛不已。如果有人已经找到了如何发送缓冲区给它,请告诉我。 - Chris
有一个开放的PR可以解决这个问题。该库在Node下工作,因为测试是针对Node编写的,我可以理解缓冲区更好。该库是为浏览器而生的,因为在Node中,该问题已经有其他产品解决了。请在GitHub存储库上打开一个问题,我们会解决它。 - AndreaBogazzi
2
在尝试将changeDPI和其他内容转换为适用于节点(而不仅仅是浏览器)的过程中,我发现https://www.npmjs.com/package/png-dpi-reader-writer很有效。 - Chris
1
太不可思议了,我已经寻找类似的东西多年了。看看处理元数据这么简单的事情竟然有多么复杂!谢谢! - OG Sean
这个工具完全满足了我的需求,而且不需要访问后端。非常感谢!! - Chris Sandvik

0

1
请始终披露您链接到的内容,并且为了提供一个好的答案,最好在答案中展示如何实现。 - Petter Friberg
抱歉,仅支持PNG格式。 - murkle

-1

分辨率/密度可以使用JavaScript标准图像处理库sharpwithMetadata函数轻松设置。

简单示例:

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

Npm模块:sharp


刚刚测试了这个设置:它只改变元数据中的数值,但不会重新采样图像。我在一个分辨率为300 dpi的图像上进行了测试,将其改为72 dpi。在文件资源管理器中检查属性,显示为72 dpi,但是Photoshop仍然显示300 dpi的分辨率。 我想知道这个功能的用途是什么。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接