I am working on a pdf file. I need to add a watermark on an exist pdf file. That's why, I wrote following code. When I used FileOutputStream it works perfectly, but I need to use ByteArrayOutputStream because my data are come from database and I need to save it as byte array. Problem starts in here. When I use ByteArrayOutputStream getOvercontent method of PdfStamper returns null. How can I handle this? Thanks in advance.
byte[] bytes = getAsByteArray();
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(bytes.length);
PdfReader reader = new PdfReader(bytes);
int numberOfPages= reader.getNumberOfPages();
outputStream.write(bytes, 0, bytes.length);
PdfStamper stamper = new PdfStamper(reader, outputStream);
Font font = font(Font.NORMAL, 135, Color.RED);
for (int i = 0; i < numberOfPages; i++) {
//over Content is null
PdfContentByte over = stamper.getOverContent(i);
Phrase p = new Phrase("WATERMARK", font);
PdfGState gs = new PdfGState();
gs.setFillOpacity(0.5f);
over.setGState(gs);
ColumnText.showTextAligned(over, Element.ALIGN_CENTER, p, 330, 450, 45);
over.saveState();
}
And the old version of code is this.
byte[] bytes = FileUtils.readFileToByteArray(new File("myPdf.pdf"));
PdfReader reader = new PdfReader(bytes);
int numberOfPages= reader.getNumberOfPages();
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream("MyPdfOut.pdf"));
Font f = font(Font.NORMAL, 135, Color.RED);
for (int i = 1; i <= numberOfPages; i++) {
PdfContentByte over = stamper.getOverContent(i);
Phrase p = new Phrase("WATERMARK", f);
PdfGState gs = new PdfGState();
gs.setFillOpacity(0.5f);
over.setGState(gs);
ColumnText.showTextAligned(over, Element.ALIGN_CENTER, p, 330, 450, 45);
over.saveState();
}
This is forbidden:
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(bytes.length);
outputStream.write(bytes, 0, bytes.length);
PdfStamper stamper = new PdfStamper(reader, outputStream);
You create an OutputStream
, named outputStream
, and it seems that you copy a full-blown existing PDF to that OutputStream
(using write()
). Then you seem to have the intention to add another full-blown PDF to that OutputStream
by passing that same OutputStream
to the PdfStamper
instance. That should result in a corrupt PDF file.
This will also result in illegal PDF syntax:
PdfContentByte over = stamper.getOverContent(i);
Phrase p = new Phrase("WATERMARK");
PdfGState gs = new PdfGState();
gs.setFillOpacity(0.5f);
over.setGState(gs);
ColumnText.showTextAligned(over, Element.ALIGN_CENTER, p, 330, 450, 45);
over.saveState();
You have a saveState()
operator, but you never use restoreState()
. For every saveState()
, you should have a restoreState()
. Your saveState()
is in the wrong position! It's as if you don't know what saveState()
and restoreState()
are about.
Finally, you start counting a 0, but the first page is page 1, not page 0. Hence for (int i = 0; i < numberOfPages; i++)
is wrong. It should be for (int i = 1; i <= numberOfPages; i++)
. This error is what causes over
to be null
.
This is an attempt to fix your code:
// create a Phrase with a certain font
Font font = font(Font.NORMAL, 135, Color.RED);
Phrase p = new Phrase("WATERMARK", font);
// Create a reader and a stamper
PdfReader reader = new PdfReader(getAsByteArray());
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
PdfStamper stamper = new PdfStamper(reader, outputStream);
int numberOfPages= reader.getNumberOfPages();
for (int i = 1; i <= numberOfPages; i++) {
PdfContentByte over = stamper.getOverContent(i);
over.saveState();
PdfGState gs = new PdfGState();
gs.setFillOpacity(0.5f);
over.setGState(gs);
ColumnText.showTextAligned(over, Element.ALIGN_CENTER, p, 330, 450, 45);
over.restoreState();
}