zoukankan      html  css  js  c++  java
  • Java中PDF的转换(图片)与展示

    解决的问题

    有些时候我们需要在项目中展示PDF,但是直接在浏览器中加入PDF展示的插件,存在兼容性问题,某些浏览器显示效果不理想,所以我们可以将PDF转为图片,然后已图片的方式展示,效果很好。

    那么怎么将PDF转为图片呢?有两种方式:

    产品 特点
    Apache 的 PDF box 免费;速度稍慢一点,但可以接受
    E-iceblue 的 Spire.PDF for Java 转换效果很好;速度快;功能强大,支持转多种格式;收费

    Spire.PDF for Java 的转换效果很好,但是如果不购买,转换过后会添加一些水印文字

    参考链接:https://www.cnblogs.com/Yesi/p/11233238.html

    PDF Box的使用

    <dependency>
    	<groupId>net.sf.cssbox</groupId>
    	<artifactId>pdf2dom</artifactId>
    	<version>1.7</version>
    </dependency>
    <dependency>
    	<groupId>org.apache.pdfbox</groupId>
    	<artifactId>pdfbox</artifactId>
    	<version>2.0.12</version>
    </dependency>
    <dependency>
    	<groupId>org.apache.pdfbox</groupId>
    	<artifactId>pdfbox-tools</artifactId>
    	<version>2.0.12</version>
    </dependency>
    

    多页PDF生成多张图片

    新建一个 PdfUtil 工具类

    public class PdfUtil {
    
        private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(PdfUtil.class);
    
        /***
         * PDF文件转PNG图片,全部页数
         *
         * @param pdfFilePath pdf完整路径
         * @param dpi dpi越大转换后越清晰,相对转换速度越慢
         */
        public static void pdf2Image(String pdfFilePath, int dpi) {
            File file = new File(pdfFilePath);
            PDDocument pdDocument;
            try {
                String imgPdfPath = file.getParent();
                int dot = file.getName().lastIndexOf('.');
                // 获取图片文件名
                String imagePdfName = file.getName().substring(0, dot);
    
                pdDocument = PDDocument.load(file);
                PDFRenderer renderer = new PDFRenderer(pdDocument);
                /* dpi越大转换后越清晰,相对转换速度越慢 */
                PdfReader reader = new PdfReader(pdfFilePath);
                int pages = reader.getNumberOfPages();
                StringBuffer imgFilePath;
                for (int i = 0; i < pages; i++) {
                    String imgFilePathPrefix = imgPdfPath + File.separator + imagePdfName;
                    imgFilePath = new StringBuffer();
                    imgFilePath.append(imgFilePathPrefix);
                    imgFilePath.append("_");
                    imgFilePath.append((i + 1));
                    imgFilePath.append(".png");
                    File dstFile = new File(imgFilePath.toString());
                    BufferedImage image = renderer.renderImageWithDPI(i, dpi);
                    ImageIO.write(image, "png", dstFile);
                }
                log.info("PDF文档转PNG图片成功!");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        
    }
    

    多页PDF组合成一张图片

    public class PdfUtil {
    
        public static final int DEFAULT_DPI = 150;
    
        /**
         * pdf转图片
         * 多页PDF会每页转换为一张图片,下面会有多页组合成一页的方法
         *
         * @param pdfFile pdf文件路径
         * @param outPath 图片输出路径
         * @param dpi 相当于图片的分辨率,值越大越清晰,但是转换时间变长
         */
        public static void pdf2multiImage(String pdfFile, String outPath, int dpi) {
            if (ObjectUtil.isEmpty(dpi)) {
                // 如果没有设置DPI,默认设置为150
                dpi = DEFAULT_DPI;
            }
            try (PDDocument pdf = PDDocument.load(new FileInputStream(pdfFile))) {
                int actSize = pdf.getNumberOfPages();
                List<BufferedImage> picList = Lists.newArrayList();
                for (int i = 0; i < actSize; i++) {
                    BufferedImage image = new PDFRenderer(pdf).renderImageWithDPI(i, dpi, ImageType.RGB);
                    picList.add(image);
                }
                // 组合图片
                ImageUtil.yPic(picList, outPath);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    

    新建 ImageUtil 类

    public class ImageUtil {
    
        private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(ImageUtil.class);
    
        /**
         * 将宽度相同的图片,竖向追加在一起 ##注意:宽度必须相同
         *
         * @param picList 文件流数组
         * @param outPath 输出路径
         */
        public static void yPic(List<BufferedImage> picList, String outPath) {// 纵向处理图片
            if (picList == null || picList.size() <= 0) {
                log.info("图片数组为空!");
                return;
            }
            try {
                // 总高度
                int height = 0,
                        // 总宽度
                        width = 0,
                        // 临时的高度 , 或保存偏移高度
                        offsetHeight = 0,
                        // 临时的高度,主要保存每个高度
                        tmpHeight = 0,
                        // 图片的数量
                        picNum = picList.size();
                // 保存每个文件的高度
                int[] heightArray = new int[picNum];
                // 保存图片流
                BufferedImage buffer = null;
                // 保存所有的图片的RGB
                List<int[]> imgRgb = new ArrayList<int[]>();
                // 保存一张图片中的RGB数据
                int[] tmpImgRgb;
                for (int i = 0; i < picNum; i++) {
                    buffer = picList.get(i);
                    // 图片高度
                    heightArray[i] = offsetHeight = buffer.getHeight();
                    if (i == 0) {
                        // 图片宽度
                        width = buffer.getWidth();
                    }
                    // 获取总高度
                    height += offsetHeight;
                    // 从图片中读取RGB
                    tmpImgRgb = new int[width * offsetHeight];
                    tmpImgRgb = buffer.getRGB(0, 0, width, offsetHeight, tmpImgRgb, 0, width);
                    imgRgb.add(tmpImgRgb);
                }
                // 设置偏移高度为0
                offsetHeight = 0;
                // 生成新图片
                BufferedImage imageResult = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
                for (int i = 0; i < picNum; i++) {
                    tmpHeight = heightArray[i];
                    if (i != 0) {
                        // 计算偏移高度
                        offsetHeight += tmpHeight;
                    }
                    // 写入流中
                    imageResult.setRGB(0, offsetHeight, width, tmpHeight, imgRgb.get(i), 0, width);
                }
                File outFile = new File(outPath);
                // 写图片
                ImageIO.write(imageResult, "png", outFile);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        
    }
    
  • 相关阅读:
    Android开发总结
    LeakCanary原理分析
    机器学习
    Kivy 中文教程 实例入门 简易画板 (Simple Paint App):2. 实现绘图功能
    Python 零基础 快速入门 趣味教程 (咪博士 海龟绘图 turtle) 3. 循环
    Kivy 中文教程 实例入门 简易画板 (Simple Paint App):1. 自定义窗口部件 (widget)
    Python 零基础 快速入门 趣味教程 (咪博士 海龟绘图 turtle) 2. 变量
    Python 零基础 快速入门 趣味教程 (咪博士 海龟绘图 turtle) 1. 神秘朋友
    Python 零基础 快速入门 趣味教程 (咪博士 海龟绘图 turtle) 0. 准备工作
    远程显示(操作) 服务器 GUI 程序(图形化界面) (基于 X11 Forwarding + Centos + MobaXterm)
  • 原文地址:https://www.cnblogs.com/reroyalup/p/13533882.html
Copyright © 2011-2022 走看看