Discussion:
[iText-questions] iText: how to remove the layer (watermark)?
olexiy
2011-06-06 12:43:40 UTC
Permalink
My task at the moment is to write a class that can do the following things:
1. Add to an already existing pdf Fail watermark "outdated"
2. Check, whether the document already has this sign
3. Remove the sign

The first two points have been resolved through iText Stamper and layers.
Saly i can't find an example of how to remove the specific layer. Please
Help, who can.
Layer added like this:

private void markAndMovePdfDocument(File pdfFile, String newPath)
throws Exception {
PdfReader reader = new PdfReader(pdfFile.getPath());
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(
newPath));
Image watermarkImage = Image.getInstance("d:/watermark.jpg");
PdfLayer wmLayer = new PdfLayer("watermark", stamper.getWriter());

wmLayer.setOnPanel(true);
// set layer parameters
wmLayer.setPrint("print", true);
wmLayer.setOn(true);
wmLayer.setView(true);
// Prepare transperancy
PdfGState transparent = new PdfGState();
transparent.setStrokeOpacity(0.4f);
transparent.setFillOpacity(0.4f);
PdfContentByte cb;
int toPage = stamper.getReader().getNumberOfPages();
for (int i = 1; i <= toPage; i++) {

cb = stamper.getUnderContent(i);

Rectangle rectangle = stamper.getReader()
.getPageSizeWithRotation(i);

cb.beginLayer(wmLayer);
cb.setGState(transparent); // set block trasparency properties

// position relative to top
watermarkImage.scaleAbsoluteHeight(rectangle.getHeight() - 20);
watermarkImage.scaleAbsoluteWidth(rectangle.getWidth() - 20);
float absoluteY = rectangle.getBottom()
+ (rectangle.getHeight() - watermarkImage.getPlainHeight() - 10);
watermarkImage.setAbsolutePosition(10, 10);
cb.addImage(watermarkImage);
cb.endLayer();

}

stamper.close();
}

any tips on optimizing my code also warmly welcomed.
Thanks in advance


--
View this message in context: http://itext-general.2136553.n4.nabble.com/iText-how-to-remove-the-layer-watermark-tp3576811p3576811.html
Sent from the iText - General mailing list archive at Nabble.com.
1T3XT BVBA
2011-06-06 13:08:23 UTC
Permalink
Post by olexiy
1. Add to an already existing pdf Fail watermark "outdated"
2. Check, whether the document already has this sign
Are you sure the sign is added as an OCG layer?
In that case, you can use the method getPdfLayers.
Post by olexiy
3. Remove the sign
That's not trivial, but: if you are sure the sign was added with PdfStamper
(and NOT with other PDF software), then you could get the /Contents
of the page (which will be an array if it was created with PdfStamper)
and remove/replace the first entry in that array.
Post by olexiy
The first two points have been resolved through iText Stamper and layers.
Saly i can't find an example of how to remove the specific layer.
You can't find an example, because this is a very specific question.
Specific questions like this are often answered:
- in the context of a support contract for those who bought a license,
- in the context of a paid consultancy assignment.
olexiy
2011-06-06 13:51:47 UTC
Permalink
Thank you for your reply.
I am sure that the layer is only created through the procedure which I
shown before. Will he be OCG I do not know (I do not know what OCG ist).
Until now i have not worked with iText , and after i solve this problem
unlikely to do it in the next time.
Here's how I check for wotermark layer (and it seem to work):

private boolean hasWatermark(File pdfFile) throws Exception {
File tempStemper = null;
try {
PdfReader reader = new PdfReader(pdfFile.getPath());
tempStemper = File.createTempFile(".pdf", "hasWatermarkTemp");
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(
tempStemper));
Map&lt;String, PdfLayer&gt; layers = stamper.getPdfLayers();
boolean wm = false;
if (!layers.isEmpty()) {
Set<String> keys = layers.keySet();
for (String key : keys) {
if (key.toString().equalsIgnoreCase("watermark"))
wm = true;
}
}
stamper.close();
return wm;
} catch (Exception e) {
throw e;
} finally {
if ((tempStemper != null) && (tempStemper.exists()))
tempStemper.delete();
}

}


