如何使用文本或图像为PDF水印?
我在一个文件夹中有一堆PDF文档,我想用水印来增加它们。 Java服务器上下文有哪些选择?
优选地,水印将支持透明度。 矢量和光栅都是可取的。
请查看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
创建了一个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度。
这是一个微妙的区别,但我想你想知道。
如果你想用法语阅读这个答案,请阅读评论créerunfiligrane transparent en PDF?
最好的选择是iText
。 在这里查看水印演示
代码的重要部分(插入watermar的地方)是这样的:
public class Watermark extends PdfPageEventHelper { @Override public void onEndPage(PdfWriter writer, Document document) { // insert here your watermark }
仔细阅读这个例子。
onEndPage()
方法会像(在我的logo-watermarks中使用com.itextpdf.text.Image;
):
Image image = Image.getInstance(this.getClass().getResource("/path/to/image.png")); // set transparency image.setTransparency(transparency); // set position image.setAbsolutePosition(absoluteX, absoluteY); // put into document document.add(image);
- jar子似乎不再签名了。 JARSigningException:找到无符号条目
- 如何使用spring mvc将图像上传到webapp / resources / images目录?
- 如何使用SwingWorker?
- 一个物体可以自行移除吗? 怎么样?
- 制作许多bean的简短方法取决于一个bean
- 如何在Spring Boot应用程序启动时启动H2 TCP服务器?
- Java 8 javax.net.ssl.SSLPeerUnverifiedException:peer未经过身份validation,但不是Java 7
- 如何测试Spring @Scheduled
- 如何配置maven hbm2hbmxml和hbm2java在mvn clean install中依次运行