C++中将Pdf转换成图片,可以使用Xpdf或者Poppler。本文介绍的是Poppler。
需要注意的是Poppler的开源协议是GPL。
编译
如果仅仅是在C++中使用,可以直接使用vcpkg进行安装。
手动编译poppler
下面介绍如何在Windows上进行手动编译。
验证环境:Windows 10, Visual Studio 2019, CMake 3.23
安装vcpkg。是为了更方便安装一些第三方依赖。
下载Poppler
1
| $ git clone git@github.com:freedesktop/poppler.git
|
Poppler依赖了freetype和pkgconf,先通过vcpkg安装它们
1 2
| $ vcpkg install freetype $ vcpkg install pkgconf
|
修改poppler/CMakeLists.txt,使CMake可以找到vcpkg安装的包。
1 2 3 4 5 6 7 8 9 10
| cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR)
project(poppler)
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules)
include(D:/vcpkg/scripts/buildsystems/vcpkg.cmake)
include(PopplerDefaults) include(PopplerMacros)
|
像上面那样,加上include(D:/vcpkg/scripts/buildsystems/vcpkg.cmake),这是我的环境上的vcpkg.cmake位置,请根据你的环境同步修改。
编译debug版本
1 2 3 4
| $ cd poppler $ cmake -G "Visual Studio 16 2019" -A Win32 -S . -B "build_win32_debug" -DCMAKE_BUILD_TYPE=debug $ cmake --build build_win32_debug $ cmake --install build_win32_debug --config debug --prefix dist/debug
|
在poppler/dist/debug目录下便是编译好的debug版本
用同样的方式编译release版本
1 2 3
| $ cmake -G "Visual Studio 16 2019" -A Win32 -S . -B "build_win32_release" -DCMAKE_BUILD_TYPE=release $ cmake --build build_win32_release --config Release $ cmake --install build_win32_release --config Release --prefix dist/release
|
在poppler/dist/release目录下便是编译好的release版本
手动编译poppler-qt5
如果你要在Qt5中使用poppler,可以编译poppler-qt5以获得更好的支持。
验证环境:Windows 10, Visual Studio 2019, CMake 3.23, Qt 5.15.2
在CMake编译增加参数即可:
1 2 3
| $ cmake -G "Visual Studio 16 2019" -A Win32 -S . -B "build_win32_release" -DCMAKE_BUILD_TYPE=release -DCMAKE_PREFIX_PATH=C:\Qt\5.15.2\msvc2019\lib\cmake $ cmake --build build_win32_release --config Release $ cmake --install build_win32_release --config Release --prefix dist/release
|
C++
示例代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| bool pdf2images(const std::string &pdfFileName, const std::string &imageDir, std::string *err) { std::unique_ptr<poppler::document> doc(poppler::document::load_from_file(pdfFileName)); if (!doc.get()) { if (err != nullptr) *err = "loading error"; return false; } if (doc->is_locked()) { if (err != nullptr) *err = "encrypted document"; return false; } int count = doc->pages(); for (int i = 0; i < count; ++i) { std::unique_ptr<poppler::page> p(doc->create_page(i)); if (!p.get()) { if (err != nullptr) *err = "NULL page"; return false; } poppler::page_renderer pr; pr.set_render_hint(poppler::page_renderer::antialiasing, true); pr.set_render_hint(poppler::page_renderer::text_antialiasing, true); poppler::image img = pr.render_page(p.get()); if (!img.is_valid()) { if (err != nullptr) *err = "rendering failed"; return false; } if (!img.save(imageDir + "/" + std::to_string(i) + ".png", "png")) { if (err != nullptr) *err = "saving to file failed"; return false; } } return true; }
|
如果需要指定dpi,修改render_page的参数,例如:
1
| poppler::image img = pr.render_page(p.get(), 96, 96);
|
Qt5
示例代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| bool pdf2images(const QString &pdfFileName, const QString &imageDir, QString *err) { QScopedPointer<Poppler::Document> doc(Poppler::Document::load(pdfFileName)); if (!doc.get()) { if (err != nullptr) *err = "loading error"; return false; } if (doc->isLocked()) { if (err != nullptr) *err = "encrypted document"; return false; } doc->setRenderHint(Poppler::Document::Antialiasing); doc->setRenderHint(Poppler::Document::TextAntialiasing); int count = doc->numPages(); for (int i = 0; i < count; ++i) { QScopedPointer<Poppler::Page> p(doc->page(i)); if (!p.get()) { if (err != nullptr) *err = "NULL page"; return false; } QImage img = p->renderToImage(); if (img.isNull()) { if (err != nullptr) *err = "rendering failed"; return false; } if (!img.save(imageDir + "/" + QString::number(i) + ".png", "png")) { if (err != nullptr) *err = "saving to file failed"; return false; } } return true; }
|
完整的示例代码在这里。
Reference