#!/bin/bash
#---------------------------------------------------------------#
#
pdf2booklet
#
#
Jerusalem, November 2006
#
#---------------------------------------------------------------#
#
# rearranges a pdf file to print it as one booklet or an array of signatures
# thanks to Mendel Cooper for the Advanced Bash-Scripting Guide
# variables used:
# W, H are the output-page width and hight AS PRINTED, i.e. height is the longer
#+ and width is the shorter
# PDFH and PDFW are the with and height of the PDF-file, respectively
# XOFFSET and YOFFSET are the "left" and "upper" margin and correspond to the xoff, yoff
#+ in pstops
# VARS
ALLOWED_PAGEFORMATS="a4 (default), letter"
factor (){
# defines F according to $1
#+ to change cm, inch into points
case $1 in
cm ) F=28.4
;;
in ) F=72
;;
pt ) F=1
;;
* )
echo " only points (pt), centimetres (cm) and inches
(in) allowed!"
exit
;;
esac
}
error () {
cat <<EOF
Usage: $0 [OPTIONS] PDF-FILE
creates ps documents from a pdf for booklet printing
OPTIONS
-I show Information and suggestions on file and exit
-T two-on-one page, not booklet (default=booklet)
-O uuXxY[:X2xY2] string to define X,Y-offset. X/Y start at upper left corner of output page,
i.e. it is left(X) and upper margin (Y)
Format:
uu<X>x<Y>[/X2xY2] where uu is a 2-letter code for the
measurement(pt,cm,in)
followed by X and Y separated by \`x' and optionally the same
for the second page ([:X2xY2])
-x center horizontically
-y center vertically
-r automatic resize (including offset)
-c <pages> amount of folios for the codex (default=6, i.e. 24 pages)
-p <pag> output page (a4 (default), letter)
-P uuWxH string to define width and height of output paper. Format:
uu<width>x<height> where uu is a 2-letter code for
the measurement(pt,cm,in)
followed by width and height separated by \`x'
-s <shrink> shrink by factor (default=.7)
-F value first page (default=1)
-L value last page (default=last)
-d show frame around page
-v show result in gv
*** save trees - think twice before printing! ***
EOF
}
while getopts ":ITO:xyrc:p:P:s:F:L:dv" OPTION
do
case $OPTION in
I ) # INFO
INFO=yes
;;
T ) # two-in-one
TWOINONE=yes
;;
r ) # left margin
RESIZE=yes
;;
O ) # offset
REST=${OPTARG:2} # rest XxY/XxY
O=${REST%:*} # first XxY/...
O2=${REST#*:} # last .../XxY
factor ${OPTARG:0:2} # units (pt,cm,in) get factor..
# as output page is landscape,the X and Y are switched !!
YOFFSET=$(echo "${O%x*} *
$F" |bc 2> /dev/null ) #+ ..for conversion
XOFFSET=$(echo "${O#*x} *
$F" |bc 2> /dev/null ) #+ .. to points
Y2OFFSET=$(echo "${O2%x*} *
$F" |bc 2> /dev/null ) #+ ..for conversion
X2OFFSET=$(echo "${O2#*x} *
$F" |bc 2> /dev/null ) #+ .. to points
;;
x) XCENTER=yes
;;
y) YCENTER=yes
;;
c ) # number of pages of codex
FOLIO=$OPTARG
;;
p )
PAGESIZE=$OPTARG
case $OPTARG in
a4 ) # do nothing
;;
letter )
H=792
W=612
SHRINK=.647
;;
* ) echo "only
$ALLOWED_PAGEFORMATS -- use -P uu<X>x<Y> other sizes"
exit
;;
esac
;;
P ) # output page size
O=${OPTARG:2}
factor ${OPTARG:0:2} # get factor for conversion to points
W=$(echo "${O%x*} * $F" |bc 2> /dev/null )
H=$(echo "${O#*x} * $F" |bc 2> /dev/null )
;;
s ) # shrink factor
SHRINK=$OPTARG
;;
F ) # first page
FIRST=$OPTARG
;;
L ) # last page
LAST=$OPTARG
;;
d ) # show frame around page
SHOWFRAME="-d"
;;
v) # gv results
GV=yes
;;
esac
done
shift $(( $OPTIND - 1 ))
if [ -z "$1" ]
then
error
exit 65
fi
#Declare varialbles
# from input (pdf) file
PDF="$1"
# our
pdf file to print
PDFINFO=`pdfinfo "$1"`
PAGES=$(echo "$PDFINFO"|grep Pages| awk '{print $2}') # number of pages in pdf-file
PDFW=$(echo "$PDFINFO"|grep "Page size"| awk '{print $3}') # height of PDF-file
PDFH=$(echo "$PDFINFO"|grep "Page size"| awk '{print $5}') # width of PDF-file
# options
FOLIO=${FOLIO-6} # size of codex, i.e. number of folios
let "PCODEX = $FOLIO * 4" # number of pages in codex,
SHRINK=${SHRINK-.7} # shrint factor, default is 0.7
FIRST=${FIRST-1} # first page, default is first
LAST=${LAST-$PAGES} # last page, default is last
# output page
H=${H-842} # height of output page
W=${W-595} # width of output page
XOFFSET=${XOFFSET-0.0} # horizontical offset
YOFFSET=${YOFFSET-0.0} # vertical offset
X2OFFSET=${X2OFFSET-$XOFFSET} # horizontical offset 2nd page
Y2OFFSET=${Y2OFFSET-$YOFFSET} # vertical offset 2nd page
PAGESIZE="-w$W -h$H"
# check, if input file exists
if ! test -f "$PDF"
then
echo "File not found"
exit
fi
# -I: show info and exit
if [[ ! -z $INFO ]]
then
# form command pdfinfo
echo -e " File: $PDF"
# file
name
echo "$PDFINFO" | sed 's/^/ /; s/:[ ]*/: /g' # pdfinfo relayouted
echo
echo -e " pages per codex # of
codices pages of last
codex %"
echo " ----------------------------------------------------------------------"
# list to see "left-over" pages when printing codices
for i in `seq 1 12`
do
# divide no of pages by pages of codex
#+ and rounded up to next higher integer
#+ (broken numbers mean empty pages)
X=$(echo $PAGES $i | awk '{
x = ( $1 / 4 )
if (x == int(x))
x = x
else
x = int(x + 1)
print x
ival = x % $2
aval = int(ival)
if (ival == 0 )
print $2
else {
if (ival == aval)
print aval
else
print aval + 1
}
ival = x / $2
aval = int(ival)
if (ival == aval)
print aval
else
print aval + 1
}')
# set awk output as arguments
set -- $X
#+ there is no more need for arguments, anyhow
SIGNATURES=$1 # number of signatures to print
LASTCODEX=$2 # pages of last codex
NOCODEX=$3 # number of codices to print
[[ $LASTCODEX -eq $i ]]
&& echo -n " >>" # mark when last codex
has 100% pages
echo -e -n "\t$i\t\t$NOCODEX\t\t$LASTCODEX\t\t\t"
echo "scale=2; $LASTCODEX / $i * 100" |bc
done
echo -e "\tsignatures to print: $SIGNATURES"
exit
fi
if [[ $RESIZE == yes ]] # calculate best resize factor accoring to input, ouput and offset
then
# find larger X-offset, avoid negative
VO=$(echo "0 $XOFFSET $X2OFFSET" |awk '{for (i=1;
i<=NF; i++) if ($i >= max ) max = $i } END {print max}')
HO=$(echo "0 $YOFFSET $Y2OFFSET" |awk '{for (i=1;
i<=NF; i++) if ($i >= max ) max = $i } END {print max}')
resize1=$(echo "scale=2; ( ($H / 2 ) - $HO ) / $PDFW" |bc)
resize2=$(echo "scale=2; ( $W - $VO ) / $PDFH" |bc)
# choose the smaller resize factor ;
if [[ ${resize1:1} -gt ${resize2:1} ]]
then
SHRINK=$resize2
else
SHRINK=$resize1
fi
fi
# creating ps file from pdf
TMP1=/tmp/pdf.ps
TMP2=/tmp/booklet.ps
OUTPUTFILE=${PDF%.pdf}
echo " converting (pdftops) ..."
pdftops -paper match -f $FIRST -l $LAST "$PDF" $TMP1
# rearrange pages for booklet
if [[ $TWOINONE == yes ]]
then
TMP2=$TMP1 # non booklet needs no rearragement, just change file
else
psbook -s$PCODEX $TMP1 >$TMP2
fi
# create string for pstops
# see pstops for details (very complex!!)
if [[ $YCENTER == yes ]] # center page to X-axis
then
XOFFSET=$(echo "scale=2; $XOFFSET + ($W - ($PDFH * $SHRINK )-$XOFFSET) / 2" |bc 2>/dev/null)
X2OFFSET=$(echo "scale=2; $X2OFFSET + ($W - ($PDFH * $SHRINK )-$X2OFFSET) / 2" |bc 2>/dev/null)
fi
if [[ $XCENTER == yes ]] # center page to y-axix
then
YOFFSET=$(echo "scale=2; $YOFFSET +( (($H / 2 ) - ($PDFW * $SHRINK ) - $YOFFSET) / 2)" |bc 2>/dev/null)
Y2OFFSET=$(echo "scale=2; $Y2OFFSET +( (($H / 2 ) - ($PDFW * $SHRINK ) - $Y2OFFSET) / 2)" |bc 2>/dev/null)
fi
# page is first shrank (with lower left corner fixed)
#+ then rotated (90 deg to the left (again lower left corner fixed)
#+ and then moved its own (new) size plus the offset
X1=$(echo "scale=2; ($PDFH * $SHRINK) + $XOFFSET" |bc 2>/dev/null) # page height and offset
Y1="$YOFFSET"
X2=$(echo "scale=2; ($PDFH * $SHRINK) + $X2OFFSET" |bc 2>/dev/null)
Y2=$(echo "scale=2; ($H / 2 ) + $Y2OFFSET" |bc 2>/dev/null)
DUPLEX="2:0L@$SHRINK($X1,$Y1)+1L@$SHRINK($X2,$Y2)"
# create final output
cat <<EOF
left margin (left page): $YOFFSET pts
upper margin (left page): $XOFFSET pts
left margin (right page): $Y2OFFSET pts
upper margin (right page): $X2OFFSET pts
shrink factor: $SHRINK
output page size: $PAGESIZE (pts)
file: $OUTPUTFILE.ps
create booklet ...
EOF
pstops $PAGESIZE -b $SHOWFRAME "$DUPLEX" $TMP2 > "$OUTPUTFILE".ps
if [[ $GV == yes ]]
then
gv --orientation=landscape --resize --scale=-1 "$OUTPUTFILE".ps
fi