请查看TransparentWatermark2 示例。它在现有 PDF 文档的每个奇数页上添加透明文本,并在每个偶数页上添加透明图像。
它是这样完成的:
public void manipulatePdf(String src, String dest) throws IOException, DocumentException {
PdfReader reader = new PdfReader(src);
int n = reader.getNumberOfPages();
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
// text watermark
Font f = new Font(FontFamily.HELVETICA, 30);
Phrase p = new Phrase("My watermark (text)", f);
// image watermark
Image img = Image.getInstance(IMG);
float w = img.getScaledWidth();
float h = img.getScaledHeight();
// transparency
PdfGState gs1 = new PdfGState();
gs1.setFillOpacity(0.5f);
// properties
PdfContentByte over;
Rectangle pagesize;
float x, y;
// loop over every page
for (int i = 1; i <= n; i++) {
pagesize = reader.getPageSizeWithRotation(i);
x = (pagesize.getLeft() + pagesize.getRight()) / 2;
y = (pagesize.getTop() + pagesize.getBottom()) / 2;
over = stamper.getOverContent(i);
over.saveState();
over.setGState(gs1);
if (i % 2 == 1)
ColumnText.showTextAligned(over, Element.ALIGN_CENTER, p, x, y, 0);
else
over.addImage(img, w, 0, 0, h, x - (w / 2), y - (h / 2));
over.restoreState();
}
stamper.close();
reader.close();
}
如您所见,我们为文本创建了一个Phrase 对象,为图像创建了一个Image 对象。我们还为透明度创建了一个PdfGState 对象。在我们的例子中,我们选择 50% 的不透明度(将 0.5f 更改为其他内容以进行实验)。
一旦我们有了这些对象,我们就会遍历每一页。我们使用PdfReader 对象来获取有关现有文档的信息,例如每个页面的尺寸。当我们想要在现有文档上标记额外内容时,我们使用PdfStamper 对象,例如在每个单页顶部添加水印。
更改图形状态时,在开始之前执行saveState() 并在完成后执行restoreState() 始终是安全的。如果您不这样做,您的代码可能也可以工作,但请相信我:如果您采用纪律来执行此操作,它可以为您节省大量调试时间,因为如果图形状态不平衡,您会得到非常奇怪的效果。
我们使用setGState() 方法应用透明度,并根据页面是奇数页还是偶数页,添加文本(使用ColumnText 和计算出的(x, y) 坐标以便添加文本在每页的中间)或图像(使用addImage() 方法和转换矩阵的适当参数)。
为文档中的每一页完成此操作后,您必须close()、stamper 和reader。
警告:
您会注意到第 3 页和第 4 页是横向的,但这两个页面之间存在肉眼不可见的差异。第 3 页实际上是一个页面,其大小定义为就好像它是纵向页面一样,但它被旋转了 90 度。第 4 页是按宽度 > 高度定义大小的页面。
这可能会影响您添加水印的方式,但如果您使用getPageSizeWithRotation(),iText 会适应。这可能不是您想要的:也许您希望添加不同的水印。
看看TransparentWatermark3:
public void manipulatePdf(String src, String dest) throws IOException, DocumentException {
PdfReader reader = new PdfReader(src);
int n = reader.getNumberOfPages();
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
stamper.setRotateContents(false);
// text watermark
Font f = new Font(FontFamily.HELVETICA, 30);
Phrase p = new Phrase("My watermark (text)", f);
// image watermark
Image img = Image.getInstance(IMG);
float w = img.getScaledWidth();
float h = img.getScaledHeight();
// transparency
PdfGState gs1 = new PdfGState();
gs1.setFillOpacity(0.5f);
// properties
PdfContentByte over;
Rectangle pagesize;
float x, y;
// loop over every page
for (int i = 1; i <= n; i++) {
pagesize = reader.getPageSize(i);
x = (pagesize.getLeft() + pagesize.getRight()) / 2;
y = (pagesize.getTop() + pagesize.getBottom()) / 2;
over = stamper.getOverContent(i);
over.saveState();
over.setGState(gs1);
if (i % 2 == 1)
ColumnText.showTextAligned(over, Element.ALIGN_CENTER, p, x, y, 0);
else
over.addImage(img, w, 0, 0, h, x - (w / 2), y - (h / 2));
over.restoreState();
}
stamper.close();
reader.close();
}
在这种情况下,我们不使用getPageSizeWithRotation(),而只是使用getPageSize()。我们还告诉stamper 不 来补偿现有的页面旋转:stamper.setRotateContents(false);
查看生成的 PDF 的不同之处:
在第一个屏幕截图中(显示TransparentWatermark2 生成的 PDF 的第 3 页和第 4 页),左侧的页面实际上是纵向旋转 90 度的页面。然而,iText 将其视为横向页面,就像右侧页面一样。
在第二个屏幕截图中(显示TransparentWatermark3 生成的 PDF 的第 3 页和第 4 页),左侧页面是旋转 90 度的纵向页面,我们添加水印,就好像页面是纵向的一样.结果,水印也被旋转了90度。右侧的页面不会发生这种情况,因为该页面的旋转角度为 0 度。
这是一个微妙的区别,但我想你会想知道的。
如果您想阅读此法文答案,请阅读Comment créer un filigrane transparent en PDF?