PDFBox v2 write PNG image to PDF file, getting empty file - java

I'm using PDFBox 2. Trying to write a PNG image file to new PDF file.
I saw there was already an answer that mention it was fixed on PDFBox2:
How to add .png images to pdf using Apache PDFBox and
https://issues.apache.org/jira/browse/PDFBOX-1990
This is my code:
package pdfProj;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.graphics.image.LosslessFactory;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
public class b {
public static void main(String[] args) {
PDDocument doc = null;
doc = new PDDocument();
doc.addPage(new PDPage());
try{
BufferedImage awtImage = ImageIO.read( new File( "c://temp//line_chart.png" ) );
PDImageXObject pdImageXObject = LosslessFactory.createFromImage(doc, awtImage);
PDPageContentStream contentStream = new PDPageContentStream(doc, new PDPage(), true, false);
contentStream.drawImage(pdImageXObject, 200, 300, awtImage.getWidth() / 2, awtImage.getHeight() / 2);
contentStream.close();
doc.save( "c://temp//pdf//PDF_image.pdf" );
doc.close();
} catch (Exception io){
System.out.println(" -- fail --" + io);
}
}
}
There is no exception. Just getting an empty PDF file created.

The issue is that you add a new page to the document
doc.addPage(new PDPage());
but then create a content stream for yet another new page which you don't add to the document:
PDPageContentStream contentStream = new PDPageContentStream(doc, new PDPage(), true, false);
You should create the content stream for the page you added to the document, e.g. like this:
PDDocument doc = null;
doc = new PDDocument();
PDPage page = new PDPage();
doc.addPage(page);
try{
BufferedImage awtImage = ImageIO.read( new File( "c://temp//line_chart.png" ) );
PDImageXObject pdImageXObject = LosslessFactory.createFromImage(doc, awtImage);
PDPageContentStream contentStream = new PDPageContentStream(doc, page, true, false);
contentStream.drawImage(pdImageXObject, 200, 300, awtImage.getWidth() / 2, awtImage.getHeight() / 2);
contentStream.close();
doc.save( "c://temp//pdf//PDF_image.pdf" );
doc.close();
} catch (Exception io){
System.out.println(" -- fail --" + io);
}

Related

Write text on image and convert into pdf in java?

