iText 7 - Add and Remove Watermark on a PDF

后端 未结 1 800
梦毁少年i
梦毁少年i 2021-01-03 05:25

I would like to add and remove a watermark to a PDF using iText 7. I was able to add the watermark, but unable to remove it again. I could only find relevant code/examples r

相关标签:
1条回答
  • 2021-01-03 06:09

    With help from the guys at iText I was able to solve this. If you intend to remove the watermark later, you will need to add it as a 'PDF watermark annotation'.

    To add a watermark on every page:

        public void WatermarkPDF(string sourceFile, string destinationPath)
        {
            float watermarkTrimmingRectangleWidth = 300;
            float watermarkTrimmingRectangleHeight = 300;
    
            float formWidth = 300;
            float formHeight = 300;
            float formXOffset = 0;
            float formYOffset = 0;
    
            float xTranslation = 50;
            float yTranslation = 25;
    
            double rotationInRads = Math.PI / 3;
    
            PdfFont font = PdfFontFactory.CreateFont(FontConstants.TIMES_ROMAN);
            float fontSize = 50;
    
            PdfDocument pdfDoc = new PdfDocument(new PdfReader(sourceFile), new PdfWriter(destinationPath));
            var numberOfPages = pdfDoc.GetNumberOfPages();
            PdfPage page = null;
    
            for (var i = 1; i <= numberOfPages; i++)
            {
                page = pdfDoc.GetPage(i);
                Rectangle ps = page.GetPageSize();
    
                //Center the annotation
                float bottomLeftX = ps.GetWidth() / 2 - watermarkTrimmingRectangleWidth / 2;
                float bottomLeftY = ps.GetHeight() / 2 - watermarkTrimmingRectangleHeight / 2;
                Rectangle watermarkTrimmingRectangle = new Rectangle(bottomLeftX, bottomLeftY, watermarkTrimmingRectangleWidth, watermarkTrimmingRectangleHeight);
    
                PdfWatermarkAnnotation watermark = new PdfWatermarkAnnotation(watermarkTrimmingRectangle);
    
                //Apply linear algebra rotation math
                //Create identity matrix
                AffineTransform transform = new AffineTransform();//No-args constructor creates the identity transform
                //Apply translation
                transform.Translate(xTranslation, yTranslation);
                //Apply rotation
                transform.Rotate(rotationInRads);
    
                PdfFixedPrint fixedPrint = new PdfFixedPrint();
                watermark.SetFixedPrint(fixedPrint);
                //Create appearance
                Rectangle formRectangle = new Rectangle(formXOffset, formYOffset, formWidth, formHeight);
    
                //Observation: font XObject will be resized to fit inside the watermark rectangle
                PdfFormXObject form = new PdfFormXObject(formRectangle);
                PdfExtGState gs1 = new PdfExtGState().SetFillOpacity(0.6f);
                PdfCanvas canvas = new PdfCanvas(form, pdfDoc);
    
                float[] transformValues = new float[6];
                transform.GetMatrix(transformValues);
                canvas.SaveState()
                    .BeginText().SetColor(Color.GRAY, true).SetExtGState(gs1)
                    .SetTextMatrix(transformValues[0], transformValues[1], transformValues[2], transformValues[3], transformValues[4], transformValues[5])
                    .SetFontAndSize(font, fontSize)
                    .ShowText("watermark text")
                    .EndText()
                    .RestoreState();
    
                canvas.Release();
    
                watermark.SetAppearance(PdfName.N, new PdfAnnotationAppearance(form.GetPdfObject()));
                watermark.SetFlags(PdfAnnotation.PRINT);
    
                page.AddAnnotation(watermark);
    
            }
            page?.Flush();
            pdfDoc.Close();
        } 
    

    To remove the watermark:

        public void RemovetWatermarkPDF(string sourceFile, string destinationPath)
        {
            PdfDocument pdfDoc = new PdfDocument(new PdfReader(sourceFile), new PdfWriter(destinationPath));
            var numberOfPages = pdfDoc.GetNumberOfPages();
    
            for (var i = 1; i <= numberOfPages; i++)
            {
                // PdfAnnotation 
                PdfDictionary pageDict = pdfDoc.GetPage(i).GetPdfObject();
                PdfArray annots = pageDict.GetAsArray(PdfName.Annots);
                for (int j = 0; j < annots.Size(); j++)
                {
                    PdfDictionary annotation = annots.GetAsDictionary(j);
                    if (PdfName.Watermark.Equals(annotation.GetAsName(PdfName.Subtype)))
                    {
                        annotation.Clear();
                    }
                }
            }
            pdfDoc.Close();
        }
    

    What about variable length watermark text? How would you dynamically resize the rectangle to fit the text? This is not inbuilt into iText, you would need to play around with the following dimension parameters:

    float watermarkTrimmingRectangleWidth = 600;
    float watermarkTrimmingRectangleHeight = 600;
    float formWidth = 600;
    float formHeight = 600;
    float formXOffset = -100;
    float fontSize = 30;
    

    For my use-case I checked the length of the watermark text and based on that adjusted the parameters accordingly eg:

            if (watermarkText.Length <= 14)
            {
                watermarkTrimmingRectangleWidth = 200;
                watermarkTrimmingRectangleHeight = 200;
                formWidth = 200;
                formHeight = 200;
                formXOffset = 0;
                fontSize = 30;
            }
            else if (watermarkText.Length <= 22)
            {
                watermarkTrimmingRectangleWidth = 300;
                watermarkTrimmingRectangleHeight = 300;
                formWidth = 300;
                formHeight = 300;
                formXOffset = 0;
                fontSize = 30;
            }
            else if (...)
            {
             ...           
            }
            .
            .
            etc.
            .
            .
            else if (watermarkText.Length <= 62)
            {
                watermarkTrimmingRectangleWidth = 600;
                watermarkTrimmingRectangleHeight = 600;
                formWidth = 600;
                formHeight = 600;
                formXOffset = -100;
                fontSize = 20;
            }
    
    0 讨论(0)
提交回复
热议问题