I start to read "iText in Action". Could you tell exactly where in the Book
can i find example to a technique from your replay or give me a small code
fragment.

P.S.: Sorry for my English.

--
View this message in context: http://itext-general.2136553.n4.nabble.com/iText-how-to-remove-the-layer-watermark-tp3576811p3576956.html
Sent from the iText - General mailing list archive at Nabble.com.
1T3XT BVBA
2011-06-06 14:12:40 UTC
Permalink
Post by olexiy
Here's how I check for wotermark layer (and it seem to work)
OK, so you can meet 2 out of 3 requirements.
Post by olexiy
I start to read "iText in Action". Could you tell exactly where in the Book
can i find example to a technique from your replay or give me a small code
fragment.
There's no ready-made solution in the book, but in section 13.3.2 you
can read how to get and manipulate a page dictionary.
Instread of PdfName.CROPBOX (listing 13.8), PdfName.ROTATE (listing
13.9),... you need PdfName.CONTENTS.
In your case, this should always be an array (because the PDF was
created with PdfStamper) of which you need to remove the first entry.
olexiy
2011-06-17 08:39:34 UTC
Permalink
This is what i have so far:


package de.inplus.umsys.web.observer.tools;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.Set;

import org.springframework.beans.factory.annotation.Required;
import org.springframework.core.io.Resource;

import com.itextpdf.text.Image;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PRStream;
import com.itextpdf.text.pdf.PdfArray;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfDictionary;
import com.itextpdf.text.pdf.PdfGState;
import com.itextpdf.text.pdf.PdfLayer;
import com.itextpdf.text.pdf.PdfName;
import com.itextpdf.text.pdf.PdfNumber;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.PdfWriter;

public class WatermarkTool {

private Resource watermark;

public void setWatermarkRight(File document, boolean shouldBeMarked)
throws Exception {
try {
byte[] buffer = new byte[(int) document.length()];
InputStream in = new FileInputStream(document);
in.read(buffer);
in.close();
PdfReader reader = new PdfReader(buffer);
PdfDictionary pageDict;
int n = reader.getNumberOfPages();
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(
document));

Map&lt;String, PdfLayer&gt; layers = stamper.getPdfLayers();
boolean wm = false;
if (!layers.isEmpty()) {
Set<String> keys = layers.keySet();
for (String key : keys) {
if (key.toString().equalsIgnoreCase("watermark"))
wm = true;
}
}
if ((shouldBeMarked==true)&&(wm==false))
{
addWatermarkLayer(reader, stamper);
}

if((shouldBeMarked ==false)&&(wm==true))
{
removeWatermark(reader, stamper);
}

stamper.close();

} catch (Exception e) {
throw e;
} finally {

}
}

private void addWatermarkLayer(PdfReader reader, PdfStamper stamper)
throws Exception {

Image watermarkImage = Image.getInstance(watermark.getFile().getPath());
PdfLayer wmLayer = new PdfLayer("watermark", stamper.getWriter());
wmLayer.setOnPanel(true);
// set layer parameters
wmLayer.setPrint("print", true);
wmLayer.setOn(true);
wmLayer.setView(true);
// Prepare transperancy
PdfGState transparent = new PdfGState();
transparent.setStrokeOpacity(0.4f);
transparent.setFillOpacity(0.4f);
PdfContentByte cb;
int toPage = stamper.getReader().getNumberOfPages();
for (int i = 1; i <= toPage; i++) {

cb = stamper.getUnderContent(i);

Rectangle rectangle = stamper.getReader()
.getPageSizeWithRotation(i);

cb.beginLayer(wmLayer);
cb.setGState(transparent); // set block trasparency properties

// position relative to top
watermarkImage.scaleAbsoluteHeight(rectangle.getHeight() - 20);
watermarkImage.scaleAbsoluteWidth(rectangle.getWidth() - 20);
float absoluteY = rectangle.getBottom()
+ (rectangle.getHeight() - watermarkImage.getPlainHeight() - 10);
watermarkImage.setAbsolutePosition(10, 10);
cb.addImage(watermarkImage);
cb.endLayer();

}
}

