iText 7 - Добавление и удаление водяных знаков в PDF

Я хотел бы добавить и удалить водяной знак в PDF с помощью iText 7. Мне удалось добавить водяной знак, но не удалось удалить его снова. Я смог найти только соответствующий код / ​​примеры, относящиеся к iText 5. Любые указатели приветствуются, спасибо.

Вот как я добавил водяной знак (используя слои):

            pdfDoc = new PdfDocument(new PdfReader(sourceFile), new PdfWriter(destinationPath));
            var numberOfPages = pdfDoc.GetNumberOfPages();

            PageSize ps = pdfDoc.GetDefaultPageSize();

            for (var i = 1; i <= numberOfPages; i++)
            {
                PdfPage page = pdfDoc.GetPage(i);
                PdfLayer layer = new PdfLayer("watermark", pdfDoc);
                var canvas = new PdfCanvas(page);
                var pageSize = page.GetPageSize();
                var paragraph = new Paragraph(message.WatermarkText).SetFontSize(60);
                paragraph.SetFontColor(Color.BLACK, 0.2f);

                Canvas canvasModel;
                canvas.BeginLayer(layer);
                canvasModel = new Canvas(canvas, pdfDoc, ps);
                canvasModel.ShowTextAligned(paragraph, pageSize.GetWidth() / 2, pageSize.GetHeight() / 2, pdfDoc.GetPageNumber(page), TextAlignment.CENTER, VerticalAlignment.MIDDLE, 45);
                canvasModel.SetFontColor(Color.GREEN, 0.2f);
                canvas.EndLayer();
            }
            pdfDoc.Close();

Это то, что я пытался удалить водяной знак. Я хочу полностью удалить его, а не просто отключить отображение слоя (приветствуется любой пример кода):

            pdfDoc = new PdfDocument(new PdfReader(sourceFile), new PdfWriter(destinationPath));                     
             IList<PdfLayer> layers = pdfDoc.GetCatalog().GetOCProperties(true).GetLayers();              

            for (var i = 0; i <= layers.Count; i++)
            {
                var t = layers[i].GetPdfObject().Get(PdfName.Name);

                if (t.ToString().Equals("watermark"))
                {
                        //Not what I want..need to remove the layer
                        layers[i].SetOn(false);
                        //This does not work...
                        //layers.RemoveAt(i);
                    }
                }
                pdfDoc.Close();

person Ivan    schedule 29.06.2017    source источник


Ответы (1)


С помощью ребят из iText я смог решить эту проблему. Если вы собираетесь удалить водяной знак позже, вам нужно будет добавить его как «аннотацию водяного знака PDF».

Чтобы добавить водяной знак на каждую страницу:

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

Чтобы удалить водяной знак:

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

А как насчет текста водяного знака переменной длины? Как бы вы динамически изменили размер прямоугольника, чтобы он соответствовал тексту? Это не встроено в iText, вам нужно будет поэкспериментировать со следующими параметрами размеров:

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

Для моего варианта использования я проверил длину текста водяного знака и на основе этого соответствующим образом скорректировал параметры, например:

        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;
        }
person Ivan    schedule 20.07.2017
comment
Спасибо за старания. - person isu3ru; 01.06.2020