Java製作PDF轉圖片小工具

背景

前幾日一位朋友突然找我幫忙將PDF轉換成圖片,我仗義相助,建議他使用福昕閱讀器,然而他說轉換需要VIP會員,老貴了。我花了半天時間尋找免費會員,結果不出所料沒有找到,我一怒之下,便決定親自動手編寫一個簡易版的PDF轉圖片的小工具。

        製作成功的作品如下圖所示,該工具可將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);

	}

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章