est
est

Reputation: 577

How to shift PDF page using perl (CAM::PDF, PDF::API2)?

I have a PDF document which I need to shift the pages to the right several inches. I.e like putting a margin on the left hand side of the page.

Can either CAM::PDF or PDF::API2 do it? Or is there anyone have experience with it?

Thanks.

Upvotes: 2

Views: 2372

Answers (3)

Kurt Pfeifle
Kurt Pfeifle

Reputation: 90213

You can do that also with Ghostscript. I'll give you some example commands for Windows (when using Unix, just replace gswin32c.exe by gs):

gswin32c.exe ^
   -o input-shifted-pages-1-inch-to-left.pdf ^
   -sDEVICE=pdfwrite ^
   -c "<</PageOffset [-72 0]>> setpagedevice" ^
   -f /path/to/input.pdf
  1. -o : specifies the output file. Implicitly also uses -dNOPAUSE -dBATCH -dSAFER.
  2. -sDEVICE=... : asks Ghostscript to output PDF.
  3. -c <<... : a PostScript code snippet passed on the commandline to make happen the page shift
  4. -f ... : specifies the input PDF (-f is required after using -c).

The units used by /PageShift are PostScript points. 72 pt == 1 inch. The value [-72 0] shifts 72pt==1in to the left and 0in to top/bottom. Now you know how to shift 2 inches to the right:

gswin32c ^
   -o input-shifted-pages-2-inches-to-right.pdf ^
   -sDEVICE=pdfwrite ^
   -c "<</PageOffset [144 0]>> setpagedevice" ^
   -f /path/to/input.pdf

Wanna shift 0.5 in to the bottom and 1 inch to the right?

gswin32c.exe ^
   -o input-shifted-pages-1-inch-to-right-half-inch-down.pdf ^
   -sDEVICE=pdfwrite ^
   -c "<</PageOffset [72 -36]>> setpagedevice" ^
   -f /path/to/input.pdf

Upvotes: 1

Steve Simms
Steve Simms

Reputation: 826

Here's how I would do it in PDF::API2:

use PDF::API2;

my $in  = PDF::API2->open('/path/to/file.pdf');
my $out = PDF::API2->new();

# Choose your margin (72 = one inch)
my $x_offset = 72;
my $y_offset = 0;

foreach my $page_num (1 .. $in->pages()) {
    # Take the source page and import it as an XObject
    my $xobject = $out->importPageIntoForm($in, $page_num);

    # Add the XObject to the new PDF
    my $page = $out->page();
    my $gfx = $page->gfx();
    $gfx->formimage($xobject, $x_offset, $y_offset);
}
$out->saveas('/path/to/new.pdf');

Another way that should work is to adjust the coordinates for the mediabox (and possibly other boxes):

use PDF::API2;

my $pdf = PDF::API2->open('/path/to/file.pdf');

# Choose your margin (72 = one inch)
my $x_offset = 72;
my $y_offset = 0;

foreach my $page_num (1 .. $pdf->pages()) {
    my $page = $pdf->openpage($page_num);

    # Get the coordinates for the page corners
    my ($llx, $lly, $urx, $ury) = $page->get_mediabox();

    # Add the margin by shifting the mediabox in the opposite direction
    $llx -= $x_offset;
    $lly -= $y_offset;
    $urx -= $x_offset;
    $ury -= $y_offset;

    # Store the new coordinates for the page corners
    $page->mediabox($llx, $lly, $urx, $ury);
}

$pdf->saveas('/path/to/new.pdf');

If you run into issues with content getting cut off, you may need to get and set one or more of cropbox, bleedbox, trimbox, and artbox as well, but this should work in most cases.

Upvotes: 2

Chris Dolan
Chris Dolan

Reputation: 8963

I'm the author of CAM::PDF. The following little program shifts the page contents right by 100 points.

use CAM::PDF;
my $pdf = CAM::PDF->new('my.pdf');
my $page = $pdf->getPage(1);
$page->{MediaBox}->{value}->[0]->{value} -= 100;
$page->{MediaBox}->{value}->[2]->{value} -= 100;
$pdf->cleanoutput('out.pdf');

I used "use Data::Dumper; print Dumper($page);" to remind myself of the $page data structure.

Upvotes: 3

Related Questions