public void removeWatermark(PdfReader reader, PdfStamper stamper){

try {

PdfDictionary root = reader.getCatalog();
root.remove(PdfName.OCPROPERTIES);
PdfDictionary page;
PdfArray contentarray;
PRStream stream;
String content;
PdfDictionary resources;
PdfDictionary xobjects;
for (int i = 0; i < reader.getNumberOfPages(); i++) {
page = reader.getPageN(1);
contentarray = page.getAsArray(PdfName.CONTENTS);
if (contentarray != null) {
for (int j = 0; j < contentarray.size(); j++) {
stream = (PRStream) contentarray.getAsStream(j);
content = new String(PdfReader.getStreamBytes(stream));
if (content.indexOf("/OC") > 0) {
stream.put(PdfName.LENGTH, new PdfNumber(0));
stream.setData(new byte[0]);
}
}
}
resources = page.getAsDict(PdfName.RESOURCES);
xobjects = resources.getAsDict(PdfName.XOBJECT);
for (PdfName name : xobjects.getKeys()) {
stream = (PRStream) xobjects.getAsStream(name);
if (stream.get(PdfName.OC) == null) {
continue;
}
stream.put(PdfName.LENGTH, new PdfNumber(0));
stream.setData(new byte[0]);
}
}


stamper.setViewerPreferences(PdfWriter.PageModeUseNone);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}


public Resource getWatermark() {
return watermark;
}

@Required
public void setWatermark(Resource watermark) {
this.watermark = watermark;
}

}

it is almost perfect. just one last problem: by watermark removes layer
content but not the layer itself. If i understand this right, i have to
remove something else from the PdfDictionary? Can somebody pleas write me
exactly what?




--
View this message in context: http://itext-general.2136553.n4.nabble.com/iText-how-to-remove-the-layer-watermark-tp3576811p3604883.html
Sent from the iText - General mailing list archive at Nabble.com.
1T3XT BVBA
2011-06-20 07:38:06 UTC
Permalink
I'm sorry, but your code to remove OCG layers is beyond repair:

* you are assuming that the CONTENTS of a page is an Array.
=> that's not always true!!!
* you are assuming that the complete stream consists of one OCG layer.
=> that's not always true!!!
* ...

Your code will remove content that shouldn't be removed.
Your code will keep layers that should be removed.
olexiy
2011-06-21 15:36:35 UTC
Permalink
Could you just give me an example code? I have a deadline at the next
Monday and I have no clue what to do.
Pdf files are always simple, without layers, one layer that contains the
watermark are added me.
You wrote that i can
"get the /Contents
of the page (which will be an array if it was created with PdfStamper)
and remove/replace the first entry in that array. " - how it looks like in
code?

