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?

3
  • @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, 2017 at 16:34
  • @DavidFoerster: Could you please look at it. I have edited my question with sample pdf.
    – Dharma
    Jul 5, 2017 at 17:09
  • @DavidFoerster: yes David.
    – Dharma
    Jul 5, 2017 at 17:15

1 Answer 1

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.

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

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .