4
votes

I need to change the resolution/density in JPG/PNG type of images in javascript. The reason I need to do this is so that I can send the image to a third party API which will then know how many pixels per inch (DPI/PPI) to print based on the resolution/density metadata.

Are there any such solution in javascript?

4
No. This is done via your graphics editor to the image itself. It is not possible to alter the image this way via programming.Scott Marcus
A solution is available on this page. - stackoverflow.com/questions/20379027/…Damien Asseya
@ScottMarcus why is not possible? I see see examples of where software adds resolution/density metadata to image conversions from specific files. One example is PDF to JPEG in this link: filestack.com/docs/document-transformations ... Another example is setting density in an SVG image which can then be converted to JPEG: sharp.dimens.io/en/stable/api-constructor ... In my case I already have an uploaded JPEG image in which I need to change density. I cannot convert it to SVG or PDF and then back to JPG.andre
Isn't it simply metadata?andre
Adding the DPI as metadata does nothing to actually modify the image. Saying that your image has 128 DPI does not make it so, the image must actually be that dense. Only graphics software can modify the actual image density. As mentioned in the link that @guest271314 posted: " DPI is purely arbitrarily when saved as meta in/with images and function as a hint when transferred to physical medium such as a screen or to paper (and the entire pipe-line displaying the image considers its DPI)."Scott Marcus

4 Answers

5
votes

For anyone curious on a solution, I ended up using graphicMagic (node's version of Image Magick). Because I am using AWS Lambda (whose instances comes preinstalled with ImageMagic), it made it easier, I just had to install 'gm' npm package.

It isn't the most performant solution because I have to resize after resample, but it works!

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)
    })
  })
}
4
votes

You can also use this recently published library, that does exactly just dpi manipulation for JPEG ( JFIF ) and PNGs

https://github.com/shutterstock/changeDPI

0
votes

You can do this by adding/changing the pHYs chunk of a PNG file:

You can check my code at https://github.com/murkle/rewrite-png-pHYs-chunk to understand more

0
votes

The resolution/density can be set easily using JavasCript standard image processing liberary sharp by withMetadata function.

Simple example:

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

Npm module: sharp