ข้ามไปยังเนื้อหา

ฝังรูปภาพลงในเอกสาร

วางรูปภาพแบบราสเตอร์ที่ตำแหน่งสัมบูรณ์ด้วยความกว้างที่กำหนดไว้อย่างชัดเจน หากละเว้นความสูง NextPDF จะคำนวณค่านั้นจากอัตราส่วนภาพของต้นฉบับ สูตรนี้อ้างอิงจาก examples/07-images.php คุณสามารถใช้ไฟล์ JPEG, PNG, GIF, BMP, WebP และ AVIF ได้

NextPDF ฝังรูปภาพในรูปแบบ image XObject ตาม ISO 32000-2 โดย image dictionary ระบุความกว้าง ความสูง และจำนวนบิตต่อองค์ประกอบไว้อย่างชัดเจน

Terminal window
composer require nextpdf/core:^3

API image() เป็นส่วนหนึ่งของ Core คุณไม่จำเป็นต้องใช้สิ่งอื่นเพิ่มเติมเพื่อฝังไฟล์ที่มีอยู่แล้ว ตัวอย่างประกอบสร้างรูปภาพทดสอบด้วย GD จึงต้องใช้ ext-gd API เสถียรมาตั้งแต่เวอร์ชัน 1.0.0 และทำงานบนเมทริกซ์ backport 8.1–8.4

