Java的PDF转图片上传oss

一、前言

 
做了一个pdf上传转图片并上传oss,并对图片识别需求
下面主要是pdf转图片实现
 
选择用pdfbox去实现

二、实现

 

1.maven配置

 
<dependency>
  <groupId>org.apache.pdfbox</groupId>
  <artifactId>pdfbox</artifactId>
  <version>2.0.28</version> 
</dependency>

<dependency>
  <groupId>org.apache.pdfbox</groupId>
  <artifactId>pdfbox-tools</artifactId>
  <version>2.0.28</version> 
</dependency>
这里用的2.0.28版本
2.0 版本最新 是2.0.29
已经发布3.0版本
 

2.关键代码

 
读取pdf文件
PDDocument document = PDDocument.load(file.getInputStream(), MemoryUsageSetting.setupTempFileOnly()
允许下采样
PDFRenderer pdfRenderer = new PDFRenderer(document);
//允许下采样
pdfRenderer.setSubsamplingAllowed(true);
分页处理
  // 渲染PDF页面为图像:
    // page:要渲染的 PDF 页面对象
    // 300:渲染的图像分辨率,通常以每英寸点数(DPI,Dots Per Inch)表示。这里将图像渲染为每英寸300个点。
    // ImageType.RGB:指定图像类型为 RGB(红绿蓝)色彩模式。这表示生成的图像将包含红、绿、蓝三种颜色通道。
ByteArrayOutputStream os;
for (int page = 0; page < document.getNumberOfPages(); ++page) {
    // dpi 设置你的dpi
    bim = pdfRenderer.renderImageWithDPI(page, dpi, ImageType.RGB);
    os = new ByteArrayOutputStream();
    // 注意设置dpi 不设置默认72 dpi
    ImageIOUtil.writeImage(bim , "png", os, dpi);
   
    //上传图片到oss
    aliOssUtil.uploadPdfImgToOSS(file.getOriginalFilename(), ossType, page, os);
}
注意:
1.ImageIOUtil.writeImage(bim , "png", os, dpi);
文件格式直接用jpeg会不清晰,可先转png再转jpg格式
 
2.dpi设置过大会导致内存溢出
 

3.png转jpg的demo

  public static void main(String[] args) {
        try {
            String pdfFilePath = "path/to/your/input.pdf"; // 输入PDF文件路径
            String outputDir = "path/to/your/output/directory/"; // 输出目录

            PDDocument document = PDDocument.load(new File(pdfFilePath));
            PDFRenderer pdfRenderer = new PDFRenderer(document);

            for (int page = 0; page < document.getNumberOfPages(); ++page) {
                BufferedImage bim = pdfRenderer.renderImageWithDPI(page, 300, ImageType.RGB);
                String pngFileName = outputDir + "page_" + (page + 1) + ".png";
                ImageIO.write(bim, "PNG", new File(pngFileName));

                // 将PNG转换为JPEG
                BufferedImage pngImage = ImageIO.read(new File(pngFileName));
                String jpgFileName = outputDir + "page_" + (page + 1) + ".jpg";
                ImageIO.write(pngImage, "JPEG", new File(jpgFileName));
            }

            document.close();
            System.out.println("PDF转PNG和JPEG完成!");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
 

4.上传至oss

 
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

InputStream inputStream = new ByteArrayInputStream(image);

// 构建上传Object的元信息
ObjectMetadata meta = new ObjectMetadata();
meta.setContentLength(image.length);
meta.setContentType("image/jpeg");

String fileUrl = getFileUrl(ossPath, type);
try {
    PutObjectResult result = ossClient.putObject(new PutObjectRequest(bucketName, fileUrl, inputStream));
}

三、 测试各pdf转图片处理各dpi(包含各种缩放处理)

 
pdf文件大小
100dpi
150dpi
300dpi
450dpi
600dpi
15页
448k
9 491ms
10 708ms
15 777ms
21 404ms
28 563ms
10页
11.08M
10 965ms
19 688ms
29 771ms
54 301ms
内存崩溃
18页
313k
10 907ms
12 554 ms
19 455ms
26 455ms
37 275ms

结论

pdf原始文件越大,在大于150dpi时,转图片处理,内存占用越大,越耗时间
 

四、遇到的问题

 

1.图片不清晰

 
  1. 先转成png格式再转jpg (见png转jpg的demo)
  2. 调高dpi大小 300是dpi配置
  BufferedImage bim = pdfRenderer.renderImageWithDPI(page, 300, ImageType.RGB);

2.图片转换失败/png转jpg图片不显示背景变黄色

 
PNG 转换为 JPEG 图像时,背景变黄色可能是由于颜色模式和压缩参数的不同引起的。PNG 图像通常使用 RGB 颜色模式,而 JPEG 图像可以使用 YCbCr 颜色模式。这种颜色模式的变化可能会导致颜色差异,从而导致背景颜色变化。
为了解决这个问题,您可以尝试在将 PNG 转换为 JPEG 时明确指定颜色模式,以确保它与您期望的颜色一致。
 
  BufferedImage bim = pdfRenderer.renderImageWithDPI(page, 300, ImageType.RGB);
 

3.对图片指定缩放处理

 
BufferedImage bim, scaledImage, rgbImage;
Graphics2D g2d;
int originalHeight, originalWidth, scaledHeight;

originalHeight = bim.getHeight();
originalWidth = bim.getWidth();
scaledHeight = (int) ((double) originalHeight / originalWidth * desiredWidth);
// desiredWidth scaledHeight 指定宽高
scaledImage = newBufferedImage(desiredWidth, scaledHeight, BufferedImage.TYPE_INT_ARGB);
g2d = scaledImage.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.drawImage(bim.getScaledInstance(desiredWidth, scaledHeight, Image.SCALE_SMOOTH), 0, 0, null);
g2d.dispose();
posted @ 2023-10-09 16:11  逐星i  阅读(332)  评论(0编辑  收藏  举报