有没有办法强制在 PDF::API2 中提前渲染图像?

Is there a way to force the early rendering of the image in PDF::API2?

这个测试程序

#!/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";

在“第 1 点”后失败,出现错误“无法在 /usr/local/lib/perl5/site_perl/PDF/API2/Basic/PDF/Dict.pm 第 196 行打开 /tmp/Ca6uBG0inC。”

如果我删除行 $tmpFile = undef;,问题就会消失(并生成包含预期图像的有效 PDF)。

考虑到您可以按任何顺序制作页面,稍后返回并修改它们,我可以看出 PDF 的最终呈现是如何不得不推迟的。我添加了 finishobjects() 调用,希望在那个时候强制渲染,但显然它不会。该文档非常 简洁地说明了 finishobjects() 应该做什么。

有没有什么方法可以强制提前渲染图像,这样我就不需要在 运行 结束时一直保留临时文件? (在“真实”代码中,临时文件是根据我正在生成的 PDF 的需要缩放的图像大小调整版本,而不是简单的副本。)

显然,我可以重新安排代码以不删除临时目录(上面的示例使用一个临时文件,但真正的代码将多个文件复制到一个临时目录中)直到保存并关闭 PDF。但是......在某些用途中,我认为这些临时目录中会有数万张中分辨率图像,对于大小为 50GB 左右的 PDF(主要由这些图像组成)。

我一直在想,边走边清理(每批照片都有自己的临时目录,当我处理完那批照片后删除)是礼貌的方式(限制资源使用)。如果我超过了临时文件系统的容量,我将不得不把它们放在真正的磁盘上,我有足够的空间,但速度可能会明显变慢。

您似乎可以使用 update() 而不是 finishobjects() :

$photo->image($img, 0, 0, 400, 600);
$pdf->update();
$tmpFile = undef;
# do something more here..
# Then save the file..
$pdf->save;

编辑:

您似乎需要在调用 update() 后重新打开 pdf:

$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();