I want to create a PDF using image and some text. here image used as mask and text set on different spatial place.
I already generate pdf using image but cannot write text on it.
Here is the image
And output
My code
import com.itextpdf.text.*;
import com.itextpdf.text.Image;
import com.itextpdf.text.pdf.PdfWriter;
import java.io.FileOutputStream;
import javax.swing.JFileChooser;
public class Test {
public static void main(String[] args) {
Document document = new Document(PageSize.A4_LANDSCAPE, 0, 0, 0, 0);
String input = "src/icon/orginal_pad.jpg"; // .gif and .jpg are ok too!
JFileChooser fileChooser = new JFileChooser();
if (fileChooser.showSaveDialog(null) == JFileChooser.APPROVE_OPTION) {
String filePath = fileChooser.getSelectedFile().getPath();
try {
FileOutputStream fos = new FileOutputStream(filePath);
PdfWriter writer = PdfWriter.getInstance(document, fos);
writer.open();
document.open();
Image im = Image.getInstance(input);
im.scaleToFit(PageSize.A4_LANDSCAPE.getWidth(), PageSize.A4_LANDSCAPE.getHeight());
document.add(im);
//code here
document.close();
writer.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}

Create 2nd Page in a PDF Document

I have written an android app to do inspections. It collects the data and then formats it and places it on a PDF document. I am having a problem creating a 2nd page of the PDF before I save it and email it. I have commented out "PAGE 2 OF PDF". This section of code up to the declaration of pdfName is where the problem is. I do not want to use anything like iText or Apose. Can anyone help???
public void createPDF(){
// Create a object of PdfDocument
PdfDocument document = new PdfDocument();
// content view is TableLayout of data
View content = findViewById(id.final_table_layout_for_pdf_page_1);
// create a page info with attributes as below
// page number, height and width
// i have used height and width to that of pdf content view
int pageNumber = 1;
PdfDocument.PageInfo pageInfo = new PdfDocument.PageInfo.Builder(content.getWidth(),
content.getHeight() - 20, pageNumber).create();
// create a new page from the PageInfo
PdfDocument.Page page = document.startPage(pageInfo);
// repaint the user's text into the page
content.draw(page.getCanvas());
// do final processing of the page
document.finishPage(page);
/* PAGE 2 OF PDF
content = findViewById(id.final_table_layout_for_pdf_page_2);
// create a page info with attributes as below
// for 2nd page
// i have used height and width to that of pdf content view
pageNumber = 2;
pageInfo = new PdfDocument.PageInfo.Builder(content.getWidth(),
content.getHeight() - 20, pageNumber).create();
// create a new page from the PageInfo
page = document.startPage(pageInfo);
// repaint the user's text into the page
content.draw(page.getCanvas());
// do final processing of the page
document.finishPage(page);*/
// saving pdf document to root dir
String pdfName = "pdf_inspection_demo.pdf";
// all created files will be saved at path /sdcard/PDFDemo_AndroidSRC/
File outputFile = new File("/storage/emulated/0/", pdfName);
try {
outputFile.createNewFile();
OutputStream out = new FileOutputStream(outputFile);
document.writeTo(out);
document.close();
out.close();
} catch (IOException e) {
e.printStackTrace();
errorString = e.getMessage();
}
}
private void generatePDF() {
PdfDocument pdfDocument = new PdfDocument();
criNewPag(1,"ان شاء الله ",pdfDocument);
criNewPag(2,"ان شاء الله ربي ",pdfDocument);
File file = new File(Environment.getExternalStorageDirectory(), "GFG.pdf");
try {
pdfDocument.writeTo(new FileOutputStream(file));
Toast.makeText(getApplicationContext(), "PDF file generated successfully.", Toast.LENGTH_SHORT).show();
} catch (IOException e) {
e.printStackTrace();
}
pdfDocument.close();
}
private void criNewPag(int numpag,String text, PdfDocument pdfDocument ){
Paint paint = new Paint();
Paint title = new Paint();
PdfDocument.PageInfo mypageInfo = new PdfDocument.PageInfo.Builder(pagewidth, pageHeight, numpag).create();
PdfDocument.Page myPage = pdfDocument.startPage(mypageInfo);
Canvas canvas = myPage.getCanvas();
bmp = BitmapFactory.decodeResource(getResources(), R.drawable.gfgimage);
scaledbmp = Bitmap.createScaledBitmap(bmp, 140, 140, false);
canvas.drawBitmap(scaledbmp, 56, 40, paint);
title.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.NORMAL));
title.setTextSize(15);
title.setColor(ContextCompat.getColor(this, R.color.purple_200));
canvas.drawText("A portal for IT professionals.", 209, 100, title);
canvas.drawText("Geeks for Geeks", 209, 80, title);
title.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));
title.setColor(ContextCompat.getColor(this, R.color.purple_200));
title.setTextSize(15);
title.setTextAlign(Paint.Align.CENTER);
canvas.drawText(text, 150, 240, title);
pdfDocument.finishPage(myPage);
}

PDFBox - checkbox is not displayed if set readonly

