Images
addImage() places an image on a page at a point you choose, and takes either a plain file path or a
Page\Image object.
Placing an Image#
addImage($path, $x, $y) reads the file and places its bottom left corner at $x, $y — see
Pages & Coordinates. Both default to 0.
use Pop\Pdf\Document;
use Pop\Pdf\Document\Page;
use Pop\Pdf\Pdf;
$page = new Page(Page::LETTER);
$page->addImage(__DIR__ . '/photo.jpg', x: 72, y: 500);
Pdf::writeToFile(new Document($page), filename: __DIR__ . '/photo.pdf');
Unresized, an image places at one PDF point per source pixel — a 400 by 200 pixel JPEG covers
exactly 400 by 200 points with no resize*() or scale() call.
Build an Image object with createImageFromFile() when a page needs to resize it, scale it, or
read its dimensions back before placing it:
use Pop\Pdf\Document;
use Pop\Pdf\Document\Page;
use Pop\Pdf\Document\Page\Image;
use Pop\Pdf\Pdf;
$page = new Page(Page::LETTER);
$image = Image::createImageFromFile(__DIR__ . '/photo.jpg');
$page->addImage($image, x: 72, y: 500);
Pdf::writeToFile(new Document($page), filename: __DIR__ . '/photo.pdf');
The two forms place identically — a bare string builds the same Image internally via
createImageFromFile() — so reach for the object only when you need what it unlocks.
Supported Formats#
createImageFromFile() accepts JPEG, PNG and GIF in any color mode — RGB, grayscale, CMYK JPEGs,
and indexed or true-grayscale PNGs all place without incident, and GIF frames convert to PNG
internally before embedding.
- A PNG with a full alpha channel throws
Pop\Pdf\Build\Image\Exceptionat write time:PNG alpha channels are not supported. Only 8-bit transparent PNG images are supported.Indexed transparency — a single transparent color rather than a per-pixel alpha channel — places fine. - Any other file type, or a missing path, throws
Pop\Pdf\Document\Page\Exceptionbefore the page is touched:That image file does not exist.orThat image type is not supported. Only GIF, JPG and PNG image types are supported.(a TIFF included).
Images from a Stream#
createImageFromStream() takes the same bytes as a string instead of a path — for an image
fetched, generated or uploaded rather than read from disk:
use Pop\Pdf\Document\Page\Image;
$bytes = file_get_contents('https://example.com/logo.png');
$image = Image::createImageFromStream($bytes);
Both createImageFromFile() and createImageFromStream() are static factories that build a new
Image and call the instance method behind them, loadImageFromFile() or loadImageFromStream().
Call load* directly on an Image already in hand to swap its source without building a new one:
use Pop\Pdf\Document\Page\Image;
$image = new Image();
$image->loadImageFromStream($bytes);
isFile() and isStream() report which source built the Image — otherwise the two are
identical: same resizing behavior, same embedded dimensions for the same bytes resized the same
way. Resizing below uses a file-sourced Image; everything there applies equally to
a stream-sourced one.
Resizing#
resizeToWidth() and resizeToHeight() set one dimension and scale the other to match the
image's original aspect ratio:
use Pop\Pdf\Document\Page\Image;
// A 400 by 200 pixel source
$image = Image::createImageFromFile(__DIR__ . '/photo.jpg');
$image->resizeToWidth(200);
echo $image->getResizedWidth() . ' x ' . $image->getResizedHeight(); // 200 x 100
resizeToHeight(50) on the same source reports 100 x 50 — width follows height at the same
2-to-1 ratio. resize($pixel) targets whichever original dimension is larger: on the 400 by 200
source, resize(100) treats width as larger and reports 100 x 50, the same as
resizeToWidth(100); on a taller-than-wide source, resize() targets height instead.
None of the three touch the source file — they record a target that getResizeDimensions()
reports back, and resampling happens once, when the document compiles.
Every resizing method takes a second, optional argument, $preserveResolution — see
Preserved Resolution for what it changes.
Scaling#
scale() multiplies both dimensions by a single factor instead of targeting a pixel count:
use Pop\Pdf\Document\Page\Image;
$image = Image::createImageFromFile(__DIR__ . '/photo.jpg');
$image->scale(0.25);
echo $image->getResizedWidth() . ' x ' . $image->getResizedHeight(); // 100 x 50
scale(0.25) reports 100 x 50, matching resize(100) above — the two agree whenever the factor
matches the ratio a resize target implies; reach for scale() when you know the ratio rather than
a target pixel count.
Reading Back Dimensions#
getWidth() and getHeight() report the source image's own pixel dimensions, unaffected by any
resize or scale call. getResizedWidth(), getResizedHeight() and getResizeDimensions() report
the target set by whichever of resizeToWidth(), resizeToHeight(), resize() or scale() ran
last:
use Pop\Pdf\Document\Page\Image;
$image = Image::createImageFromFile(__DIR__ . '/photo.jpg');
var_dump($image->getResizedWidth()); // NULL
var_dump($image->getResizeDimensions()); // NULL
$image->resizeToWidth(150);
var_dump($image->getResizeDimensions()); // array('width' => 150, 'height' => 75)
Until one of those four methods runs, all three getters return null.
Preserved Resolution#
Every resizing and scaling method takes a trailing $preserveResolution argument, and
isPreserveResolution() reports what was passed:
false(default) — re-samples the pixel data down to the resize target before embedding; placed and embedded sizes match, and the file is smaller.true— keeps the full source pixel data embedded and only shrinks the placed size: a resize to100 x 50still shows a 100 by 50 point box on the page, but the pixels behind it stay at the original resolution.
use Pop\Pdf\Document\Page\Image;
$image = Image::createImageFromFile(__DIR__ . '/photo.jpg');
$image->resizeToWidth(100, preserveResolution: true);
var_dump($image->isPreserveResolution()); // true
The benefit of this is that it will keep high quality images looking sharp when they are scaled down. Performing a resize without preserving the resolution can lead to noticeable image degradation. However, the trade-off of preserving resolution is that the PDF file size will be larger.
A Page Built From an Image#
Page::createFromImage($file, $quality = 70) builds a page sized to match the image exactly, with
the image placed to cover it edge to edge:
use Pop\Pdf\Document;
use Pop\Pdf\Document\Page;
use Pop\Pdf\Pdf;
$document = new Document();
$scans = ['scanned-1.jpg', 'scanned-2.jpg', 'scanned-3.jpg'];
foreach ($scans as $scan) {
$document->addPage(Page::createFromImage(__DIR__ . '/' . $scan, quality: 50));
}
Pdf::writeToFile($document, filename: __DIR__ . '/scanned.pdf');
The page always matches the source's pixel dimensions exactly. Every source, JPEG, PNG or GIF,
converts to JPEG before embedding, so $quality always applies, even to an already-JPEG source.
The lower the quality, the smaller the PDF file size, but the more the page images will show
degradation.
createFromImage() is the direct route from a scanned page image to a one-page PDF; reach for
Placing an Image instead when the image is one element among others — text,
a drawn path, other images — on a page you are composing yourself.
See Also#
- Pages & Coordinates — the coordinate system every
addImage()call places against - Drawing & Paths — combining drawn shapes with placed images on the same page
- Saving & Output — writing the finished document to a file or a browser response