Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose setting xres/yres for JPEG/PNG output #967

Closed
Andriy-Kulak opened this issue Sep 29, 2017 · 18 comments
Closed

Expose setting xres/yres for JPEG/PNG output #967

Andriy-Kulak opened this issue Sep 29, 2017 · 18 comments

Comments

@Andriy-Kulak
Copy link

Hi!

I saw that in the documentation it is possible to adjust the density metadata in the constructor, but it doesn't work in my case for some reason. Below is the code which works but the density is never adjusted. Does anyone know how I can do this with the code snippet below?

Thanks!

const sharpImage = sharp(imagedData /* tried adding density here ... , {density: 170} */)
      sharpImage
      .rotate()
      .metadata()
      .then(function(metadata) {
        return sharpImage
                .extract({
                  left: Math.round(metadata.width * parasedBody.x),
                  top: Math.round(metadata.height * parasedBody.y),
                  width: Math.round(metadata.width * parasedBody.width),
                  height: Math.round(metadata.height * parasedBody.height)})
                .toBuffer((err, outputBuffer, info) => {
                  console.log("BUFF FUNC ERR", err);
                  console.log("BUFF FUNC outputBuffer", outputBuffer);
                  console.log("BUFF FUNC info", info);
                })
        })
@lovell
Copy link
Owner

lovell commented Sep 29, 2017

Hello, density only applies to vector-based input such as SVG. What input format are you using?

@Andriy-Kulak
Copy link
Author

I allow user to only upload a PNG/JPEG type of image. I then convert it to base64 image (which is labeled "imageData" above) and then do the cropping as seen above. I need to set a specific density/DPI/resolution in the metadata so that when I interact with a third party API that does prints, their API knows exactly how many pixels per inch to print. By default the sharp module changes the density to 72 (as explained in documentation and seen in image attached). I assume that if is changing the density from whatever it was before to 72, then I can customize this metadata.

Is this possible to change this metadata?

Thanks!
screen shot 2017-09-29 at 1 42 33 pm

@lovell
Copy link
Owner

lovell commented Sep 29, 2017

Did you see #823 (comment) ?

@Andriy-Kulak
Copy link
Author

@lovell Yes, so when the image is Jpeg, I cannot add a resolution/DPI to it. However, once I convert it to a base 64 image, is it still not possible to add a resolution metatag? If it is automatically set to 72 once I am done cropping, maybe I can change it to 170 which is what I need. I don't have in depth knowledge of image processing but if you can give a hint on where that is being done within sharp code, I can take a look.

@Andriy-Kulak
Copy link
Author

This is the metadata coming from the JPG image in line 5 of the code i provided above. I understand that density/resolution doesn't mean anything for JPG in the digital sense per se, but is it possible to change the metadata here so that when the jpeg is used for printing, it will be used by the third party API I have to work with?

Thanks!

{ format: 'jpeg',
width: 3840,
height: 2560,
space: 'srgb',
channels: 3,
density: 72,
hasProfile: false,
hasAlpha: false }

@lovell
Copy link
Owner

lovell commented Sep 30, 2017

The presence of density in the output of metadata for a JPEG input image is probably a bug. It's not derived from actual metadata, sorry for the confusion.

@lovell lovell changed the title How to add density when returning an image metadata: images without density, e.g. JPEG, should not report it Sep 30, 2017
@lovell lovell added bug and removed question labels Sep 30, 2017
@lovell lovell added this to the v0.19.0 milestone Sep 30, 2017
@Andriy-Kulak
Copy link
Author

So is there any possibility to add density in some sort of way via Sharp to JPEG/PNGs in the future? I found that in imagemagick it is possible per link below, but I don't want to run a whole instance of ImageMagick just to add one piece of metadata. If you point me in the right direction, I can try to help implement this.

https://superuser.com/questions/479197/i-want-to-change-dpi-with-imagemagick-without-changing-the-actual-byte-size-of-t

@lovell
Copy link
Owner

lovell commented Oct 1, 2017

The addition of custom EXIF metadata is covered by #650.

@lovell
Copy link
Owner

