PDFBox操作pdf文件转换为图片

原文在Vic's blog

我是如何接触到PDFBox的

疫情期间,周末在家老实呆着,女友在学法律,但女友学习法律的pdf文件资料里每页都有一些类似培训机构联系方式的一些文字,共三四百页,用普通的编辑软件删除不了,如果要删除的话必须开通会员,也可能我没找到免费的软件吧,我国的办公编辑软件也真够可以的了,编辑个PDF还要收费,我是程序员,也明白软件开发需要成本和消耗,但如果作为大众使用者还是接受不了收费软件.于是乎,作为猿的我只能自己研究下怎么自己写代码去掉那些不怎么好看的文字,上网查找资料有哪些基于Java的类库可以读取PDF,就找到了很多猿都用的PDFBox,PDFBox同样是来自给我们猿贡献了很多免费软件的Apache基金会.

Apache PDFBox介绍

直接去官网Apache PDFBox,看版本已经发布到2.0了,首页说该类库的功能对PDF文件有:创建,提取文字,分割合并,填写表格,打印,另存为图片和加密功能,对于我的需求来说足够了,操作文档pdf操作内置对象文档,看不懂翻译即可

需求代码

我的需求是去掉PDF里每页的固定位置的文字(多余的培训机构的联系方式),以下称"多余部分",但我经过测试发下,哪些其实不是文字而是图片,整页是一张大图片,那更好操作了,首先maven引入dependency你懂得,计划为共分为三步.

1.先把pdf三四百页,以每页为一张图片导出来

/**
     * pdf 转换为图片
     * @param pdfPath pdf文件路径
     * @param imgPath 图片导出目标路径
     */
public static void getImgInPDF(String pdfPath,String imgPath){
    PDDocument document = null;
    try {
        File pdfFile = new File(pdfPath);
        // 加载pdf文档,在pdmodel包
        document = PDDocument.load(pdfFile);
        // PDF文档总页数
        System.out.println("共 "+num+" 页.");
        // PDF文档渲染对象,在rendering包
        PDFRenderer renderer = new PDFRenderer(document);
        String startDate = DateTool.now();
        int pageCount = document.getNumberOfPages();
        System.out.println("共 "+pageCount+" 页.");
        for (int i = 0; i < pageCount; i++) {
          /**
           * renderImage(i,1.9f)
           * 
           * i: 指定页对象下标,从0开始,0即第一页
           * 
           * 1.9f:DPI值(Dots Per Inch),官方描述比例因子,其中1=72 DPI
           *      DPI是指每英寸的像素,也就是扫描精度,DPI越低,扫描的清晰度越低
           *      根据根据自己需求而定,我导出的图片是 927x1372
           */
            BufferedImage image = renderer.renderImage(i,1.9f);
            // 导出图片命名为:0-n.jpeg
            ImageIO.write(image, "JPEG", new File(imgPath+i+".jpeg"));
            System.out.println("导出 "+imgPath+i+".jpeg...");
        }
        System.out.println("开始时间:"+startDate);
        System.out.println("结束时间:"+ DateTool.now());
    }catch (Exception e){
        e.printStackTrace();
    }
}

2.java操作图片去掉固定位置的RGB(多余部分), 这部操作简单了

/**
 * 设置图片的指定区域为指定颜色
 * @param imgPath 图片路径
 */
public static void cleanImgRgb(String imgPath){
    try{
        String startDate = DateTool.now();
        File dir = new File(imgPath);
        File[] img = dir.listFiles();
        // 处理imgPath中所有带jpeg后缀的图片
        for (int i = 0; i < img.length; i++) {
            String imgName =  img[i].getName();
            if(imgName.contains("jpeg")){
                System.out.println("正在处理:"+imgName);
                BufferedImage bufImage = ImageIO.read(new File(imgPath+imgName));
                int rgb = 0xffffff; // 替换多余部分为白色rgb
                int width = 470;// 替换区域宽
                int height = 34;// 替换区域高
                int startX = 230;// 替换区域x开始点
                int startY = 16;// 替换区域y开始点
                // rgb颜色数组,替换多余部分的width*height的总数
                int[] rgbArray = new int[width*height];
                for (int j = 0; j < width*height; j++) {
                    rgbArray[j] = rgb;
                }
                bufImage.setRGB(startX,startY,width,height,rgbArray,0,width);
                FileOutputStream out = new FileOutputStream(imgPath+imgName);
                ImageIO.write(bufImage, "JPEG",out);
            }
        }
        System.out.println("开始时间:"+startDate);
        System.out.println("结束时间:"+ DateTool.now());
    }catch (Exception e){
        e.printStackTrace();
    }
}

