summaryrefslogtreecommitdiffstats
path: root/pdftool.pl
diff options
context:
space:
mode:
Diffstat (limited to 'pdftool.pl')
-rwxr-xr-xpdftool.pl88
1 files changed, 47 insertions, 41 deletions
diff --git a/pdftool.pl b/pdftool.pl
index b374c45..14cad52 100755
--- a/pdftool.pl
+++ b/pdftool.pl
@@ -10,7 +10,7 @@
$VERSION = "0.4, 12 May 2011";
use Getopt::Long qw(:config posix_default no_ignore_case gnu_compat
- bundling auto_version auto_help);
+ bundling auto_version auto_help);
use Pod::Usage;
use IPC::Open2;
use IPC::Open3;
@@ -47,7 +47,7 @@ If no output file is given, or if a single hyphen-minus (B<->) is given as
file name, B<PDFTool> will send the data to the standard output.
By default, B<PDFTool> rotates the pages in order to ensure that your pdf will
-be printable using your favorite duplex mode for portrait documents (tumble if
+be printable using your favorite duplex mode for portrait documents (Tumble if
you prefer to turn the pages like those of a book). See the B<--screen>
option to bypass this behavior.
@@ -55,15 +55,17 @@ The document will be treated as follows:
=over 4
-=item * Conversion from PDF to PostScript (if necessary),
+=item * Convert from PDF to PostScript (if necessary),
-=item * Selection of the page range,
+=item * Select of the page range,
-=item * Rearranging pages for printing books or booklets,
+=item * Calculate the minimal bounding box
-=item * Putting multiple pages per sheets,
+=item * Rearrange pages for printing books or booklets,
-=item * Conversion back from PS to PDF.
+=item * Put multiple pages per sheets,
+
+=item * Convert back from PS to PDF.
=back
@@ -140,7 +142,10 @@ demanding for the CPU. See the note for the border option (B<-b>) above.
=item B<--book>
-Rearrange pages for printing books or booklets.
+Rearrange pages for printing books or booklets. If your "default" duplex
+mode (see B<DESCRIPTION>) is "NoTumble", you should either use lpr with
+the option "Tumble" manually, or consider the B<PDFTool> option
+B<--screen> instead.
=item B<-n, --nup=>I<num>
@@ -185,9 +190,10 @@ Display the manual page.
=head1 EXAMPLES
The following comand can be used to remotely crop a PDF file, convert it
-to A4 paper, and rearrange the pages to print a booklet:
+to A4 paper, and rearrange the pages to print a booklet:
-C<< ssh remote pdftool.pl -cpA4 --book -2 -b2cm -m-1cm < in.pdf | lpr >>
+C<< ssh remote pdftool.pl -cpA4 --book -2 -b2cm -m-1cm < in.pdf | \
+ lpr -o Duplex=DumplexTumble >>
=head1 REQUIREMENTS
@@ -206,7 +212,7 @@ conditions.
my $tmpdir = '/tmp';
#
-# Options & arguments
+# Options & arguments
#
my $select;
@@ -291,7 +297,7 @@ if (defined $infile && $infile ne "-") {
$infile_display = "(stdin)";
}
# After the pipe, it won't be detected as seekable
-my $inseek = (seek FIN, 0, 1) ? 1 : undef;
+my $inseek = (seek FIN, 0, 1) ? 1 : undef;
if (defined $outfile && $outfile ne "-") {
@@ -320,7 +326,7 @@ while (not (defined $filetype) && defined (my $l = <FIN>)) {
$filetype = "PS";
} elsif (defined $l && $l =~ /^%PDF/) {
$filetype = "PDF";
- }
+ }
}
die "Cannot recognise FileType" unless defined $filetype;
@@ -329,7 +335,7 @@ unless (my $pid = fork) {
# Child: cat FIN > WRITE in background
die "Can't fork: $!" unless defined $pid;
close READ or die "Can't close: $!";
-
+
while (<FIN>) {
print WRITE or die "Can't print: $!";
}
@@ -339,7 +345,7 @@ unless (my $pid = fork) {
close WRITE or die "Can't close: $!";
close FIN or die "Can't close: $!";
-
+
open *FIN, "<&READ" or die "Can't dup: $!";
@@ -353,14 +359,14 @@ my @pids;
#
-# Conversion from PDF to PS, if necessary
+# Conversion from PDF to PS, if necessary
#
my @cmd;
if ($filetype eq "PDF") {
unless (defined $infile && $inseek) {
# Need to copy the whole input to an auxiliary file, since
# conversion from PDF to PS requires random access to the data
-
+
$infile = "$tmpdir/pdftool-stdin-$$" . lc ".$filetype";
open FINAUX, '>', "$infile"
@@ -383,12 +389,12 @@ if ($filetype eq "PDF") {
undef $first if defined $rmin && not $rmin;
undef $last if defined $rmax && not $rmax;
if (defined $rmin && $rmin) {
- $first = $rmin if defined $first && $rmin < $first;
- $last = $rmin if defined $last && $rmin > $last;
+ $first = $rmin if defined $first && $rmin < $first;
+ $last = $rmin if defined $last && $rmin > $last;
}
if (defined $rmax && $rmax) {
- $first = $rmax if defined $first && $rmax < $first;
- $last = $rmax if defined $last && $rmax > $last;
+ $first = $rmax if defined $first && $rmax < $first;
+ $last = $rmax if defined $last && $rmax > $last;
}
}
@@ -404,15 +410,15 @@ if ($filetype eq "PDF") {
$r .= $rmax if defined $rmax;
push @newselect, $r;
}
-
+
$select = join ',', @newselect;
}
-
+
# Convert to PS
@cmd = ('pdftops', '-origpagesizes', "$infile", '-');
- push @cmd, '-f', $first if defined $first;
- push @cmd, '-l', $last if defined $last;
+ push @cmd, '-f', $first if defined $first;
+ push @cmd, '-l', $last if defined $last;
push @cmd, '-q' if defined $quiet;
my $pid = open *PSIN, "-|", @cmd
or die "Can't run `" . &printcmd (@cmd) . "'";
@@ -433,7 +439,7 @@ if (defined $select) {
my $pid = open3 "<&IN", *OUT, ">&LOG", @cmd;
push @pids, [$pid, @cmd];
open *IN, "<&OUT" or die "Can't dup: $!";
-}
+}
@@ -443,7 +449,7 @@ if (defined $select) {
my @bbox;
if (defined $crop) {
# Calculate the maximal bounding box
-
+
unless (seek IN, 0, 1) {
# The input is not seekable: have to create a seekable auxiliary file
@@ -462,13 +468,13 @@ if (defined $crop) {
open IN, '<', "$auxfile" or die "Can't read `$auxfile': $!";
}
-
+
# Need to duplicate IN, since it will be closed in the parent process
open *GSIN, '<&IN';
@cmd = ('gs', '-sDEVICE=bbox', '-dBATCH', '-dNOPAUSE', '-');
my $pid = open3 "<&GSIN", ">&GSOUT", *GSOUT, @cmd;
-
+
my ($p,$c) = (0,0); # Page & character counter
my ($x0, $y0, $x1, $y1) = (1<<16, 1<<16, -(1<<16), -(1<<16));
while (<GSOUT>) {
@@ -490,11 +496,11 @@ if (defined $crop) {
}
close GSOUT or die "Can't close: $!";;
print LOG "\n" or die "Can't close: $!" unless defined $quiet;
-
+
# No zombie processes
waitpid $pid, 0;
die "Can't run `" . &printcmd (@cmd) . "'" if $? >> 8;
-
+
die "Error when calculating bounding box" if ($x0 >= $x1 || $y0 >= $y1);
@bbox = ($x0, $y0, $x1, $y1);
@@ -505,7 +511,7 @@ if (defined $crop) {
@bbox = (0, 0, $inwidth, $inheight);
} else {
# Guess page size from the input file
-
+
# To avoid to seek into IN, it gonna be copied from WRITE to READ
# in background, once the Bounding Box has been read
pipe *READ, *WRITE or die "Can't pipe: $!";
@@ -515,14 +521,14 @@ if (defined $crop) {
@bbox = ($1, $2, $3, $4)
if ($l =~ m/^\%\%BoundingBox: (\d+) (\d+) (\d+) (\d+)/);
}
-
+
die "Cannot guess input page size!" unless @bbox;
unless (my $pid = fork) {
# Child: cat IN > WRITE in background
die "Can't fork: $!" unless defined $pid;
close READ or die "Can't close: $!";;
-
+
while (<IN>) {
print WRITE or die "Can't close: $!";
}
@@ -532,7 +538,7 @@ if (defined $crop) {
close WRITE or die "Can't close: $!";
close IN or die "Can't close: $!";
-
+
open *IN, "<&READ" or die "Can't dup: $!";
}
@@ -553,7 +559,7 @@ if (defined $book) {
#
-# PSNup
+# PSNup (inlined here, to keep track of the possible rotation)
#
my $landscape;
if ((($bbox[2]-$bbox[0] > $bbox[3]-$bbox[1])
@@ -646,7 +652,7 @@ sub calc_layout {
my ($inwidth, $inheight) = ($bbox[2]-$bbox[0], $bbox[3]-$bbox[1]);
my ($horiz, $vert, $rotate, $scale, $hshift, $vshift);
-
+
my $tolerance = 100000; # layout tolerance
my $best = $tolerance;
@@ -654,7 +660,7 @@ sub calc_layout {
my $ver = $nup / $hor;
# try normal orientation first
my $scl = &min ($outheight/($inheight*$ver), $outwidth/($inwidth*$hor));
-
+
my $optim = ($outwidth-$scl*$inwidth*$hor)*($outwidth-$scl*$inwidth*$hor)
+ ($outheight-$scl*$inheight*$ver)*($outheight-$scl*$inheight*$ver);
if ($optim < $best) {
@@ -682,7 +688,7 @@ sub calc_layout {
$rotate = 3;
}
}
-
+
# fail if nothing better than worst tolerance was found
die "Can't find acceptable layout for $nup-up" if $best == $tolerance;
@@ -750,7 +756,7 @@ sub calc_specs {
sub topoints {
my $l = $_[0];
return unless defined $$l;
-
+
$$l =~ /^([+-]?\d*\.?\d+)(\w*)$/ or die "Unable to parse `$$l'";
my $r = $1;
@@ -829,7 +835,7 @@ sub printcmd {
push @cmd, $s;
}
- join ' ', @cmd;
+ join ' ', @cmd;
}