java实现pdf黑白化
- 背景
- 研究方向选择
- 功能实现
- 依赖
- pdf转图片
- 图片黑白化
- 黑白化后的图片转pdf
- 效果对比
背景
最近开发办公系统,客户需求中有要求能使用传真机发传真。遇到问题:硬件方面,传真机只能发特定的tif文件,于是系统需要把客户上传的文件转成pdf,然后用Ghostscript 命令把pdf转成符合传真机要求的tif。因为客户方属于政府部门,一般上传的文件都是红头文件,在pdf转tif文件后,生成的tif文件所有的红色字体都看不清。下面是我的解决思路。
研究方向选择
解决这个问题无外乎有两种解决思路。
- 将pdf原件黑白化;
- 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);//生成pdffile.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)); //通过文件路径获取imagefloat 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;}
效果对比
黑化后的效果还是很理想的,基本能解决我的问题。
本人 小白一枚、记录下我的第一篇博客····