Pagination

Back in 2005, my mother wanted to print a 8.5“x11” booklet by printing it on tabloid paper, stapling down the middle, and folding. While this is an extremely easy process from a publishing perspective, actually printing the 11“x22” pages properly is not. Having just learned shell scripting, I decided to tackle the problem in the UNIX fashion by using a couple of already-made utilities (pdftk and pdfjam) and a shell script.

A few years later, the need for this script came up again and I vastly simplified the process by rewriting the script in perl and using the pdfpages package in \(\LaTeX\) directly. The perl script can be found here:

#! /usr/bin/perl
# Copyright (c) 2010 Jason Ekstrand
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to permit
# persons to whom the Software is furnished to do so, subject to the
# following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
# NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
# USE OR OTHER DEALINGS IN THE SOFTWARE.
use strict;

my $help_string = <<END;
Usage:
paginate.pl [options] input.pdf

Options:
  -v        verbose mode
  -k        keep the first page and the last page as the first and last
            pages. (Good if the first and last pages are the front and back
            cover.)
  -h        prints this help screen
  -o file   specifies the output file (default: out.pdf)
END

my $ver = 0;
my $keep = 0;
my $ifile;
my $ofile;

if (not @ARGV) {
    print $help_string;
    exit;
}

while (my $arg = shift) {
    if ($arg eq '-v') {
        $ver = 1;
    } elsif ($arg eq '-k') {
        $keep = 1;
    } elsif ($arg eq '-o') {
        $ofile = shift;
    } elsif ($arg eq '-h') {
        print $help_string;
        exit;
    } else {
        $ifile = $arg;
    }
}

if (not $ofile) {
    $ofile = 'out.pdf';
}

`cp $ifile /tmp/paginate-$$-initial.pdf`;

my $pages = `pdfinfo $ifile |grep Pages`;
$pages =~ /Pages:\s*([0-9]*)/ || die "pdfinfo failed\n";
$pages = $1;
my $blanks = $pages % 4;
if ($blanks) {
    $blanks = 4 - $blanks;
}
my $sheets = ($pages + $blanks) / 4;

if ($ver) {
    print "The new document will contain:\n";
    print "$pages Pages\n";
    print "$blanks Blank Pages\n";
    print "$sheets Sheets\n";
}

my @pages_list = 1..($pages - 1);
if ($keep) {
    for my $i (1..$blanks) {
        push @pages_list, '{}';
    }
    push @pages_list, $pages;
} else {
    push @pages_list, $pages;
    for my $i (1..$blanks) {
        push @pages_list, '{}';
    }
}
$pages += $blanks;

$ver and print "Initial Page List:\n@pages_list\n";

($#pages_list + 1) == ($sheets * 4) or die "Page count wrong\n";

my @final_pages;

for my $i (0..($sheets - 1)) {
    push @final_pages, (
            $pages_list[$pages - ($i * 2) - 1],
            $pages_list[$i * 2],
            $pages_list[($i * 2) + 1],
            $pages_list[$pages - ($i * 2) - 2]);
}

$ver and print "Final Page List:\n@final_pages\n";
$ver and print "Creating Tex File...\n";

$" = ',';
my $texfile = "/tmp/paginate-$$.tex";
open TEXFILE, '>', $texfile or die "Could not open tex file\n";
print TEXFILE <<END;
\\documentclass{article}
\\usepackage[papersize={17in,11in}]{geometry}
\\usepackage{pdfpages}
\\begin{document}
\\includepdf[
    pages={@final_pages},
    nup=2x1,
    frame=false,
    fitpaper=false,
    trim=0 0 0 0,
    delta=0 0,
    offset=0 0,
    scale=1.00,
    turn=true,
    noautoscale=false,
    column=false,
    columnstrict=false,
    openright=false
]{/tmp/paginate-$$-initial.pdf}
\\end{document}
END
$" = ' ';

$ver and print "Running pdflatex...\n";
`pdflatex -output-directory /tmp $texfile`;
`cp /tmp/paginate-$$.pdf $ofile`;
`rm /tmp/paginate-$$*`;