截取PDF文件并转为图片输出

1.引入依赖

<dependency>
  <groupId>org.apache.pdfbox</groupId>
  <artifactId>pdfbox</artifactId>
  <version>1.8.2</version>
</dependency>
<dependency>
  <groupId>org.apache.pdfbox</groupId>
  <artifactId>fontbox</artifactId>
  <version>1.8.2</version>
</dependency>

2.实现获取PDF指定页的流处理工具



import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriter;
import javax.imageio.stream.ImageOutputStream;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;

public class PDFSavePNG {

  public static void main(String[] args) throws IOException {
    convertPdf2Image("c:/temp/test.pdf");
//      try
//      {
//        // 打开来源 pdf
//        PDDocument pdfDocument = PDDocument.load(new File("c:/temp/aaa.pdf"));
//        PDFRenderer pdfRenderer = new PDFRenderer(pdfDocument);
//
//        // 提取的页码
//        int pageNumber = 1;
//        // 以300 dpi 读取存入 BufferedImage 对象
//        int dpi = 300;
//        BufferedImage buffImage = pdfRenderer.renderImageWithDPI(0, dpi, ImageType.RGB);
//        System.out.println(buffImage);
//        BufferedImage buffImage2 = pdfRenderer.renderImageWithDPI(1, dpi, ImageType.RGB);
//        BufferedImage buffImage3 = pdfRenderer.renderImageWithDPI(2, dpi, ImageType.RGB);
//        // 将 BufferedImage 写入到 png
//        ImageIOUtil.writeImage(buffImage, "c:/temp/xx1.png", dpi);
//        ImageIOUtil.writeImage(buffImage2, "c:/temp/xx2.png", dpi);
//        ImageIOUtil.writeImage(buffImage3, "c:/temp/xx3.png", dpi);
//
//        // 关闭文档
//        pdfDocument.close();
//      }
//      catch (InvalidPasswordException e)
//      {
//        e.printStackTrace();
//      }
//      catch (IOException e)
//      {
//        e.printStackTrace();
//      }
  }

  public static void convertPdf2Image(String pdfFilePath)
      throws IOException
  {
    File pdfFile = new File(pdfFilePath);
    File imageFileParent = new File(pdfFile.getParent());
    OutputStream output = null;
    PDDocument pdDoc = null;
    List<File> files = new ArrayList<File>();
    try{
      if(pdfFile.exists()){
        if(!imageFileParent.exists()){
          imageFileParent.mkdirs();
        }
        pdDoc = PDDocument.load(pdfFile);
        int pageCount = pdDoc.getNumberOfPages();
        List pages = pdDoc.getDocumentCatalog().getAllPages();
        for(int i = 0; i < pages.size(); i++){
          PDPage page = (PDPage)pages.get(i);
          BufferedImage image = page.convertToImage();
          Iterator iter = ImageIO.getImageWritersBySuffix("jpg");
          ImageWriter writer = (ImageWriter)iter.next();
          File tempFile = new File(imageFileParent.getPath(),"xx" + i + ".jpg");
          files.add(tempFile);
          output = new FileOutputStream(tempFile);
          ImageOutputStream imageOut = ImageIO.createImageOutputStream(output);
          writer.setOutput(imageOut);
          writer.write(new IIOImage(image,null,null));
          output.close();
        }
        pdDoc.close();
//        mergeMultiImageFiles(files,imageFile);//合并多张图片为一张图片
      }

    }finally{
      try{
        if(pdDoc != null){
          pdDoc.close();
        }
        if(output != null){
          output.close();
        }
      }catch(IOException e){
        e.printStackTrace();
      }
    }
  }
}

3.实现业务实际的业务处理,以及将文件输出


import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.imageio.ImageIO;
import lombok.extern.slf4j.Slf4j;
import org.apache.pdfbox.io.RandomAccessBuffer;
import org.apache.pdfbox.pdfparser.PDFParser;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Slf4j
@Service
public class ServiceImpl {

