PNG-to-PDF in PHP is usually about wrapping an image in a printable document — a scan, a screenshot, an infographic. FPDF is the simplest library for this and has no dependencies beyond PHP. TCPDF has more features (metadata, encryption, barcodes) but is heavier. Both work well for the common case of embedding one or more PNGs in a properly sized PDF page.
Method 1: FPDF (lightweight, no dependencies)
FPDF is a single PHP file — no composer needed. It handles PNG, JPEG, and GIF.
composer require setasign/fpdf
# Or download fpdf.php from fpdf.org and include manuallyAddPage();
$pdf->Image($pngPath, 0, 0, $mmW, $mmH);
$pdf->Output('F', $outPath);
}
function pngsToPdf(array $pngPaths, string $outPath, string $pageSize = 'A4'): void {
$pdf = new FPDF('P', 'mm', $pageSize);
$pageW = $pdf->GetPageWidth();
$pageH = $pdf->GetPageHeight();
foreach ($pngPaths as $pngPath) {
[$imgW, $imgH] = getimagesize($pngPath);
$aspect = $imgW / $imgH;
$pageAspect = $pageW / $pageH;
// Scale to fit within page margins
$margin = 10;
$availW = $pageW - 2 * $margin;
$availH = $pageH - 2 * $margin;
if ($aspect > $pageAspect) {
$drawW = $availW;
$drawH = $availW / $aspect;
} else {
$drawH = $availH;
$drawW = $availH * $aspect;
}
$x = ($pageW - $drawW) / 2;
$y = ($pageH - $drawH) / 2;
$pdf->AddPage();
$pdf->Image($pngPath, $x, $y, $drawW, $drawH);
}
$pdf->Output('F', $outPath);
}
// Single image
pngToPdf('scan.png', 'output.pdf');
// Multiple images → multi-page PDF
pngsToPdf(['page1.png', 'page2.png', 'page3.png'], 'document.pdf');
FPDF's Image() supports PNG, JPEG, and GIF natively. PNG transparency is preserved in the PDF. If your PNG has an alpha channel, FPDF handles it correctly — the transparent areas show the white page background.
Method 2: TCPDF (metadata, encryption, advanced features)
TCPDF is heavier but handles PDF metadata, encryption, and more image formats including TIFF and WEBP.
composer require tecnickcom/tcpdfSetCreator('MyApp');
$pdf->SetAuthor($meta['author'] ?? 'ChangeThisFile');
$pdf->SetTitle($meta['title'] ?? pathinfo($pngPath, PATHINFO_FILENAME));
$pdf->SetSubject($meta['subject'] ?? '');
$pdf->SetMargins(0, 0, 0);
$pdf->SetAutoPageBreak(false);
$pdf->AddPage();
$pdf->Image($pngPath, 0, 0, $mmW, $mmH, 'PNG');
$pdf->Output($outPath, 'F');
}
pngToPdfTcpdf('diagram.png', 'output.pdf', [
'title' => 'System Architecture Diagram',
'author' => 'Engineering Team',
]);
echo "Done\n";
TCPDF's SetMargins(0,0,0) with SetAutoPageBreak(false) ensures the image fills the page edge-to-edge with no white margins.
Method 3: ChangeThisFile API (no library install)
The API converts PNG to PDF server-side. Source is auto-detected from the filename. Free tier: 1,000 conversions/month, no card required.
true,
CURLOPT_TIMEOUT => 60,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $apiKey],
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => [
'file' => new CURLFile($pngPath, 'image/png', basename($pngPath)),
'target' => 'pdf',
],
]);
$result = curl_exec($ch);
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($code !== 200) throw new RuntimeException("API error: HTTP {$code}");
file_put_contents($outPath, $result);
}
pngToPdfApi('screenshot.png', 'output.pdf', 'ctf_sk_your_key_here');
echo "Done\n";
When to use each
| Approach | Best for | Tradeoff |
|---|---|---|
| FPDF | Simple image-to-PDF, minimal dependencies | No metadata, no encryption, limited format support |
| TCPDF | PDF metadata, encryption, multiple images | Heavier library (~5MB); slower than FPDF |
| ChangeThisFile API | Zero local installs, shared hosting | Network call; free tier 25MB limit |
Production tips
- Size the page to the image, not the other way around. Fitting an arbitrary image to A4 adds white bars. Creating a page sized to the image gives a clean result with no padding.
- Handle alpha channels in PNG. Both FPDF and TCPDF handle PNG transparency — transparent areas show the white page background. If you need a different background color, fill the page with a colored rectangle before calling Image().
- Batch conversions: avoid re-creating FPDF instances in a loop. For multi-page PDFs from multiple images, keep one FPDF instance and call AddPage() for each image. Creating a new instance per image is ~3x slower due to initialization overhead.
- Set PDF version for archival. For legal or archival PDFs, use PDF/A-1 compliance. TCPDF supports $pdf->setOpenAction(null) and specific PDF/A settings.
FPDF is the right default for simple PNG-to-PDF wrapping. TCPDF when you need metadata or multi-format support. For environments where you can't install libraries, the API handles it with just curl. Free tier: 1,000 conversions/month.