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

使用Apache PDFBox删除PDF多余图片后如何去除遗留的空白区域

问题原因

你当前的代码只是删除了页面资源字典中的图片XObject对象,并没有移除页面内容流中对应的图片绘制指令,也没有对删除图片位置下方的内容做上移排版,所以才会留下空白区域。

具体解决步骤

  • 第一步:解析并修改页面内容流,移除对应图片的绘制指令
    你需要遍历页面的内容流运算符,识别出绘制待删除图片的Do指令,直接移除这些指令,避免渲染时预留图片位置。
  • 第二步:调整剩余内容的排版(可选,按需开启)
    如果需要删除空白后下方内容自动上移填充空缺,你需要先记录被删除图片的坐标和尺寸,再遍历所有后续内容元素(文本、图形、其他图片等)的坐标,将Y轴坐标减去对应空白区域的高度,完成内容上移。

可参考的修改后代码

import org.apache.pdfbox.contentstream.PDFStreamEngine;
import org.apache.pdfbox.contentstream.operator.Operator;
import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.pdfwriter.ContentStreamWriter;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDResources;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

// 移除图片及对应的绘制指令
private ByteArrayOutputStream clearimages(ByteArrayOutputStream destinationStream) throws IOException {
    PDDocument document = PDDocument.load(destinationStream.toByteArray());
    AtomicInteger keepImage = new AtomicInteger(0);
    List<COSName> toRemoveImageNames = new ArrayList<>();

    // 第一步:先标记需要删除的图片资源名
    for (PDPage page : document.getPages()) {
        PDResources pdResources = page.getResources();
        for (COSName propertyName : pdResources.getXObjectNames()) {
            if(!pdResources.isImageXObject(propertyName)) {
                continue;
            }
            keepImage.incrementAndGet();
            if (keepImage.get() > 4) {
                toRemoveImageNames.add(propertyName);
            }
        }

        // 第二步:遍历内容流,移除对应图片的Do绘制指令
        List<Object> newTokens = new ArrayList<>();
        PDFStreamEngine engine = new PDFStreamEngine() {};
        List<Object> tokens = engine.parsePage(page);
        for (int i = 0; i < tokens.size(); i++) {
            Object token = tokens.get(i);
            if (token instanceof Operator && ((Operator) token).getName().equals("Do")) {
                COSName imgName = (COSName) tokens.get(i - 1);
                if (toRemoveImageNames.contains(imgName)) {
                    // 移除Do指令和前面的资源名参数
                    newTokens.remove(newTokens.size() - 1);
                    continue;
                }
            }
            newTokens.add(token);
        }

        // 把修改后的内容流写回页面
        try (OutputStream out = page.getContents().createOutputStream()) {
            ContentStreamWriter writer = new ContentStreamWriter(out);
            writer.writeTokens(newTokens);
        }

        // 第三步:删除资源字典中标记的图片对象
        for (COSName name : toRemoveImageNames) {
            pdResources.getCOSObject().getCOSDictionary(COSName.XOBJECT).removeItem(name);
        }
        toRemoveImageNames.clear();
    }

    ByteArrayOutputStream out = new ByteArrayOutputStream();
    document.save(out);
    document.close();
    return out;
}

注意:如果需要完全消除空白、让下方内容上移,还需要额外计算每张被删图片的占位高度,遍历所有内容元素的Y坐标做对应偏移,该逻辑需要根据你的PDF排版规则调整,不同PDF的坐标系原点设置可能存在差异。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.16 17:36:00