Sharp: Metadata not updated after rotate()

Created on 28 Jun 2018  路  2Comments  路  Source: lovell/sharp

If I have a file of dimensions 1999x1124, exif orientation=8, and I run it through sharp:

sharp(file).rotate().metadata().then(metadata => console.log(metadata))

I get the original metadata. I would have expected to see the new dimensions: (1124x1999) I tried inserting sharp.cache(false) after rotating, but that had no effect.

I suspect this is because the metadata function works "without decoding any compressed image data," and it would need to read the buffer in order to redetermine it? This seems broken to me. Shouldn't the rotate() function update whatever source it's pulling this metadata from?

Perhaps one non-breaking solution to this could be accepting a second options argument to the rotate method with a "resolveWithObject" flag that would work just like toBuffer, resolving an additional data object containing the new size after rotation. I don't particularly like this idea design-wise, just brainstorming.

My use-case is, I need to resize an overlay image down to match the rotated image, prior to applying it. I've had to resort to calling toBuffer twice: once to just fetch the dimensions, and then again after applying the overlay. It's just really ugly and inefficient. Here's the simplified version:

function applyOverlay(file, overlayFile) {
    return sharp(file)
        .rotate()
        .toBuffer({resolveWithObject: true})
        .then(async ({data, info}) => {
            const newWidth  = info.width;
            const newHeight = info.height;

            const overlay = await sharp(overlayFile)
                .resize(newWidth, newHeight)
                .max()
                .toBuffer();

            return sharp(data)
                .overlayWith(overlay)
                .toBuffer();
        });
}

If there's some easier way to do this that I'm missing, by all means let me know where I've gone wrong. Thanks!

question

All 2 comments

Hello, to perform a calculation based on EXIF Orientation without decoding pixel data, try something like the following (untested):

sharp(file)
  .metadata()
  .then(({ width, height, orientation }) => {
    const [newWidth, newHeight] = orientation < 5
      ? [width, height]
      : [height, width];
    ...
  });

Ha, well that is ridiculously simple, thanks. I still think there's a case to be made for retrieving current metadata (or at least dimensions) at an arbitrary point in the pipeline, but this will work for my case.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

henbenla picture henbenla  路  3Comments

emmtte picture emmtte  路  3Comments

zilions picture zilions  路  3Comments

jaekunchoi picture jaekunchoi  路  3Comments

kachurovskiy picture kachurovskiy  路  3Comments