문서에 이미지 삽입하기
한눈에 보기
섹션 제목: “한눈에 보기”래스터 이미지를 명시적 너비로 절대 위치에 배치합니다. 높이를 생략하면 NextPDF가 원본 가로세로 비율을 기준으로 높이를 계산합니다. 이 레시피는 examples/07-images.php를 따릅니다. NextPDF는 JPEG, PNG, GIF, BMP, WebP, AVIF를 허용합니다.
삽입된 이미지는 ISO 32000-2 이미지 XObject가 됩니다. 해당 딕셔너리는 너비, 높이, 구성 요소당 비트 수를 명시적으로 기술합니다.
composer require nextpdf/core:^3이 image() API는 Core입니다. 기존 파일을 삽입하는 데에는 추가 항목이 필요하지 않습니다. 아래 예제처럼 GD로 테스트 이미지를 생성하려면 ext-gd가 필요합니다. 이 API는 1.0.0 이후 안정적이며 8.1–8.4 백포트 매트릭스에서 실행됩니다.
개념 개요
섹션 제목: “개념 개요”image($file, x, y, width, height)는 이미지 레지스트리를 통해 파일을 로드하고 디코딩한 뒤 배치합니다. 레지스트리는 디코딩 전에 경로를 검증합니다. NUL 바이트가 포함된 경로와 URL 스킴처럼 보이는 경로(scheme://…)를 거부합니다. 이는 image()가 로컬 파일만 읽으며 원격 URL은 절대 읽지 않기 때문입니다. 레지스트리는 양수가 아닌 width 또는 height도 거부합니다.
배치 과정에서는 현재 변환 행렬을 사용해 이미지의 단위 정사각형을 대상 사각형으로 매핑합니다. ISO 32000-2 §8.8은 이를 위해 cm 연산자를 q/Q 쌍 내부에서 사용하도록 규정하므로, 변환은 격리된 상태로 유지됩니다. 디코딩된 래스터는 이미지 XObject가 됩니다. 해당 BitsPerComponent는 필수이며 1, 2, 4, 8, 16 중 하나여야 합니다 (§8.9.5).
API 표면
섹션 제목: “API 표면”API 표면은 PHPDoc에서 자동 생성됩니다. 이 레시피는 하나의 메서드에 의존합니다:
image(string $file, ?float $x = null, ?float $y = null, ?float $width = null, ?float $height = null): static— 로컬 래스터 이미지를 삽입하고 배치합니다. 원본 가로세로 비율을 유지하려면height를 생략하세요. URL 스킴 경로, NUL 바이트 경로, 양수가 아닌 치수는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');코드 샘플 — 프로덕션
섹션 제목: “코드 샘플 — 프로덕션”이것은 완전하며 하니스에서 바로 실행 가능한 예제입니다. 이 예제는 GD로 결정적 테스트 이미지를 생성하므로, 레시피가 자체 완결형으로 유지됩니다. 이 예제는 NEXTPDF_COOKBOOK_OUTPUT를 존중하며 자체 엔트로피를 고정하지 않습니다.
<?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);}엣지 케이스 및 주의 사항
섹션 제목: “엣지 케이스 및 주의 사항”- 원격 URL 사용 불가.
scheme://…와 일치하는 경로는PageLayoutException으로 거부됩니다. 먼저 에셋을 로컬 파일로 다운로드한 다음, 그 경로를 전달하세요. 로더가 대신 네트워크에서 가져오지 않습니다. 이는 의도적인 SSRF 방어입니다. - 양수가 아닌 치수는 예외를 발생시킵니다.
width <= 0또는height <= 0이면PageLayoutException이 발생합니다. 원본 크기를 사용하려면0을 전달하지 말고 인수를 생략하세요. - NUL 바이트 경로 거부.
\0이 포함된 경로는 거부됩니다. 이는 포이즌 널 바이트 방어입니다. 사용자가 제공한 파일 이름을 검증하세요. - 가로세로 비율. 비례해서 크기를 조정하려면
width만 또는height만 전달하세요. 둘 다 전달하면 이미지가 왜곡될 수 있습니다. - 같은 파일을 두 번 삽입. 하나의 경로를 재사용하면 변환 행렬을 통해 크기가 조정됩니다. 엔진은 동일한 바이트를 다시 디코딩하지 않습니다. 파일을 복제하기보다 경로를 재사용하는 것이 좋습니다.
디코딩 비용은 원본 픽셀 수에 비례하므로, 적당한 크기의 사진을 허용하도록 예산은 96 MB로 설정되어 있습니다. 같은 경로를 다시 배치하는 비용은 작습니다. 두 번째 디코딩이 아니라 추가 Do 하나와 cm 하나만 필요합니다. 너비를 줄여 배치해도 저장된 픽셀 수는 줄어들지 않습니다. 문서 크기가 중요하다면 큰 원본 이미지를 미리 크기 조정하세요.
보안 참고 사항
섹션 제목: “보안 참고 사항”URL 스킴 및 NUL 바이트 거부는 SSRF 및 경로 인젝션 방어입니다. image()는 속아서 http://…를 가져오거나 널 바이트 뒤의 경로를 해석하게 만들 수 없습니다. 그렇더라도 사용자가 제공한 파일 이름은 신뢰할 수 없는 것으로 취급하세요. image()를 호출하기 전에 해당 경로가 허용된 기준 디렉터리 아래에 있는지 확인하세요. 파일이 사용자가 업로드한 것이라면, 이미지 디코딩은 공격자가 영향을 미친 바이트에 대해 실행됩니다. 입력 크기를 제한하고 격리된 워커에서 디코딩하는 것을 고려하세요.
적합성
섹션 제목: “적합성”| 설명 | 사양 | 조항 | reference_id (참조 ID) |
|---|---|---|---|
| 이미지 딕셔너리는 너비, 높이, 구성 요소당 비트 수를 명시적으로 지정합니다. | ISO 32000-2 | §8.9.5 | |
BitsPerComponent는 필수이며 1, 2, 4, 8, 16입니다. | ISO 32000-2 | §8.9.5 | |
이미지는 q/Q 내부에서 cm 연산자로 배치됩니다. | ISO 32000-2 | §8.8 |
재현성 프로파일 — 구조적. 이미지 바이트는 고정된 원본에 대해 결정적입니다. 저장된 모든 문서는 여전히 트레일러 /ID와 날짜 아톰을 포함하므로, 하니스는 이를 제거하고 qpdf로 정규화된 구조를 비교합니다. 이 레시피는 NextPDF가 구조를 생성하는 방식을 설명합니다. 이 레시피는 ISO 32000-2 적합성을 포괄적으로 주장하지 않습니다.
상업적 맥락
섹션 제목: “상업적 맥락”해당 없음. 래스터 이미지 삽입은 Premium 게이트가 적용되지 않는 Core 기능입니다.