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.86k stars 1.29k forks source link

Enhancement: allow pageHeight to be set for raw input and when creating images #3236

Open everskies opened 2 years ago

everskies commented 2 years ago

Is there currently a way to merge multiple images into a single animation file using Sharp/Libvips?

I've tried using raw buffer data that contains 10 frames, however calling metadata() shows that there is only a single page

  const outputBuffer = Buffer.concat(frames); // 10 different frames merged into a single buffer

  const animatedImage = sharp(outputBuffer, {
      raw: {
          width: canvasSize.x,
          height: canvasSize.y,
          channels: 4,
      },
      animated: true,
      pages: 10,
  });

  console.log(await animatedImage.metadata());
console.log:
{
  format: 'raw',
  size: 3005600,
  width: 221,
  height: 340,
  space: 'srgb',
  channels: 4,
  depth: 'uchar',
  isProgressive: false,
  hasProfile: false,
  hasAlpha: true
}

Saving to WebP also results in a single (non animated) frame

  animatedImage.webp({
    delay: frames.map(() => 100),
    lossless: true,
  }).toBuffer();
lovell commented 2 years ago

Please see future possible enhancement #1580

lovell commented 2 years ago

I hope this information helped. Please feel free to re-open with more details if further assistance is required.

nikolasdas commented 1 year ago

Just in case, has anything changed here @lovell? I'm trying to create an animated webp file from raw pixel data. sharp(array, { raw: { width, height, channels }, animated: true }).webp().toFile(...) does not work, only one frame is created :/ My current solution is to export single frames as images and concat them with ffmeg. This works, but it would be nice if it could be done just using sharp

lovell commented 4 months ago

I'm re-opening as this has come up again in #4092 and I can see there's a group of requests here that differ slightly from #1580 in that they relate only to raw, uncompressed pixel data input.

This proposed API might allow enough to be able to achieve this.

// PROPOSED API, NOT YET AVAILABLE
await sharp(rawInput, {
  raw: {
    width: 8,
    height: 24,
    pageHeight: 8,
    channels: 4
  }
})...

This might also be relevant when creating new images:

// PROPOSED API, NOT YET AVAILABLE
await sharp({
  create: {
    width: 8,
    height: 24,
    pageHeight: 8,
    channels: 4,
    background: 'green'
  }
})...

The use of pageHeight as a property name is to avoid possible confusion with the existing pages property that determines how many pages of a multi-page image are to be opened.

There would need to be some height % pageHeight === 0 validation too.