I have a an SWT image I want to export this image into a pdf file using iText API.
I have tried saving this image on the disk and then using the path of image to export
it to the pdf, this takes lots of time to generate the pdf.
I have also tried converting the SWT image into AWT image and then exporting it into the
pdf, this approach takes even more time to generate pdf.
Another approach I have been trying is to convert the raw data of image into
jpeg byteArrayOutputStream using ImageLoader Object as shown below :
ImageLoader tempLoader = new ImageLoader();
tempLoader.data = new ImageData[] {
image.getImageData()
};
ByteArrayOutputStream bos = new ByteArrayOutputStream();
tempLoader.save(bos, SWT.IMAGE_JPEG);
Now I am using this ByteArrayOutputStream as input to
OutputStream outStream = new FileOutputStream(selectedPathAndName);
Document document = new Document();
document.setMargins(0,0,0,0);
document.setPageSize(new Rectangle(0,0,width,height));
PdfWriter.getInstance(document, outStream);
document.open();
com.itextpdf.text.Image pdfImage = com.itextpdf.text.Image.getInstance(bos.toByteArray());
document.add(pdfImage);
document.close();
This generates pdf files with the width and height I have set, but the page seems to be empty.
Any suggestions or any other approach is most welcome.
Thank you,
It looks your page sizes are zero, try setting them to something like A4 in the constructor.
Document document = new Document(PageSize.A4, 50, 50, 50, 50);
Related
I have a problem with converting from png/jpg to pdf ... Everytime I try to convert it the pdf document doesnt take the full size of the png/jpg photo like the photo below.. and this is my converting code.. I am using itextpdf lib.
Document document = new Document(PageSize.A4);
PdfWriter.getInstance(document, new FileOutputStream("C:\\AFKO Fatura\\fatura.pdf"));
document.open();
Image image2 = Image.getInstance("C:\\AFKO FATURA\\fatura.jpg");
document.add(image2);
document.close();`
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?
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();
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();
}
}
}
I am trying to read one PDF and copy its data into another PDF. The first PDF contains some text and images and I wish to write an image in the second PDF exactly where the text ends(which is basically the end of the PDF file). RIght now it just prints at the top. How can I make this change?
PdfReader reader = null;
reader = new PdfReader(Var.input);
Document document=new Document();
PdfWriter writer = null;
writer = PdfWriter.getInstance(document,new FileOutputStream(Var.output));
PdfImportedPage page = writer.getImportedPage(reader, 1);
reader.close();
document.open();
PdfContentByte cb = writer.getDirectContent();
// Copy first page of existing PDF into output PDF
document.newPage();
cb.addTemplate(page, 0, 0);
// Add your new data / text here
Image image = null;
image = Image.getInstance (Var.qr);
document.add(image);
document.close();
Try this:
First get the location/co-ords of where the image needs to go, then simply add the second line from below to your code so the image is inserted at that location "X, Y"
Image image = Image.getInstance(String RESOURCE);
image.setAbsolutePosition(X, Y);
writer.getDirectContent().addImage(image);
Take a look here for some examples in iText 5: https://itextpdf.com/en/resources/examples/itext-5-legacy/chapter-3-adding-content-absolute-positions
You should use a PdfStamper instead of a PdfWriter with imported pages. Your approach throws away all interactive contents. You can use sorifiend's idea there, too.
To determine where the text on the given page ends, have a look at the iText in Action, 2nd edition example ShowTextMargins which parses a PDF and ads a rectangle showing the text margin.
I am producing a PDF file in a HttpServlet with itText. Adding a Text on the canvas. If I open the url the PDF is shown correctly with the text. Also if I print it direclty from the browser, the text is visible on the printed paper. If I download the PDF on the other hand, the text not shown anymore (The image still is). The PDF can be viewed here: http://www.vegantastic.de/pdfTest
My code looks like this:
Document document = new Document();
// step 2
ByteArrayOutputStream baos = new ByteArrayOutputStream();
private PdfWriter writer = PdfWriter.getInstance(document, baos);
// step 3
document.open();
Font helvetica = new Font(FontFamily.TIMES_ROMAN, 12);
BaseFont bf_helv = helvetica.getCalculatedBaseFont(false);
PdfContentByte canvas = writer.getDirectContentUnder();
canvas.setFontAndSize(bf_helv, 12);
canvas.showTextAligned(Element.ALIGN_LEFT, "Test TEXT - Why is it missing after download?", 100, 800,0);
document.close();
// setting some response headers
response.setHeader("Expires", "0");
response.setHeader("Cache-Control",
"must-revalidate, post-check=0, pre-check=0");
response.setHeader("Pragma", "public");
// setting the content type
response.setContentType("application/pdf");
// the contentlength
response.setContentLength(baos.size());
// write ByteArrayOutputStream to the ServletOutputStream
OutputStream os = response.getOutputStream();
baos.writeTo(os);
os.flush();
os.close();
Is there any reasonable explanation for that or this this some kind of bug? Any way to resove this?
You aren't adding the text correctly. The PDF you are creating contains a serious syntax error. Some PDF viewers will ignore this syntax error and show the text anyway (which may be why you can print the PDF from a browser); others will not show anything because you are showing text outside a text object.
There are different ways to add text at an absolute position. One way is to create a text object yourself:
canvas.beginText();
canvas.setFontAndSize(bf_helv, 12);
canvas.showTextAligned(Element.ALIGN_LEFT, "Test TEXT - Why is it missing after download?", 100, 800,0);
canvas.endText();
In this case, you need to manually begin and end the text object. That's missing in your code.
Another way, is to have iText create the text object:
ColumnText.showTextAligned(canvas, Element.ALIGN_LEFT,
new Phrase("Test TEXT - Why is it missing after download?", new Font(bf_helv, 12)),
100, 800,0);
This single line is the equivalent of the four lines above.
Important note:
You are using this canvas:
PdfContentByte canvas = writer.getDirectContentUnder();
However: if your document contains opaque elements (an image, a colored rectangle,...), then whatever text you're adding will be covered by these opaque elements. Are you sure you don't want:
PdfContentByte canvas = writer.getDirectContent();
Try this
PdfContentByte canvas = writer.getDirectContentUnder();
canvas.saveState();
canvas.beginText();
canvas.setFontAndSize(bf_helv, 12);
canvas.showTextAligned(Element.ALIGN_LEFT, "Test TEXT - Why is it missing after download?", 100, 800,0);
canvas.endText();
canvas.restoreState();
I am trying to read one PDF and copy its data into another PDF. The first PDF contains some text and images and I wish to write an image in the second PDF exactly where the text ends(which is basically the end of the PDF file). RIght now it just prints at the top. How can I make this change?
PdfReader reader = null;
reader = new PdfReader(Var.input);
Document document=new Document();
PdfWriter writer = null;
writer = PdfWriter.getInstance(document,new FileOutputStream(Var.output));
PdfImportedPage page = writer.getImportedPage(reader, 1);
reader.close();
document.open();
PdfContentByte cb = writer.getDirectContent();
// Copy first page of existing PDF into output PDF
document.newPage();
cb.addTemplate(page, 0, 0);
// Add your new data / text here
Image image = null;
image = Image.getInstance (Var.qr);
document.add(image);
document.close();
Try this:
First get the location/co-ords of where the image needs to go, then simply add the second line from below to your code so the image is inserted at that location "X, Y"
Image image = Image.getInstance(String RESOURCE);
image.setAbsolutePosition(X, Y);
writer.getDirectContent().addImage(image);
Take a look here for some examples in iText 5: https://itextpdf.com/en/resources/examples/itext-5-legacy/chapter-3-adding-content-absolute-positions
You should use a PdfStamper instead of a PdfWriter with imported pages. Your approach throws away all interactive contents. You can use sorifiend's idea there, too.
To determine where the text on the given page ends, have a look at the iText in Action, 2nd edition example ShowTextMargins which parses a PDF and ads a rectangle showing the text margin.