Pular para o conteúdo

Incorpore imagens em um documento

Posicione uma imagem raster de forma absoluta, com uma largura explícita. Quando você omite a altura, o NextPDF a deriva da proporção da fonte. Esta receita segue examples/07-images.php. Você pode usar arquivos JPEG, PNG, GIF, BMP, WebP e AVIF.

O NextPDF incorpora a imagem como um XObject de imagem da ISO 32000-2. O dicionário de imagem declara explicitamente a largura, a altura e os bits por componente.

Terminal window
composer require nextpdf/core:^3

A API image() faz parte do Core. Você não precisa de mais nada para incorporar um arquivo existente. O exemplo de suporte gera uma imagem de teste com o GD, por isso ele precisa da ext-gd. A API é estável desde a versão 1.0.0 e funciona na matriz de backport 8.1–8.4.

image($file, x, y, width, height) carrega o arquivo pelo registro de imagens, decodifica-o e o posiciona. O registro valida o caminho antes da decodificação. Ele rejeita qualquer caminho que contenha um byte NUL ou que pareça usar um esquema de Uniform Resource Locator (URL) (scheme://…). image() lê apenas arquivos locais, nunca uma URL remota. O registro também rejeita valores não positivos para width ou height.

O posicionamento usa a matriz de transformação atual para mapear o quadrado unitário da imagem no retângulo de destino. A ISO 32000-2 §8.8 especifica o operador cm dentro de um par q/Q para esse posicionamento, de modo que a transformação permaneça isolada. O raster decodificado se torna um XObject de imagem. Seu BitsPerComponent é obrigatório e deve ser um dos valores 1, 2, 4, 8 ou 16 (§8.9.5).

A superfície da API é gerada a partir do PHPDoc. Esta receita usa um método:

  • image(string $file, ?float $x = null, ?float $y = null, ?float $width = null, ?float $height = null): static — incorpora e posiciona uma imagem raster local. Omita height para preservar a proporção da fonte. O método rejeita caminhos com esquema de URL, caminhos com byte NUL e dimensões não positivas lançando uma 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');

Este exemplo completo, pronto para o harness, gera uma imagem de teste determinística com o GD, para que a receita continue autossuficiente. Ele respeita NEXTPDF_COOKBOOK_OUTPUT e não introduz entropia própria.

<?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);
}
  • Sem URLs remotas. Um caminho que corresponda a scheme://… é rejeitado com uma PageLayoutException. Baixe o recurso para um arquivo local primeiro e, em seguida, passe esse caminho. O carregador não acessa a rede por você. Esta é uma proteção deliberada contra Server-Side Request Forgery (SSRF).
  • Dimensões não positivas lançam exceção. Uma width <= 0 ou height <= 0 gera uma PageLayoutException. Para usar o tamanho natural, omita o argumento em vez de passar 0.
  • Caminho com byte NUL rejeitado. Um caminho que contenha \0 é rejeitado. Isso protege contra caminhos com poison-null-byte. Valide os nomes de arquivo que você recebe de usuários.
  • Proporção. Passe apenas width, ou apenas height, para escalar proporcionalmente. Passar os dois valores pode distorcer a imagem.
  • O mesmo arquivo incorporado duas vezes. Reutilize um único caminho para escalar usando a matriz de transformação. O motor não redecodifica bytes idênticos. Prefira reutilizar o caminho a duplicar arquivos.

O custo de decodificação é proporcional à contagem de pixels da fonte, por isso o orçamento é de 96 MB para permitir uma foto de tamanho moderado. Posicionar o mesmo caminho novamente custa pouco: um Do extra mais um cm, não uma segunda decodificação. Reduzir a escala pela largura não diminui os pixels armazenados. Redimensione previamente imagens de origem grandes se o tamanho do documento for importante.

A rejeição de esquemas de URL e bytes NUL protege contra SSRF e injeção de caminho. image() não pode ser induzida a buscar http://… nem a atravessar caminhos depois de um byte nulo. Ainda assim, trate como não confiáveis os nomes de arquivo que você recebe de usuários. Resolva-os em relação a um diretório base permitido antes de chamar image(). Quando o arquivo vem de um usuário, a decodificação da imagem é executada em bytes que o invasor pode influenciar. Limite o tamanho da entrada e considere decodificar em um worker isolado.

DeclaraçãoEspecificaçãoCláusulareference_id
Um dicionário de imagem especifica largura, altura e bits por componente de forma explícita.ISO 32000-2§8.9.5
BitsPerComponent é obrigatório e vale 1, 2, 4, 8 ou 16.ISO 32000-2§8.9.5
Uma imagem é posicionada pelo operador cm dentro de q/Q.ISO 32000-2§8.8

Perfil de reprodutibilidade — estrutural. Os bytes da imagem são determinísticos para uma fonte fixa. Todo documento salvo ainda contém um /ID no trailer e átomos de data, por isso o harness os remove e compara a estrutura normalizada pelo qpdf. Esta receita descreve como o NextPDF produz a estrutura. Ela não faz uma alegação genérica de conformidade com a ISO 32000-2.

Não se aplica. A incorporação de imagens raster é um recurso do Core, sem restrição Premium.