diff options
-rwxr-xr-x | pdftool.pl | 88 |
1 files changed, 47 insertions, 41 deletions
@@ -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; } |