Skip to content

About

Pre-compiled Xpdf command-line tools (pdftotext, pdfinfo, pdftopng, pdfimages and more) for Linux and macOS, with fluent PHP wrappers

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Xpdf tools for PHP

Read text, metadata, page sizes and images out of PDF files from PHP, without installing anything on the server: this package ships the Xpdf command-line tools (pdftotext, pdfinfo, pdftopng, pdfimages and five more) as pre-compiled binaries for Linux and macOS, with a fluent PHP wrapper class per tool.

Xpdf version: 4.06

Maintained by Restruct. If this package saves you time, you can support ongoing maintenance.

Reading a PDF from PHP usually means a system package and a shell string

PHP cannot read PDF content on its own. The usual route is to install xpdf or poppler on every server and development machine, build a shell_exec() command line by hand, and parse the tool's text output yourself: which version is installed differs per machine, a missing binary only shows up at runtime, and a damaged PDF easily parses as "0 pages" instead of an error.

This package bundles one known xpdf version with the code, finds the right binary for the platform itself, runs it through symfony/process with a timeout, and returns parsed results.

A wrapper per tool, with the binaries included

Quick examples

use Restruct\Xpdf\PdfToText;
use Restruct\Xpdf\PdfInfo;
use Restruct\Xpdf\PdfToPng;
use Restruct\Xpdf\PdfImages;

// Extract text (UTF-8, layout preserved)
$text = PdfToText::extract('/path/to/file.pdf');

// Page count
$pages = PdfInfo::pageCount('/path/to/file.pdf');

// Full document info
$info = PdfInfo::create('/path/to/file.pdf');
echo $info->getTitle();
echo $info->getPageCount();
$dims = $info->getPageDimensions();
echo $dims->standard; // 'A4'

// Render pages to PNG
$pngs = PdfToPng::render('/path/to/file.pdf', '/tmp/output', dpi: 240);

// Extract images
$images = PdfImages::extractAll('/path/to/file.pdf', '/tmp/img');

// List images without extracting
$listing = PdfImages::list('/path/to/file.pdf');

Restruct\Xpdf\PdfToText: text extraction

use Restruct\Xpdf\PdfToText;

// Quick extraction
$text = PdfToText::extract('input.pdf');

// Fluent API with full control
$text = PdfToText::create('input.pdf')
    ->encoding('UTF-8')
    ->layout()
    ->pages(1, 5)
    ->noPageBreak()
    ->noDiag()        // skip watermarks
    ->getText();

// Table mode for tabular data
$text = PdfToText::create('input.pdf')
    ->table()
    ->encoding('UTF-8')
    ->getText();

// Save to file
PdfToText::create('input.pdf')
    ->encoding('UTF-8')
    ->toFile('output.txt');

The layout modes (layout(), simple(), simple2(), table(), linePrinter(), raw()) exclude each other: setting one clears the others. getText() returns an empty string when pdftotext fails, toFile() returns false.

Restruct\Xpdf\PdfInfo: document metadata and paper size

Replaces howtomakeaturn/pdfinfo with improved page dimension detection.

use Restruct\Xpdf\PdfInfo;

$info = PdfInfo::create('input.pdf');

// Basic metadata
$info->getTitle();
$info->getAuthor();
$info->getPageCount();
$info->getPdfVersion();
$info->getCreationDate();

// Page dimensions with paper size detection
$dims = $info->getPageDimensions();
$dims->width;       // 595 (points)
$dims->height;      // 842 (points)
$dims->standard;    // 'A4'
$dims->orientation; // 'portrait'
$dims->rotation;    // 0
$dims->nearestDIN;  // 'A4' or 'A3'

// Rotation of the page, in degrees
$info->getPageRotation();

// All fields as array
$all = $info->getAll();

// Or in one call
$all = PdfInfo::info('input.pdf');

If pdfinfo fails (damaged, unreadable or user-password-protected file, timeout), every parsed getter throws a RuntimeException with the exit code and pdfinfo's error output, instead of returning 0 pages (from 1.0.2). A failed run is not cached, so each getter call runs pdfinfo again. run() still returns the raw XpdfResult without throwing. (A PDF with only an owner password opens fine and does not throw.)

Empty fields (e.g. a document without a title) return null. When pdfinfo prints a label twice, the first value wins.

standard is the A-size label pdfinfo prints itself when it prints one (A0 to A6), otherwise the nearest entry in the built-in table of ISO A/B/C, ANSI and a few other sizes (Letter among them), within 2 points in either orientation. null means no standard size matched. width and height are rounded to whole points; nearestDIN is A4 for pages up to roughly A4 or Letter size and A3 for anything larger.

Restruct\Xpdf\PdfToPng: page rendering