3.再把处理过后的图片对应的插入到PDF每页里面,并覆盖以前,这步最重要!!!!

/**
  * 插入图片到pdf,400+张依次插入到pdf的400+页中
  * @param pdfPath pdf路径
  * @param imgPath 要插入的图片路径(正是第一步的图片路径)
  * @param start  插入pdf开始页
  * @param end    插入pdf结束页
 */
private static void imgInsertToPdf(String pdfPath,String imgPath,int start,int end){
    try {
        System.out.println("图片路径:"+imgPath);
        File file = new File(pdfPath);
        PDDocument document = PDDocument.load(file);
        int pageSie = document.getNumberOfPages();
        System.out.println("pdf总页数:"+pageSie);
        int insert = 0;
        System.out.println("开始时间:"+ DateTool.now());
        for (;start <=end; start++) {
            insert++;
            String img = imgPath+start+".jpeg";
            System.out.println("第"+(start+1)+"个文件,图片"+img);
            // 当前页
            PDPage page = document.getPage(start);
            File imgFile = new File(img);
            if(imgFile.exists() && imgFile.getName().endsWith( ".jpeg" ) ){
                //根据图片路径创建一张图片
                PDImageXObject pdImage = PDImageXObject.createFromFile(img,document);
                /**
                 * (document, page,false, true)
                 *  document: pdf对象
                 *  page :    当前页对象
                 *  false :   是否是追加内容,false不追加,清空之前的内容
                 *  true :    是否压缩
                */
                PDPageContentStream contents = new PDPageContentStream(document, page,false, true);
               /**
                * 比例值
                *  如果pdf页大,图片小,可调整此值放大图片沾满
                *  建议值 0-1
                */
                float scale = 0.527f;
                // 绘制开始的xy点
                contents.drawImage(pdImage, 0, 0, pdImage.getWidth() * scale, pdImage.getHeight() * scale);
                contents.close();
                //Saving the document 保存文档
                document.save(pdfPath);
            }else{
                break;
            }

        }
        System.out.println("插入次数:"+insert);
        System.out.println("结束时间:"+ DateTool.now());
        System.out.println("插入完毕.....");

        //Closing the document
        document.close();
    }catch (Exception e){
        e.printStackTrace();
    }
}

PDFBox常用API,更多看官网

// pdf路径
String pdfPath = "/Users/Documents/pdf_file.pdf";
File file = new File(pdfPath);
// 加载pdf
PDDocument document = PDDocument.load(file);
/**
 * 1.读取pdf文本
 */

// 文本分离器
PDFTextStripper textStripper = new PDFTextStripper();
// 输出pdf的文本内容
System.out.println(textStripper.getText(document));

/**
 * 2.删除页面,存在的页,从0开始
 */
document.removePage(2);
// 获取总页数
document.getNumberOfPages();
/**
 * 3.添加页面
 */
PDPage my_page = new PDPage();
document.addPage(my_page);
// 保存pdf
document.save("Path");

/**
 * 4.插入图像
 */
// 获取pdf中的图片
PDFRenderer renderer = new PDFRenderer(document);
// 后去指定页的图像
BufferedImage image = renderer.renderImage(0);
// 另存到
ImageIO.write(image, "JPEG", new File("/Users/Documents/pdf_img.jpg"));

/**
 * 5.合并pdf文档
 */
File pdf1 = new File("F:/worksp/pdfbox/pdf_1.pdf");
PDDocument doc1 = PDDocument.load(pdf1);
File pdf2 = new File("/Users/Documents/pdf_2.pdf");
PDDocument doc2 = PDDocument.load(pdf2);
// 合并后的文件
PDFMergerUtility merger = new PDFMergerUtility();
merger.setDestinationFileName("/Users/Documents/merger.pdf");
merger.addSource(file1);
merger.addSource(file2);
// 合并
merger.mergeDocuments();
doc2.close();
doc1.close();


// 关闭
document.close();
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,590评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,808评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,151评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,779评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,773评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,656评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,022评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,678评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,038评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,756评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,411评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,005评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,973评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,053评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,495评论 2 343

推荐阅读更多精彩内容