Sharp: Multi Page pdf conversion

Created on 31 Oct 2019  路  11Comments  路  Source: lovell/sharp

First of all, this project is amazing.

I have a question is about sharp api.

I am converting multi-pages pdf files to jpeg (each page is a separate file).
What would be most efficient way to do this? This is a sample implementation that I am using now.

const input = getBufferSomeHow()
const metatada = await sharp(input).metadata()
const conversions = []
for (let i = 0; i < metadata.pages; i++) {
  conversions.push(
   sharp(input, {
       density: myDensity,
       pages: 1,
       page: i,
   }.jpeg().toBuffer())
}
const buffers = await Promise.all(conversions)

When I say most efficient I mean that "given an input buffer that is a multipage pdf, what is the best way to use that buffer to convert its pages in single jpeg files? Is the approach of instantiating sharp every time valid?". Would sharp.clone help in any way?

Thank you 馃槃 .

question

Most helpful comment

Both your approaches look good to me given the complete PDF/GIF is already in memory, or at least on a fast local filesystem. libvips' default caching should help too - use sharp.cache() to check.

All 11 comments

I'm having a similar question, I was trying to resize an animated Gif, to do this, I would read all the pages the input gif, then resize each frame, output to buffer and stitch them together using https://github.com/eugeneware/gifencoder.

let transform = sharp(image.path, {
        pages: -1
    });

    let pages = await transform.metadata().then(metadata => {
        return metadata.pages;
    });

    const encoder = new GIFEncoder(975, 635);
    encoder.setRepeat(0);
    encoder.start();

    for (let i = 0; i < pages; i++) {

        let frame = sharp(image.path, {
            page: i
        })

        frame.resize(975, 635, {
            fit: 'contain',
            background: {
                r: 0,
                g: 0,
                b: 0,
                alpha: 1
            }
        });

        frame.ensureAlpha();
        frame.raw();
        let buffer = await frame.toBuffer();

        encoder.setTransparent(0x000000);
        encoder.addFrame(buffer);

    }

    encoder.finish();

    return encoder.out.getData();

This works, but having to create a new Sharp instance doesn't seem like the best solution, is there a way to export an array of buffers when using pages:-1 ?

Both your approaches look good to me given the complete PDF/GIF is already in memory, or at least on a fast local filesystem. libvips' default caching should help too - use sharp.cache() to check.

@lovell Thank you for the quick repsonse and the explanation.

This example with PDF won't work I believe. It comes back as unsupported file input

@jamiegalbreath have you installed all the dependencies required for pdf support?

Quoting @jamiegalbreath

This example with PDF won't work I believe. It comes back as unsupported file input

Same happening to me. I have run brew install poppler and brew install vips. Maybe I am missing something?

@brecke could you post the version of vips and if the conversion works using it from the command line?

@dnlup I have since found out the reason, vips needs to be compiled for pdf support. It's stated on several issues, but maybe it should be directly in the documentation?

Anyway, thanks.

@brecke Yes, sorry I could have been more clear about it. I remember that it worked on mac without compiling but only adding poppler and ImageMagick (before installing vips). Anyway, you can't go wrong with compiling. I am glad you resolved.

maybe it should be directly in the documentation?

I think it would help

@brecke Last thing, you might find this useful

Was this page helpful?
0 / 5 - 0 ratings

Related issues

terbooter picture terbooter  路  3Comments

jaekunchoi picture jaekunchoi  路  3Comments

zilions picture zilions  路  3Comments

AVVS picture AVVS  路  3Comments

iq-dot picture iq-dot  路  3Comments