I am generating PDF using PDFBox, where I need to add a checkbox, which needs to be preset to checked and readonly. But some how it does not work.
Please find below code, which adds the checkbox on PDF:
import java.io.File;
import java.io.IOException;
import org.apache.pdfbox.cos.COSArray;
import org.apache.pdfbox.cos.COSDictionary;
import org.apache.pdfbox.cos.COSFloat;
import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.cos.COSString;
import org.apache.pdfbox.exceptions.COSVisitorException;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;
import org.apache.pdfbox.pdmodel.interactive.form.PDCheckbox;
import org.apache.pdfbox.pdmodel.interactive.form.PDField;
public class MyTest {
public static void main(String arg[]) throws IOException, COSVisitorException
{
PDDocument document = new PDDocument();
PDPage page = new PDPage(PDPage.PAGE_SIZE_LETTER);
document.addPage(page);
COSDictionary acroFormDict = new COSDictionary();
acroFormDict.setItem(COSName.getPDFName("Fields"), new COSArray()); // Added this line for Tilman's comment
PDAcroForm acroForm = new PDAcroForm(document, acroFormDict);
document.getDocumentCatalog().setAcroForm(acroForm);
float x = 10f;
float y = page.getMediaBox().getHeight();
float yOffset = 15f;
float yCurrent = y - yOffset;
COSDictionary cosDict = new COSDictionary();
COSArray rect = new COSArray();
rect.add(new COSFloat(x));
rect.add(new COSFloat(yCurrent));
rect.add(new COSFloat(x+20));
rect.add(new COSFloat(yCurrent-20));
cosDict.setItem(COSName.RECT, rect);
cosDict.setItem(COSName.FT, COSName.getPDFName("Btn")); // Field Type
cosDict.setItem(COSName.TYPE, COSName.ANNOT);
cosDict.setItem(COSName.SUBTYPE, COSName.getPDFName("Widget"));
cosDict.setItem(COSName.T, new COSString("testChk"));
cosDict.setItem(COSName.DA, new COSString("/Helv 7 Tf 0 g"));
PDCheckbox checkbox = new PDCheckbox(acroForm, cosDict);
// checkbox.setReadonly(true);
// checkbox.setFieldFlags(PDField.FLAG_READ_ONLY);
checkbox.setValue("Yes");
// checkbox.check();
page.getAnnotations().add(checkbox.getWidget());
acroForm.getFields().add(checkbox); // Added this line for Tilman's comment
yCurrent = yCurrent - 20 - yOffset;
File file = new File("C:\\pdf\\CheckBox\\CheckBoxSample1.pdf");
System.out.println("Sample file saved at : " + file.getAbsolutePath());
document.save(file);
document.close();
}
}
Now if you uncomment the line:
checkbox.setReadonly(true);
Or
checkbox.setFieldFlags(PDField.FLAG_READ_ONLY);
The checkbox will no more displayed (or may be there but value is unchecked).
I am using PDFBox 1.8.10
Behavior is similar in Adobe Reader 11 and Foxit.
Also if I generate the PDF without setting the box readonly, in Adobe, I see the checkbox displayed with value set, but when I bring focus on it using tab, it gets disappear. And again on focus out (I click somewhere else other than checkbox), it appears again.
It seems like I am missing a very small thing, but could not find out.
Any help?
Thanks in advance.
You need to give field appearance using PDAppearanceCharacteristicsDictionary class. That will fix above issue.
Please check sample code below:
import java.io.File;
import java.io.IOException;
import org.apache.pdfbox.cos.COSArray;
import org.apache.pdfbox.cos.COSDictionary;
import org.apache.pdfbox.cos.COSFloat;
import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.cos.COSString;
import org.apache.pdfbox.exceptions.COSVisitorException;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDResources;
import org.apache.pdfbox.pdmodel.font.PDFont;
import org.apache.pdfbox.pdmodel.font.PDType1Font;
import org.apache.pdfbox.pdmodel.graphics.color.PDGamma;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAppearanceCharacteristicsDictionary;
import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;
import org.apache.pdfbox.pdmodel.interactive.form.PDCheckbox;
public class MyCheckBox {
public static void main(String arg[]) throws IOException, COSVisitorException
{
PDDocument document = new PDDocument();
PDPage page = new PDPage(PDPage.PAGE_SIZE_LETTER);
document.addPage(page);
PDFont font = PDType1Font.HELVETICA;
PDResources res = new PDResources();
String fontName = res.addFont(font);
String da = "/" + fontName + " 10 Tf 0 0.4 0 rg";
COSDictionary acroFormDict = new COSDictionary();
acroFormDict.setBoolean(COSName.getPDFName("NeedAppearances"), true);
acroFormDict.setItem(COSName.FIELDS, new COSArray());
acroFormDict.setItem(COSName.DA, new COSString(da));
PDAcroForm acroForm = new PDAcroForm(document, acroFormDict);
acroForm.setDefaultResources(res);
document.getDocumentCatalog().setAcroForm(acroForm);
float x = 10f;
float y = page.getMediaBox().getHeight();
float yOffset = 15f;
float yCurrent = y - yOffset;
PDGamma colourBlack = new PDGamma();
PDAppearanceCharacteristicsDictionary fieldAppearance =
new PDAppearanceCharacteristicsDictionary(new COSDictionary());
fieldAppearance.setBorderColour(colourBlack);
COSArray arr = new COSArray();
arr.add(new COSFloat(227/255f));
arr.add(new COSFloat(239/255f));
arr.add(new COSFloat(1f));
fieldAppearance.setBackground(new PDGamma(arr));
COSDictionary cosDict = new COSDictionary();
COSArray rect = new COSArray();
rect.add(new COSFloat(x));
rect.add(new COSFloat(yCurrent));
rect.add(new COSFloat(x+20));
rect.add(new COSFloat(yCurrent-20));
cosDict.setItem(COSName.RECT, rect);
cosDict.setItem(COSName.FT, COSName.getPDFName("Btn")); // Field Type
cosDict.setItem(COSName.TYPE, COSName.ANNOT);
cosDict.setItem(COSName.SUBTYPE, COSName.getPDFName("Widget"));
cosDict.setItem(COSName.TU, new COSString("Test Checkbox with PDFBox"));
cosDict.setItem(COSName.T, new COSString("testChk"));
cosDict.setItem(COSName.DA, new COSString("/F0 10 Tf 0 0.4 0 rg"));
// cosDict.setInt(COSName.FF, 49152); //Radio Button Symbol
cosDict.setInt(COSName.F, 4);
// cosDict.setInt(COSName.FF, 16384);
PDCheckbox checkbox = new PDCheckbox(acroForm, cosDict);
checkbox.setFieldFlags(PDCheckbox.FLAG_READ_ONLY);
checkbox.setValue("Yes");
// checkbox.setValue("Off");
checkbox.getWidget().setAppearanceCharacteristics(fieldAppearance);
page.getAnnotations().add(checkbox.getWidget());
acroForm.getFields().add(checkbox);
yCurrent = yCurrent - 20 - yOffset;
File file = new File("C:\\pdf\\CheckBoxSample.pdf");
System.out.println("Sample file saved at : " + file.getAbsolutePath());
document.save(file);
document.close();
}
}

