4

I have many pdf files in a folder. All I want to do is load a pdf file and generate 100 random crops from it and convert each crop to image of size 256x256. So if I have 100 pdf files, I will have 100x100 jpg images as output as I want to get 100 crops from 100 pdf files inside a folder. Can this process be automated? The pdf files are scientific journal papers from CiteSeerX. I have provided a sample document.

I would also like the random crop to focus on the places that has texts rather than on the regions with just white background. Can I enforce this using some techniques?

  • @DavidFoerster: 1. The pdf files are multi-paged. 2. The pdf page is simply consists of scintific journals from CiteSeex. 3. I want to crop a random square region . By 100x100 i mean i want to extract 100 crops from 100 pdf files. I am not clear about the size in millimeter I need, but later I want to convert each crop to a high quality jpg image of size about 256x256. – Dharma Jul 5 '17 at 16:34
  • @DavidFoerster: Could you please look at it. I have edited my question with sample pdf. – Dharma Jul 5 '17 at 17:09
  • @DavidFoerster: yes David. – Dharma Jul 5 '17 at 17:15
3

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.

  • Works Great. Thank you so much. For maximum quality-how much dpi can I set David? – Dharma Jul 6 '17 at 3:33
  • @Dharma: See the foot note – David Foerster Jul 6 '17 at 7:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.