使用 Apache Batik 将 SVG 转换为 PNG,然后使用 PDFBox 附加到 PDF 而不保存图像
SVG to PNG with Apache Batik then attach to PDF with PDFBox without saving images
所以正如标题所说,我正在寻找一种方法,使用 Apache Batik 将 SVG 转换为 PNG,然后使用 PDFBox 将此图像附加到 PDF 文件,而无需在任何地方实际创建 svg 和 png。
目前我有一个 Web 表单,其中包含 SVG 图像以及其中的可选部分。
提交表单后,我采用 svg 的 "html" 部分,这意味着我将 <svg bla bla> <path bla bla/></svg>
之类的内容保存在字符串中,然后 Spring 用于在给定文件夹中创建“.svg”文件,然后 Batik 在同一文件夹中创建一个 PNG 文件,然后 PDFBox 将其附加到 PDF - 这工作正常(代码如下)。
//Get the svg data from the Form and Create the svg file
String svg = formData.getSvg();
File svgFile = new File("image.svg");
BufferedWriter writer = new BufferedWriter(new FileWriter(svgFile));
writer.write(svg);
writer.close();
// Send to Batik to turn to PNG
PNGTranscoder pngTranscode = new PNGTranscoder();
File svgFile = new File("image.svg");
InputStream in = new FileInputStream(svgFile);
TranscoderInput tIn = new TranscoderInput(in);
OutputStream os = new FileOutputStream("image.png");
TranscoderOutput tOut = new TranscoderOutput(os)
pngTranscode .transcode(tIn , tOut);
os.flush();
os.close();
//Send to PDFBox to attach to pdf
File pngfile = new File("image.png");
String path = pngfile.getAbsolutePath();
PDImageXObject pdImage = PDImageXObject.createFromFile(path, pdf);
PDPageContentStream contents = new PDPageContentStream(pdf, pdf.getPage(1));
contents.drawImage(pdImage, 0, pdf.getPage(1).getMediaBox().getHeight() - pdImage.getHeight());
contents.close();
如您所见,有很多文件和东西(需要稍微整理一下),但是是否可以在 运行 上执行此操作而无需创建和不断获取 svg和 png 文件?
鉴于评论中的建议,我选择使用 ByteArrayOutputStream、ByteArrayInputStream、BufferedImage 和 LosslessFactory。它比保存慢一点(如果你在调试中经历它,因为 BufferedImage 在创建图像之前似乎先去度假)。
我发现使用的来源是:How to convert SVG into PNG on-the-fly and
byte[] streamBytes = IOUtils.toByteArray(new ByteArrayInputStream(formData.getSvg().getBytes()));
PNGTranscoder pngTranscoder = new PNGTranscoder();
ByteArrayOutputStream os = new ByteArrayOutputStream();
pngTranscoder.transcode(new TranscoderInput(new ByteArrayInputStream(streamBytes)), new TranscoderOutput(os));
InputStream is = new ByteArrayInputStream(os.toByteArray());
BufferedImage bim = ImageIO.read(is);
PDImageXObject pdImage = LosslessFactory.createFromImage(pdf, bim);
PDPageContentStream contents = new PDPageContentStream(pdf, pdf.getPage(1));
contents.drawImage(pdImage, 0, pdf.getPage(1).getMediaBox().getHeight() - pdImage.getHeight());
contents.close();
根据 D.V.D. 提供的评论和链接,我也解决了这个问题。我只是想 post 这个简单但完整的例子,供以后想复习的任何人使用。
public class App {
private static String OUTPUT_PATH = "D:\so52875145\output\PdfWithPngImage.pdf";
public static void main(String[] args) {
try {
// obtain the SVG source (hardcoded here, but the OP would obtain the String from form data)
byte[] svgByteArray = "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"><polygon points=\"200,10 250,190 160,210\" style=\"fill:lime;stroke:purple;stroke-width:1\" /></svg>".getBytes();
System.out.println("Converted svg to byte array...");
// convert SVG into PNG image
PNGTranscoder pngTranscoder = new PNGTranscoder();
ByteArrayOutputStream os = new ByteArrayOutputStream();
pngTranscoder.transcode(new TranscoderInput(new ByteArrayInputStream(svgByteArray)), new TranscoderOutput(os));
System.out.println("Transcoded svg to png...");
// create PDF, and add page to it
PDDocument pdf = new PDDocument();
pdf.addPage(new PDPage());
// generate in-memory PDF image object, using the transcoded ByteArray stream
BufferedImage bufferedImage = ImageIO.read( new ByteArrayInputStream(os.toByteArray()) );
PDImageXObject pdImage = LosslessFactory.createFromImage(pdf, bufferedImage);
System.out.println("Created PDF image object...");
// write the in-memory PDF image object to the PDF page
PDPageContentStream contents = new PDPageContentStream(pdf, pdf.getPage(0));
contents.drawImage(pdImage, 0, 0);
contents.close();
System.out.println("Wrote PDF image object to PDF...");
pdf.save(OUTPUT_PATH);
pdf.close();
System.out.println("Saved PDF to path=[" + OUTPUT_PATH + "]");
}
catch (Exception e) {
e.printStackTrace();
}
}
}
所以正如标题所说,我正在寻找一种方法,使用 Apache Batik 将 SVG 转换为 PNG,然后使用 PDFBox 将此图像附加到 PDF 文件,而无需在任何地方实际创建 svg 和 png。
目前我有一个 Web 表单,其中包含 SVG 图像以及其中的可选部分。
提交表单后,我采用 svg 的 "html" 部分,这意味着我将 <svg bla bla> <path bla bla/></svg>
之类的内容保存在字符串中,然后 Spring 用于在给定文件夹中创建“.svg”文件,然后 Batik 在同一文件夹中创建一个 PNG 文件,然后 PDFBox 将其附加到 PDF - 这工作正常(代码如下)。
//Get the svg data from the Form and Create the svg file
String svg = formData.getSvg();
File svgFile = new File("image.svg");
BufferedWriter writer = new BufferedWriter(new FileWriter(svgFile));
writer.write(svg);
writer.close();
// Send to Batik to turn to PNG
PNGTranscoder pngTranscode = new PNGTranscoder();
File svgFile = new File("image.svg");
InputStream in = new FileInputStream(svgFile);
TranscoderInput tIn = new TranscoderInput(in);
OutputStream os = new FileOutputStream("image.png");
TranscoderOutput tOut = new TranscoderOutput(os)
pngTranscode .transcode(tIn , tOut);
os.flush();
os.close();
//Send to PDFBox to attach to pdf
File pngfile = new File("image.png");
String path = pngfile.getAbsolutePath();
PDImageXObject pdImage = PDImageXObject.createFromFile(path, pdf);
PDPageContentStream contents = new PDPageContentStream(pdf, pdf.getPage(1));
contents.drawImage(pdImage, 0, pdf.getPage(1).getMediaBox().getHeight() - pdImage.getHeight());
contents.close();
如您所见,有很多文件和东西(需要稍微整理一下),但是是否可以在 运行 上执行此操作而无需创建和不断获取 svg和 png 文件?
鉴于评论中的建议,我选择使用 ByteArrayOutputStream、ByteArrayInputStream、BufferedImage 和 LosslessFactory。它比保存慢一点(如果你在调试中经历它,因为 BufferedImage 在创建图像之前似乎先去度假)。
我发现使用的来源是:How to convert SVG into PNG on-the-fly and
byte[] streamBytes = IOUtils.toByteArray(new ByteArrayInputStream(formData.getSvg().getBytes()));
PNGTranscoder pngTranscoder = new PNGTranscoder();
ByteArrayOutputStream os = new ByteArrayOutputStream();
pngTranscoder.transcode(new TranscoderInput(new ByteArrayInputStream(streamBytes)), new TranscoderOutput(os));
InputStream is = new ByteArrayInputStream(os.toByteArray());
BufferedImage bim = ImageIO.read(is);
PDImageXObject pdImage = LosslessFactory.createFromImage(pdf, bim);
PDPageContentStream contents = new PDPageContentStream(pdf, pdf.getPage(1));
contents.drawImage(pdImage, 0, pdf.getPage(1).getMediaBox().getHeight() - pdImage.getHeight());
contents.close();
根据 D.V.D. 提供的评论和链接,我也解决了这个问题。我只是想 post 这个简单但完整的例子,供以后想复习的任何人使用。
public class App {
private static String OUTPUT_PATH = "D:\so52875145\output\PdfWithPngImage.pdf";
public static void main(String[] args) {
try {
// obtain the SVG source (hardcoded here, but the OP would obtain the String from form data)
byte[] svgByteArray = "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"><polygon points=\"200,10 250,190 160,210\" style=\"fill:lime;stroke:purple;stroke-width:1\" /></svg>".getBytes();
System.out.println("Converted svg to byte array...");
// convert SVG into PNG image
PNGTranscoder pngTranscoder = new PNGTranscoder();
ByteArrayOutputStream os = new ByteArrayOutputStream();
pngTranscoder.transcode(new TranscoderInput(new ByteArrayInputStream(svgByteArray)), new TranscoderOutput(os));
System.out.println("Transcoded svg to png...");
// create PDF, and add page to it
PDDocument pdf = new PDDocument();
pdf.addPage(new PDPage());
// generate in-memory PDF image object, using the transcoded ByteArray stream
BufferedImage bufferedImage = ImageIO.read( new ByteArrayInputStream(os.toByteArray()) );
PDImageXObject pdImage = LosslessFactory.createFromImage(pdf, bufferedImage);
System.out.println("Created PDF image object...");
// write the in-memory PDF image object to the PDF page
PDPageContentStream contents = new PDPageContentStream(pdf, pdf.getPage(0));
contents.drawImage(pdImage, 0, 0);
contents.close();
System.out.println("Wrote PDF image object to PDF...");
pdf.save(OUTPUT_PATH);
pdf.close();
System.out.println("Saved PDF to path=[" + OUTPUT_PATH + "]");
}
catch (Exception e) {
e.printStackTrace();
}
}
}