Salta ai contenuti

Incorporare immagini in un documento

Posizionare un’immagine raster in posizione assoluta con una larghezza esplicita. Omettere l’altezza: NextPDF la ricava dalle proporzioni dell’immagine di origine. Questa ricetta segue examples/07-images.php. NextPDF accetta JPEG, PNG, GIF, BMP, WebP e AVIF.

Un’immagine incorporata diventa un XObject immagine secondo ISO 32000-2. Il suo dizionario dichiara esplicitamente larghezza, altezza e bit per componente.

Terminal window
composer require nextpdf/core:^3

L’API image() fa parte di Core. Incorporare un file già esistente non richiede componenti aggiuntivi. Generare un’immagine di test con GD, come nell’esempio di riferimento, richiede ext-gd. L’API è stabile da 1.0.0 e funziona sulla matrice di backport 8.1–8.4.

image($file, x, y, width, height) carica il file tramite il registro delle immagini, lo decodifica e lo posiziona. Il registro convalida il percorso prima della decodifica. Rifiuta i percorsi che contengono un byte NUL e quelli che assomigliano a uno schema URL (scheme://…), perché image() legge solo file locali, mai URL remoti. Il registro rifiuta anche width o height non positive.

Il posizionamento usa la matrice di trasformazione corrente per mappare il quadrato unitario dell’immagine nel rettangolo di destinazione. ISO 32000-2 §8.8 specifica l’operatore cm all’interno di una coppia q/Q a questo scopo, in modo che la trasformazione rimanga isolata. Il raster decodificato diventa un XObject immagine. Il suo BitsPerComponent è obbligatorio e deve essere uno tra 1, 2, 4, 8 o 16 (§8.9.5).

La superficie dell’API è generata automaticamente da PHPDoc. Questa ricetta usa un solo metodo:

  • image(string $file, ?float $x = null, ?float $y = null, ?float $width = null, ?float $height = null): static — incorpora e posiziona un’immagine raster locale. Omettere height per mantenere le proporzioni dell’immagine di origine. Rifiuta i percorsi con schema URL, quelli con byte NUL e le dimensioni non positive generando una PageLayoutException.
<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
$doc = Document::createStandalone();
$doc->addPage();
// Absolute position; height inferred from the source aspect ratio.
$doc->image(__DIR__ . '/logo.png', x: 15, y: 30, width: 80);
$doc->save(getenv('NEXTPDF_COOKBOOK_OUTPUT') ?: __DIR__ . '/images.pdf');

Questo è l’esempio completo, pronto per l’harness. Genera con GD un’immagine di test deterministica, in modo che la ricetta resti autonoma. Rispetta NEXTPDF_COOKBOOK_OUTPUT e non introduce entropia propria.

<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
if (!\extension_loaded('gd')) {
fwrite(STDERR, "ext-gd required for the self-contained test image\n");
exit(1);
}
// Build a deterministic test image (fixed pixels — no entropy).
$imgPath = \tempnam(\sys_get_temp_dir(), 'npf') . '.png';
$img = \imagecreatetruecolor(200, 100);
if ($img === false) {
fwrite(STDERR, "GD imagecreatetruecolor failed\n");
exit(1);
}
$bg = (int) \imagecolorallocate($img, 30, 58, 138);
$fg = (int) \imagecolorallocate($img, 255, 255, 255);
\imagefilledrectangle($img, 0, 0, 199, 99, $bg);
\imagestring($img, 5, 40, 40, 'NextPDF Image', $fg);
\imagepng($img, $imgPath);
\imagedestroy($img);
try {
$doc = Document::createStandalone();
$doc->setTitle('Image Embedding');
$doc->addPage();
$doc->setFont('helvetica', 'B', 18);
$doc->cell(0, 12, 'Image Embedding', newLine: true);
$doc->ln(5);
// Absolute placement; width fixed, height from aspect ratio.
$doc->image($imgPath, x: 15, y: 50, width: 80);
// Same image, narrower — scaled down by the CTM, not re-decoded.
$doc->image($imgPath, x: 15, y: 105, width: 40);
$out = getenv('NEXTPDF_COOKBOOK_OUTPUT') ?: __DIR__ . '/images.pdf';
$doc->save($out);
echo "Created images.pdf\n";
} finally {
@\unlink($imgPath);
}
  • Nessun URL remoto. Un percorso che corrisponde a scheme://… viene rifiutato con una PageLayoutException. Scaricare prima la risorsa in un file locale, quindi passare quel percorso. Il loader non effettua download dalla rete per conto dell’utente. È una protezione SSRF deliberata.
  • Le dimensioni non positive generano un’eccezione. Una width <= 0 o una height <= 0 genera una PageLayoutException. Per usare la dimensione naturale, omettere l’argomento invece di passare 0.
  • Percorsi con byte NUL rifiutati. Un percorso che contiene \0 viene rifiutato. È una protezione contro il poison null byte. Convalidare i nomi di file forniti dall’utente.
  • Proporzioni. Passare solo width, oppure solo height, per ridimensionare in modo proporzionale. Passare entrambi può distorcere l’immagine.
  • Lo stesso file incorporato due volte. Riutilizzare un unico percorso applica il ridimensionamento tramite la matrice di trasformazione. Il motore non decodifica di nuovo byte identici. È preferibile riutilizzare il percorso invece di duplicare i file.

Il costo della decodifica è proporzionale al numero di pixel dell’origine, quindi il budget è di 96 MB per consentire una foto di dimensioni moderate. Riposizionare lo stesso percorso è poco costoso: un Do aggiuntivo più un cm, non una seconda decodifica. Ridimensionare tramite larghezza non riduce i pixel memorizzati. Ridimensionare in anticipo le immagini di origine molto grandi se la dimensione finale del documento è importante.

Il rifiuto dei percorsi con schema URL e con byte NUL protegge da SSRF e path injection. image() non può essere indotto a scaricare http://… né a proseguire oltre un null byte. Ciò nonostante, trattare i nomi di file forniti dall’utente come non attendibili. Risolverli rispetto a una directory di base consentita prima di chiamare image(). Quando il file proviene da un caricamento dell’utente, la decodifica dell’immagine viene eseguita su byte influenzabili da un aggressore. Limitare la dimensione dell’input e valutare di eseguire la decodifica in un worker isolato.

DichiarazioneSpecificaClausolareference_id
Un dizionario immagine specifica in modo esplicito larghezza, altezza e bit per componente.ISO 32000-2§8.9.5
BitsPerComponent è obbligatorio ed è 1, 2, 4, 8 o 16.ISO 32000-2§8.9.5
Un’immagine viene posizionata dall’operatore cm all’interno di q/Q.ISO 32000-2§8.8

Profilo di riproducibilità — strutturale. I byte dell’immagine sono deterministici per un’origine fissa. Ogni documento salvato include comunque un /ID nel trailer e atomi data, quindi l’harness li rimuove e confronta la struttura normalizzata con qpdf. Questa ricetta descrive la struttura prodotta da NextPDF. Non formula una dichiarazione generale di conformità a ISO 32000-2.

Non applicabile. L’incorporazione di immagini raster è una funzionalità di Core senza vincoli Premium.