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

低DPI扫描PDF转Base64格式JPEG时出现空白问题求助

问题描述

我需要实现将PDF的Base64编码转换为JPEG的Base64编码的功能,但遇到了一个问题:如果PDF是通过低于600DPI扫描生成的,转换后的JPEG图像无法正常渲染,显示为无内容的空白图。

以下是我的代码:

public String convertPDFtoJPEG(byte[] pdfData) {
    try {
      PDDocument document = PDDocument.load(pdfData);
      PDFRenderer renderer = new PDFRenderer(document);

      for (int pageIndex = 0; pageIndex < document.getNumberOfPages(); pageIndex++) {
        BufferedImage image = renderer.renderImageWithDPI(pageIndex, 300);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ImageIO.write(image, "JPEG", baos);

        baos.flush();

        String base64JPEG = Base64.getEncoder().encodeToString(baos.toByteArray());

        baos.close();
      }

      document.close();
    } catch (IOException e) {
      e.printStackTrace();
    }
    return base64JPEG;
  }

 public byte[] readBase64FromFile(String filePath) {
    File file = new File(filePath);
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
      String line;
      while ((line = reader.readLine()) != null) {
        baos.write(line.getBytes());
      }
    } catch (IOException e) {
      e.printStackTrace();
    } 
    return Base64.getDecoder().decode(baos.toByteArray());
  }

调用方式:

String filepath = "path:\\to\\file.txt";
byte[] pdfData = readBase64FromFile(filePath);

convertPDFtoJPEG(pdfData);

其中file.txt存储的是PDF的Base64编码内容。


问题分析与修复方案

1. 变量作用域错误

convertPDFtoJPEG方法中,base64JPEG是在循环内部定义的,方法最终返回的变量未在外部初始化,会导致编译/运行时错误。需要将变量声明移到循环外。

2. JPEG不支持透明背景导致空白

低DPI扫描的PDF渲染出的BufferedImage通常是ARGB带透明通道模式,而JPEG不支持透明,直接写入会将透明区域转为空白。需强制将图像转为RGB模式后再生成JPEG。

3. Base64读取的编码问题

使用FileReader读取Base64文件时,默认采用系统编码,可能导致Base64字符解析错误,进而损坏PDF数据,引发渲染失败。应改用字节流读取,避免编码干扰。


修正后的代码

修正Base64读取方法

public byte[] readBase64FromFile(String filePath) {
    File file = new File(filePath);
    try (FileInputStream fis = new FileInputStream(file);
         ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
        byte[] buffer = new byte[1024];
        int len;
        while ((len = fis.read(buffer)) != -1) {
            baos.write(buffer, 0, len);
        }
        return Base64.getDecoder().decode(baos.toByteArray());
    } catch (IOException e) {
        e.printStackTrace();
        return new byte[0];
    }
}

修正PDF转JPEG方法

public String convertPDFtoJPEG(byte[] pdfData) {
    String base64JPEG = "";
    try (PDDocument document = PDDocument.load(pdfData)) {
        PDFRenderer renderer = new PDFRenderer(document);

        // 示例处理第一页,多页场景可改为返回List<String>存储所有页的Base64
        if (document.getNumberOfPages() > 0) {
            // 强制渲染为RGB模式,避免透明通道问题
            BufferedImage image = renderer.renderImageWithDPI(0, 300, ImageType.RGB);
            try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
                // 自定义JPEG压缩质量(可选)
                ImageWriter writer = ImageIO.getImageWritersByFormatName("JPEG").next();
                ImageWriteParam param = writer.getDefaultWriteParam();
                param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
                param.setCompressionQuality(0.9f);

                writer.setOutput(ImageIO.createImageOutputStream(baos));
                writer.write(null, new IIOImage(image, null, null), param);

                base64JPEG = Base64.getEncoder().encodeToString(baos.toByteArray());
            }
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    return base64JPEG;
}

额外提示

  • 多页PDF场景:可将返回值改为List<String>,遍历所有页面并将每一页的JPEG Base64加入列表。
  • 匹配原PDF DPI:如果需要更贴合原扫描件的清晰度,可通过PDF页面的MediaBox计算原DPI,再用该值渲染:
    PDPage page = document.getPage(0);
    PDRectangle mediaBox = page.getMediaBox();
    float originalDpi = (float) (mediaBox.getWidth() / (page.getCropBox().getWidth() / 72));
    
  • 依赖版本:确保使用最新稳定版的PDFBox,旧版本可能存在低DPI渲染的兼容性bug。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 21:12:46