Search code examples
imagepdfpngimagemagickghostscript

How to convert a PDF to PNG with ImageMagick "convert" or Ghostscript?


I'm trying to convert a PDF to a PNG image (at least the cover of one). I'm successfully extracting the first page of the PDF with pdftk. I'm using imagemagick to do the conversion:

convert cover.pdf cover.png

This works, but unfortunately the cover.png comes through incorrectly rendered (some of the alpha object in the PDF aren't rendered properly). I know ImageMagick uses GhostScript to do the conversion and if I do it directly with gs I can get the desired results, but I'd rather use the convert library as it has other tools I'd like to leverage.

This command in GhostScript accomplishes the desired image:

gs -sDEVICE=pngalpha -sOutputFile=cover.png -r144 cover.pdf

I'm wondering is there any way to pass arguments through convert to GhostScript or am I stuck with calling GhostScript directly?


Solution

  • You can use one commandline with two commands (gs, convert) connected through a pipe, if the first command can write its output to stdout, and if the second one can read its input from stdin.

    1. Luckily, gs can write to stdout (... -o %stdout ...).
    2. Luckily, convert can read from stdin (convert -background transparent - output.png).

    Problem solved:

    • GS used for alpha channel handling a special image,
    • convert used for creating transparent background,
    • pipe used to avoid writing out a temp file on disk.

    Complete solution:

    gs -sDEVICE=pngalpha       \
       -o %stdout              \
       -r144 cover.pdf         \
       |                       \
    convert                    \
       -background transparent \
       -                       \
        cover.png
    

    Update

    If you want to have a separate PNG per PDF page, you can use the %d syntax:

    gs -sDEVICE=pngalpha -o file-%03d.png -r144 cover.pdf
    

    This will create PNG files named page-000.png, page-001.png, ... (Note that the %d-counting is zero-based -- file-000.png corresponds to page 1 of the PDF, 001 to page 2...

    Or, if you want to keep your transparent background, for a 100-page PDF, do

    for i in {1..100}; do        \
                                 \
      gs -sDEVICE=pngalpha       \
         -dFirstPage="${i}"      \
         -dLastPage="${i}"       \
         -o %stdout              \
         -r144 input.pdf         \
         |                       \
      convert                    \
         -background transparent \
         -                       \
          page-${i}.png ;        \
                                 \
    done