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

如何用iText与Java将PDF内图像转为单色调/二值图及替换图像

用iText 7 + Java将PDF内的RGB/灰度图像转为二值图像

我来帮你梳理下实现思路和具体方案,结合你已经在用的工具和纯iText两种方式来解决:

方案一:结合ImageMagick处理(推荐,精准度更高)

既然你已经能通过ImageMagick提取并转换图像,那可以把这个流程整合到Java代码里,步骤如下:

  • 遍历PDF中的图像资源,提取原图像的字节流
  • 调用ImageMagick的convert命令完成二值化转换
  • 将处理后的二值图像重新封装为PDF可识别的PdfImageXObject
  • 替换PDF中原有的图像引用

示例代码片段:

// 打开PDF文档
PdfDocument pdfDoc = new PdfDocument(new PdfReader("input.pdf"), new PdfWriter("output.pdf"));

// 遍历每一页的图像资源
for (int pageNum = 1; pageNum <= pdfDoc.getNumberOfPages(); pageNum++) {
    PdfPage page = pdfDoc.getPage(pageNum);
    PdfDictionary resources = page.getResources();
    PdfDictionary xObjects = resources.getAsDictionary(PdfName.XObject);
    
    if (xObjects != null) {
        for (PdfName imgName : xObjects.keySet()) {
            PdfObject obj = xObjects.get(imgName);
            if (obj.isIndirectReference()) {
                PdfStream imgStream = pdfDoc.getPdfObject(obj.getIndirectReference()).getAsStream();
                if (PdfName.Image.equals(imgStream.getAsName(PdfName.Subtype))) {
                    // 提取原图像字节
                    PdfImageXObject originalImg = new PdfImageXObject(imgStream);
                    byte[] imgBytes = originalImg.getImageBytes();
                    Files.write(Paths.get("temp-original.png"), imgBytes);
                    
                    // 调用ImageMagick执行二值化(阈值可根据实际调整)
                    ProcessBuilder pb = new ProcessBuilder(
                        "convert", "temp-original.png", "-threshold", "50%", "temp-binary.png"
                    );
                    pb.inheritIO().start().waitFor();
                    
                    // 生成新的PDF图像对象并替换原图像
                    PdfImageXObject newBinaryImg = new PdfImageXObject(ImageDataFactory.create("temp-binary.png"));
                    xObjects.put(imgName, newBinaryImg.getPdfObject());
                }
            }
        }
    }
}

pdfDoc.close();
// 清理临时文件
Files.deleteIfExists(Paths.get("temp-original.png"));
Files.deleteIfExists(Paths.get("temp-binary.png"));

方案二:纯Java/iText实现二值化(无需外部工具)

如果不想依赖ImageMagick,可以用Java自带的图像API完成二值化,步骤如下:

  • 从PdfImageXObject获取BufferedImage对象
  • 对图像进行二值化处理(固定阈值或自适应阈值)
  • 将处理后的图像转为PDF可识别的格式,替换原图像

示例代码片段:

PdfDocument pdfDoc = new PdfDocument(new PdfReader("input.pdf"), new PdfWriter("output.pdf"));

for (int pageNum = 1; pageNum <= pdfDoc.getNumberOfPages(); pageNum++) {
    PdfPage page = pdfDoc.getPage(pageNum);
    PdfDictionary resources = page.getResources();
    PdfDictionary xObjects = resources.getAsDictionary(PdfName.XObject);
    
    if (xObjects != null) {
        for (PdfName imgName : xObjects.keySet()) {
            PdfObject obj = xObjects.get(imgName);
            if (obj.isIndirectReference()) {
                PdfStream imgStream = pdfDoc.getPdfObject(obj.getIndirectReference()).getAsStream();
                if (PdfName.Image.equals(imgStream.getAsName(PdfName.Subtype))) {
                    PdfImageXObject originalImg = new PdfImageXObject(imgStream);
                    BufferedImage originalBufImg = originalImg.getBufferedImage();
                    
                    // 二值化处理:使用Java自带的TYPE_BYTE_BINARY格式
                    BufferedImage binaryBufImg = new BufferedImage(
                        originalBufImg.getWidth(), originalBufImg.getHeight(), BufferedImage.TYPE_BYTE_BINARY
                    );
                    Graphics2D g2d = binaryBufImg.createGraphics();
                    g2d.drawImage(originalBufImg, 0, 0, null);
                    g2d.dispose();
                    
                    // 将二值图像转为PDF图像对象
                    ByteArrayOutputStream baos = new ByteArrayOutputStream();
                    ImageIO.write(binaryBufImg, "png", baos);
                    ImageData binaryImgData = ImageDataFactory.create(baos.toByteArray());
                    PdfImageXObject newBinaryImg = new PdfImageXObject(binaryImgData);
                    
                    // 替换原图像
                    xObjects.put(imgName, newBinaryImg.getPdfObject());
                }
            }
        }
    }
}

pdfDoc.close();

额外注意事项

  • 高DPI图像的二值化阈值可以根据实际情况调整,固定阈值效果不好的话,可以尝试Otsu自适应阈值算法来优化
  • iText 7.1.x版本对图像处理的兼容性不错,如果你遇到奇怪的问题,升级到最新稳定版(比如7.1.17+)会更稳妥
  • 替换图像时,原图像的位置、尺寸等属性会自动保留,不需要额外处理

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 07:33:48