lovell commented Oct 1, 2017

Ah, I see what's happening here, the input image probably has a JFIF metadata block. Sorry for the confusion (I'm confusing myself).

After the work for #650 to make the existing withMetadata more powerful, exposing the ability to set libvips' internal xres and yres fields on the jpeg() function (like is already available on the tiff() function) is probably the best way to achieve what is needed here.

@lovell lovell changed the title metadata: images without density, e.g. JPEG, should not report it Expose setting xres/yres for JPEG output Oct 1, 2017
@lovell lovell added enhancement and removed bug labels Oct 1, 2017
@lovell
Copy link
Owner

lovell commented Oct 2, 2017

See #823 (comment) for implementation guidance.

@lovell lovell removed this from the v0.19.0 milestone Oct 2, 2017
@lovell
Copy link
Owner

lovell commented Oct 3, 2017

@Andriy-Kulak
Copy link
Author

Yes, thats my post lol. I was able to get it to work in node's version of image magic. I had trouble getting it to work with piexifjs package for some reason. I will be away the next two weeks, but afterwards I will look into implementation in sharp.

Thanks!

@borie88
Copy link

borie88 commented Mar 19, 2018

Any updates to this? I'm also using this for printing purposes, thanks

@jasonmacdonald
Copy link

Funny, I'm having the opposite problem. A JPG uploaded with the DPI of 300, is still 300 when I resize it and save it. :( I need it to convert to 72 but it doesn't seem to work.

@giorgionetg
Copy link

giorgionetg commented May 10, 2018

Currently, as in Gimp/Photoshop, the density it's only a parameter, as parameter does not change size resolution!* With 300 DPI or 72 DPI of 300200 image we have always 300200 pixel at all. I think the library here, get the allready exist parameter inside image.

There are two ways to solve this:

  • Working with fixed DPI (like as 72 DPI default) and change resolution by itself (with size and resize). More easy to implement.
  • Working as Gimp/Photoshop, but this means a lot of work on library.

/* I know in Gimp/Photoshop if you change DPI you can change resolutions, but nothing to much than you can do by yourself as first way I shown.

@jadrake75
Copy link

jadrake75 commented Oct 1, 2018

Is there any update to this?

So I have an open-source application I have provided to the stamp collection community (which I am a member of) for over 10+ years. Currently it is a Java Swing based app with Web Start (which is going away - thanks Oracle!) I have been rewriting it to electron.js calling into my particle analysis engine (leveraging NASA's imageJ library) using the node-java bridge to find stamps on the image scan, and then outputting the images with this Sharp library. I was previously using jimp, but I really like this library and want to switch to it (which was a snap!). Many of the users of the application produce auction catalogues for printing and need the DPI settings on their jpeg/png images. This works A-ok for tiff( ) but I am struggling to get this to work with jpeg. I have gotten it to "retain" the DPI settings using the "withMetaData()" call (such that a 300dpi image writes out at 300dpi vs 72dpi) but if they wanted to scale it to say 456dpi I would like to use these xres/yres options similiar to the tiff( ) options.

I am using changeDpiBlob library at the point before I read the file to a buffer for analysis (in the client window) but unfortunately this means I can not apply the dpi settings at the point of cropped image creation - I can only do it upon initial object load since it needs to modify the file Blob directory to set the meta headers (which are picked up with the withMetaData( ) api).

@lovell lovell changed the title Expose setting xres/yres for JPEG output Expose setting xres/yres for JPEG/PNG output Sep 8, 2020
lovell added a commit that referenced this issue Apr 17, 2021
@lovell lovell added this to the v0.28.2 milestone Apr 17, 2021
@lovell
Copy link
Owner

lovell commented Apr 17, 2021

Commit 4237f55 adds a new output density property to withMetadata() to set the DPI resolution, which keeps things consistent with the input density property of metadata().

// Available from v0.28.2

const data = await sharp(input)
  .withMetadata({ density: 96 })
  .toBuffer();

This will be in v0.28.2.

@lovell
Copy link
Owner

lovell commented May 10, 2021

v0.28.2 is now available.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants