Poppler
| Language | C++ (APIs: poppler-cpp, poppler-glib for C, poppler-qt5/qt6) |
|---|---|
| License | GPL-2.0-or-later or GPL-3.0 (parts originally from Xpdf) |
| Repository | gitlab.freedesktop.org/poppler/poppler |
| Documentation | poppler.freedesktop.org, poppler-cpp API |
| Depends on | FreeType, fontconfig, zlib, libjpeg, libpng, libtiff, OpenJPEG, lcms2; Cairo for the GLib API |
| Read / write | yes / limited: render, extract text, fonts, attachments, forms; save metadata changes and form values |
Poppler is a fork of Xpdf and the PDF engine behind GNOME Papers/Evince, Okular, LibreOffice’s PDF import, Inkscape and the poppler-utils command line tools (pdftotext, pdftoppm, pdfinfo, pdffonts, pdfimages, pdfunite, pdfseparate). It renders accurately (with Splash or Cairo backends) and extracts text with a good layout mode.
Use the poppler-cpp or poppler-glib API: the core classes (PDFDoc, GfxState) are internal and change between releases. Poppler is GPL, so a program that links it must be GPL-compatible. It isn’t meant for creating PDFs or for structural edits like merging (the command line tools do simple merges).
Installation#
# Debian / Ubuntu
sudo apt install libpoppler-cpp-dev poppler-utils
# Fedora
sudo dnf install poppler-cpp-devel poppler-utils
# macOS
brew install poppler
# Windows (vcpkg)
vcpkg install poppler
With CMake and pkg-config:
find_package(PkgConfig REQUIRED)
pkg_check_modules(POPPLER REQUIRED IMPORTED_TARGET poppler-cpp)
target_link_libraries(myapp PRIVATE PkgConfig::POPPLER)
Basic usage: extract text and render a page#
#include <poppler-document.h>
#include <poppler-page.h>
#include <poppler-page-renderer.h>
#include <poppler-image.h>
#include <iostream>
#include <memory>
int main() {
std::unique_ptr<poppler::document> doc(poppler::document::load_from_file("in.pdf"));
if (!doc || doc->is_locked()) {
std::cerr << "cannot open file\n";
return 1;
}
std::cout << doc->pages() << " pages\n";
for (int i = 0; i < doc->pages(); i++) {
std::unique_ptr<poppler::page> page(doc->create_page(i));
poppler::byte_array utf8 = page->text().to_utf8();
std::cout << std::string(utf8.begin(), utf8.end()) << "\n";
}
// render page 1 at 150 dpi
std::unique_ptr<poppler::page> first(doc->create_page(0));
poppler::page_renderer renderer;
renderer.set_render_hint(poppler::page_renderer::antialiasing, true);
renderer.set_render_hint(poppler::page_renderer::text_antialiasing, true);
poppler::image img = renderer.render_page(first.get(), 150, 150);
if (!img.is_valid() || !img.save("page1.png", "png")) {
std::cerr << "render failed\n";
return 1;
}
return 0;
}
How to extract text with the physical layout#
page::text takes a rectangle (empty for the whole page) and a layout mode. physical_layout keeps columns and table cells in place, like pdftotext -layout:
poppler::ustring text = page->text(poppler::rectf(), poppler::page::physical_layout);
page->text_list() returns text_box objects with each word’s bounding box.
How to read PDF metadata#
auto to_utf8 = [](const poppler::ustring &s) {
poppler::byte_array b = s.to_utf8();
return std::string(b.begin(), b.end());
};
std::cout << "Title: " << to_utf8(doc->get_title()) << "\n";
std::cout << "Author: " << to_utf8(doc->get_author()) << "\n";
std::cout << "Producer: " << to_utf8(doc->get_producer()) << "\n";
int major, minor;
doc->get_pdf_version(&major, &minor);
std::cout << "PDF " << major << "." << minor
<< (doc->is_encrypted() ? ", encrypted" : "") << "\n";
// XMP metadata as XML
std::cout << to_utf8(doc->metadata()) << "\n";
How to open a password-protected PDF#
std::unique_ptr<poppler::document> doc(
poppler::document::load_from_file("secret.pdf", "owner-password", "user-password"));
Or call doc->unlock(owner, user) on a document where is_locked() returns true.
How to merge, split and convert with poppler-utils#
pdfunite a.pdf b.pdf merged.pdf # merge
pdfseparate in.pdf page-%d.pdf # split into single pages
pdftoppm -png -r 150 in.pdf page # render every page to page-1.png, ...
pdftotext -layout in.pdf out.txt # extract text keeping the layout
pdfinfo in.pdf # metadata, page size, encryption
pdfimages -all in.pdf img # extract embedded images in their original format
Tips#
- The GLib API (
poppler_document_new_from_file,poppler_page_renderto a Cairo surface,poppler_page_get_text) is the most stable C interface and has the most features for forms and annotations. poppler::document::load_from_raw_dataopens a PDF from memory.- For a permissive license use PDFium; for faster rendering consider MuPDF (AGPL).