Java 处理 PDF 图片:提取 PDF 中的图片,并压缩 PDF 图片体积

在一些文档处理场景中,PDF 里经常会包含大量图片,例如扫描件、产品手册、报告附件、合同图片等。 有时候我们需要把 PDF 里的图片单独提取出来,用于归档、识别、二次编辑;也有时候 PDF 文件过大,原因正是里面嵌入了高分辨率图片,这时就需要对图片进行压缩。

本文以 Spire.PDF for Java 为例,实现两类常见图片操作:

  1. 从 PDF 文档中提取图片
  2. 压缩 PDF 文档中的高质量图片

一、准备工作

示例代码使用 Maven 项目。先在 ​​pom.xml​​ 中加入 Spire.PDF for Java 依赖。

xml 复制代码
<repositories>
    <repository>
        <id>com.e-iceblue</id>
        <name>e-iceblue</name>
        <url>https://repo.e-iceblue.cn/repository/maven-public/</url>
    </repository>
</repositories>

<dependencies>
    <dependency>
        <groupId>e-iceblue</groupId>
        <artifactId>spire.pdf</artifactId>
        <version>12.6.1</version>
    </dependency>
</dependencies>

如果是普通 Java 项目,也可以手动引入对应的 Jar 包。 为了方便演示,下面的代码都使用本地文件路径,需要根据自己的实际目录修改。


二、从 PDF 中提取图片

1. 实现思路

提取图片的核心流程并不复杂:

  • 加载 PDF 文件;
  • 遍历 PDF 的每一页;
  • 获取当前页中的图片信息;
  • 将图片对象保存为本地图片文件。

Spire.PDF 中可以使用 ​​PdfImageHelper​​ 获取页面里的图片信息,再通过 ​​PdfImageInfo.getImage()​​ 拿到 ​​BufferedImage​​ 对象,最后用 ​​ImageIO.write()​​ 写出到本地。


2. 示例代码

ini 复制代码
import com.spire.pdf.PdfDocument;
import com.spire.pdf.PdfPageBase;
import com.spire.pdf.utilities.PdfImageHelper;
import com.spire.pdf.utilities.PdfImageInfo;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

public class ExtractPdfImages {

    public static void main(String[] args) throws IOException {
        String inputPdf = "C:/pdf/input.pdf";
        String outputDir = "C:/pdf/images/";

        PdfDocument document = new PdfDocument();

        try {
            // 加载 PDF 文件
            document.loadFromFile(inputPdf);

            // 创建输出目录
            File dir = new File(outputDir);
            if (!dir.exists()) {
                dir.mkdirs();
            }

            PdfImageHelper imageHelper = new PdfImageHelper();
            int imageIndex = 1;

            // 遍历 PDF 每一页
            for (int pageIndex = 0; pageIndex < document.getPages().getCount(); pageIndex++) {
                PdfPageBase page = document.getPages().get(pageIndex);

                // 获取当前页中的所有图片
                PdfImageInfo[] imageInfos = imageHelper.getImagesInfo(page);

                // 保存图片
                for (PdfImageInfo imageInfo : imageInfos) {
                    BufferedImage image = imageInfo.getImage();

                    String fileName = String.format(
                            "page-%d-image-%d.png",
                            pageIndex + 1,
                            imageIndex++
                    );

                    File outputFile = new File(outputDir + fileName);
                    ImageIO.write(image, "PNG", outputFile);
                }
            }

            System.out.println("图片提取完成,共导出 " + (imageIndex - 1) + " 张图片。");

        } finally {
            document.dispose();
        }
    }
}

3. 代码说明

这里没有直接使用简单的 ​​图片-1.png​​ 命名,而是把页码也放进了文件名,例如:

arduino 复制代码
page-1-image-1.png
page-2-image-3.png

这样做的好处是,后续排查图片来源时更方便。 尤其是 PDF 页数较多时,只用连续编号不太容易判断图片原本属于哪一页。

需要注意的是,提取出来的图片格式在示例中统一保存为 PNG。 如果原 PDF 中图片本身较大,保存为 PNG 后文件体积可能并不会变小。如果只是为了预览或网页展示,也可以根据需求改成 JPG。

例如:

arduino 复制代码
ImageIO.write(image, "JPG", outputFile);

不过 JPG 是有损格式,适合照片类图片,不太适合文字截图、表格截图或带透明背景的图片。


三、压缩 PDF 中的图片

1. 适用场景

PDF 文件过大时,图片通常是主要原因之一。比如:

  • 扫描件分辨率过高;
  • 报告中插入了大量高清图片;
  • 图片没有经过压缩就直接嵌入 PDF;
  • 页面内容不多,但 PDF 文件却几十 MB。

这类情况可以尝试压缩 PDF 中的图片,从而减小整个 PDF 文件体积。

不过要注意,图片压缩通常会带来一定清晰度损失。 如果 PDF 用于打印、归档或正式交付,建议先备份原文件,再对副本进行压缩。


2. 示例代码

ini 复制代码
import com.spire.pdf.FileFormat;
import com.spire.pdf.PdfDocument;
import com.spire.pdf.PdfPageBase;
import com.spire.pdf.utilities.PdfImageHelper;
import com.spire.pdf.utilities.PdfImageInfo;

import java.io.File;

public class CompressPdfImages {

