This is a quick script I got Gemini to write for me. Seemed to make more sense to ask Gemini than to dig through the docs. Essentially a simple wrapper around imagemagick, whose command line args tend to involve a lot of reading the docs.
- Dependencies:
poppler-utilsandimagemagick - Works out if it needs to append page numbers
Usage
cvpdf a.pdf b.pdf c.pdf
cvpdf -d 150 a.pdf b.pdf
cvpdf -d 300 -q 60 --gs a.pdf # greyscale
cvpdf -d 240 -f png --rgba a.pdf # png with transparency
Prompt
python script to make it easier to convert pdf to e.g. jpg or png. It should use ImageMagick to do the conversion, print out information about what it is doing. Desired example usage
cvpdf -d 300 -q 90 --gs a.pdf b.pdf c.pdf
should produce jpegs with -quality 90, filenames a_00.jpg a_01.jpg etc, if the pdf has more than one page. It should check if the pdf has a single page or many. If a single page, don't append numbers, else append. If the page count is 100 or less (00..99) then use 2 digits, else use more (i.e. don't use a single digit like a_1.pdf).
-q or --quality is quality, -d or --dpi is dpi, -f or --output-format is output format, --gs is grayscale, --cmyk is cmyk, --rgb is rgb , --rgba is rgba, default is rgb. --bg is background color (in case of transparency and if output colors aren't --rgba)
The -f png option will produce pngs instead. Default quality is 90. Default dpi is 200
Code
#!/usr/bin/env python3
# requires poppler-utils and imagemagick
prompt = r"""
python script to make it easier to convert pdf to e.g. jpg or png. It should use ImageMagick to do the conversion, print out information about what it is doing. Desired example usage
cvpdf -d 300 -q 90 --gs a.pdf b.pdf c.pdf
should produce jpegs with -quality 90, filenames a_00.jpg a_01.jpg etc, if the pdf has more than one page. It should check if the pdf has a single page or many. If a single page, don't append numbers, else append. If the page count is 100 or less (00..99) then use 2 digits, else use more (i.e. don't use a single digit like a_1.pdf).
-q or --quality is quality, -d or --dpi is dpi, -f or --output-format is output format, --gs is grayscale, --cmyk is cmyk, --rgb is rgb , --rgba is rgba, default is rgb. --bg is background color (in case of transparency and if output colors aren't --rgba)
The -f png option will produce pngs instead. Default quality is 90. Default dpi is 200
"""
import argparse
import subprocess
import sys
import os
import re
def get_page_count(pdf_path):
"""Uses pdfinfo to determine the number of pages in the PDF."""
try:
output = subprocess.check_output(['pdfinfo', pdf_path], stderr=subprocess.STDOUT).decode()
pages_line = [line for line in output.splitlines() if line.startswith('Pages:')]
if pages_line:
return int(re.search(r'\d+', pages_line[0]).group())
except Exception as e:
print(f"Error reading PDF info for {pdf_path}: {e}")
return 1
def convert_pdf(pdf_file, args):
if not os.path.exists(pdf_file):
print(f"Error: File {pdf_file} not found.")
return
pages = get_page_count(pdf_file)
base_name = os.path.splitext(pdf_file)[0]
# Determine padding for numbers
padding = 2 if pages <= 100 else len(str(pages - 1))
print(f"Processing: {pdf_file} ({pages} page(s))")
# Build the ImageMagick command
# Use 'magick' for v7+, fallback to 'convert' for v6
cmd = ['magick', '-density', str(args.dpi)]
# Input file (ImageMagick handles PDF frames/pages with [i])
cmd.append(pdf_file)
# Colorspace and Grayscale logic
if args.gs:
cmd.extend(['-colorspace', 'gray'])
elif args.cmyk:
cmd.extend(['-colorspace', 'CMYK'])
elif args.rgba:
cmd.extend(['-colorspace', 'sRGB', '-alpha', 'on'])
else:
cmd.extend(['-colorspace', 'sRGB'])
# Background and Quality
if args.bg and not args.rgba:
cmd.extend(['-background', args.bg, '-alpha', 'remove', '-alpha', 'off'])
cmd.extend(['-quality', str(args.quality)])
# Output filename logic
if pages == 1:
output_file = f"{base_name}.{args.format}"
print(f" -> Converting to {output_file}...")
subprocess.run(cmd + [output_file])
else:
# For multiple pages, we let ImageMagick handle the sequence
# but we control the naming pattern
output_pattern = f"{base_name}_%0{padding}d.{args.format}"
print(f" -> Converting to {base_name}_[00-{pages-1}].{args.format}...")
subprocess.run(cmd + [output_pattern])
def main():
parser = argparse.ArgumentParser(description="Convert PDF to Images using ImageMagick")
parser.add_argument('files', nargs='+', help="PDF files to convert")
parser.add_argument('-d', '--dpi', type=int, default=200, help="DPI for conversion (default: 200)")
parser.add_argument('-q', '--quality', type=int, default=90, help="Output quality (default: 90)")
parser.add_argument('-f', '--format', default='jpg', choices=['jpg', 'jpeg', 'png', 'tiff'], help="Output format (default: jpg)")
parser.add_argument('--gs', action='store_true', help="Convert to grayscale")
parser.add_argument('--cmyk', action='store_true', help="Use CMYK colorspace")
parser.add_argument('--rgb', action='store_true', help="Use RGB colorspace (default)")
parser.add_argument('--rgba', action='store_true', help="Use RGBA (transparency)")
parser.add_argument('--bg', help="Background color (e.g., white) when flattening transparency")
args = parser.parse_args()
for pdf in args.files:
convert_pdf(pdf, args)
if __name__ == "__main__":
main()