ssimms / pdfapi2

Create, modify, and examine PDF files in Perl
Other
15 stars 20 forks source link

RFC: Proposal for more flexible file/data handling for image routines. #72

Open sciurius opened 8 months ago

sciurius commented 8 months ago

To include an image in a PDF document, PDF::API2 provides the method image:

$img = $pdf->image( $file, %options );

where $file may be either a file name, a filehandle, or a GD::Image object.

In a number of situations the calling program provides the image data itself, or has the image file already read into a scalar variable. To pass this data to the image method we need a temporary file, or 'wrap' it in a file handle:

open( my $fh, '<:raw', \$data );
$img = $pdf->image( $fh, %options );

This works most of the time, but crashes Image::PNG::Libpng.

Although it is not very hard to augment image to (also) take scalar data as its first argument I think it is better to add a new method, image_from_scalar.

$img = $pdf->image_from_scalar( $data, %options );

This will allow PDF::API2 and calling programs to take advantage of file data in scalars without the need to use temporary files or faked file handles.

If you agree I offer to make a PR.

EDIT: $font = $pdf->font($file) is another good candidate for a font_from_scalar sibling.

ssimms commented 7 months ago

image_from_scalar sounds fine to me. That said, if PNG is the only case that isn't working with a wrapper, would it make sense to update that one case to work as documented (probably by transparently creating a tempfile and passing that to libpng) and then add an example to the POD about wrapping a scalar in a file handle?

Not sure about the font case -- how likely is it that someone is going to have a font file loaded into memory and not have a copy on disk?

sciurius commented 7 months ago

how likely is it that someone is going to have a font file loaded into memory and not have a copy on disk?

It occurs frequently in my SVG to PDF module. SVG files can have CSS with @font-face, and this can contain in-line data. For example, a snippet from an SVG file generated by the very popular abc2svg software:

<style>
.f0{font:20.0px text,serif}
.f1{font:italic 14.0px text,serif}
.f2{font:24.0px music}
@font-face{
 font-family:music;
 src:url("data:application/octet-stream;base64,AAEAAAAOAIAAAwBgRkZUTY1L868AAFg.....AAADeLXWv") format("truetype")}
.f2 text,tspan{white-space:pre}
.f3{font:bold 12.0px text,serif}
.f4{font:12.0px text,sans-serif}
.stroke{stroke:currentColor;fill:none}
.bW{stroke:currentColor;fill:none;stroke-width:1}
.bthW{stroke:currentColor;fill:none;stroke-width:3}
.slW{stroke:currentColor;fill:none;stroke-width:.7}
.slthW{stroke:currentColor;fill:none;stroke-width:1.5}
.sW{stroke:currentColor;fill:none;stroke-width:.7}
.box{outline:1px solid black;outline-offset:1px}
</style>

In any case, let's try to avoid the horrible scenario of a user program that does its best to read a file into memory, passes the memory data to a wrapper that writes the data to a temp file, and then passes the temp file to a third module that reads the temp file into memory.

sciurius commented 7 months ago

Also many popular fonts are retrieved from the net, e.g. awesome, and google fonts.

ssimms commented 6 months ago

Works for me. I'll accept a PR for both of those.