use Restruct\Xpdf\PdfToPng;

// Render all pages
$files = PdfToPng::render('input.pdf', '/tmp/page', dpi: 240);
// ['/tmp/page-000001.png', '/tmp/page-000002.png', ...]

// Render single page
$file = PdfToPng::renderPage('input.pdf', 1, '/tmp/thumb', dpi: 72);

// Full control
$files = PdfToPng::create('input.pdf')
    ->resolution(300)
    ->pages(1, 10)
    ->gray()
    ->convert('/tmp/output');

The default resolution of render() and renderPage() is 150 dpi. On failure, convert() and render() return an empty array and renderPage() returns null.

Restruct\Xpdf\PdfImages: image extraction

use Restruct\Xpdf\PdfImages;

// Extract all images (JPEG where possible)
$files = PdfImages::extractAll('input.pdf', '/tmp/img');

// Extract unique images only
$files = PdfImages::extractUnique('input.pdf', '/tmp/img');

// List images without extracting
$list = PdfImages::list('input.pdf');
foreach ($list as $img) {
    echo "{$img['page']}: {$img['width']}x{$img['height']} {$img['color']} {$img['enc']}\n";
}

// Full control
$files = PdfImages::create('input.pdf')
    ->pages(1, 5)
    ->jpeg()
    ->unique()
    ->extract('/tmp/img');

Restruct\Xpdf\Xpdf: binary resolution and a generic runner

For the tools without a wrapper class (pdffonts, pdftohtml, pdftoppm, pdftops, pdfdetach), or any option a wrapper does not expose:

use Restruct\Xpdf\Xpdf;

// Check availability
Xpdf::isAvailable();
Xpdf::availableTools(); // ['pdftotext', 'pdfinfo', ...]

// Run any tool directly
$result = Xpdf::run('pdftotext', ['-layout', '-enc', 'UTF-8', 'input.pdf', '-']);
echo $result->output;
echo $result->isSuccessful();

run() throws a RuntimeException when the tool's binary is not available. Otherwise it returns an XpdfResult with output, errorOutput and exitCode (-1 on a timeout), and never throws on a failed run.

Technical

Version compatibility

Branch Package version Xpdf PHP
main 1.x 4.06 8.1+

composer.json is the source of truth for exact constraints. This is a plain PHP package; it does not depend on any framework.

Requirements

  • PHP 8.1 or higher and symfony/process ^6 or ^7.
  • Bundled binaries are x86_64 only: Linux x86_64, and macOS x86_64 or Apple Silicon via Rosetta 2. On other platforms (e.g. Linux ARM64) install xpdf yourself and point XPDF_BIN_DIR at it.
  • The Linux binaries are dynamically linked: they need libfontconfig.so.1 (all tools) and, for the rendering tools such as pdftopng, libz and libbz2. Most distributions and CI images have these; a minimal container image may not.

Installation

composer require restruct/xpdf-static

Binary resolution

On first use, the package includes its bootstrap.php, which detects the platform and defines the XPDF_BIN_DIR constant, taking the first of:

  1. XPDF_BIN_DIR constant (if already defined)
  2. XPDF_BIN_DIR environment variable (when it is an existing directory)
  3. macOS: bundled x64/mac/ binaries
  4. Linux: bundled x64/linux/ binaries

On any other platform nothing is defined, Xpdf::isAvailable() returns false and run() throws.

Timeouts

Every tool runs with a timeout of 30 seconds by default (Xpdf::setDefaultTimeout() changes it). PdfToPng defaults to 120 seconds and PdfImages extraction to 60. The run(), getText(), toFile(), convert(), extract() and listImages() methods take a $timeout argument in seconds.

Available binaries

All 9 xpdf tools are bundled: pdftotext, pdfinfo, pdffonts, pdfimages, pdftohtml, pdftopng, pdftoppm, pdftops, pdfdetach. Their options are in the man pages in xpdf-doc/ and at https://www.xpdfreader.com/.

Running the tests

composer install
vendor/bin/phpunit

Tests that run the real pdfinfo are skipped when it is not available.

Changelog

See CHANGELOG.md.

License

  • Wrapper code (bootstrap.php, src/): MIT (Copyright Restruct web & apps).
  • Bundled xpdf binaries (x64/): unmodified xpdf-tools 4.06, Copyright Glyph & Cog, LLC, licensed under the GNU General Public License version 2 or 3. They are not covered by the MIT licence. The upstream README, man pages and GPL texts that must accompany them are in xpdf-doc/; source is available from https://www.xpdfreader.com/download.html.

See LICENSE for the full terms.

About

Pre-compiled Xpdf command-line tools (pdftotext, pdfinfo, pdftopng, pdfimages and more) for Linux and macOS, with fluent PHP wrappers

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages