Search code examples
javaitext

java itext7 watermark text is hiding behind images


I try to add a watermark using itext in pdf. it work without problem using this code :

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();
        
        
    }
    
    
    
    

}

but I have a problem for specific case when the source pdf contain image or the source pdf is a scanning file meaning the pdf become like image .

the watermark text is hiding behind images

can someone help me to resolve this problem

updated :

In some case the watermark cover content, how can I make the text more transparent . I have update my code without success to make the watermark more transparent

I try with this code :

  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();
    

Solution

  • You use page.newContentStreamBefore() to add a content stream for your water mark. Thus, when the page is drawn, the watermark is drawn first and the content thereafter over it. For usual text and sparse vector graphics that is good but for full area covering content the watermark may be totally hidden.

    Try to use page.newContentStreamAfter() instead. But beware, you may not want to bold the watermark text then anymore, probably even restrict to outline only, as the mark now covers content.


    In a question update and a comment you asked how to

    make the text transparent.

    Transparency usually is achieved by selecting a matching extended graphics state, e.g.:

    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 test testAddLikeFrancoImproved)

    You can try and find out whether you want to use a blend mode (like "Multiply" in the example here) or alpha value transparency (set using setFillOpacity and setStrokeOpacity instead of setBlendMode)