在一些文档处理场景中,PDF 里经常会包含大量图片,例如扫描件、产品手册、报告附件、合同图片等。 有时候我们需要把 PDF 里的图片单独提取出来,用于归档、识别、二次编辑;也有时候 PDF 文件过大,原因正是里面嵌入了高分辨率图片,这时就需要对图片进行压缩。
本文以 Spire.PDF for Java 为例,实现两类常见图片操作:
示例代码使用 Maven 项目。先在 pom.xml 中加入 Spire.PDF for Java 依赖。
<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 包。 为了方便演示,下面的代码都使用本地文件路径,需要根据自己的实际目录修改。
提取图片的核心流程并不复杂:
Spire.PDF 中可以使用 PdfImageHelper 获取页面里的图片信息,再通过 PdfImageInfo.getImage() 拿到 BufferedImage 对象,最后用 ImageIO.write() 写出到本地。
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();
}
}
}这里没有直接使用简单的 图片-1.png 命名,而是把页码也放进了文件名,例如:
page-1-image-1.png
page-2-image-3.png这样做的好处是,后续排查图片来源时更方便。 尤其是 PDF 页数较多时,只用连续编号不太容易判断图片原本属于哪一页。
需要注意的是,提取出来的图片格式在示例中统一保存为 PNG。 如果原 PDF 中图片本身较大,保存为 PNG 后文件体积可能并不会变小。如果只是为了预览或网页展示,也可以根据需求改成 JPG。
例如:
ImageIO.write(image, "JPG", outputFile);不过 JPG 是有损格式,适合照片类图片,不太适合文字截图、表格截图或带透明背景的图片。
PDF 文件过大时,图片通常是主要原因之一。比如:
这类情况可以尝试压缩 PDF 中的图片,从而减小整个 PDF 文件体积。
不过要注意,图片压缩通常会带来一定清晰度损失。 如果 PDF 用于打印、归档或正式交付,建议先备份原文件,再对副本进行压缩。
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 时,代码里有一行:
document.getFileInfo().setIncrementalUpdate(false);这一步建议保留。
PDF 保存时可能会使用增量更新机制,也就是在原文件后面追加修改内容,而不是完全重写整个文件。 这种方式适合部分编辑场景,但在压缩图片时,可能导致旧数据仍然保留在文件中,最终出现“明明压缩了,文件却没有明显变小”的情况。
所以在压缩 PDF 图片时,可以关闭增量更新,让保存结果更符合预期。
虽然两个功能都和 PDF 图片有关,但它们解决的问题不同。
操作 | 目的 | 输出结果 |
|---|---|---|
提取图片 | 把 PDF 中的图片单独导出 | 多个图片文件 |
压缩图片 | 减小 PDF 中图片占用空间 | 一个新的 PDF 文件 |
简单理解:
并不是所有看起来像图片的内容都一定是图片对象。
例如:
所以实际项目中要根据 PDF 来源测试,不能只用一个样例判断兼容性。
可能有几种原因:
建议压缩前后对比文件大小,并尽量使用真实业务文件测试。
有可能会。
图片压缩的目标是减少文件体积,通常会在一定程度上影响图片质量。 如果 PDF 需要打印、盖章、归档,建议不要直接覆盖原文件,而是输出一个新的压缩版本。
本文使用 Java 演示了两个常见 PDF 图片处理需求:
PdfImageHelper.getImagesInfo() 获取 PDF 页面中的图片信息;PdfImageInfo.getImage() 提取图片;PdfImageInfo.tryCompressImage() 压缩 PDF 中的图片;在实际业务中,建议把“提取图片”和“压缩 PDF”封装成独立工具方法,并增加文件大小校验、异常处理、目录检查等逻辑。 这样无论是做文档归档、附件处理,还是后台批量压缩 PDF,都更容易复用。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。