【问题标题】:SVG to PNG with Apache Batik then attach to PDF with PDFBox without saving images使用 Apache Batik 将 SVG 转换为 PNG,然后使用 PDFBox 附加到 PDF 而不保存图像
【发布时间】:2018-10-18 13:26:18
【问题描述】:

正如标题所说,我正在寻找一种使用 Apache Batik 将 SVG 转换为 PNG 的方法,然后使用 PDFBox 将此图像附加到 PDF 文件,而无需在任何地方实际创建 svg 和 png。

目前我有一个包含 SVG 图像的 Web 表单,其中包含可选部分。 提交表单后,我会使用 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 文件的情况下在运行时执行此操作?

【问题讨论】:

  • BATIK 可以创建 BufferedImage 吗?您可以将它与 LosslessFactory 一起使用。
  • 如果没有,则使用 ByteArrayOutputStream 和 ByteArrayInputStream。
  • 另一种选择:stackoverflow.com/questions/31718075/… 那会更好,因为它会保留矢量图形,因此在任何分辨率下看起来都很棒。
  • @TilmanHausherr 感谢您的建议 - 认为我现在可以正常工作了

标签: java spring pdfbox batik


【解决方案1】:

鉴于 cmets 中的建议,我选择使用 ByteArrayOutputStream、ByteArrayInputStream、BufferedImage 和 LosslessFactory。它比保存慢一点(如果你在调试中通过它,似乎 BufferedImage 在创建图像之前先去度假)。 我发现使用的来源是:How to convert SVG into PNG on-the-flyPrint byte[] to pdf using pdfbox

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

【讨论】:

    【解决方案2】:

    根据D.V.D.提供的cmets和链接,我也解决了这个问题。我只是想发布一个简单但完整的示例,供任何想在未来查看的人使用。

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

    【讨论】:

      猜你喜欢
      • 2016-10-20
      • 2016-03-12
      • 1970-01-01
      • 1970-01-01
      • 2014-09-25
      • 1970-01-01
      • 1970-01-01
      • 2021-02-13
      相关资源
      最近更新 更多