PDF Thumbnails (PDF to image conversion in a resource pipe?)

Does anyone have a method (in a shortcode or not) for generating a thumbnail image from a PDF?

Something that would get me a small PNG from a PDF (that is a resource, or is otherwise in the build tree).

For images, this is easy (get a resource, pipe it through resize…) - and there are great tools for manipulating images. But I don’t have a way to convert the PDF to an image.

There was a similar post a long ways back: Generate pdf thumbnail
But I don’t know if there is a more modern solution. (and I prefer not to learn how to wrap go libraries)

Thank you!

I’d probably run a Ghostscript command recursively over the content, assets, and static directories to create the thumbs before the build. There’s no way to convert a PDF to a raster image within Hugo.

Thanks!

I was afraid of that… but thought it would be worth asking.

Imagemagick may be easier to use; it delegates to ghostscript.

I’m going to slightly revise my answer. I would use Ghostscript to convert PDF to PNG at 300 dpi, then resize, crop, or fill as needed using Hugo’s image methods.

pdf-to-png.sh
#!/usr/bin/env bash

#------------------------------------------------------------------------------
# @file
# Recursively creates PNG images from the first page of each PDF file in the
# content, assets, and static directories. The PNG images will be placed
# adjacent to the PDF files.
#------------------------------------------------------------------------------

main() {
  if ! hash gs 2>/dev/null; then
    echo "Unable to find Ghostscript executable. Please install Ghostscript."
    exit 1
  fi

  find ./content/ ./assets/ ./static/ -type f -iname "*.pdf" -print0 | while IFS= read -r -d $'\0' file
  do
    dir_name=$(dirname "${file}")
    file_name=$(basename "${file}")
    file_name_without_ext=${file_name%.*}
    output_file=${dir_name}/${file_name_without_ext}.png

    gs  -dSAFER \
        -dBATCH \
        -dNOPAUSE \
        -dFirstPage=1 \
        -dLastPage=1 \
        -sDEVICE=png16m \
        -r300 \
        -dTextAlphaBits=4 \
        -dGraphicsAlphaBits=4 \
        -q \
        -sOutputFile="${output_file}" \
        "${file}" < /dev/null
  done
}

set -euo pipefail
main "$@"

Note that the above will not create PNG images from PDF files imported via modules.

If you need to create PNG images from many PDF files, you may wish to lower the resolution (the r value in the script above) from 300 to 200, 150, or 100 to improve performance and reduce file size. The default value of 300 dpi is the generally accepted minimum value for printing the file at full size.

Like all PDF and PostScript pipelines, it’s a garbage-in garbage-out conversion. Always embed all fonts when creating PDF files (no exceptions), and use a PDF creation tool that actually follows the spec.