lovell / sharp

High performance Node.js image processing, the fastest module to resize JPEG, PNG, WebP, AVIF and TIFF images. Uses the libvips library.
https://sharp.pixelplumbing.com
Apache License 2.0
28.91k stars 1.29k forks source link

Automatically set resolution of vector images based on density #338

Closed lookfirst closed 8 years ago

lookfirst commented 8 years ago

I'd like to be able to set the output DPI to 300 for an EPS -> PNG conversion. We are successfully doing the output as 300 with some Java code:

https://github.com/depsypher/pngtastic/blob/master/src/main/java/com/googlecode/pngtastic/core/PngChunkInserter.java#L17

I've found all the previous issues that talk about doing this: #181 and #96. In #96, I saw that a change was made to output as 72 dpi, but in my simple tests, I'm still seeing the output as 25 dpi. screenshot: http://take.ms/NeZoO

osx 10.11 sharp v0.12.1 node 5.4.0 libvips 8.1.1 (brew) libpng 1.6.20 (brew)

I'd love to hear your thoughts on this. Thanks.

lovell commented 8 years ago

Hi Jon, I see you've since discovered #110. Its density option should provide what you're looking for to solve this problem. I'll close this question in preference to it.

lookfirst commented 8 years ago

@lovell I think this issue should be reopened. How can I get the output png image to be 300dpi? This is relatively easy with graphicsmagick by specifying the density option. http://aheckmann.github.io/gm/docs.html#density

lookfirst commented 8 years ago
            gm(response)
                .resize(width, height)
                .density(density, density)
                .units('PixelsPerInch')
                .stream(toFormat)
                .pipe(res);
jcupitt commented 8 years ago

I suppose there are times when you might want to explicitly set the DPI tag on an output image.

In libvips you do this with a combination of vips_copy(), to set the resolution fields in the header in pixels/mm, and vips_image_set_string() to set the "resolution-unit" tag to in or cm. Something like (untested):

// xres/yres in pixels/mm
// unit can be "cm" or "in", meaning xres and yres will be converted to that
// unit on write ... so set_res(11.81, 11.81, "in") means 300 dpi
VImage set_res(VImage in, double xres, double yres, char *unit)
{
  return in.
    copy(VImage::option()->set("xres", xres)->set("yes", yres)).
    set("resolution-unit", unit);
}
lovell commented 8 years ago

Hi Jon, when outputting bitmap formats that support "resolution", libvips will faithfully set this based on its Xres and Yres internal values. Here's the code for PNG output - https://github.com/jcupitt/libvips/blob/master/libvips/foreign/vipspng.c#L868-L872

It looks like the real problem is that *magick often provides no value for the input resolution - https://github.com/jcupitt/libvips/blob/master/libvips/foreign/magick2vips.c#L384-L386 - and libvips will assume a default resolution of 1 pixel/mm, =25 pixels/inch.

The *magick API accepts a string for density rather than numeric value(s), which increases the complexity of fixing this in libvips at input time. However the sharp API accepts a single numeric value, so the least complex solution here is to set libvips Xres and Yres values (via the method that John posted above whilst I was writing this comment).

lookfirst commented 8 years ago

Thanks @lovell and @jcupitt

The images I'm generating are being digitally printed on tshirts and the printer needs to have the correct DPI specified. =)

lovell commented 8 years ago

Commit bb37dc1 on the needle branch should provide everything needed for this. It also exposes the density attribute via metadata() so all the tests can use it too.

lookfirst commented 8 years ago

@lovell :heart: :+1: :heart: :heart_eyes:

lookfirst commented 8 years ago

@lovell Can I get a release with this in it please? =)

lovell commented 8 years ago

@lookfirst This will be in v0.14.0. We're waiting for libvips v8.2.3+ for the hist_entropy fix.

lookfirst commented 8 years ago

@lovell Released! =)

lovell commented 8 years ago

@lookfirst needle merged to master, now awaiting https://github.com/Homebrew/homebrew-science/pull/3459 for OS X users.

In the meantime, if you're able to share details publicly, it's always great to learn more about the problems people are solving with this module in the survey at #35

lovell commented 8 years ago

You'll be pleased to hear that v0.14.0 is now available via npm.

lookfirst commented 8 years ago

@lovell I just tested this and I'm still seeing the PNG being output with a DPI of 25.

    let transform = (width, height, density, toFormat) => {
        return sharp(null, {density: density})
            .resize(width, height)
            .max()
            .withoutEnlargement()
            .toFormat(toFormat);
    };

Screenshot of Preview.app info window for the generated image: http://take.ms/ZbJwG

lovell commented 8 years ago

@lookfirst Is this on OS X? What flags did you use when installing vips? IIRC support for this varies between differing versions of ImageMagick and GraphicsMagick.