You'll need Ghostscript, Poppler utilities, and ImageMagick:
sudo apt install ghostscript poppler-utils imagemagick
Let's go through this step by step (because I need to go through this mental process myself).
Extract a random page from a PDF
pagecount=$(pdfinfo in.pdf | sed -ne 's/^Pages:\s*//p')
page=$(($RANDOM % $pagecount + 1))
gs -q -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT -sDEVICE=pdfwrite \
-dFirstPage="$page" -dLastPage="$page" -sOutputFile="in.$page.pdf" -f in.pdf
Crop a pre-defined section from the same page
gs -q -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT -sDEVICE=pdfwrite \
-c "[/CropBox [50 50 250 250] /PAGES pdfmark" \
-sOutputFile=out.pdf -f "in.$page.pdf"
Crop a random section from the same page
Select a decimal value for cropsize
(in points, 1 point = 1/72 inch) that is less than both width and height.
cropsize=50
bbox=$(gs -q -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT -sDEVICE=bbox -f "in.$page.pdf" 2>&1 >&- | sed -ne 's/^%%HiResBoundingBox:\s*//p')
cropbbox=$(python3 - "$cropsize" "$bbox" <<EOF
import sys, random
cropsize = float(sys.argv[1])
llx, lly, urx, ury = map(float, sys.argv[2].split(None, 3))
width = urx - llx
height = ury - lly
if width < cropsize or height < cropsize:
print('Crop size too small for bounds', llx, lly, urx, ury, file=sys.stderr)
sys.exit(1)
cropllx = random.uniform(0, width - cropsize) + llx
croplly = random.uniform(0, height - cropsize) + lly
cropurx = cropllx + cropsize
cropury = croplly + cropsize
print(*map(lambda x: format(x, '.6f'), (cropllx, croplly, cropurx, cropury)))
EOF
)
gs -q -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT -sDEVICE=pdfwrite \
-c "[/CropBox [$cropbbox] /PAGES pdfmark" \
-sOutputFile=cropped.pdf -f "in.$page.pdf"
Convert a cropped PDF to JPEG
Adjust size
, -density
(DPI for rendering the PDF), and -quality
(JPEG compression quality) to your needs.
size=256
convert -define pdf:use-cropbox=true -colorspace sRGB -density 600 cropped.pdf \
-flatten -resize "${size}x${size}^" -crop "${size}x${size}+0+0!" -quality 75% cropped.jpg
Putting it all together: Crop N random sections from an arbitrary amount of PDFs
The result is a bit unwieldy for in-line inclusion. Therefore you need to download crop.sh
and crop-calc.py
from my Gist into the same directory.
Usage:
bash /path/to/crop.sh [OPTIONS...] <N> <PDF...>
with:
N
– the count of random areas to extract per document
PDF...
– any number of PDF files
-s|--size PX
– size of the resulting images in pixels (default 256)
-c|--cropsize PT
– size of the document regions to crop in points (default 50)
-d|--density DPI
– pixel density when rendering the document (default 600)1
-q|--quality Q
– compression quality of the resulting image, usually in percent (default 75%)
--destext EXT
– the file extension (and format) of the resulting images (default jpg
)
1 ImageMagick sets a hard limit of 500 mio. pixels which means for a square area the value of cropsize
÷ 72 ⋅ density
may not exceed √500 mio.