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);//生成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;
}
效果对比
黑化后的效果还是很理想的,基本能解决我的问题。
本人 小白一枚、记录下我的第一篇博客····