--
View this message in context: http://itext-general.2136553.n4.nabble.com/iText-how-to-remove-the-layer-watermark-tp3576811p3614506.html
Sent from the iText - General mailing list archive at Nabble.com.
1T3XT BVBA
2011-06-21 15:52:38 UTC
Permalink
Post by olexiy
Could you just give me an example code?
No, I've spent a full day coding to parse the content stream and to
remove specific OCG layers.
It works and it doesn't work.
It works in the sense that the correct PDF syntax is removed.
It doesn't work in the sense that for some PDFs the state operators are
no longer balanced if you remove stuff like this /OC /SomeLayer BDC q
some q syntax Q EMC
As you can see, there are two "save state" operators in this (pseudo)
PDF snippet, and only one "restore state" operator.
I've written code to deal with this problem, but I can't just add 'q' or
'Q' at arbitrary places: in some cases, this results in a graphics state
that is changed in a way that is not desired.
Post by olexiy
Pdf files are always simple, without layers, one layer that contains the
watermark are added me.
Unfortunately for you, I'm not that interested in writing non-generic
code: it will work in some cases, but not in all. There is no honor in
writing such code.
I'm sorry that you have a deadline. Are you a customer of iText Software
Corp? If so, you may get help from their support.
Leonard Rosenthol
2011-06-21 16:15:13 UTC
Permalink
Yeah - this is one of those things you simply can NOT do with a pure stream-based solution. You need a higher level abstraction - aka a "display list".

Leonard

-----Original Message-----
From: 1T3XT BVBA [mailto:***@1t3xt.info]
Sent: Tuesday, June 21, 2011 11:53 AM
To: Post all your questions about iText here
Subject: Re: [iText-questions] iText: how to remove the layer (watermark)?
Post by olexiy
Could you just give me an example code?
No, I've spent a full day coding to parse the content stream and to remove specific OCG layers.
It works and it doesn't work.
It works in the sense that the correct PDF syntax is removed.
It doesn't work in the sense that for some PDFs the state operators are no longer balanced if you remove stuff like this /OC /SomeLayer BDC q some q syntax Q EMC As you can see, there are two "save state" operators in this (pseudo) PDF snippet, and only one "restore state" operator.
I've written code to deal with this problem, but I can't just add 'q' or 'Q' at arbitrary places: in some cases, this results in a graphics state that is changed in a way that is not desired.
Post by olexiy
Pdf files are always simple, without layers, one layer that contains
the watermark are added me.
Unfortunately for you, I'm not that interested in writing non-generic
code: it will work in some cases, but not in all. There is no honor in writing such code.
I'm sorry that you have a deadline. Are you a customer of iText Software Corp? If so, you may get help from their support.

------------------------------------------------------------------------------
EditLive Enterprise is the world's most technically advanced content authoring tool. Experience the power of Track Changes, Inline Image Editing and ensure content is compliant with Accessibility Checking.
http://p.sf.net/sfu/ephox-dev2dev
_______________________________________________
iText-questions mailing list
iText-***@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/itext-questions

iText(R) is a registered trademark of 1T3XT BVBA.
Many questions posted to this list can (and will) be answered with a reference to the iText book: http://www.itextpdf.com/book/ Please check the keywords list before you ask for examples: http://itextpdf.com/themes/keywords.php
1T3XT BVBA
2011-06-28 14:44:01 UTC
Permalink
Hello,
short note to inform the list that I was able to write code that enables
you to remove the content of OCG-layers from a PDF.
This code needs further testing and it will be part of iText-tk, an
addon for iText that is available for iText Software customers (upon
demand).
Post by Leonard Rosenthol
Yeah - this is one of those things you simply can NOT do with a pure stream-based solution. You need a higher level abstraction - aka a "display list".
Leonard
-----Original Message-----
Sent: Tuesday, June 21, 2011 11:53 AM
To: Post all your questions about iText here
Subject: Re: [iText-questions] iText: how to remove the layer (watermark)?
Post by olexiy
Could you just give me an example code?
No, I've spent a full day coding to parse the content stream and to remove specific OCG layers.
It works and it doesn't work.
It works in the sense that the correct PDF syntax is removed.
It doesn't work in the sense that for some PDFs the state operators are no longer balanced if you remove stuff like this /OC /SomeLayer BDC q some q syntax Q EMC As you can see, there are two "save state" operators in this (pseudo) PDF snippet, and only one "restore state" operator.
I've written code to deal with this problem, but I can't just add 'q' or 'Q' at arbitrary places: in some cases, this results in a graphics state that is changed in a way that is not desired.
Loading...