java itext7 水印文本隐藏在图像后面

java itext7 watermark text is hiding behind images

我尝试在 pdf 中使用 itext 添加水印。 使用此代码可以正常工作:

import com.itextpdf.io.font.constants.StandardFonts;
import com.itextpdf.kernel.colors.ColorConstants;
import com.itextpdf.kernel.colors.PatternColor;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfPage;
import com.itextpdf.kernel.pdf.PdfReader;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
import com.itextpdf.kernel.pdf.canvas.PdfPatternCanvas;
import com.itextpdf.kernel.pdf.colorspace.PdfPattern;
import com.itextpdf.kernel.pdf.colorspace.PdfPattern.Tiling;
import com.itextpdf.layout.Canvas;
import com.itextpdf.layout.element.Paragraph;


public class TestNewPdf {

    @SuppressWarnings("resource")
    public static void main(String[] args) throws Exception {
        
        
        
        
          PdfReader reader = new PdfReader("F:/barcode/test.pdf");        
          PdfWriter writer = new PdfWriter("F:/barcode/outputTest.pdf");
        
        
        PdfDocument pdfDocument = new PdfDocument(reader,writer);
    
        PdfPattern.Tiling tiling = new Tiling(new Rectangle(220, 100));
        new Canvas(new PdfPatternCanvas(tiling, pdfDocument), pdfDocument, tiling.getBBox()).add(new Paragraph("franco")
                .setFontColor(ColorConstants.RED)
                .setBold()
                .setFont(PdfFontFactory.createFont(StandardFonts.HELVETICA_BOLD))
                .setFontSize(10f)
                .setRotationAngle(Math.PI / 10)
                );

        for (int i = 1; i <= pdfDocument.getNumberOfPages(); i++) {
            PdfPage page = pdfDocument.getPage(i);
            
            new PdfCanvas(page.newContentStreamBefore(), page.getResources(), pdfDocument)
                    .saveState()
                    
                    .setFillColor(new PatternColor(tiling))
                    .rectangle(page.getCropBox())
                    .fill()
                    .restoreState();
        }

        pdfDocument.close();
        
        
    }
    
    
    
    

}

但是当源 pdf 包含图像或源 pdf 是扫描文件意味着 pdf 变得像图像时,我遇到了特定情况的问题。

水印文字隐藏在图片后面

谁能帮我解决这个问题

已更新:

在某些情况下水印覆盖内容, 我怎样才能使文本更透明。 我已经更新我的代码但没有成功使水印更透明

我尝试使用此代码:

  PdfFont helvetica = PdfFontFactory.createFont();
          
        PdfDocument pdfDocument = new PdfDocument(reader,writer);
        
    
        PdfPattern.Tiling tiling = new Tiling(new Rectangle(220, 100));
        new Canvas(new PdfPatternCanvas(tiling, pdfDocument), pdfDocument, tiling.getBBox()).add(new Paragraph("uhatem")
                
                   .setFontColor(ColorConstants.GRAY)
                   .setFont(helvetica)
                   .setFontSize(15f)
                .setRotationAngle(Math.PI / 10)
                );

        for (int i = 1; i <= pdfDocument.getNumberOfPages(); i++) {
            PdfPage page = pdfDocument.getPage(i);
            new PdfCanvas(page.newContentStreamAfter(), page.getResources(), pdfDocument)
                    .saveState()
                    
                    .setFillColor(new PatternColor(tiling))
                    .rectangle(page.getCropBox())
                    .fill()
                    .restoreState();
        }

        pdfDocument.close();
    

您使用 page.newContentStreamBefore() 为您的水印添加内容流。因此,在绘制页面时,首先绘制水印,然后在其上绘制内容。对于普通文本和稀疏矢量图形来说很好,但对于覆盖整个区域的内容,水印可能会完全隐藏。

请尝试使用 page.newContentStreamAfter()。但请注意,您可能不想再将水印文本加粗,甚至可能仅限于轮廓,因为标记现在覆盖了内容。


在问题更新和评论中,您询问了如何

make the text transparent.

透明度通常是通过选择匹配的扩展图形状态来实现的,例如:

PdfExtGState extGState = new PdfExtGState().setBlendMode(new PdfName("Multiply"));
for (int i = 1; i <= pdfDocument.getNumberOfPages(); i++) {
    PdfPage page = pdfDocument.getPage(i);
    new PdfCanvas(page.newContentStreamAfter(), page.getResources(), pdfDocument)
            .saveState()
            .setExtGState(extGState)
            .setFillColor(new PatternColor(tiling))
            .rectangle(page.getCropBox())
            .fill()
            .restoreState();

(AddWatermark 测试 testAddLikeFrancoImproved)

您可以尝试确定是否要使用混合模式(如此处示例中的“乘法”)或 alpha 值透明度(使用 setFillOpacitysetStrokeOpacity 而不是 setBlendMode)