    public static void main(String[] args) {
        String inputPdf = "C:/pdf/input.pdf";
        String outputPdf = "C:/pdf/output-compressed.pdf";

        PdfDocument document = new PdfDocument();

        try {
            // 加载 PDF 文件
            document.loadFromFile(inputPdf);

            // 关闭增量更新,避免保存后文件体积异常增大
            document.getFileInfo().setIncrementalUpdate(false);

            PdfImageHelper imageHelper = new PdfImageHelper();

            // 遍历每一页,对页面中的图片进行压缩
            for (int pageIndex = 0; pageIndex < document.getPages().getCount(); pageIndex++) {
                PdfPageBase page = document.getPages().get(pageIndex);

                PdfImageInfo[] imageInfos = imageHelper.getImagesInfo(page);

                for (PdfImageInfo imageInfo : imageInfos) {
                    imageInfo.tryCompressImage();
                }
            }

            // 保存压缩后的 PDF
            document.saveToFile(outputPdf, FileFormat.PDF);

            printFileSize(inputPdf, outputPdf);

        } finally {
            document.dispose();
        }
    }

    private static void printFileSize(String beforePath, String afterPath) {
        File before = new File(beforePath);
        File after = new File(afterPath);

        double beforeMb = before.length() / 1024.0 / 1024.0;
        double afterMb = after.length() / 1024.0 / 1024.0;

        System.out.printf("压缩前:%.2f MB%n", beforeMb);
        System.out.printf("压缩后:%.2f MB%n", afterMb);
    }
}

四、关于 ​​setIncrementalUpdate(false)​​ 的说明

压缩 PDF 时,代码里有一行:

javascript 复制代码
document.getFileInfo().setIncrementalUpdate(false);

这一步建议保留。

PDF 保存时可能会使用增量更新机制,也就是在原文件后面追加修改内容,而不是完全重写整个文件。 这种方式适合部分编辑场景,但在压缩图片时,可能导致旧数据仍然保留在文件中,最终出现"明明压缩了,文件却没有明显变小"的情况。

所以在压缩 PDF 图片时,可以关闭增量更新,让保存结果更符合预期。


五、提取和压缩的区别

虽然两个功能都和 PDF 图片有关,但它们解决的问题不同。

操作 目的 输出结果
提取图片 把 PDF 中的图片单独导出 多个图片文件
压缩图片 减小 PDF 中图片占用空间 一个新的 PDF 文件

简单理解:

  • 想拿到 PDF 里的图片,用"提取";
  • 想让 PDF 文件变小,用"压缩"。

六、常见问题

1. 为什么有些 PDF 提取不到图片?

并不是所有看起来像图片的内容都一定是图片对象。

例如:

  • 页面内容可能是矢量图;
  • 文字和图形可能是由绘制指令组成;
  • 扫描件可能整页就是一张大图;
  • 某些 PDF 的图片可能经过特殊编码或封装。

所以实际项目中要根据 PDF 来源测试,不能只用一个样例判断兼容性。


2. 压缩后文件体积没有明显变化怎么办?

可能有几种原因:

  • PDF 主要体积不在图片,而在字体、附件或其他资源;
  • 图片本身已经被压缩过;
  • 图片数量不多;
  • 原 PDF 保存结构比较特殊;
  • 压缩比例有限,变化不明显。

建议压缩前后对比文件大小,并尽量使用真实业务文件测试。


3. 压缩会不会影响图片清晰度?

有可能会。

图片压缩的目标是减少文件体积,通常会在一定程度上影响图片质量。 如果 PDF 需要打印、盖章、归档,建议不要直接覆盖原文件,而是输出一个新的压缩版本。


七、总结

本文使用 Java 演示了两个常见 PDF 图片处理需求:

  • 使用 ​PdfImageHelper.getImagesInfo()​ 获取 PDF 页面中的图片信息;
  • 使用 ​PdfImageInfo.getImage()​ 提取图片;
  • 使用 ​PdfImageInfo.tryCompressImage()​ 压缩 PDF 中的图片;
  • 保存 PDF 时关闭增量更新,避免压缩结果不明显。

在实际业务中,建议把"提取图片"和"压缩 PDF"封装成独立工具方法,并增加文件大小校验、异常处理、目录检查等逻辑。 这样无论是做文档归档、附件处理,还是后台批量压缩 PDF,都更容易复用。

相关推荐
用户3721574261351 小时前
Java 打印 Word 文档:从基础打印到高级设置
java
用户35218024547517 小时前
当 Prompt 学会"热更新":Spring Boot × Nacos3 AI 实战
java·spring boot·ai编程
东坡白菜20 小时前
破局全栈:一个前端开发的Java入门实战记录(1)
java·全栈
唐青枫20 小时前
Java Tomcat 实战指南:从 Servlet 容器到 Spring Boot 部署
java
wsaaaqqq21 小时前
roudan:自由选择实体、灵活操作数据、快速写入数据库的 Java 框架
java
plainGeekDev1 天前
null 判断 → Kotlin 可空类型
android·java·kotlin
糖拌西瓜皮1 天前
Java开发者视角:深入理解Node.js异步编程模型
java·后端·node.js
plainGeekDev1 天前
getter/setter → Kotlin 属性
android·java·kotlin
一线大码1 天前
Smart-Doc 的简单使用
java·后端·restful