Reputation: 257
So as the title says I am looking for a way to turn SVG to PNG with Apache Batik and then attach this image to PDF file using PDFBox without actually creating the svg and png anywhere.
Currently I have a web form that has SVG image with selectable parts of it.
When the form is submitted I take the "html" part of the svg meaning I keep something like <svg bla bla> <path bla bla/></svg>
in a string that Spring then uses to create a ".svg" file in a given folder, then Batik creates a PNG file in the same folder and then PDFBox attaches it to the PDF - this works fine(code below).
//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();
As you can see there are a lot of files and stuff (need to tidy it up a bit), but is it possible to do this on the run without the creation and constant fetching of the svg and png files?
Upvotes: 1
Views: 3750
Reputation: 106
Based on the comments and links provided by D.V.D., I also worked through the problem. I just wanted to post the simple but full example, for anyone wanting to review in the future.
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();
}
}
}
Upvotes: 0
Reputation: 257
Given the suggestion in the comments I opted for using ByteArrayOutputStream, ByteArrayInputStream, BufferedImage and LosslessFactory. Its a bit slower than the saving (if you go through it in debug as seems the BufferedImage goes on a holiday first before creating the image). The sources I found to use are: How to convert SVG into PNG on-the-fly and Print 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();
Upvotes: 1