  /**
   * 处理PDF预览图
   */
  @Override
  public void dealPDF(String url) {
    try {
      log.info("[处理PDF预览图] 开始处理文档 startTime:{}", JsonUtil.toJson(new Date()));
      InputStream io = getIOByURL(url);

      // 加载pdf文档
      PDFParser parser = new PDFParser(new RandomAccessBuffer(io));
      parser.parse();
      PDDocument pdDocument = parser.getPDDocument();
      // PDF文档渲染对象,在rendering包
      PDFRenderer renderer = new PDFRenderer(pdDocument);
      // 读取pdf页数
      int pageCount = pdDocument.getNumberOfPages();

      uploadPreview(i, renderer, previewlist);
      pdDocument.close();
      io.close();
      log.info("[处理PDF预览图] 结束处理文档 endTime:{}", JsonUtil.toJson(new Date()));
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  /**
   * 通过URL获取文件流
   */
  private InputStream getIOByURL(String fileUrl) throws IOException {
    log.info("[获取COS上PDF的IO流] 入参 fileUrl:{}", JsonUtil.toJson(fileUrl));
    // 从文件链接里获取文件流
    URL url = new URL(fileUrl);
    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    // 设置超时间为3秒
    conn.setConnectTimeout(3 * 1000);
    // 防止屏蔽程序抓取而返回403错误
    conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
    // 得到输入流
    InputStream io = conn.getInputStream();
    return io;
  }

  /**
   * 上传预览图
   */
  private void uploadPreview(PDFRenderer renderer) throws IOException {
    log.info("[上传预览图] 入参 i:{},previewlist:{}", i, JsonUtil.toJson(previewlist));
    // 保存预览图
    BufferedImage image = renderer.renderImage(i, 1.9f);
    // 将生成图片放在outStream
    ByteArrayOutputStream outStream =new ByteArrayOutputStream();
    ImageIO.write(image, "JPG", outStream);
    System.out.println(outStream.toByteArray());
    String path = uploadService.uploadByByte(outStream.toByteArray());
    log.info("[上传预览图] 返回预览图路径 path:{}", path);
  }
}

以下为对分割出来的图片进行合并的处理代码


import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
import javax.imageio.ImageIO;

public class Test {

  public static void main(String[] args) throws Exception {
    List<File> files = new ArrayList<>();
    File file1 = new File("F:/worksoft/test/111.png");
    File file2 = new File("F:/worksoft/test/222.png");
    File file3 = new File("F:/worksoft/test/111.png");
    String path = "F:/worksoft/test/111+222.jpg";
    file1 = compressImage(ImageIO.read(file1),
        ImageIO.read(file1).getWidth()/2, ImageIO.read(file1).getHeight()/2);
    file2 = compressImage(ImageIO.read(file2),
        ImageIO.read(file2).getWidth()/2, ImageIO.read(file2).getHeight()/2);
    files.add(file1);
    files.add(file2);
    files.add(file3);
    files = mergeHorizontal(files, path);
    mergeVertical(files, "F:/worksoft/test/111+222+333.jpg");
  }

  //竖向合成
  public static void mergeVertical(List<File> files, String path) {
    try {
      Integer allWidth = 0;  //计算画布总宽
      Integer allHeight = 0;  //计算画布总高
      List<BufferedImage> imgs = new ArrayList<>();
      for (int i = 0; i < files.size(); i++) {
        imgs.add(ImageIO.read(files.get(i)));
        //因为是竖向合成,拿图片里最大的一个宽度就行
        allWidth = Math.max(allWidth, imgs.get(i).getWidth());
        allHeight += imgs.get(i).getHeight();
      }
      BufferedImage combined = new BufferedImage(allWidth, allHeight, BufferedImage.TYPE_INT_RGB);
      Graphics g = combined.getGraphics();
      //设置画布背景颜色 ,默认黑色
      g.setColor(Color.white);
      g.fillRect(0, 0, allWidth, allHeight);
      Integer height = 0;
      for (int i = 0; i < imgs.size(); i++) {
        g.drawImage(imgs.get(i), 0, height, null);
        //+10为了设置上下两个图片间距
        height += imgs.get(i).getHeight();
      }
      ImageIO.write(combined, "jpg", new File(path));
      System.out.println("===合成成功====");
    } catch (Exception e) {
      System.out.println("===合成失败====");
      e.printStackTrace();
    }
  }

  //横向合成
  public static List<File> mergeHorizontal(List<File> files, String path) {
    try {
      Integer allWidth = 0;
      Integer allHeight = 0;
      List<BufferedImage> imgs = new ArrayList<>();
      for (int i = 0; i < 2; i++) {
        imgs.add(ImageIO.read(files.get(i)));
        allHeight = Math.max(allHeight, imgs.get(i).getHeight());
        allWidth += imgs.get(i).getWidth();
      }
      BufferedImage combined = new BufferedImage(allWidth, allHeight, BufferedImage.TYPE_INT_RGB);
      Graphics g = combined.getGraphics();
      g.setColor(Color.white);
      g.fillRect(0, 0, allWidth, allHeight);
      Integer width = 0;
      for (int i = 0; i < 2; i++) {
        g.drawImage(imgs.get(i), width, 0, null);
        //设置横向间距
        width += imgs.get(i).getWidth();
      }
      int i = 2;
      while (i > 0) {
        files.remove(0);
        i--;
      }
      File newFile = new File("F:/worksoft/test/111+222.jpg");
      ImageIO.write(combined, "jpg", newFile);
      files.add(newFile);
      files.add(newFile);
      System.out.println("===合成成功====");
    } catch (Exception e) {
      System.out.println("===合成失败====");
      e.printStackTrace();
    }
    return files;
  }

  //字符串类型图片转换
  public static BufferedImage base64StringToImg(String base64String) {
    try {
      byte[] bytes = Base64.getDecoder().decode(base64String);
      ByteArrayInputStream in = new ByteArrayInputStream(bytes);
      return ImageIO.read(in);
    } catch (final IOException ioe) {
      throw new UncheckedIOException(ioe);
    }
  }

  /**
   * * 将图片按照指定的图片尺寸压缩
   * @param new_w :压缩后的图片宽
   * @param new_h :压缩后的图片高
   */
  public static File compressImage(BufferedImage bufferedImage,
                                   int new_w, int new_h) throws IOException {
    return disposeImage(bufferedImage, new_w, new_h);
  }

  /**
   * 图片文件读取
   * @param srcImgPath
   * @return
   */
  private static BufferedImage InputImage(String srcImgPath) {
    BufferedImage srcImage = null;
    try {
      FileInputStream in = new FileInputStream(srcImgPath);
      srcImage = javax.imageio.ImageIO.read(in);
    } catch (IOException e) {
      System.out.println("读取图片文件出错!" + e.getMessage());
      e.printStackTrace();
    }
    return srcImage;
  }
  /**
   * 处理图片
   */
  private synchronized static File disposeImage(BufferedImage src, int new_w, int new_h) throws IOException {
    // 得到图片
    int old_w = src.getWidth();
    // 得到源图宽
    int old_h = src.getHeight();
    // 得到源图长
    BufferedImage newImg = null;
    // 判断输入图片的类型
    switch (src.getType()) {
      case 13:
        // png,gifnewImg = new BufferedImage(new_w, new_h,
        // BufferedImage.TYPE_4BYTE_ABGR);
        break;
      default:
        newImg = new BufferedImage(new_w, new_h, BufferedImage.TYPE_INT_RGB);
        break;
    }
    Graphics2D g = newImg.createGraphics();
    // 从原图上取颜色绘制新图
    g.drawImage(src, 0, 0, old_w, old_h, null);
    g.dispose();
    // 根据图片尺寸压缩比得到新图的尺寸
    newImg.getGraphics().drawImage(
        src.getScaledInstance(new_w, new_h, Image.SCALE_SMOOTH), 0, 0,
        null);
    // 调用方法输出图片文件
    File newFile = new File("F:/worksoft/test/111_yasuo.jpg");
    ImageIO.write(newImg, "jpg", newFile);
    return newFile;
  }
  /**
   * 将图片文件输出到指定的路径,并可设定压缩质量
   */
  private static void OutImage(String outImgPath, BufferedImage newImg) {
    // 判断输出的文件夹路径是否存在,不存在则创建
    File file = new File(outImgPath);
    if (!file.getParentFile().exists()) {
      file.getParentFile().mkdirs();
    }// 输出到文件流
    try {
      ImageIO.write(newImg,
          outImgPath.substring(outImgPath.lastIndexOf(".") + 1),
          new File(outImgPath));
    } catch (FileNotFoundException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值