SVG line not getting rendered properly in PDF

I am using iText and some SVG rendering library.
I want to render a SVG image to PDF. I am using following code to do that. Now the problem is I am giving an area chart SVG to it, it is not rendering line properly. Attaching screenshots.
Following classes has been used:
import org.apache.batik.bridge.BridgeContext;
import org.apache.batik.bridge.DocumentLoader;
import org.apache.batik.bridge.GVTBuilder;
import org.apache.batik.bridge.UserAgent;
import org.apache.batik.bridge.UserAgentAdapter;
import org.apache.batik.dom.svg.SAXSVGDocumentFactory;
import org.apache.batik.gvt.GraphicsNode;
import org.apache.batik.util.XMLResourceDescriptor;
import org.w3c.dom.svg.SVGDocument;
and here the cop snippet:
String parser = XMLResourceDescriptor.getXMLParserClassName();
factory = new SAXSVGDocumentFactory(parser);
UserAgent userAgent = new UserAgentAdapter();
DocumentLoader loader = new DocumentLoader(userAgent);
ctx = new BridgeContext(userAgent, loader);
ctx.setDynamicState(BridgeContext.DYNAMIC);
builder = new GVTBuilder();
PdfContentByte cb = writer.getDirectContent();
PdfTemplate chartImageTemplate = cb.createTemplate(1000, 1000);
SVGDocument svgDoc=null;
try {
InputStream in = new ByteArrayInputStream(chartImage.getBytes());
svgDoc = factory.createSVGDocument("", in);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
try{
GraphicsNode mapGraphics = builder.build(ctx, svgDoc);
DefaultFontMapper mapper = new DefaultFontMapper();
PdfGraphics2D g2 = (PdfGraphics2D)cb.createGraphics(1000, 500, mapper);
Graphics2D g2d = g2;
mapGraphics.paint(g2d);
g2d.dispose();
cb.addTemplate(chartImageTemplate, 0, 0);
return mapGraphics.getGeometryBounds().getHeight();
}catch(Exception e){
}
You can find SVG here:
http://speedy.sh/xvDp8/demo.svg
Actual SVG:
Rendered PDF

How to add hyperlink in pdf using pdfbox

I want to add a hyperlink in PDF created using PDFBOX, such that i click on some text example 'Click here' will redirect to URL. I tried using PDAnnotationLink and PDActionURI, but how to add it in contentstream?
PDBorderStyleDictionary borderULine = new PDBorderStyleDictionary();
borderULine.setStyle(PDBorderStyleDictionary.STYLE_UNDERLINE);
PDAnnotationLink txtLink = new PDAnnotationLink();
txtLink.setBorderStyle(borderULine);
txtLink.setColour(colourBlue);
// add an action
PDActionURI action = new PDActionURI();
action.setURI("www.google.com");
txtLink.setAction(action);
contentStream.beginText();
contentStream.moveTextPositionByAmount(400, y-30);
contentStream.drawString(txtLink);----error
contentStream.endText();
To add to contentStream use the following code
PDRectangle position = new PDRectangle();
position.setLowerLeftX(10);
position.setLowerLeftY(20);
position.setUpperRightX(100);
position.setUpperRightY(10);
txtLink.setRectangle(position);
page.getAnnotations().add(txtLink);
There is a library called PDFBox-Layout which makes it easier to add hyperlinks:
Document document = new Document();
Paragraph paragraph = new Paragraph();
paragraph.addMarkup(
"This is a link to {link[https://github.com/ralfstuckert/pdfbox-layout]}PDFBox-Layout{link}",
18f, BaseFont.Helvetica);
document.add(paragraph);
final OutputStream outputStream = new FileOutputStream("link.pdf");
document.save(outputStream);
This is a fully working example, tested with PDFBox 2.0.19:
import java.awt.Color;
import java.io.File;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.font.PDType1Font;
import org.apache.pdfbox.pdmodel.graphics.color.PDColor;
import org.apache.pdfbox.pdmodel.graphics.color.PDDeviceRGB;
import org.apache.pdfbox.pdmodel.interactive.action.PDActionURI;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationLink;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDBorderStyleDictionary;
public class MainCreateHyerLink
{
public static void main (final String [] args) throws Exception
{
try (final PDDocument doc = new PDDocument ())
{
final PDPage page = new PDPage (new PDRectangle (250, 150));
doc.addPage (page);
try (final PDPageContentStream contentStream = new PDPageContentStream (doc, page))
{
final PDAnnotationLink txtLink = new PDAnnotationLink ();
// border style
final PDBorderStyleDictionary linkBorder = new PDBorderStyleDictionary ();
linkBorder.setStyle (PDBorderStyleDictionary.STYLE_UNDERLINE);
linkBorder.setWidth (10);
txtLink.setBorderStyle (linkBorder);
// Border color
final Color color = Color.GREEN;
final float [] components = new float [] { color.getRed () / 255f, color.getGreen () / 255f, color.getBlue () / 255f };
txtLink.setColor (new PDColor (components, PDDeviceRGB.INSTANCE));
// Destination URI
final PDActionURI action = new PDActionURI ();
action.setURI ("https://www.helger.com");
txtLink.setAction (action);
// Position
final PDRectangle position = new PDRectangle ();
position.setLowerLeftX (10);
position.setLowerLeftY (10);
position.setUpperRightX (200);
position.setUpperRightY (10 + 2 + 10 + 2);
txtLink.setRectangle (position);
page.getAnnotations ().add (txtLink);
// Main page content
contentStream.beginText ();
contentStream.newLineAtOffset (12, 12);
contentStream.setFont (PDType1Font.COURIER_BOLD, 10);
contentStream.showText ("This is linked to the outside world");
contentStream.endText ();
}
}
}
}

Categories