#!/usr/bin/perl -w
# Author : Dr. Detlef Groth dgroth(at)gmx(dot)de
# Created : Sat Oct 21 07:27:38 2006
# Last Modified : <070603.1811>
# $Log:$
package CombinePDFs;
our $VERSION = "0.2" ;
use PDF::Reuse;
use strict;
our @parts ; # keeps track of the pages ranges
our $total = 0 ; # current page number
sub addDoc {
my $file = shift ;
my $pages = shift;
my $n = 0 ;
if ($pages =~ m/^[0-9]+$/) {
# single page
prDoc($file,$pages,$pages);
$n = 1 ;
} elsif ($pages =~ m/^[0-9]+-[0-9]+$/) {
# pagerange
my @range = split(/-/,$pages);
$n = prDoc($file,$range[0],$range[1]);
} elsif ($pages =~ m/^[0-9]+-end+$/) {
# pages till the end of the document
my @range = split(/-/,$pages);
$n = prDoc($file,$range[0]);
} elsif ($pages eq "all") {
$n = prDoc($file);
}
$total += $n ;
#print "$file\t$total\n";
}
sub createBookmarks {
my $file = shift;
my @last_levels ;
my @bookmarks ;
my $cnt = 0 ;
my $current ;
open (FILE, "$file") or die "Could not open file $file at $!" ;
while (<FILE>) {
next if /^\n/ ;
if (/^([0-9])\s+"(.+)"\s+([0-9]+)\s*([0-9]*)/) {
my $level = $1 ;
my $text = $2 ;
my $page = $3;
$page-- ;
my $scroll = $4;
if ($level == 0) {
if ($current) {
$bookmarks[$cnt++] = $current;
}
# redefine current
if ($scroll) {
$current = {
text => $text,
act => "$page,40,$scroll",
page => "$page,40,$scroll",
close => 1
};
} else {
$current = {
text => $text,
close => 1 ,
act => "this.pageNum = $page;",
page => "$page"
};
}
} elsif ($level >= 1) {
my $mark ;
if ($scroll) {
$mark = {
text => $text,
act => "$page,40,$scroll",
page => "$page,40,$scroll"
};
} else {
$mark = {
text => $text,
act => "this.pageNum = $page;",
page => "$page"
};
}
if ($level == 1) {
if ($current->{kids}) {
push @{$current->{kids}}, $mark;
} else {
$current->{kids} = [$mark];
}
} elsif ($level == 2) {
if ($current->{kids}[-1]->{kids}) {
push @{$current->{kids}[-1]->{kids}}, $mark ;
} else {
$current->{kids}[0]->{kids} = [$mark] ;
}
} elsif ($level == 3) {
if ($current->{kids}[-1]->{kids}[-1]) {
push @{$current->{kids}[-1]->{kids}[-1]->{kids}}, $mark ;
} else {
$current->{kids}[-1]->{kids}[0]->{kids} = [$mark] ;
}
}
}
}
}
close (FILE);
$bookmarks[$cnt] = $current;
#prBookmark({text => "Dokument", close => 1, kids => \@bookmarks});
prBookmark(\@bookmarks);
}
sub createPDF {
my $infile = shift ;
my @infile = @{$infile} ;
my $pages = shift ;
my @pages = @{$pages} ;
@parts = ();
$total = 0;
my $outfile = shift ;
my $bookmarks = shift ;
my $ndocs = $#pages ;
unlink $outfile if (-e $outfile) ;
unlink "$outfile.tmp" if (-e "$outfile.tmp") ;
prFile($outfile);
if($bookmarks) {
createBookmarks($bookmarks);
}
foreach my $x (0..$ndocs) {
push(@parts,$total);
foreach my $prange (split(/,/,$pages[$x])) {
addDoc($infile[$x],$prange);
}
}
# last entry must be added as well
push(@parts,$total);
prEnd();
}
sub isPDF {
my $pdffile = shift;
open (PDFFILE, "$pdffile") or die "Could not open file at $!" ;
my $header = <PDFFILE> ;
my $res = 0 ;
if ($header =~ m/^%PDF-1.[0-9]/) {
$res = 1 ;
}
close (PDFFILE);
}
sub getPagesParts {
return @parts ;
}
sub addBookmarksByArray {
my $infile = shift ;
my $outfile = shift ;
my @partnames = @_ ;
my @last_levels ;
my @bookmarks ;
my $cnt = 0 ;
my $current ;
my $mark ;
my $x = 0 ;
foreach my $part (@partnames) {
my @bm = split(/\t/,$part) ;
if ($bm[0] == 0) {
if ($current) {
$bookmarks[$cnt++] = $current;
}
# redefine current
if ($parts[$x] eq "None") {
$current = {
text => $bm[1],
close => 1
};
} else {
$current = {
text => $bm[1],
close => 1 ,
act => "this.pageNum = $parts[$x];",
page => "$parts[$x]"
};
}
} elsif ($bm[0] == 1) {
$mark = {
text => $bm[1],
act => "this.pageNum = $parts[$x];",
page => "$parts[$x]"
#act => $parts[$x]
};
if ($current->{kids}) {
push @{$current->{kids}}, $mark;
} else {
$current->{kids} = [$mark];
}
}
$x++;
}
$bookmarks[$cnt] = $current;
prFile($outfile);
prBookmark(\@bookmarks);
prDoc($infile);
prEnd();
prBookmark(\@bookmarks);
prDoc($infile);
prEnd();
}
1;
__END__
=head1 NAME
CombinePDFs - utility package for combining PDF documents with PDF::Reuse
=head1 SYNOPSIS
use CombinePDFs;
prFile('myFile.pdf');
my @infiles = ('in1.pdf','in2.pdf','in1.pdf');
my @ranges = ('1-4,5','9-12','8-10');
if (CombinePDFs::isPDF(@infiles)) {
CombinePDFs::createPDF(\@infiles,\@ranges,'outfile.pdf');
}
prEnd();
=head1 DESCRIPTION
This module provides an high level abstraction layer over the great PDF::Reuse module of Lars Lundberg.
=head1 FUNCTION
=head2 createPDF - add files with possible page ranges
createPDF(\@infiles,\@ranges,$outfile,[$bookmarksfile])
The specified range might be a single page specified with a number,
a range specified like from-to or the complete document specified with the keyword all.
Different parts of a document can be separated with commas like seen in the SYNOPSIS.
The optional $bookmarksfile must have the following format:
<level> "<booomark text" <pagenumber>
Root bookmarks have level=0, their childs level=1 and grandchilds level=2 and so on.
=head2 isPDF - check a file if has a valid PDF-header
isPDF($filename)
Checks a file if ith contains a valid PDF-header.
=cut