image($file, x, y, width, height) โหลดไฟล์ผ่าน image registry ถอดรหัส แล้ววางลงในเอกสาร registry จะตรวจสอบความถูกต้องของพาธก่อนถอดรหัส และปฏิเสธพาธใด ๆ ที่มี NUL byte หรือมีลักษณะเป็น Uniform Resource Locator (URL) scheme (scheme://…) image() อ่านเฉพาะไฟล์ในเครื่องเท่านั้น ไม่อ่าน URL จากระยะไกล registry ยังปฏิเสธค่า width หรือ height ที่ไม่เป็นบวกด้วย

การวางใช้ current transformation matrix เพื่อแมป unit square ของรูปภาพลงในสี่เหลี่ยมผืนผ้าเป้าหมาย ISO 32000-2 §8.8 กำหนดให้ใช้ตัวดำเนินการ cm ภายในคู่ q/Q สำหรับการวางนี้ การแปลงจึงยังคงแยกจากกัน ราสเตอร์ที่ถอดรหัสแล้วจะกลายเป็น image XObject ค่า BitsPerComponent เป็นค่าที่จำเป็นและต้องเป็นหนึ่งใน 1, 2, 4, 8 หรือ 16 (§8.9.5)

ขอบเขตของ API สร้างจาก PHPDoc สูตรนี้ใช้เมธอดเดียว:

  • image(string $file, ?float $x = null, ?float $y = null, ?float $width = null, ?float $height = null): static — ฝังและวางรูปภาพแบบราสเตอร์ในเครื่อง ละเว้น height เพื่อรักษาอัตราส่วนภาพของต้นฉบับ เมธอดนี้ปฏิเสธพาธแบบ URL-scheme พาธที่มี NUL byte และมิติที่ไม่เป็นบวก โดยจะโยน 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');

ตัวอย่างที่สมบูรณ์และพร้อมใช้กับ harness นี้สร้างรูปภาพทดสอบแบบกำหนดได้ด้วย 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 ให้ดาวน์โหลดทรัพยากรไปยังไฟล์ในเครื่องก่อน แล้วจึงส่งพาธนั้นเข้าไป ตัวโหลดจะไม่ดึงข้อมูลผ่านเครือข่ายให้คุณ นี่คือมาตรการป้องกัน Server-Side Request Forgery (SSRF) ที่ออกแบบไว้อย่างจงใจ
  • มิติที่ไม่เป็นบวกจะโยนข้อยกเว้น ค่า width <= 0 หรือ height <= 0 จะทำให้เกิด PageLayoutException หากต้องการใช้ขนาดตามธรรมชาติ ให้ละเว้นอาร์กิวเมนต์แทนการส่งค่า 0
  • พาธที่มี NUL byte จะถูกปฏิเสธ พาธที่มี \0 จะถูกปฏิเสธ มาตรการนี้ป้องกันพาธแบบ poison-null-byte ให้ตรวจสอบความถูกต้องของชื่อไฟล์ที่ผู้ใช้ระบุ
  • อัตราส่วนภาพ ส่งเฉพาะ width หรือเฉพาะ height อย่างใดอย่างหนึ่ง เพื่อปรับขนาดตามสัดส่วน การส่งทั้งสองค่าอาจทำให้รูปภาพบิดเบี้ยว
  • การฝังไฟล์เดียวกันสองครั้ง ใช้พาธเดียวซ้ำเพื่อปรับขนาดผ่าน transformation matrix เอนจินจะไม่ถอดรหัสไบต์ที่เหมือนกันซ้ำ ควรเลือกใช้พาธซ้ำมากกว่าการทำสำเนาไฟล์

ต้นทุนการถอดรหัสแปรผันตามจำนวนพิกเซลของต้นฉบับ งบประมาณจึงกำหนดไว้ที่ 96 MB เพื่อรองรับภาพถ่ายขนาดปานกลาง การวางพาธเดิมซ้ำมีต้นทุนน้อย: เพิ่มเพียงหนึ่ง Do บวกกับหนึ่ง cm ไม่ใช่การถอดรหัสครั้งที่สอง การลดขนาดตามความกว้างไม่ได้ลดจำนวนพิกเซลที่จัดเก็บไว้ หากขนาดเอกสารเป็นเรื่องสำคัญ ให้ปรับขนาดรูปภาพต้นฉบับขนาดใหญ่ไว้ล่วงหน้า

การปฏิเสธ URL-scheme และ NUL byte ช่วยป้องกัน SSRF และ path injection image() ไม่สามารถถูกหลอกให้ดึง http://… หรือลัดผ่าน null byte ได้ ถึงกระนั้น ให้ถือว่าชื่อไฟล์ที่ผู้ใช้ระบุเป็นข้อมูลที่ไม่น่าเชื่อถือเสมอ จงแปลงพาธเหล่านั้นเทียบกับไดเรกทอรีฐานที่อนุญาตก่อนเรียก image() เมื่อไฟล์เป็นไฟล์ที่ผู้ใช้อัปโหลด การถอดรหัสรูปภาพจะทำงานบนไบต์ที่ผู้โจมตีควบคุมได้ จำกัดขนาดอินพุตและพิจารณาถอดรหัสใน worker ที่แยกออกมาต่างหาก

ข้อความระบุข้อกำหนดข้อรหัสอ้างอิง (reference_id)
image dictionary ระบุความกว้าง ความสูง และจำนวนบิตต่อองค์ประกอบไว้อย่างชัดเจนISO 32000-2§8.9.5
BitsPerComponent เป็นค่าที่จำเป็นและมีค่าเป็น 1, 2, 4, 8 หรือ 16ISO 32000-2§8.9.5
รูปภาพถูกวางด้วยตัวดำเนินการ cm ภายในคู่ q/QISO 32000-2§8.8

โปรไฟล์การทำซ้ำได้ — เชิงโครงสร้าง ไบต์ของรูปภาพเป็นแบบกำหนดได้สำหรับต้นฉบับที่คงที่ เอกสารที่บันทึกทุกฉบับยังคงมี /ID ใน trailer และค่า date atoms ดังนั้น harness จะตัดส่วนเหล่านั้นออก แล้วเปรียบเทียบโครงสร้างที่ปรับให้เป็นมาตรฐานด้วย qpdf สูตรนี้อธิบายวิธีที่ NextPDF สร้างโครงสร้างดังกล่าว ไม่ได้กล่าวอ้างความสอดคล้องตาม ISO 32000-2 แบบครอบคลุมทั้งหมด

ไม่เกี่ยวข้อง การฝังรูปภาพแบบราสเตอร์เป็นความสามารถของ Core โดยไม่ถูกกั้นไว้สำหรับ Premium