繁体   English   中英

如何使用文本或图像给PDF加水印?

[英]How to watermark PDFs using text or images?

我的文件夹中有一堆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对象。 我们还为透明度创建了一个PdfGState对象。 在本例中,我们将不透明度设为50%(将0.5f更改为其他值进行实验)。

一旦有了这些对象,便会遍历每个页面。 我们使用PdfReader对象获取有关现有文档的信息,例如每页的尺寸。 当我们想在现有文档上标记额外的内容时,例如,在每个页面的顶部添加水印,我们将使用PdfStamper对象。

更改图形状态时,始终可以在开始之前执行saveState()并在完成后立即恢复restoreState()始终是安全的。 如果您不这样做,您的代码也可能会工作,但是请相信我:如果采用相应的准则,这样做可以节省大量调试时间,因为如果图形状态不平衡,您会得到非常奇怪的效果。

我们使用setGState()方法应用透明度,并根据页面是奇数页还是偶数页,添加文本(使用ColumnText和计算的(x, y)坐标,以便将文本添加到中间(每一页的大小)或图像(使用addImage()方法和转换矩阵的适当参数)。

对文档中的每个页面完成此操作后,就必须close() stamperreader

警告:

您会注意到第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度。

在此处输入图片说明

这是一个微妙的区别,但我想您想知道。

如果您想用法语阅读此答案,请阅读PDF注释评论?

最好的选择是iText 在此处查看水印演示

代码的重要部分(插入watermar的地方)是:

public class Watermark extends PdfPageEventHelper {

        @Override
        public void onEndPage(PdfWriter writer, Document document) {
             // insert here your watermark
        }

仔细阅读示例。

onEndPage()方法将类似于(在我的徽标水印中,我使用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);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM