背景:
前幾日一位朋友突然找我幫忙將PDF轉換成圖片,我仗義相助,建議他使用福昕閱讀器,然而他說轉換需要VIP會員,老貴了。我花了半天時間尋找免費會員,結果不出所料沒有找到,我一怒之下,便決定親自動手編寫一個簡易版的PDF轉圖片的小工具。
製作成功的作品如下圖所示,該工具可將PDF轉換成圖片:
現在,就介紹一下如何使用Java製作PDF轉圖片工具。
一、需求描述:
用戶指定PDF文件(包括掃描件)目錄以及轉成圖片後存放的目錄之後,點擊開始轉換按鈕即可將PDF文件全部轉換成圖片。一般轉換操作可放在桌面上進行,爲了方便,PDF地址以及圖片輸出地址均默認爲桌面。因爲轉換過程比較耗時,PDF文件頁數也可能比較多,因此提供一個進度條顯示轉換進度。
二、環境準備:
- JDK:1.8
- icePDF
PDF轉圖片離不開第三方架包,個人比較推薦使用icePDF。icePDF架包不好找,就用我的吧:點擊該鏈接免費下載icePDF,提取碼:2jax。該版本匹配JDK1.8,注意一定要與JDK版本匹配,否則運行會拋異常。
三、開發:
1、新建Java工程,命名爲testpdf,引入所需架包,並新建類:PDFToPNG.java。
2、PDFToPNG.java文件源碼:
package testpdf;
import java.awt.HeadlessException;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JProgressBar;
import javax.swing.JTextField;
import javax.swing.filechooser.FileNameExtensionFilter;
import org.icepdf.core.pobjects.Document;
import org.icepdf.core.util.GraphicsRenderingHints;
public class PDFToPNG extends JFrame {
private static final long serialVersionUID = 1L;
/** 頁面控件 */
// PDF地址輸入域
private static JTextField textFieldPdf;
// 圖片輸出地址輸入域
private static JTextField textFieldOut;
// 進度條
private static JProgressBar progressBar;
// 圖片輸出目錄顯示
private static JLabel labelOutShowPath;
/** 全局變量 */
// PDF文件絕對路徑
private static String inPath;
// 圖片輸出目錄
private static String outPath;
static {
// 初始化變量
outPath = "C:\\Users\\Administrator\\Desktop";
}
/**
* 無參構造方法
*/
public PDFToPNG() {
// 頁面控件相關尺寸
int frameWidth = 550;// 窗口寬度
int frameHeight = 200;// 窗口高度
this.setTitle("PDF轉圖片工具");// 窗口標題
this.setSize(frameWidth, frameHeight);
this.setResizable(false);// 設置固定窗口大小
this.setLocationRelativeTo(null);// 窗口顯示到屏幕中央
this.setLayout(null);// 設置佈局爲空,即可使用絕對位置
/** PDF地址 */
// PDF地址標籤
JLabel labelPdf = new JLabel(" PDF地址:");
labelPdf.setBounds(10, 10, 70, 25);
this.add(labelPdf);
// PDF地址文本輸入框
textFieldPdf = new JTextField();
textFieldPdf.setBounds(75, 10, 400, 25);
textFieldPdf.setText(outPath + "\\csmlshy.pdf");// 設置默認目錄
this.add(textFieldPdf);
// PDF地址瀏覽按鈕
JButton btnPdf = new JButton("瀏覽");
btnPdf.setBounds(475, 10, 60, 25);
this.add(btnPdf);
/** 圖片輸出地址 */
// 輸出地址
JLabel labelOut = new JLabel("輸出地址:");
labelOut.setBounds(10, 40, 70, 25);
this.add(labelOut);
// 輸出文本選擇框
textFieldOut = new JTextField();
textFieldOut.setBounds(75, 40, 400, 25);
textFieldOut.setText(outPath);
this.add(textFieldOut);
// 輸出地址瀏覽按鈕
JButton btnOut = new JButton("瀏覽");
btnOut.setBounds(475, 40, 60, 25);
this.add(btnOut);
/** 開始轉換按鈕 */
JButton btnToPng = new JButton("開始轉換");
btnToPng.setBounds(200, 70, 100, 30);
this.add(btnToPng);
/** 進度條 */
progressBar = new JProgressBar();
progressBar.setBounds(10, 110, 520, 18);
progressBar.setIndeterminate(false);// 設置進度條的樣式爲不確定的進度條樣式(進度條來回滾動),false爲確定的進度條樣式(即進度條從頭到尾顯示)
progressBar.setStringPainted(true);// 設置進度條顯示提示信息
progressBar.setString("0/0");// 設置提示信息
this.add(progressBar);
/** 輸出目錄顯示 */
// 輸出目錄
JLabel labelOutShow = new JLabel("輸出目錄:");
labelOutShow.setBounds(10, 140, 70, 25);
this.add(labelOutShow);
// 輸出目錄標籤顯示
labelOutShowPath = new JLabel(outPath);
labelOutShowPath.setBounds(80, 140, 320, 25);
this.add(labelOutShowPath);
// 打開輸出目錄按鈕
JButton btnOpenDir = new JButton("打開輸出目錄");
btnOpenDir.setBounds(410, 140, 120, 22);
this.add(btnOpenDir);
/** 按鈕點擊事件 */
// PDF地址瀏覽按鈕點擊事件
btnPdf.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
openFileWindow(e, textFieldPdf,
JFileChooser.FILES_AND_DIRECTORIES);
}
});
// 圖片地址瀏覽按鈕點擊事件
btnOut.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// 彈出文件選擇框,只能選擇目錄
openFileWindow(e, textFieldOut, JFileChooser.DIRECTORIES_ONLY);
}
});
// 開始轉換按鈕點擊事件
btnToPng.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
btnToPng_onclick(btnToPng);
}
});
// 打開文件所在位置按鈕點擊事件
btnOpenDir.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
btnOpenDir_onclick();
}
});
}
/**
* 開始轉換按鈕點擊事件
*/
protected void btnToPng_onclick(JButton btnToPng) {
// 校驗
if (!checkAll()) {
return;
}
// 生成轉換後的圖片目錄
String pdfName = new File(inPath).getName();
pdfName = pdfName.substring(0, pdfName.length() - 4);// 去掉後綴.pdf
labelOutShowPath.setText(outPath + "\\" + pdfName);
// 開始轉換PDF
Thread thread = new Thread(new Progress(progressBar, inPath, outPath,
btnToPng));
thread.start();
}
/**
* 打開文件所在位置按鈕點擊事件
*/
protected void btnOpenDir_onclick() {
try {
String dirpath = labelOutShowPath.getText();
if (new File(dirpath).exists()) {
final Runtime runtime = Runtime.getRuntime();
final String cmd = "rundll32 url.dll FileProtocolHandler file://"
+ dirpath;
runtime.exec(cmd);
return;
}
JOptionPane.showMessageDialog(null, "目錄不存在,請檢查!" + dirpath, "警告",
JOptionPane.ERROR_MESSAGE);
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
/**
* 瀏覽按鈕點擊事件
*/
public void openFileWindow(ActionEvent e, JTextField textField, int mode) {
JFileChooser chooser = new JFileChooser();
FileNameExtensionFilter filter = new FileNameExtensionFilter("PDF",
"pdf");// 過濾pdf外的文件
chooser.setFileFilter(filter);
chooser.setFileSelectionMode(mode);
chooser.showDialog(new JLabel(), "選擇");
File file = chooser.getSelectedFile();
if (file != null) {
textField.setText(file.getAbsoluteFile().toString());
}
}
/**
* 內部類
*/
public class Progress extends Thread {
private JProgressBar bar;
private JButton btnToPng;
private String inPath;
private String outPath;
public Progress(JProgressBar progressBar, String inPath,
String outPath, JButton btnToPng) {
this.bar = progressBar;
this.btnToPng = btnToPng;
this.inPath = inPath;
this.outPath = outPath;
}
public void run() {
btnToPng.setEnabled(false);
btnToPng.setText("正在轉換");
try {
Document document = new Document();
document.setFile(inPath);
float scale = 2.5f;// 縮放比例
float rotation = 0f;// 旋轉角度
File pdfFile = new File(inPath);
String pdfName = pdfFile.getName().substring(0,
pdfFile.getName().length() - 4);
File dirFile = new File(outPath + "/" + pdfName);
if (!dirFile.exists()) {
dirFile.mkdir();
} else {
JOptionPane.showMessageDialog(null, "己存在同名目錄,請檢查!"
+ dirFile.getAbsolutePath(), "警告",
JOptionPane.ERROR_MESSAGE);
return;
}
System.out.println("正在轉換...");
int totalPages = document.getNumberOfPages();
bar.setMaximum(totalPages);
for (int i = 0; i < totalPages; i++) {
bar.setValue(i + 1);
bar.setString((i + 1) + "/" + totalPages);
BufferedImage image = (BufferedImage) document
.getPageImage(
i,
GraphicsRenderingHints.SCREEN,
org.icepdf.core.pobjects.Page.BOUNDARY_CROPBOX,
rotation, scale);
RenderedImage rendImage = image;
try {
File file = new File(dirFile.getAbsolutePath() + "/"
+ pdfName + "_" + (i + 1) + ".png");
ImageIO.write(rendImage, "png", file);
} catch (IOException e) {
System.out.println(e.getMessage());
}
image.flush();
}
document.dispose();
bar.setString("轉換完成!");
} catch (HeadlessException e) {
System.out.println(e.getMessage());
} finally {
btnToPng.setEnabled(true);
btnToPng.setText("開始轉換");
}
}
}
/**
* 校驗
*/
protected boolean checkAll() {
// 校驗是否選擇
inPath = textFieldPdf.getText().trim();
outPath = textFieldOut.getText().trim();
if (inPath.length() == 0) {
JOptionPane.showMessageDialog(null, "請選擇PDF地址!", "警告",
JOptionPane.ERROR_MESSAGE);
return false;
}
if (outPath.length() == 0) {
JOptionPane.showMessageDialog(null, "請選擇輸出地址!", "警告",
JOptionPane.ERROR_MESSAGE);
return false;
}
// 校驗PDF地址是否正確
if (!new File(inPath).exists()) {
JOptionPane.showMessageDialog(null, "選定PDF文件不存在,請重新選擇!", "警告",
JOptionPane.ERROR_MESSAGE);
return false;
}
if (new File(inPath).isDirectory()) {
JOptionPane.showMessageDialog(null, "PDF地址不是PDF文件,請重新選擇!", "警告",
JOptionPane.ERROR_MESSAGE);
return false;
}
return true;
}
/**
* main方法
*/
public static void main(String[] args) {
PDFToPNG toPNG = new PDFToPNG();
toPNG.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
toPNG.setVisible(true);
}
}