1.引入依赖
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>1.8.2</version>
</dependency>
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>fontbox</artifactId>
<version>1.8.2</version>
</dependency>
2.实现获取PDF指定页的流处理工具
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriter;
import javax.imageio.stream.ImageOutputStream;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
public class PDFSavePNG {
public static void main(String[] args) throws IOException {
convertPdf2Image("c:/temp/test.pdf");
// try
// {
// // 打开来源 pdf
// PDDocument pdfDocument = PDDocument.load(new File("c:/temp/aaa.pdf"));
// PDFRenderer pdfRenderer = new PDFRenderer(pdfDocument);
//
// // 提取的页码
// int pageNumber = 1;
// // 以300 dpi 读取存入 BufferedImage 对象
// int dpi = 300;
// BufferedImage buffImage = pdfRenderer.renderImageWithDPI(0, dpi, ImageType.RGB);
// System.out.println(buffImage);
// BufferedImage buffImage2 = pdfRenderer.renderImageWithDPI(1, dpi, ImageType.RGB);
// BufferedImage buffImage3 = pdfRenderer.renderImageWithDPI(2, dpi, ImageType.RGB);
// // 将 BufferedImage 写入到 png
// ImageIOUtil.writeImage(buffImage, "c:/temp/xx1.png", dpi);
// ImageIOUtil.writeImage(buffImage2, "c:/temp/xx2.png", dpi);
// ImageIOUtil.writeImage(buffImage3, "c:/temp/xx3.png", dpi);
//
// // 关闭文档
// pdfDocument.close();
// }
// catch (InvalidPasswordException e)
// {
// e.printStackTrace();
// }
// catch (IOException e)
// {
// e.printStackTrace();
// }
}
public static void convertPdf2Image(String pdfFilePath)
throws IOException
{
File pdfFile = new File(pdfFilePath);
File imageFileParent = new File(pdfFile.getParent());
OutputStream output = null;
PDDocument pdDoc = null;
List<File> files = new ArrayList<File>();
try{
if(pdfFile.exists()){
if(!imageFileParent.exists()){
imageFileParent.mkdirs();
}
pdDoc = PDDocument.load(pdfFile);
int pageCount = pdDoc.getNumberOfPages();
List pages = pdDoc.getDocumentCatalog().getAllPages();
for(int i = 0; i < pages.size(); i++){
PDPage page = (PDPage)pages.get(i);
BufferedImage image = page.convertToImage();
Iterator iter = ImageIO.getImageWritersBySuffix("jpg");
ImageWriter writer = (ImageWriter)iter.next();
File tempFile = new File(imageFileParent.getPath(),"xx" + i + ".jpg");
files.add(tempFile);
output = new FileOutputStream(tempFile);
ImageOutputStream imageOut = ImageIO.createImageOutputStream(output);
writer.setOutput(imageOut);
writer.write(new IIOImage(image,null,null));
output.close();
}
pdDoc.close();
// mergeMultiImageFiles(files,imageFile);//合并多张图片为一张图片
}
}finally{
try{
if(pdDoc != null){
pdDoc.close();
}
if(output != null){
output.close();
}
}catch(IOException e){
e.printStackTrace();
}
}
}
}
3.实现业务实际的业务处理,以及将文件输出
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.imageio.ImageIO;
import lombok.extern.slf4j.Slf4j;
import org.apache.pdfbox.io.RandomAccessBuffer;
import org.apache.pdfbox.pdfparser.PDFParser;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Slf4j
@Service
public class ServiceImpl {
/**
* 处理PDF预览图
*/
@Override
public void dealPDF(String url) {
try {
log.info("[处理PDF预览图] 开始处理文档 startTime:{}", JsonUtil.toJson(new Date()));
InputStream io = getIOByURL(url);
// 加载pdf文档
PDFParser parser = new PDFParser(new RandomAccessBuffer(io));
parser.parse();
PDDocument pdDocument = parser.getPDDocument();
// PDF文档渲染对象,在rendering包
PDFRenderer renderer = new PDFRenderer(pdDocument);
// 读取pdf页数
int pageCount = pdDocument.getNumberOfPages();
uploadPreview(i, renderer, previewlist);
pdDocument.close();
io.close();
log.info("[处理PDF预览图] 结束处理文档 endTime:{}", JsonUtil.toJson(new Date()));
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 通过URL获取文件流
*/
private InputStream getIOByURL(String fileUrl) throws IOException {
log.info("[获取COS上PDF的IO流] 入参 fileUrl:{}", JsonUtil.toJson(fileUrl));
// 从文件链接里获取文件流
URL url = new URL(fileUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
// 设置超时间为3秒
conn.setConnectTimeout(3 * 1000);
// 防止屏蔽程序抓取而返回403错误
conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
// 得到输入流
InputStream io = conn.getInputStream();
return io;
}
/**
* 上传预览图
*/
private void uploadPreview(PDFRenderer renderer) throws IOException {
log.info("[上传预览图] 入参 i:{},previewlist:{}", i, JsonUtil.toJson(previewlist));
// 保存预览图
BufferedImage image = renderer.renderImage(i, 1.9f);
// 将生成图片放在outStream
ByteArrayOutputStream outStream =new ByteArrayOutputStream();
ImageIO.write(image, "JPG", outStream);
System.out.println(outStream.toByteArray());
String path = uploadService.uploadByByte(outStream.toByteArray());
log.info("[上传预览图] 返回预览图路径 path:{}", path);
}
}
以下为对分割出来的图片进行合并的处理代码
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
import javax.imageio.ImageIO;
public class Test {
public static void main(String[] args) throws Exception {
List<File> files = new ArrayList<>();
File file1 = new File("F:/worksoft/test/111.png");
File file2 = new File("F:/worksoft/test/222.png");
File file3 = new File("F:/worksoft/test/111.png");
String path = "F:/worksoft/test/111+222.jpg";
file1 = compressImage(ImageIO.read(file1),
ImageIO.read(file1).getWidth()/2, ImageIO.read(file1).getHeight()/2);
file2 = compressImage(ImageIO.read(file2),
ImageIO.read(file2).getWidth()/2, ImageIO.read(file2).getHeight()/2);
files.add(file1);
files.add(file2);
files.add(file3);
files = mergeHorizontal(files, path);
mergeVertical(files, "F:/worksoft/test/111+222+333.jpg");
}
//竖向合成
public static void mergeVertical(List<File> files, String path) {
try {
Integer allWidth = 0; //计算画布总宽
Integer allHeight = 0; //计算画布总高
List<BufferedImage> imgs = new ArrayList<>();
for (int i = 0; i < files.size(); i++) {
imgs.add(ImageIO.read(files.get(i)));
//因为是竖向合成,拿图片里最大的一个宽度就行
allWidth = Math.max(allWidth, imgs.get(i).getWidth());
allHeight += imgs.get(i).getHeight();
}
BufferedImage combined = new BufferedImage(allWidth, allHeight, BufferedImage.TYPE_INT_RGB);
Graphics g = combined.getGraphics();
//设置画布背景颜色 ,默认黑色
g.setColor(Color.white);
g.fillRect(0, 0, allWidth, allHeight);
Integer height = 0;
for (int i = 0; i < imgs.size(); i++) {
g.drawImage(imgs.get(i), 0, height, null);
//+10为了设置上下两个图片间距
height += imgs.get(i).getHeight();
}
ImageIO.write(combined, "jpg", new File(path));
System.out.println("===合成成功====");
} catch (Exception e) {
System.out.println("===合成失败====");
e.printStackTrace();
}
}
//横向合成
public static List<File> mergeHorizontal(List<File> files, String path) {
try {
Integer allWidth = 0;
Integer allHeight = 0;
List<BufferedImage> imgs = new ArrayList<>();
for (int i = 0; i < 2; i++) {
imgs.add(ImageIO.read(files.get(i)));
allHeight = Math.max(allHeight, imgs.get(i).getHeight());
allWidth += imgs.get(i).getWidth();
}
BufferedImage combined = new BufferedImage(allWidth, allHeight, BufferedImage.TYPE_INT_RGB);
Graphics g = combined.getGraphics();
g.setColor(Color.white);
g.fillRect(0, 0, allWidth, allHeight);
Integer width = 0;
for (int i = 0; i < 2; i++) {
g.drawImage(imgs.get(i), width, 0, null);
//设置横向间距
width += imgs.get(i).getWidth();
}
int i = 2;
while (i > 0) {
files.remove(0);
i--;
}
File newFile = new File("F:/worksoft/test/111+222.jpg");
ImageIO.write(combined, "jpg", newFile);
files.add(newFile);
files.add(newFile);
System.out.println("===合成成功====");
} catch (Exception e) {
System.out.println("===合成失败====");
e.printStackTrace();
}
return files;
}
//字符串类型图片转换
public static BufferedImage base64StringToImg(String base64String) {
try {
byte[] bytes = Base64.getDecoder().decode(base64String);
ByteArrayInputStream in = new ByteArrayInputStream(bytes);
return ImageIO.read(in);
} catch (final IOException ioe) {
throw new UncheckedIOException(ioe);
}
}
/**
* * 将图片按照指定的图片尺寸压缩
* @param new_w :压缩后的图片宽
* @param new_h :压缩后的图片高
*/
public static File compressImage(BufferedImage bufferedImage,
int new_w, int new_h) throws IOException {
return disposeImage(bufferedImage, new_w, new_h);
}
/**
* 图片文件读取
* @param srcImgPath
* @return
*/
private static BufferedImage InputImage(String srcImgPath) {
BufferedImage srcImage = null;
try {
FileInputStream in = new FileInputStream(srcImgPath);
srcImage = javax.imageio.ImageIO.read(in);
} catch (IOException e) {
System.out.println("读取图片文件出错!" + e.getMessage());
e.printStackTrace();
}
return srcImage;
}
/**
* 处理图片
*/
private synchronized static File disposeImage(BufferedImage src, int new_w, int new_h) throws IOException {
// 得到图片
int old_w = src.getWidth();
// 得到源图宽
int old_h = src.getHeight();
// 得到源图长
BufferedImage newImg = null;
// 判断输入图片的类型
switch (src.getType()) {
case 13:
// png,gifnewImg = new BufferedImage(new_w, new_h,
// BufferedImage.TYPE_4BYTE_ABGR);
break;
default:
newImg = new BufferedImage(new_w, new_h, BufferedImage.TYPE_INT_RGB);
break;
}
Graphics2D g = newImg.createGraphics();
// 从原图上取颜色绘制新图
g.drawImage(src, 0, 0, old_w, old_h, null);
g.dispose();
// 根据图片尺寸压缩比得到新图的尺寸
newImg.getGraphics().drawImage(
src.getScaledInstance(new_w, new_h, Image.SCALE_SMOOTH), 0, 0,
null);
// 调用方法输出图片文件
File newFile = new File("F:/worksoft/test/111_yasuo.jpg");
ImageIO.write(newImg, "jpg", newFile);
return newFile;
}
/**
* 将图片文件输出到指定的路径,并可设定压缩质量
*/
private static void OutImage(String outImgPath, BufferedImage newImg) {
// 判断输出的文件夹路径是否存在,不存在则创建
File file = new File(outImgPath);
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}// 输出到文件流
try {
ImageIO.write(newImg,
outImgPath.substring(outImgPath.lastIndexOf(".") + 1),
new File(outImgPath));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}