You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用C++提取PDF文件中的图片?寻求技术协助

用C++提取PDF中的图片

直接用记事本打开或解压PDF拿不到图片的原因是:PDF里的图片并非以普通文件形式嵌入,而是编码后存储在PDF的对象结构中,多数还经过了压缩(如FlateDecode、DCTDecode),必须通过解析PDF的对象模型并解码数据流才能提取有效图片。

下面分两种方案说明:

一、使用成熟PDF处理库(推荐)

手动解析PDF的图片逻辑复杂,涉及对象引用、压缩解码、颜色空间转换等,优先用现成库实现。

1. Poppler

Poppler是广泛使用的PDF处理库,提供完善的C++接口:

  • 核心流程:加载PDF → 遍历页面 → 获取页面内图片 → 保存为标准图像格式
  • 示例代码:
#include <poppler-document.h>
#include <poppler-page.h>
#include <poppler-image.h>
#include <iostream>
#include <QString>

int main() {
    // 加载PDF文档
    Poppler::Document* doc = Poppler::Document::load("input.pdf");
    if (!doc) {
        std::cerr << "无法加载PDF文件" << std::endl;
        return 1;
    }

    int pageCount = doc->numPages();
    // 遍历每一页
    for (int pageIdx = 0; pageIdx < pageCount; ++pageIdx) {
        Poppler::Page* page = doc->page(pageIdx);
        if (!page) continue;

        // 获取当前页所有图片
        QList<Poppler::Image> pageImages = page->images();
        for (int imgIdx = 0; imgIdx < pageImages.size(); ++imgIdx) {
            Poppler::Image img = pageImages[imgIdx];
            // 保存为PNG文件
            img.save(QString("page_%1_img_%2.png").arg(pageIdx + 1).arg(imgIdx + 1));
        }

        delete page;
    }

    delete doc;
    return 0;
}
  • 注意:编译时需要链接Poppler库,需提前安装Poppler开发包。

2. MuPDF

轻量级PDF渲染库,以C接口为主,可封装为C++使用:

  • 核心流程:创建上下文 → 打开PDF → 遍历页面 → 列出图片引用 → 加载并保存图片
  • 示例代码:
#include <mupdf/fitz.h>
#include <iostream>
#include <string>

int main() {
    // 创建MuPDF上下文
    fz_context* ctx = fz_new_context(nullptr, nullptr, FZ_STORE_UNLIMITED);
    if (!ctx) {
        std::cerr << "无法创建MuPDF上下文" << std::endl;
        return 1;
    }

    fz_register_document_handlers(ctx);
    // 打开PDF文档
    fz_document* doc = fz_open_document(ctx, "input.pdf");
    if (!doc) {
        std::cerr << "无法打开PDF文件" << std::endl;
        fz_drop_context(ctx);
        return 1;
    }

    int pageCount = fz_count_pages(ctx, doc);
    // 遍历每一页
    for (int pageIdx = 0; pageIdx < pageCount; ++pageIdx) {
        fz_page* page = fz_load_page(ctx, doc, pageIdx);
        if (!page) continue;

        // 获取当前页图片数量
        int imgCount = fz_list_page_images(ctx, page, nullptr, 0);
        fz_image_reference* imgRefs = static_cast<fz_image_reference*>(malloc(imgCount * sizeof(fz_image_reference)));
        fz_list_page_images(ctx, page, imgRefs, imgCount);

        // 遍历并保存图片
        for (int imgIdx = 0; imgIdx < imgCount; ++imgIdx) {
            fz_image* img = fz_load_image(ctx, &imgRefs[imgIdx].xref);
            if (img) {
                std::string fileName = "page_" + std::to_string(pageIdx + 1) + "_img_" + std::to_string(imgIdx + 1) + ".png";
                fz_write_png(ctx, img, fz_open_file(ctx, fileName.c_str()), 0);
                fz_drop_image(ctx, img);
            }
        }

        free(imgRefs);
        fz_drop_page(ctx, page);
    }

    fz_drop_document(ctx, doc);
    fz_drop_context(ctx);
    return 0;
}
  • 注意:需管理好MuPDF的资源,使用后及时释放。

二、手动解析PDF(不推荐)

如果想深入了解PDF格式,手动解析的核心步骤如下:

  1. 解析PDF的交叉引用表,定位所有类型为XObject、子类型为Image的对象
  2. 读取图片对象的属性:宽度、高度、位深度、颜色空间、压缩过滤器等
  3. 根据Filter字段对原始数据流解码(如FlateDecode用zlib解压,DCTDecode对应JPG格式)
  4. 将解码后的像素数据转换为标准图像格式(如PNG),注意处理颜色空间转换(如CMYK转RGB)

手动解析需处理大量边缘情况(如加密PDF、特殊压缩算法),仅适合研究场景。

内容的提问来源于stack exchange,提问作者zcnc

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 11:22:43