java实现pdf黑白化

  • 背景
  • 研究方向选择
  • 功能实现
  • 依赖
  • pdf转图片
  • 图片黑白化
  • 黑白化后的图片转pdf
  • 效果对比


背景

最近开发办公系统,客户需求中有要求能使用传真机发传真。遇到问题:硬件方面,传真机只能发特定的tif文件,于是系统需要把客户上传的文件转成pdf,然后用Ghostscript 命令把pdf转成符合传真机要求的tif。因为客户方属于政府部门,一般上传的文件都是红头文件,在pdf转tif文件后,生成的tif文件所有的红色字体都看不清。下面是我的解决思路。

研究方向选择

解决这个问题无外乎有两种解决思路。

  1. 将pdf原件黑白化
  2. pdf转tif时将彩色字体黑化

由于自己是一个小白,感觉第一种解决思路对自己来说还可能搞定,于是选择了走第一种思路去解决这个问题。
尝试过很多办法,比如:
1. 使用itext直接编辑pdf,识别pdf中彩色字体,设置字体颜色。
2. pdf转word,然后编辑word字体颜色,再把word转pdf。
3. pdf转html,编辑html替换collor为红色的属性值为黑色,html转pdf。
4. pdf转换为图片,图片黑白化,把图片转换为pdf。

前三种方法我尝试了,但是多多少少都存在一些问题,不能满足我的需求,最终使用第四种方法实现的。

功能实现

我是采用springBoot集成itextpdf、pdfbox及cssbox,分别实现了pdf转图片、图片黑白化、图片转pdf的功能,下面是具体的实现代码。

依赖

<dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itextpdf</artifactId>
            <version>5.5.13</version>
        </dependency>
        <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转图片

/***
     * PDF文件转PNG图片,全部页数
     *
     * @param PdfFilePath pdf完整路径
     * @param dirUrl 图片存放的文件夹
     * @param dpi dpi越大转换后越清晰,相对转换速度越慢
     * @return
     */
    public static List<String> pdfToImage(String PdfFilePath, String dirUrl, int dpi) {
        File file = new File(PdfFilePath);
        PDDocument pdDocument = null;
        PDFRenderer renderer;
        PdfReader reader = null;
        try {
            int dot = file.getName().lastIndexOf('.');
            String imagePDFName = file.getName().substring(0, dot); // 获取pdf文件名
            String imgFolderPath = null;
            if (StringUtils.isNotBlank(dirUrl)) {
                imgFolderPath = dirUrl + "/" + imagePDFName;// 获取图片存放的文件夹路径
            } else {
                imgFolderPath = "D:/img" + "/" + imagePDFName;//设置默认路径
            }

            if (createDirectory(imgFolderPath)) {
                pdDocument = PDDocument.load(file);
                renderer = new PDFRenderer(pdDocument);
                /* dpi越大转换后越清晰,相对转换速度越慢 */
                reader = new PdfReader(PdfFilePath);
                int pages = reader.getNumberOfPages();
                StringBuffer imgFilePath = null;
                List<String> imgUrlList = new ArrayList<>();
                for (int i = 0; i < pages; i++) {
                    String imgFilePathPrefix = imgFolderPath + "/" + imagePDFName;
                    imgFilePath = new StringBuffer();
                    imgFilePath.append(imgFilePathPrefix);
                    imgFilePath.append("_");
                    imgFilePath.append(String.valueOf(i + 1));
                    imgFilePath.append(".png");
                    File dstFile = new File(imgFilePath.toString());
                    BufferedImage image = renderer.renderImageWithDPI(i, dpi);
                    ImageIO.write(image, "png", dstFile);
                    imgUrlList.add(imgFilePath.toString());
                }
                System.out.println("PDF文档转PNG图片成功!");
                return imgUrlList;
            } else {
                System.out.println("PDF文档转PNG图片失败:" + "创建" + imgFolderPath + "失败");
                return null;
            }

        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }finally {
            if (reader != null){
                try {
                    reader.close();
                } catch (Exception e){
                    e.printStackTrace();
                }
                if (pdDocument != null){
                    try {
                        pdDocument.close();
                    } catch (Exception e){
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    
     private static boolean createDirectory(String folder) {
        File dir = new File(folder);
        if (dir.exists()) {
            return true;
        } else {
            return dir.mkdirs();
        }
    }

图片黑白化

public static void changeImg(List<String> imgUrlList) {
        try {
            if (imgUrlList != null && imgUrlList.size() > 0){
                for (String imgUrl : imgUrlList){
                    File img = new File(imgUrl);
                    java.awt.Image image = ImageIO.read(img);
                    int srcH = image.getHeight(null);
                    int srcW = image.getWidth(null);
                    BufferedImage bufferedImage = new BufferedImage(srcW, srcH,BufferedImage.TYPE_3BYTE_BGR);
                    bufferedImage.getGraphics().drawImage(image, 0,0, srcW, srcH, null);
                    bufferedImage=new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_GRAY),null).filter (bufferedImage,null);
                    FileOutputStream fos = new FileOutputStream(img);
                    JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(fos);
                    encoder.encode(bufferedImage);
                    fos.close();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
            throw new IllegalStateException("图片转换出错!", e);
        }
    }

黑白化后的图片转pdf

public static String imgToPdf(List<String> imageUrllist,String dirUrl,String PDFName) {
        try {
            String pdfUrl = null;
            if (StringUtils.isNotBlank(dirUrl)){
                pdfUrl = dirUrl + "/" + PDFName + "/" + PDFName + ".pdf";
            } else {
                pdfUrl = "D:/img" + "/" + PDFName + "/" + PDFName + ".pdf";
            }
            File file = img2Pdf(imageUrllist, pdfUrl);//生成pdf
            file.createNewFile();
            return pdfUrl;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static File img2Pdf(List<String> imageUrllist, String mOutputPdfFileName) {
        Document doc = new Document(PageSize.A4, 20, 20, 0, 20); //new一个pdf文档
        try {
            mOutputPdfFileName = mOutputPdfFileName;
            PdfWriter.getInstance(doc, new FileOutputStream(mOutputPdfFileName)); //pdf写入
            doc.open();//打开文档
            for (int i = 0; i < imageUrllist.size(); i++) {  //循环图片List,将图片加入到pdf中
                doc.newPage();  //在pdf创建一页
                com.itextpdf.text.Image png1 = com.itextpdf.text.Image.getInstance(imageUrllist.get(i)); //通过文件路径获取image
                float heigth = png1.getHeight();
                float width = png1.getWidth();
                int percent = getPercent2(heigth, width);
                png1.setAlignment(com.itextpdf.text.Image.MIDDLE);
                png1.scalePercent(percent+3);// 表示是原来图像的比例;
                doc.add(png1);
            }
            doc.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (DocumentException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        File mOutputPdfFile = new File(mOutputPdfFileName);  //输出流
        if (!mOutputPdfFile.exists()) {
            mOutputPdfFile.deleteOnExit();
            return null;
        }
        return mOutputPdfFile; //返回文件输出流
    }
 	public static int getPercent2(float h, float w) {
        int p = 0;
        float p2 = 0.0f;
        p2 = 530 / w * 100;
        p = Math.round(p2);
        return p;
    }

效果对比

java的PDF文件转图片空白 java pdf转图片不清晰_java

java的PDF文件转图片空白 java pdf转图片不清晰_List_02

黑化后的效果还是很理想的,基本能解决我的问题。
本人 小白一枚、记录下我的第一篇博客····