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);

	}

}

  • 7
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值