如何在java中实现类似pdf渲染的网页浏览器?
How to achieve a web browser like pdf rendering in java?
我目前正在尝试做一个 pdf 编写器应用程序,最终用户可以在 pdf 文件上绘制(线条/形状或文本)。我正在使用 pdfbox 将 pdf 文件显示到 java swing 组件,如 jPanel。 pdfbox 的问题是它在渲染 pdf 文件方面很慢,因为它使用 bufferedImage 然后绘制到 jPanel。该文件的分辨率也很差,我无法缩放文件 in/out。
我想为我的 pdf 文件实现一个类似 web 浏览器的显示。
谢谢。
使用 pdfbox 将 pdf 转换为 bufferedImage 的代码。
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.ImageType;
import org.apache.pdfbox.rendering.PDFRenderer;
public class Parse {
private static File file;
private int imageWidth;
private int imageHeight;
public Parse(File file) {
this.file = file;
}
public BufferedImage getPage(int pageIndex) throws IOException {
PDDocument pdf = PDDocument.load(file);
Float realWidth = new Float(pdf.getPage(0).getMediaBox().getWidth());
Float realHeight = new
Float(pdf.getPage(0).getMediaBox().getHeight());
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
Double ratio = .8;
imageHeight = (int) (screenSize.getHeight() * ratio);
imageWidth = (int) ((imageHeight * realWidth) / realHeight);
PDFRenderer renderer = new PDFRenderer(pdf);
BufferedImage renderImage = renderer.renderImage(pageIndex, 1, ImageType.RGB);
pdf.close();
return renderImage;
}
public int getImageWidth() {
return imageWidth;
}
public void setImageWidth(int imageWidth) {
this.imageWidth = imageWidth;
}
public int getImageHeight() {
return imageHeight;
}
public void setImageHeight(int imageHeight) {
this.imageHeight = imageHeight;
}
}
将图像绘制到 JPanel 的代码。
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
public class PDFPanel extends JPanel {
private Image image;
private int width;
private int height;
public PDFPanel(Image image, int width, int height) {
this.image = image;
this.width = width;
this.height = height;
setBorder(new EmptyBorder(0, 0, 0, 0));
setSize(width, height);
}
@Override
protected void paintComponent(Graphics graphics) {
super.paintComponent(graphics);
Graphics2D graphics2D = (Graphics2D) graphics;
graphics2D.drawImage(image, 0, 0, width, height, null);
}
}
根据问题 PDFBOX-3359 中提交的代码,下面是使用 PDFBox 2.0 在 JPanel 中显示 PDF 的一些代码。它不会缩放,但可以改变大小。它仍然会很慢,window 越大,速度越慢。
public class PDFBox3359PanelTestEnhanced
{
private static JPanel getTestPanel()
{
final PDDocument doc;
try
{
doc = PDDocument.load(new File("XXXXX.pdf"));
}
catch (IOException e)
{
e.printStackTrace();
return null;
}
final PDFRenderer renderer = new PDFRenderer(doc);
JPanel panel = new JPanel()
{
int i;
@Override
protected void paintComponent(Graphics g)
{
try
{
g.setColor(Color.red);
g.fillRect(0, 0, getWidth(), getHeight());
PDPage page = doc.getPage(0);
PDRectangle cropBox = page.getCropBox();
boolean rot = false;
if (page.getRotation() == 90 || page.getRotation() == 270)
{
rot = true;
}
//
float imgWidth = rot ? cropBox.getHeight() : cropBox.getWidth();
float imgHeight = rot ? cropBox.getWidth() : cropBox.getHeight();
float xf = getWidth() / imgWidth;
float yf = getHeight() / imgHeight;
float scale = Math.min(xf, yf);
if (yf < xf)
{
g.translate((int) ((getWidth() - imgWidth * yf) / 2), 0);
}
else
{
g.translate(0, (int) ((getHeight() - imgHeight * xf) / 2));
}
renderer.renderPageToGraphics(0, (Graphics2D) g, scale);
}
catch (IOException e)
{
e.printStackTrace();
}
}
};
return panel;
}
public static void main(String[] args) throws Exception
{
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.add(getTestPanel());
frame.pack();
frame.setSize(600, 400);
Dimension paneSize = frame.getSize();
Dimension screenSize = frame.getToolkit().getScreenSize();
frame.setLocation((screenSize.width - paneSize.width) / 2, (screenSize.height - paneSize.height) / 2);
frame.setTitle("Test");
frame.setVisible(true);
}
});
}
}
我目前正在尝试做一个 pdf 编写器应用程序,最终用户可以在 pdf 文件上绘制(线条/形状或文本)。我正在使用 pdfbox 将 pdf 文件显示到 java swing 组件,如 jPanel。 pdfbox 的问题是它在渲染 pdf 文件方面很慢,因为它使用 bufferedImage 然后绘制到 jPanel。该文件的分辨率也很差,我无法缩放文件 in/out。
我想为我的 pdf 文件实现一个类似 web 浏览器的显示。
谢谢。
使用 pdfbox 将 pdf 转换为 bufferedImage 的代码。
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.ImageType;
import org.apache.pdfbox.rendering.PDFRenderer;
public class Parse {
private static File file;
private int imageWidth;
private int imageHeight;
public Parse(File file) {
this.file = file;
}
public BufferedImage getPage(int pageIndex) throws IOException {
PDDocument pdf = PDDocument.load(file);
Float realWidth = new Float(pdf.getPage(0).getMediaBox().getWidth());
Float realHeight = new
Float(pdf.getPage(0).getMediaBox().getHeight());
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
Double ratio = .8;
imageHeight = (int) (screenSize.getHeight() * ratio);
imageWidth = (int) ((imageHeight * realWidth) / realHeight);
PDFRenderer renderer = new PDFRenderer(pdf);
BufferedImage renderImage = renderer.renderImage(pageIndex, 1, ImageType.RGB);
pdf.close();
return renderImage;
}
public int getImageWidth() {
return imageWidth;
}
public void setImageWidth(int imageWidth) {
this.imageWidth = imageWidth;
}
public int getImageHeight() {
return imageHeight;
}
public void setImageHeight(int imageHeight) {
this.imageHeight = imageHeight;
}
}
将图像绘制到 JPanel 的代码。
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
public class PDFPanel extends JPanel {
private Image image;
private int width;
private int height;
public PDFPanel(Image image, int width, int height) {
this.image = image;
this.width = width;
this.height = height;
setBorder(new EmptyBorder(0, 0, 0, 0));
setSize(width, height);
}
@Override
protected void paintComponent(Graphics graphics) {
super.paintComponent(graphics);
Graphics2D graphics2D = (Graphics2D) graphics;
graphics2D.drawImage(image, 0, 0, width, height, null);
}
}
根据问题 PDFBOX-3359 中提交的代码,下面是使用 PDFBox 2.0 在 JPanel 中显示 PDF 的一些代码。它不会缩放,但可以改变大小。它仍然会很慢,window 越大,速度越慢。
public class PDFBox3359PanelTestEnhanced
{
private static JPanel getTestPanel()
{
final PDDocument doc;
try
{
doc = PDDocument.load(new File("XXXXX.pdf"));
}
catch (IOException e)
{
e.printStackTrace();
return null;
}
final PDFRenderer renderer = new PDFRenderer(doc);
JPanel panel = new JPanel()
{
int i;
@Override
protected void paintComponent(Graphics g)
{
try
{
g.setColor(Color.red);
g.fillRect(0, 0, getWidth(), getHeight());
PDPage page = doc.getPage(0);
PDRectangle cropBox = page.getCropBox();
boolean rot = false;
if (page.getRotation() == 90 || page.getRotation() == 270)
{
rot = true;
}
//
float imgWidth = rot ? cropBox.getHeight() : cropBox.getWidth();
float imgHeight = rot ? cropBox.getWidth() : cropBox.getHeight();
float xf = getWidth() / imgWidth;
float yf = getHeight() / imgHeight;
float scale = Math.min(xf, yf);
if (yf < xf)
{
g.translate((int) ((getWidth() - imgWidth * yf) / 2), 0);
}
else
{
g.translate(0, (int) ((getHeight() - imgHeight * xf) / 2));
}
renderer.renderPageToGraphics(0, (Graphics2D) g, scale);
}
catch (IOException e)
{
e.printStackTrace();
}
}
};
return panel;
}
public static void main(String[] args) throws Exception
{
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.add(getTestPanel());
frame.pack();
frame.setSize(600, 400);
Dimension paneSize = frame.getSize();
Dimension screenSize = frame.getToolkit().getScreenSize();
frame.setLocation((screenSize.width - paneSize.width) / 2, (screenSize.height - paneSize.height) / 2);
frame.setTitle("Test");
frame.setVisible(true);
}
});
}
}