I'm trying to programmatically crop a PDF using GhostScript, which is mostly yielding the correct results. However, the TrimBox dimensions are inherited from the old PDF and nothing I have tried seems to overwrite the TrimBox metadata, and the invalid layout then prevents me from being able to requesting a PDFX from GhostScript.
Here's my almost-working command:
gs -o OUTFILE.pdf -sDEVICE=pdfwrite -dFirstPage=2 -dLastPage=2\
-dPDFSETTINGS=/screen -g6120x6120 \
-c "<< /PageOffset [-9 -9] >> setpagedevice" \
-f INFILE.pdf
and here are the additional Postscript commands I've tried to (the numbers are random and really just there for troubleshooting at this stage):
-c "<< /PDFXSetBleedBoxToMediaBox true /PDFXTrimBoxToMediaBoxOffset [90 90 90 90] /PDFXBleedBoxToTrimBoxOffset [50 50 50 50] >> setdistillerparams"\
-c "<< /BleedBox [36 36 576 576] /TrimBox [72 72 540 540] /ArtBox [0 0 612 612] /CropBox [0 0 612 612] /MediaBox [0 0 612 612] /PDFXSetBleedBoxToMediaBox true >> setpagedevice" \
-c "[/BleedBox [10 20 602 601] /Trim [10 20 598 597] /ArtBox [0 0 612 792] /CropBox [0 0 612 792] /MediaBox [0 0 612 792] /TrimBox pdfmark" \
To add insult to injury, I discover that pdfinfo -box FILE.pdf
does not provide the actual dimensions encoded in the PDF, but if defaults to the bounds of the media box. For an accurate rendition of the encoded dimensions, I use cpdf -page-info FILE.pdf
.
MediaBox: 0.000000 0.000000 612.000000 612.000000
CropBox: 0.000000 0.000000 1242.000000 630.000000
BleedBox: 0.000000 0.000000 1242.000000 630.000000
TrimBox: 9.000000 9.000000 1233.000000 621.000000
As you can see, the BleedBox, CropBox and TrimBoxes are all outside the bounds of the MediaBox, and afaik that should not happen.
I've tried nearly every combination in nearly every order, so I'm clearly missing something. I'm on gs v9.55.0. Help!
[SOLVING THE PROBLEM - IN PROGRESS]
Simplifying, the following does not achieve the desired result:
gs -o OUTFILE.pdf -sDEVICE=pdfwrite -g6120x6120 \
-f INFILE.pdf \
-c "/CropBox [0 0 288 288] /PAGES pdfmark"
and nor does it using /PAGE, however, this does work:
gs -o OUTPUT.pdf -sDEVICE=pdfwrite -g6120x6120 \
-f INPUT.pdf \
-c "[{Page 1} <</TrimBox [0 0 600 600]>> /PUT pdfmark" \
-c "[{Page 2} <</TrimBox [0 0 590 590]>> /PUT pdfmark"
but repeating the last command hundreds of times for a large document would be cumbersome(albeit notionally programmatically possible if prepared in bash and passed to gs). So now I'm trying to write a loop as @KenS suggests:
pages=2 # will substitute programmatically later
gs -o OUTPUT.pdf -sDEVICE=pdfwrite -g6120x6120 \
-f INPUT.pdf \
-c "1 1 $pages {
/n exch def
[ {Page n} <</TrimBox [0 0 600 600]>> /PUT pdfmark
} for"
If I substitute "{Page n}" with "{Page 1}", I get the expected output, but n is not being substituted when expected. "{Page n}" gives a /typecheck error. "/Page 1" gives a range check error so "/Page n" is out of the question. I have also tried to substitute a string for "Page 1" and "{Page 1}" to no avail.
I've also had a go at an EndPage procedure but so far I'm running into the same problem of not being able to substitute a page number. The following is the only combination I can get to work behave as expected so far:
gs -o OUTPUT.pdf -sDEVICE=pdfwrite -g6120x6120 \
-f INPUT.pdf \
-c "<< /EndPage {
[ {Page 1} <</TrimBox [0 0 600 600]>> /PUT pdfmark
} bind >> setpagedevice"