我已经设法使用Apache的Javafx和PDFbox将文本放入pdf文件中。现在,我正在尝试将拍摄场景屏幕截图的图像放入pdf文档中。
WritableImage snapshot = quotes.getScene().snapshot(null);
PDDocument doc = null;
PDPage page = null;
PDXObjectImage ximg = null;
BufferedImage bufferedImg = SwingFXUtils.fromFXImage(snapshot, null);
try{
doc = new PDDocument();
page = new PDPage();
doc.addPage(page);
PDPageContentStream content = new PDPageContentStream(doc, page);
/* ByteArrayOutputStream out = new ByteArrayOutputStream();
InputStream in = new ByteArrayInputStream(out.toByteArray());*/
ximg = new PDJpeg(doc, bufferedImg);
//ximg = new PDJpeg(doc, in);
content.drawImage(ximg, 100, 100);
content.close();
doc.save("PDFWithText.pdf");
doc.close();
} catch (Exception e){
System.out.println(e);
}
当我使用InputStream和OutputStream类时,会创建文档,但当我打开文档时,Adobe和其他程序会给我一个错误,说Acrobat无法正确显示页面。当我使用上面代码中注释掉的BuffereImage类时,文档很简单,没有创建,我不知道为什么。
笔记
这是在JavaFX2.2中拍摄场景或部分场景的屏幕截图的后续问题,但特定于pdf创建部分,而不是节点快照部分。
通过将图像转换为PNG并首先将其写入Outputstream,然后将转换后的PNG从Outputstream读取到BuffereImage,我将快照转换为PDF格式。
最终的BufferedImage在PDJpeg中渲染良好,没有任何问题。
这是我的密码。
public static BufferedImage generate_png_from_container(Node node) {
SnapshotParameters param = new SnapshotParameters();
param.setDepthBuffer(true);
WritableImage snapshot = node.snapshot(param, null);
BufferedImage tempImg = SwingFXUtils.fromFXImage(snapshot, null);
BufferedImage img = null;
byte[] imageInByte;
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(tempImg, "png", baos);
baos.flush();
imageInByte = baos.toByteArray();
baos.close();
InputStream in = new ByteArrayInputStream(imageInByte);
img = ImageIO.read(in);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//the final image sent to the PDJpeg
return img;
}
这不是一个实际的解决方案(因为提供的代码不起作用),而是我试图解决问题的文档
我花了一些时间试图解决这个问题,但无法解决。我已经包含了我的解决方案的示例代码,因为它提供了一个SSCCE和方法,可以帮助其他试图解决这个问题的人。
我尝试的两种方法是:
>
这种方法不起作用,因为SwingFXUtils创建的BuffereImage是使用SampleModel编码的,该SampleModel与pdfbox api所需的不兼容。
通过JavaFX方法SwingFXUtils.fromFXImage从BufferedImage输出创建Jpeg流(使用ImageIO),并将其用作pdfbox api的输入。
这种方法不起作用。失败的原因可能是ImageIO从SwingFXUtils创建的BuffereImage创建了粉色(即编码错误的)JPEG。这可能是ImageIO中的一个错误。此外,我使用pdfbox将结果图像添加到jpeg中的方式可能存在缺陷。
正式建议
还有许多其他API可以从JavaFX创建PDF文件。与其继续解决JavaFX与pdfbox输出的图像集成问题,我建议尝试使用其他任何API来执行创建pdf文件的任务(谷歌搜索会发现它们)。
可执行示例代码
import javafx.application.Application;
import javafx.embed.swing.SwingFXUtils;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import org.apache.pdfbox.exceptions.COSVisitorException;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.edit.PDPageContentStream;
import org.apache.pdfbox.pdmodel.graphics.xobject.PDJpeg;
import org.apache.pdfbox.pdmodel.graphics.xobject.PDXObjectImage;
import javax.imageio.ImageIO;
import javax.imageio.stream.ImageOutputStream;
import java.awt.image.*;
import java.io.*;
import java.nio.file.Paths;
import java.util.Arrays;
// #### THIS CODE CURRENTLY DOES NOT FUNCTION CORRECTLY - SEE INLINE COMMENTS IN THE CODE TO UNDERSTAND WHY ####
//
// Demonstrates converting a JavaFX SceneGraph to a pdf (just as a bitmapped image, not as vector graphics).
// 1. creating a snapshot of a JavaFX node.
// 2. creating a pdf from the snapshot (using apache pdfbox http://pdfbox.apache.org/).
// 3. saving the pdf to a file.
// 4. opening the saved pdf in a web browser so the web browser can trigger showing
// the pdf in an appropriate pdf viewer (if the user has such a viewer installed).
public class PdfWithImageCreator extends Application {
// icon courtesy of http://www.aha-soft.com/ not for commercial use (free for non-commercial use).
private static final String imageURL =
"http://icons.iconarchive.com/icons/aha-soft/free-global-security/512/Global-Network-icon.png";
private static final String PDF_PATH =
Paths.get("exported.pdf").toAbsolutePath().toString();
@Override public void start(Stage stage) {
VBox layout = new VBox(20);
ImageView imageView = new ImageView(
new Image(imageURL)
);
Button export = new Button("Export");
export.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent actionEvent) {
exportToPDF(layout, PDF_PATH);
}
});
layout.setStyle("-fx-font-size: 20px;");
layout.setAlignment(Pos.CENTER);
layout.setPadding(new Insets(20));
layout.getChildren().setAll(
export,
imageView
);
stage.setScene(
new Scene(
new Group(
layout
)
)
);
stage.show();
}
/**
* Snapshots the provided node.
* Encodes the snapshot in a pdf.
* Saves the pdf to the provided file path.
* Opens the pdf in the default system web browser.
*
* @param node the node for which the snapshot is to be taken.
* @param filePath the path where the pdf is to be saved.
*/
private void exportToPDF(Node node, String filePath){
PDDocument doc = null;
PDPage page = null;
PDPageContentStream content = null;
PDXObjectImage ximage = null;
try {
// snapshot the node and convert it to an awt buffered image.
Image fxImage = node.snapshot(null, null);
BufferedImage bufferedImage = SwingFXUtils.fromFXImage(fxImage, null);
// create a pdf containing the snapshot image.
doc = new PDDocument();
page = new PDPage();
doc.addPage(page);
content = new PDPageContentStream(doc, page);
// alternate path A => try to create a PDJpeg from a jpegInputStream.
ximage = createPDJpegFromJpegStream(doc, bufferedImage);
// alternate path B => try to create a PDJpeg from directly from a BufferedImage directly.
// ximage = createPDJpegFromBufferedImage(doc, bufferedImage);
content.drawImage(ximage, 0, 0);
content.close();
// save the created image to disk.
doc.save(filePath);
System.out.println("Exported PDF to: " + filePath);
// show the generated pdf in a web browser.
// (if the browser is pdf enabled, this will display the pdf in the web browser).
getHostServices().showDocument(filePath);
} catch(IOException | COSVisitorException ie) {
ie.printStackTrace();
} finally {
try {
if (content != null) { content.close(); }
if (doc != null) { doc.close(); }
} catch (IOException e) {
e.printStackTrace();
}
}
}
// #### THIS METHOD DOES NOT FUNCTION AS EXPECTED
// alternate path => try to create a PDJpeg from a jpegInputStream.
// when using a jpeg stream this doesn't work, the created pdf is not well formed and
// you end up with adobe pdf reader running out of memory trying to read the resultant pdf.
// Also outputs a weird message that I currently don't understand =>
// INFO: About to return NULL from unhandled branch. filter = COSName{DCTDecode}
private PDXObjectImage createPDJpegFromJpegStream(PDDocument doc, BufferedImage bufferedImage) throws IOException {
// provide the buffered image data as input to a jpeg input stream.
ByteArrayOutputStream jpegOutputStream = new ByteArrayOutputStream();
ImageOutputStream jpegImageOutputStream = ImageIO.createImageOutputStream(jpegOutputStream);
ImageIO.write(bufferedImage, "jpeg", jpegImageOutputStream);
InputStream jpegInputStream = new ByteArrayInputStream(
Arrays.copyOf(jpegOutputStream.toByteArray(), jpegOutputStream.size())
);
// output created jpg file for debugging purposes
// => when you view it is pink due to (I believe) an ImageIO bug.
// you can see how the resultant image is pink by opening the image file named in system.out in any image viewer.
// this improper encoding of the jpeg data may be why the subsequent use of it to generate a pdf
// will generate a an invalid pdf.
File file = new File("output.jpg");
FileOutputStream fos = new FileOutputStream(file);
fos.write(Arrays.copyOf(jpegOutputStream.toByteArray(), jpegOutputStream.size()));
System.out.println(file.getAbsolutePath());
return new PDJpeg(doc, jpegInputStream);
}
// #### THIS METHOD DOES NOT FUNCTION AS EXPECTED
// alternate path => try to create a PDJpeg from directly from a BufferedImage directly, get the following exception:
// Exception in thread "JavaFX Application Thread" java.lang.IllegalArgumentException: Raster IntegerInterleavedRaster: width = 552 height = 616 #Bands = 1 xOff = 0 yOff = 0 dataOffset[0] 0 is incompatible with ColorModel ColorModel: #pixelBits = 8 numComponents = 1 color space = java.awt.color.ICC_ColorSpace@125fe1b6 transparency = 1 has alpha = false isAlphaPre = false
// at java.awt.image.BufferedImage.<init>(BufferedImage.java:630)
// Browsing the awt PDJpeg and awt code it appears that the BufferedImage returned by JavaFX uses a
// SinglePixelPackedSampleModel, but PDJpeg required the buffered image to use a ComponentColorModel
// and the two are incompatible. So the bufferedimage needs to be re-encoded to a compatible
// raster format that utilizes a SampleModel (i.e. a ComponentColorModel) that is acceptable by PDJpeg.
//
private PDXObjectImage createPDJpegFromBufferedImage(PDDocument doc, BufferedImage bufferedImage) throws IOException {
return new PDJpeg(doc, bufferedImage);
}
public static void main(String[] args) { launch(args); }
}
我正在使用iText生成Pdf。但当我试图在pdf中添加图像时, 我mage.get实例(新的URL(timetableResource.getImageUrl()));document.add(学校标志); 但我得到的错误是 HTTP状态500-服务器为URL返回了HTTP响应代码400:http://139.59.72.150:8080/sms/attachments/23/42/school
有人能给我举个例子,说明如何使用ApachePDFBox转换不同图像中的PDF文件(PDF的每一页对应一个图像)?
问题内容: 我正在尝试做一些非常简单的事情。我想在表中特定行的列中放置一个图标。如果是文件夹,则显示文件夹图标。如果是文件,则显示文件图标。 有人知道如何在JavaFX 2中执行此操作吗? 我已经尝试了很多事情,这似乎应该很简单,或者至少是某个地方的例子。 问题答案: 好吧,我有一个巨大的假时刻。原来我的图片网址路径错误。 我确实找到了一个网站,该网站提供了为表添加元素的绝佳示例。这帮助我了解了一
问题内容: 我想将PDF文档转换为图像。我正在使用Ghost4j。 问题: Ghost4J需要gsdll32.dll文件在运行时,我也 并不 想使用的DLL文件。 问题1: 在ghost4j中,有没有办法在没有dll的情况下转换图像? 问题2: 我在PDFBox API中找到了解决方案。convertToImage()将PDF页面转换为图像格式。 PDF文档上只有文本。运行此代码时出现该异常: 问
我想把PDF文档转换成图像。我用的是Ghost4j。 问题:Ghost4J需要gsdll32。dll文件,我不想使用dll文件。 问题1:是否有任何方法,在ghost4j转换图像没有dll? 问题2:我在PDFBox API中找到了解决方案<代码>组织。阿帕奇。pdfbox。pdmodel。PDPagep具有将PDF页面转换为图像格式的方法convertToImage()。 我只有PDF文档上的文
问题内容: 如何将图像放在特定位置的现有PDF文件上。pdf表示一张图纸页。图像将被缩放。我正在检查ReportLab,但找不到答案。谢谢。 问题答案: http://pybrary.net/pyPdf/: 我觉得就像,请参阅手册以获取更好的主意