在实际应用中,需要把pdf文件转换图片,每页生成一张图片,试过PDFrenderer、pdfbox,jepdal,最终选择pdfbox和jepdal共同完成任务。
1、工具类的选择
pdfrenderer和pdfbox的缺点是不支持JBIG2Decode格式的pdf文件,对文本和中文都支持;而jepdal支持JBIG2Decode格式的pdf,不支持中文pdf文件;pdfbox有判断pdf文件的格式是否为JBIG2Decode,所以选用pdfbox。最后,利用pdfbox做主要的pdf转图片,jepdal完成对JBIG2Decode格式的pdf的转换。
jepdal有商业版和开源版,选开源版就足够了。
2、设计思路
接收pdf文件流,利用pdfbox判断PDF文件的压缩算法是否为JBIG2Decode,如果是调用jepdal,否则调用pdfbox进行转换;最后输出Image流。
3、依赖包
a) commons-io-1.4.jar
b) jpedal_lgpl.jar
c) pdfbox-app-1.6.0.jar
d) slf4j-api-1.5.6.jar
e) slf4j-jdk14-1.5.6.jar
4、代码示例
判断pdf文件的格式:
/**
* 判断PDF文件的压缩算法是否为JBIG2Decode
* @param
*/
private static boolean isJbig2(File file) throws IOException
{
//返回标志,默认为否
boolean isJbig2 = false;
//读pdf文件
PDDocument pdfDoc = PDDocument.load(file);
//生成COSDocument
COSDocument doc = pdfDoc.getDocument();
COSObject obj = doc.getObjectByType(COSName.XOBJECT);
if(obj != null)
{
COSBase base = obj.getDictionaryObject(COSName.FILTER);
String decode = base.toString();
if(decode.equals("COSName{JBIG2Decode}"))
{
isJbig2 = true;
}
}
doc.close();
pdfDoc.close();
return isJbig2;
}
调用pdfbox进行pdf文件转换:
private static List<BufferedImage> toImageProcess(File file) throws IOException
{
//读pdf文件
PDDocument pdDoc = PDDocument.load(file);
@SuppressWarnings("unchecked")
//获取pdf文件的所有PDpage
List<PDPage> pages = pdDoc.getDocumentCatalog().getAllPages();
//定义输出的Image
List<BufferedImage> bufImages = new ArrayList<BufferedImage>();
for(PDPage page : pages)
{
BufferedImage image;
try
{
//进行转换
image = page.convertToImage();
bufImages.add(image);
}
catch (IOException e)
{
e.printStackTrace();
}
}
pdDoc.close();
return bufImages;
}
调用jepdal对JBIG2Decode格式的pdf文件进行转换:
/**
* 针对JBIG2Decode格式的PDF文件的转换处理
* @param
*/
private static List<BufferedImage> toImageOfJbig2(String file) throws IOException, PdfException
{
PdfDecoder decodePdf = new PdfDecoder(true);
List<BufferedImage> bufImages = new ArrayList<BufferedImage>();
try
{
decodePdf.openPdfFile(file);
//PdfDecoder.setFontReplacements(decodePdf);
for(int i = 1; i <= decodePdf.getPageCount(); i++)
{
//设置转换参数
decodePdf.setPageParameters(1.8f, i);
//进行转换
BufferedImage img=decodePdf.getPageAsImage(i);
bufImages.add(img);
}
decodePdf.closePdfFile();
}
catch (PdfException e)
{
e.printStackTrace();
}
return bufImages;
}
对外的方法,对调用者来说,无需知道是用哪种工具类转换的。
代码:
/**
* PDF转换成图片
* @param pdfStream PDF文件流
* @return List<BufferedImage>
*/
public static List<BufferedImage> toImage(InputStream pdfStream) throws IOException, PdfException, SecurityException
{
//接收PDF流,生成临时文件
File tempFile = File.createTempFile("pdf2image", null);
String strFile = tempFile.toString();
byte[] data = IOUtils.toByteArray(pdfStream);
FileOutputStream fo = new FileOutputStream(tempFile);
fo.write(data);
fo.close();
List<BufferedImage> bufImages = new ArrayList<BufferedImage>();
//判断PDF算法格式
if(isJbig2(tempFile))
{
bufImages = toImageOfJbig2(strFile);
}
else
{
bufImages = toImageProcess(tempFile);
}
//删除临时文件
if(!tempFile.delete())
{
Logger logger = LoggerFactory.getLogger(PdfToImage.class);
logger.warn(tempFile.toString() + " -- This file is not deleted.");
}
return bufImages;
}
以上代码都是在同一个类里,类名定为PdfToImage。
5、测试
public class Demo
{
public static void main(String[] args) throws IOException, PdfException, InterruptedException
{
//设置需要转换的PDF文件
FileInputStream in = null;
File file = new File("D:\\temp\test2.pdf");
in = new FileInputStream(file);
//调用PdfToImage类的转换方法
List<BufferedImage> bufImages = new ArrayList<BufferedImage>();
bufImages = PdfToImage.toImage(in);
in.close();
//输出图片
int i = 1;
for(BufferedImage img : bufImages)
{
ImageIO.write(img, "png", new File("D:/temp/Image"+i+".png"));
i++;
}
}