7

How can I add a gutter margin (different for odd and even pages) to a PDF document so that there is room to hole-punch it after I print it? I am familiar with Ghostscript and the Linux Terminal but have been unable to find commands to fulfil this specific need.

Currently some content is too close to the edge. I could use scaling in the print dialog box to create room for the binding, but this would reduce the size more than absolutely necessary and leave a gap on both sides of the page.

A solution that simply adds an extra centimetre to either side of the page (left for odd pages and right for even) would be adequate here since I can then choose "scale to fit" feature when I print it.

My question was initially marked as a duplicate of this, but neither answer solves my problem. I tried using both Briss and PDF Scissors, but they are PDF cropping tools and can only make the pages smaller, not larger. My question is also different because I need to resize differently on odd and even pages. The asker of the original question did not have this requirement.

HullCityFan852
  • 1,191
  • 1
  • 10
  • 13
  • Do you have Adobe Acrobat? (Not Adobe "Reader") – skub Apr 21 '15 at 17:47
  • No, unfortunately not. I also tried GhostScript as instructed in [this answer](http://graphicdesign.stackexchange.com/a/35435) to a related question, but the resulting PDF appeared identical to the original, as the asker of that question found when he tried it. – HullCityFan852 Apr 21 '15 at 17:57
  • 1
    Here’s a possible partial answer: use `pdftk` ([The PDF Toolkit](https://www.pdflabs.com/tools/pdftk-the-pdf-toolkit)) to [break the file apart](https://www.pdflabs.com/blog/how-to-collate-even-odd-scanned-pages) into one file with the even pages and one file with the odd pages, pad the pages in each file appropriately (I don’t know how to do that), and recombine them with `pdftk`.  See also [\[How to\] merge two PDF files containing even and odd pages of a book](http://superuser.com/q/516612/150988) for some other tools. – Scott - Слава Україні Apr 23 '15 at 11:53
  • @Scott Thanks, this would certainly work. The padding could be done like [this](http://superuser.com/q/440146/388203). (Notice that although the question refers to centering the answer achieves this using a manual offset.) However, I have actually managed to solve this in a single step (i.e. without splitting the file). See my answer below. – HullCityFan852 Apr 24 '15 at 02:01

2 Answers2

10

I intend to expand this into a proper answer when I have time, but here is the solution I found, in case anyone needs it in the meantime. The idea is to use Ghostscript with the -c option to modify the PDF file using custom PostScript.

Firstly, you need to know the height and width of the original PDF in Points (there are 72 Points in an inch). You could use the tool "pdfinfo" to find this information:

pdfinfo "inputFile.pdf"

Let's say you have an A4 document - A4 is 595pts × 842pts (210mm × 297mm).

If you want to add a 10mm (= 1cm = 28pts) gutter to the A4 document, then you need to give the following information to Ghostscript:

-dDEVICEHEIGHTPOINTS=842 (height of A4)
 -dDEVICEWIDTHPOINTS=623 (=595+28, i.e., width of A4 + the gutter to be added)
   {28 0 translate} {}     ({shift odd pages 28pts right & 0pts up} {do nothing to even pages})

Note: Specifying the increased width adds space to the right hand side of the page, so it is only the odd numbered pages that must be translated - the even pages are already laid out correctly.

Here is the full command for Linux:

gs -q -sDEVICE=pdfwrite -dBATCH -dNOPAUSE -sOutputFile=outputFile.pdf \
  -dDEVICEWIDTHPOINTS=623 -dDEVICEHEIGHTPOINTS=842 -dFIXEDMEDIA \
  -c "<< /CurrPageNum 1 def /Install { /CurrPageNum CurrPageNum 1 add def
   CurrPageNum 2 mod 1 eq {28 0 translate} {} ifelse } bind  >> setpagedevice" \
  -f "inputFile.pdf"

Note: This command makes the PDF 1cm wider than A4. If you then print on A4 everything will be scaled down to fit and the gutter will actually be slightly thinner than 1cm (it will be 9.5mm). If that's not good enough then you will have to do a bit of algebra to get the correct offset. In this case it would be 29.8pts, instead of 28pts, to get a 10.0mm printed gutter (you would also need to set -dDEVICEWIDTHPOINTS=624.8). However, if the gutter is less than ~2cm then it's probably not worth doing the calculation, especially considering the tolerances in printing and paper size.

HullCityFan852
  • 1,191
  • 1
  • 10
  • 13
  • 1
    Where did you find the original solution? :-) *(Good improvement with PostScript-coding the automatic translation for odd pages, BTW)* :) – Kurt Pfeifle May 24 '15 at 16:31
  • @Kurt Thanks :) But I'm not entirely sure what you mean. I drew inspiration from a few [other](http://superuser.com/a/440164/388203) [answers](http://graphicdesign.stackexchange.com/a/35435), also from the GhostScript man pages, and from Adobe's [PostScript Language Reference](https://www.adobe.com/products/postscript/pdfs/PLRM.pdf). As you said, adapting it to only affect odd pages was entirely my own invention, and it was actually extremely difficult due to the limitations of stack-based languages like PostScript. – HullCityFan852 May 25 '15 at 01:47
  • @Kurt Interestingly, page 414 of the [PostScript Language Reference](https://www.adobe.com/products/postscript/pdfs/PLRM.pdf) mentions a built in ImageShift function for performing this very task, and page 427 suggests using BeginPage. However, I tried both and neither appeared to work with Ghostscript, hence the manual page counter in my solution. – HullCityFan852 May 25 '15 at 01:49
  • This should also work: *`gs -o out.pdf -sDEVICE=pdfwrite -c "<>setpagedevice" -f in.pdf`*. The `/ImageShift` pagedevice parameter is only available in PostScript 3 and may not be supported by Ghostscript. – Kurt Pfeifle May 25 '15 at 03:34
  • 1
    @Kurt That appears to give the same shift for odd and even pages, not opposite shift which is what I am trying to achieve, and my solution does. – HullCityFan852 May 25 '15 at 11:00
  • I know, I was just hinting at its difference to /ImageShift . – Kurt Pfeifle May 25 '15 at 11:04
  • There is no need to increase dDEVICEWIDTHPOINTS if you just want to move the content of the page. – Grzegorz Smulko Aug 03 '18 at 10:37
  • @GrzegorzSmulko, true, but I didn't just want to move the content: I also wanted to make the page wider (actually I wanted to keep the page the same size and make the content smaller, but it's the same thing when you print with "Fit to page" enabled). – HullCityFan852 Aug 03 '18 at 13:10
  • I tried with `pdfjam` but it didn't work and it had some issues with the format which was not accepted by another system. This was the only solution that worked. This is my command: `gs -q -sDEVICE=pdfwrite -dBATCH -dNOPAUSE -sOutputFile=output.pdf \ -dDEVICEWIDTHPOINTS=447 -dDEVICEHEIGHTPOINTS=594 -dFIXEDMEDIA \ -c "<< /CurrPageNum 1 def /Install { /CurrPageNum CurrPageNum 1 add def CurrPageNum 2 mod 1 eq {} {25 0 translate} ifelse } bind >> setpagedevice" \ -f "input.pdf"` . In this case I was adding 1cm of binding margin to the right page in a A5 document. – lepe Oct 29 '21 at 14:22
  • Seemingly unnecessarily complicated. Here is a much easier solution (as far as I understood, for the same purpose): https://stackoverflow.com/questions/16158435/add-margin-to-pdf-file-when-merging-using-pdftk-or-similar – Binyomin Nov 18 '21 at 22:43
0

I wanted to keep the same size of the text, and only move it to the side. This modification of HullCityFan's answer achieves that, assuming your side margin is large enough so that the text does not overflow:

$cmd = "<< /CurrPageNum 1 def /Install { /CurrPageNum CurrPageNum 1 add def CurrPageNum 2 mod 0 eq {-20 0 translate} {20 0 translate} ifelse } bind  >> setpagedevice"
    
gs -q -sDEVICE=pdfwrite -dBATCH -dNOPAUSE "-sOutputFile=$output" `
    -dDEVICEWIDTHPOINTS='594.96' -dDEVICEHEIGHTPOINTS='841.92' `
    -dFIXEDMEDIA -c $cmd -f ./path_to_file

The page size is an A4 – if your PDF has a different size, modify the dimensions accordingly. To vary the margin size, change the 20 and -20 values in the PostScript snippet.

a-n
  • 29
  • 1
  • 5