5

When printing a pdf with no border (or margins), the printer choppes off around 1mm of the image data at the edges of the paper. I am therefore looking for a solution to scale/resize a pdf page slightly on the page to add a white border at the edges that will correspond with the white space at the edges produced by the printer.

I have tried using gs so far.. For instance, suppose i have an A4 size pdf 1.pdf, then I used:

gs -sDEVICE=pdfwrite \
    -q -dBATCH -dNOPAUSE \
     -dPDFFitPage \
     -r300x300 \
     -g2232x3157 \
    -sOutputFile=1A.pdf \
     1.pdf 

Here, a full a4 paper is given by -g2480x3508 and I have tried to multiply by 0.9 to scale, but I do not see any effect of this..

Håkon Hægland
  • 39,012
  • 21
  • 81
  • 174

4 Answers4

4

Here's a Gist of a bash script that builds on the prev. Fixes a color compatibility problem (possibly specific to my pdf), and does some dependency checking:

#!/bin/bash

# pdfScale.sh
#
# Scale PDF to specified percentage of original size.
# Ref: http://ma.juii.net/blog/scale-page-content-of-pdf-files.

echo "This script doesn't handle files with spaces in them."

SCALE=0.95 # scaling factor (0.95 = 95%, e.g.)

# Validate args.
[ $# -eq 1 ] || { echo "***ERROR: Usage pdfScale.sh <inFile>.pdf"; exit 99; }
INFILEPDF="$1"
[[ "$INFILEPDF" =~ ^..*\.pdf$ ]] || { echo "***ERROR: Usage pdfScale.sh <inFile>.pdf"; exit 99; }
OUTFILEPDF=$(echo "$INFILEPDF" | sed -e s/\.pdf$// -).SCALED.pdf

# Dependencies
command -v identify >/dev/null 2>&1 || { echo >&2 "Please install 'imagemagick' (sudo apt-get install imagemagick).  Aborting."; exit 1; }
command -v gs >/dev/null 2>&1 || { echo >&2 "Please install 'ghostscript' (sudo apt-get install ghostscript ?).  Aborting."; exit 1; }
command -v bc >/dev/null 2>&1 || { echo >&2 "Please install 'bc' arbitrary precision calculator language.  Aborting."; exit 1; }

# Get width/height in postscript points (1/72-inch), via ImageMagick identify command.
# (Alternatively, could use Poppler pdfinfo command; or grep/sed the PDF by hand.)
IDENTIFY=($(identify $INFILEPDF 2>/dev/null)) # bash array
[ $? -ne 0 ] &GEOMETRY=($(echo ${IDENTIFY[2]} | tr "x" " ")) # bash array — $IDENTIFY[2] is of the form PGWIDTHxPGHEIGHT
PGWIDTH=${GEOMETRY[0]}; PGHEIGHT=${GEOMETRY[1]}

# Compute translation factors (to center page.
XTRANS=$(echo "scale=6; 0.5*(1.0-$SCALE)/$SCALE*$PGWIDTH" | bc)
YTRANS=$(echo "scale=6; 0.5*(1.0-$SCALE)/$SCALE*$PGHEIGHT" | bc)

echo $PGWIDTH , $PGHEIGHT , $OUTFILEPDF , $SCALE , $XTRANS , $YTRANS , $INFILEPDF , $OUTFILEPDF

# Do it.
gs \
-q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -dSAFER \
-dCompatibilityLevel="1.5" -dPDFSETTINGS="/printer" \
-dColorConversionStrategy=/LeaveColorUnchanged \
-dSubsetFonts=true -dEmbedAllFonts=true \
-dDEVICEWIDTH=$PGWIDTH -dDEVICEHEIGHT=$PGHEIGHT \
-sOutputFile="$OUTFILEPDF" \
-c "<</BeginPage{$SCALE $SCALE scale $XTRANS $YTRANS translate}>> setpagedevice" \
-f "$INFILEPDF"

https://gist.github.com/MichaelJCole/86e4968dbfc13256228a

More information about this method and a discussion of this gist is availanle on this blog post:

See tavinus/pdfScale, it's a fork with some other features added to it.

SebMa
  • 4,037
  • 29
  • 39
Michael Cole
  • 15,473
  • 7
  • 79
  • 96
  • While this link may answer the question, it is better to include the essential parts of the answer [here](http://meta.stackoverflow.com/a/8259) and provide the link for reference. Link-only answers can become invalid if the linked page changes. – bummi Dec 27 '14 at 19:12
  • If you fork the gist, please repost back here. – Michael Cole Mar 04 '15 at 05:08
  • 2
    @MichaelCole's code has recently been forked and extended in the [tavinus/pdfScale](https://github.com/tavinus/pdfScale) Github repo. – tanius Jul 11 '16 at 11:38
  • 2
    Hi guys! I have refactored [pdfScale](https://github.com/tavinus/pdfScale) again and added a lot of extra stuff. The GS call for scaling is basically still the same, though (which is why I probably will never really post an answer here). V2 now has resizing paper, pdf info printing, paper tables printing and a bunch of other options related to page-resizing (flipping, auto-rotation, etc). [tavinus/pdfScale](https://github.com/tavinus/pdfScale) – Gus Neves May 16 '17 at 08:14
2

It seems like the solution provided at http://ma.juii.net/blog/scale-page-content-of-pdf-files works well here..

Based on that solution, I wrote the following bash script (scaleA4Pdf) for scaling the page content of an A4 pdf file. You can now just write scaleA4Pdf 10 to scale the page 10%..

#! /bin/bash

if [ $# -ne 1 ] ; then
    echo "Bad arguments!"
    exit
fi

# assume 0<=$1<=100 (no error checks!)
xx="595" #width of A4 in post script points 
yy="842" #height of A4 in pps

ss=$(echo "scale=4; $1 / 2" | bc)
sx=$(echo "scale=4; ${xx}"'*'"( ${ss}/ 100 )" | bc)
sy=$(echo "scale=4; ${yy}"'*'"( ${ss}/ 100 )" | bc)
s=$(echo "scale=4; 1 - $1 / 100" | bc)
gs -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -dSAFER \
  -dCompatibilityLevel="1.3" -dPDFSETTINGS="/printer" \
  -dSubsetFonts=true -dEmbedAllFonts=true \
  -sPAPERSIZE=a4 -sOutputFile="1A.pdf" \
  -c "<</BeginPage{${s} ${s} scale ${sx} ${sy} translate}>> setpagedevice" \
  -f 1.pdf
Håkon Hægland
  • 39,012
  • 21
  • 81
  • 174
2

Nice Håkon Hægland! I make a little improvement to make easy select the input.

So if you run

$ scaleA4PDF 10 yourfile.pdf

you will receive a yourfile_scaled.pdf file.

 #! /bin/bash
 input=$2
 output=$(echo $2 | sed s/.pdf/_scaled.pdf/)
 if [ $# -ne 2 ] ; then
 echo "Bad arguments!"
 exit
 fi

 # assume 0<=$1<=100 (no error checks!)
 xx="595" #width of A4 in post script points
 yy="842" #height of A4 in pps

 ss=$(echo "scale=4; $1 / 2" | bc)
 sx=$(echo "scale=4; ${xx}"'*'"( ${ss}/ 100 )" | bc)
 sy=$(echo "scale=4; ${yy}"'*'"( ${ss}/ 100 )" | bc)
 s=$(echo "scale=4; 1 - $1 / 100" | bc)
 gs -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -dSAFER \
 -dCompatibilityLevel="1.3" -dPDFSETTINGS="/printer" \
 -dSubsetFonts=true -dEmbedAllFonts=true \
 -sPAPERSIZE=a4 -sOutputFile="${output}" \
 -c "<</BeginPage{${s} ${s} scale ${sx} ${sy} translate}>> setpagedevice" \
 -f ${input}
Newton_Jose
  • 141
  • 6
  • I got the following error when running: `GPL Ghostscript 9.10: Set UseCIEColor for UseDeviceIndependentColor to work properly. Unrecoverable error: stackunderflow in .setdistillerparams`. I fixed it by replacing `-dPDFSETTINGS="/printer"` with `-dPDFSETTINGS="/screen"`. I also made it work with more weird file names, which contain spaces. See my [gist](https://gist.github.com/cipri-tom/7d482b0f3c7df470691c) – Ciprian Tomoiagă Dec 08 '14 at 12:41
1

Since you did not specify a particular tool you are interested in, I would use iText to accomplish such a task. You could write simple code in Java or .NET (iTextSharp) to accomplish this task easily. Use this as inspiration (n-up tool). While it is actually putting multiple pages of a document into single pages, you could adopt this code to slightly scale individual pages in the same way.

Kevin Brown
  • 8,805
  • 2
  • 20
  • 38