This test program
#!/usr/bin/env perl
# Test program for multiple-page tifs with pictures -- when must the
# file exist? And can I force that to end earlier?
use strictures 2;
use utf8;
use PDF::API2;
use Path::Tiny qw ( path tempdir tempfile );
my $pdf = PDF::API2->new( -file => "t001.pdf" );
$pdf->mediabox(11 * 72, 8.5 * 72);
my $page = $pdf->page;
# Add image to page
my $photo = $page->gfx;
my $photoFile = path('mcplay/pcd 138-02.jpg');
my $tmpFile = tempfile();
$photoFile->copy ($tmpFile);
my $img = $pdf->image_jpeg($tmpFile->stringify);
$photo->image($img, 0, 0, 400, 600);
# Does "finishing" the objects remove the further need for the file?
$pdf->finishobjects($photo, $page);
$tmpFile = undef; # Remove the temp file before save
# Yes, this duplicates the observed error in the more complex code
# And finish the page and the file
print "point 1\n";
$pdf->save;
print "point 10\n";
$pdf->end();
print "point 20\n";
Fails after "point 1" with the error "Unable to open /tmp/Ca6uBG0inC at /usr/local/lib/perl5/site_perl/PDF/API2/Basic/PDF/Dict.pm line 196."
If I remove the line $tmpFile = undef;
, the problem goes away (and a valid PDF is generated that contains the expected image).
Given that you can do pages in any order, and go back and modify them later, I can see how final rendering of the PDF has to get postponed. I added the finishobjects()
call in hopes that that would force rendering at that point, but obviously it doesn't. The documentation is extremely terse on what, if anything, finishobjects()
is supposed to do.
Is there any way to force the early rendering of the image, so I don't need to keep the temp file around through the end of the run? (In the "real" code, the temp file is a resized version of the image scaled to the needs of the PDF I'm producing rather than a simple copy.)
Obviously, I can rearrange the code to not delete the temp directories (the example above uses one temp file, but the real code copies multiple files into a temp directory) until after the PDF has been saved and closed. But...in some uses I think there would be tens of thousands of medium-res images in those temp directories, for a PDF that would be 50GB or so in size (mostly made up of those images).
I've been thinking that cleaning up as I go (every batch of photos has its own temp directory, which is deleted when I'm done with that batch of photos) is the polite way to do it (limiting resource use). And if I exceed the capacity of the temp filesystem I'll have to put them on real disk, which I've got room for, but which will probably be notably slower.
It seems like you can use update() instead of finishobjects()
:
$photo->image($img, 0, 0, 400, 600);
$pdf->update();
$tmpFile = undef;
# do something more here..
# Then save the file..
$pdf->save;
It seems like you might need to reopen the pdf after having called update()
:
$photo->image($img, 0, 0, 400, 600);
$pdf->update();
$pdf->end();
$tmpFile = undef;
# Reopen the file to do something more with it..
$pdf = PDF::API2->open("t001.pdf" );
# do something more here..
# Then save the file..
$pdf->update();
$pdf->end();