Convert PDF to Images with a Watermark using ImageMagick
How to turn a PDF into images and stamp a watermark on every page, from the command line, with ImageMagick. One command for a single file, a short loop for a whole folder — and the two things that trip almost everybody up the first time.
Before anything else: two things that will stop you
1. ImageMagick cannot read a PDF on its own. It hands PDFs to Ghostscript. If Ghostscript is not installed, every PDF command fails no matter how correct it is. Install Ghostscript first — gs on Linux and macOS, or the Ghostscript installer on Windows.
2. On most Linux servers, ImageMagick refuses PDFs by default. You will see:
attempt to perform an operation not allowed by the security policy `PDF'
That is not a bug and not your command. Distributions disabled the PDF coder after a Ghostscript security problem. Open the policy file — usually /etc/ImageMagick-6/policy.xml or /etc/ImageMagick-7/policy.xml — and find this line:
<policy domain="coder" rights="none" pattern="PDF" />
Change rights="none" to rights="read|write", save, and the same command works. Only do this on a machine where you control which PDFs get processed.
On Windows and macOS you will usually not hit this at all.
The command names changed
ImageMagick 7 uses magick. Version 6 used convert. Every example below uses magick; on an older install, swap it for convert. Check which you have with magick -version.
PDF to images
The basic conversion:
magick -density 300 input.pdf page-%02d.png
That writes page-00.png, page-01.png and so on, one per page.
-density must come before the input file. It tells Ghostscript what resolution to render at, so it is a read-time setting; put it after the PDF and it does nothing useful. 300 is right for printing. Use 150 for something that will only ever be looked at on screen, and 600 only if you are going to zoom in — the files get large quickly.
If the images come out with black or see-through backgrounds
PDF pages have no background of their own, so a PNG can end up transparent — which looks fine in a browser and black in plenty of other viewers. Force it white:
magick -density 300 input.pdf -background white -alpha remove -alpha off page-%02d.png
Or write JPEGs, which cannot be transparent in the first place:
magick -density 300 input.pdf -background white -alpha remove -quality 88 page-%02d.jpg
One page, or a smaller image
magick -density 300 input.pdf[0] cover.png
magick -density 300 input.pdf -resize 1200x page-%02d.png
[0] is the first page — the numbering starts at zero. -resize 1200x sets the width and works the height out to match.
Adding a watermark
Text, in the same pass
magick -density 300 input.pdf \
-background white -alpha remove -alpha off \
-gravity center -pointsize 64 -fill "rgba(0,0,0,0.18)" \
-annotate +0+0 "whatistheurl.com" \
page-%02d.png
The whole watermark is in three settings. -fill takes an rgba() colour, and the fourth number is the opacity — 0.18 is a good starting point. Solid black is unreadable over the page; below about 0.10 it disappears when printed. -gravity center puts it in the middle, and -annotate +0+0 offsets it from there, so +0-200 moves it up.
Use -gravity south with -annotate +0+40 for a footer-style mark instead of one across the middle.
A logo image
magick composite -dissolve 25 -gravity center logo.png page-00.png out.png
-dissolve 25 is the opacity as a percentage. Use a PNG with a transparent background, or the logo arrives inside a white rectangle.
A whole folder at once
This is the part that turns it from a command into automation.
Linux, macOS, or Git Bash on Windows:
for f in *.pdf; do
magick -density 300 "$f" \
-background white -alpha remove -alpha off \
-gravity center -pointsize 64 -fill "rgba(0,0,0,0.18)" \
-annotate +0+0 "whatistheurl.com" \
"${f%.pdf}-%02d.png"
done
${f%.pdf} strips the extension, so lesson.pdf becomes lesson-00.png, lesson-01.png and so on. Quote "$f" or the first filename with a space in it will break the loop.
Windows PowerShell:
Get-ChildItem *.pdf | ForEach-Object {
magick -density 300 $_.FullName `
-background white -alpha remove -alpha off `
-gravity center -pointsize 64 -fill "rgba(0,0,0,0.18)" `
-annotate +0+0 "whatistheurl.com" `
"$($_.BaseName)-%02d.png"
}
Getting the watermark size right
-pointsize is in points at the resolution you rendered, so the same number looks completely different at different densities. A 64 pt mark on a 300 dpi page is modest; the same 64 pt on a 150 dpi page looks twice as big relative to the page.
If you change -density, scale -pointsize with it. Going from 300 to 600 means doubling the point size to keep the mark looking the same.
Why bother automating it
One PDF is faster to convert by hand in any graphics program. The command line wins the moment there are twenty of them, or the moment you have to do it again next month with the same settings — a loop you can re-run gives you the identical result every time, which clicking through a dialog never does.
It also runs where there is no screen. The same loop works over SSH on a server, or inside a scheduled task, which is the real reason to learn it.