Skip to content

Enhancement: use density provided to withMetadata as fallback value for TIFF xres/yres #2941

@mbklein

Description

@mbklein

What are you trying to achieve?

Set a specific density/resolution on an output image. (I realize this changes nothing inherent about the image, but some of our users are getting confused by the default print dimensions of an image based on its stored resolution and I'd like to make the problem go away.)

Have you searched for similar questions?

Yes. Other questions/issues have come close, but haven't quite addressed the difference between output formats when it comes to metadata and density.

Are you able to provide a minimal, standalone code sample that demonstrates this question?

Given this input file:

$ identify -verbose input.tif
Image:
  Filename: input.tif
  Format: TIFF (Tagged Image File Format)
  Mime type: image/tiff
  Class: DirectClass
  Geometry: 2998x4454+0+0
  Resolution: 3000x3000
  Print size: 0.999333x1.48467
  Units: PixelsPerInch

I run the following:

sharp('input.tif').withMetadata({ density: 96 }).jpeg().toFile('output.jpg');
sharp('input.tif').withMetadata({ density: 96 }).png().toFile('output.png');
sharp('input.tif').withMetadata({ density: 96 }).tiff().toFile('output.tif');

The output looks like this:

$ identify -verbose output.jpg
Image:
  Filename: output.jpg
  Format: JPEG (Joint Photographic Experts Group JFIF format)
  Mime type: image/jpeg
  Class: DirectClass
  Geometry: 2998x4454+0+0
  Resolution: 96x96
  Print size: 31.2292x46.3958
  Units: PixelsPerInch

$ identify -verbose output.png
Image:
  Filename: output.png
  Format: PNG (Portable Network Graphics)
  Mime type: image/png
  Class: DirectClass
  Geometry: 2998x4454+0+0
  Resolution: 37.8x37.8
  Print size: 79.3122x117.831
  Units: PixelsPerCentimeter

$ identify -verbose output.tif
Image:
  Filename: output.tif
  Format: TIFF (Tagged Image File Format)
  Mime type: image/tiff
  Class: DirectClass
  Geometry: 2998x4454+0+0
  Resolution: 25.4x25.4
  Print size: 118.031x175.354
  Units: PixelsPerInch

I get why the JPEG and the PNG are using different units (because the PNG header always expresses density in pixels per meter), but at least the density math works out to 96 PPI. The TIFF keeps the original units, but gets written out using sharp's default density of 1000 pixels per meter.

FWIW, sharp is capable of reading the density from the source TIFF:

> await sharp('input.tif').metadata();
{
  format: 'tiff',
  width: 2998,
  height: 4454,
  space: 'b-w',
  channels: 1,
  depth: 'uchar',
  density: 3000,
  isProgressive: false,
  pages: 1,
  hasProfile: true,
  hasAlpha: false,
  orientation: 1,
  ...
}

Are you able to provide a sample image that helps explain the question?

Yes. (It's zipped just to prevent GitHub from trying to create a derivative or inlining it into the issue.)
input.tif.zip

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions