Fastest way to add a watermark

We are using Apose.PDF version 18.1 to add an image watermark on every page. We are concerned with the performance of this.
I attached the input PDF(lorem.input.pdf (49.5 KB)) and the output PDF (lorem.output.pdf (537.2 KB))

Details:

  1. We are aiming at adding a watermark that is formed of 2 pieces of text that are separated by some empty lines
  2. We are creating a BMP memory file of the watermark and then apply it to each page of the input PDF using this code:
        //entertain a list of watermark images that are page size specific
        var imageWatermarks = new List<ImageWatermarkData>();

        for (var i = 1; i <= inputPdfDocument.Pages.Count; i++)
        {
            var page = inputPdfDocument.Pages[i];

            var imageWatermarkWidth = (int) page.CropBox.Width;
            var imageWatermarkHeight = (int) page.CropBox.Height;

            //search for an existing image watermark of the same width and height
            var imageWatermarkToUse =
                imageWatermarks
                    .FirstOrDefault(iw =>
                        iw.Width == imageWatermarkWidth
                        && iw.Height == imageWatermarkHeight);

            if (imageWatermarkToUse == null)
            {
                imageWatermarkToUse =
                    new ImageWatermarkData
                    {
                        Width = imageWatermarkWidth,
                        Height = imageWatermarkHeight,
                        Image = new MemoryStream()
                    };

                FromTextWatermarks(inputTextWatermarks, imageWatermarkWidth, imageWatermarkHeight,
                    imageWatermarkToUse.Image);

                imageWatermarks.Add(imageWatermarkToUse);
            }

            //add it to PDF resources
            var xImageIdentifier =
                page.Resources.Images.Add(imageWatermarkToUse.Image);

            page.Contents.Add(new Operator.GSave());
            page.Contents.Add(
                new Operator.ConcatenateMatrix(new Aspose.Pdf.Matrix(
                    imageWatermarkWidth,
                    0,
                    0,
                    imageWatermarkHeight,
                    0,
                    0)
                ));
            page.Contents.Add(new Operator.Do(xImageIdentifier));
            page.Contents.Add(new Operator.GRestore());
        }
  1. FromTextWatermarks will create the bitmap image that is specific the size of page.

We struggled in the past with text stamps for creating this flexible watermark that works well with 2 separate pieces of text and different sizes for them and spans vertically both on top and center-bottom of the page.

Is there any way to get this with kind of watermark with better performance? It takes even 45 seconds for a 245 pages for some of specific PDFs and in general is the most consuming task we have when handling PDFs.

Best regards!

@gwert

Thank you for contacting support.

We would like to request you to use Aspose.PDF for .NET 18.5 in your environment and then share your observations about time consumption while adding watermarks. The code snippet shared by you includes undefined Class and Method so it can not be tested. Please share a sample application containing SSCCE code so that we may investigate the scenario in our environment. Please also share the sample file with 245 pages, that you are referring to; for our reference.

Hi,

I attached the ImageWatermarker.zip (257.5 KB)
The only thing this project is missing is the license file that should stay at Properties\Aspose.Total.lic with Build Action = EmbeddedResource.

As for the version of Aspose.PDF, we are forced by this issue (Exception "Image export failed" when coverting DWG to PDF using Aspose.CAD for .NET - #2 by mudassir.fayyaz) to stay on version 18.1 so that we can still have CAD support.

Just as a quick reminder, we would like to achieve a flexible watermark that works well with 2 separate pieces of text and different sizes for them and spans vertically both on top and center-bottom of the page. We are using an image watermark since we had a hard time using textstamps in the past.

But we can embrace any suggestion that will improve performance of applying a watermark that suits our needs (now is 5 seconds on a 120 pages doc) and reduce the size of the output (now is 21Mb from a 300KB one).

Thank you!

@gwert

Thank you for sharing requested data.

We would like to share with you that you are adding the image to resources of each page which results in slow performance and larger PDF file. Alternatively, you can reference to the same PDF object as original image with XImageCollection.Add(XImage) method as in the code snippet below:

        var pdfLicense = new License();
        pdfLicense.SetLicense("Aspose.Total.lic");
        pdfLicense.Embedded = true;
        
        using (Aspose.Pdf.Document document = new Document("lorem.input.pdf"))
        {
            using (var imageStream = File.Open("watermark.png", FileMode.Open))
            {
                XImage image = null;
                foreach (Page page in document.Pages)
                {
                    Rectangle imageRectangle = page.CropBox;
                    WatermarkAnnotation annotation = new WatermarkAnnotation(page, page.Rect);

                    string name;
                    if (image == null)
                    {
                        name = page.Resources.Images.Add(imageStream);
                        image = page.Resources.Images[name];
                    }
                    else
                    {
                        name = page.Resources.Images.Add(image);
                    }

                    page.Contents.Add(new Operator.GSave());
                    page.Contents.Add(new Operator.ConcatenateMatrix(new Aspose.Pdf.Matrix(imageRectangle.Width, 0, 0, imageRectangle.Height, 0, 0)));
                    page.Contents.Add(new Operator.Do(name));
                    page.Contents.Add(new Operator.GRestore());

                    page.Annotations.Add(annotation);
                }
            }

            document.Save("output_18.5.pdf");

It adds the watermark in about three seconds and resultant file size is about 500 KB. We have also attached the PDF file for your kind reference. output.pdf (507.0 KB). We hope this will be helpful.

Hello,

This is indeed great improvement! Clearly the watermark is getting applied faster and the output PDF is smaller!

Is there any reason an annotation was added?

Also, is there any way to accomplish the same watermark (in terms of layout: with 2 lines of different font sizes, one aligned to top and the other center-bottom) using text stamps?

Thank you!

@gwert

Thank you for your kind feedback.

We are glad to know that suggested approach has helped you. Moreover, different approaches including TextStamp, ImageStamp, Annotation can be used to add a watermark and annotation approach is randomly used in previous code snippet.

About TextStamp, we are afraid that a single stamp can not include text of different font heights. Therefore, you need to use more than one TextStamp for such a scenario, as in the code snippet below:

        Document pdfDocument = new Document(dataDir + "lorem.input.pdf");
        string str = "Very long text watermark";
        TextStamp textStamp = new TextStamp(str);
        //set text properties
        textStamp.TextState.Font = FontRepository.FindFont("Arial");
        textStamp.TextState.FontSize = 16F;
        textStamp.TextState.FontStyle = FontStyles.Bold;
        textStamp.TextState.FontStyle = FontStyles.Italic;
        textStamp.TextState.ForegroundColor = Aspose.Pdf.Color.FromRgb(System.Drawing.Color.Red);
        textStamp.Opacity = 0.5;
        textStamp.VerticalAlignment = VerticalAlignment.Top;
        textStamp.HorizontalAlignment = HorizontalAlignment.Center;

        TextStamp textStamp1 = new TextStamp(str);
        //set text properties
        textStamp1.TextState.Font = FontRepository.FindFont("Arial");
        textStamp1.TextState.FontSize = 28F;
        textStamp1.TextState.FontStyle = FontStyles.Bold;
        textStamp1.TextState.FontStyle = FontStyles.Italic;
        textStamp1.TextState.ForegroundColor = Aspose.Pdf.Color.FromRgb(System.Drawing.Color.Red);
        textStamp1.Opacity = 0.5;
        //textStamp1.VerticalAlignment = VerticalAlignment.Bottom;
        textStamp1.YIndent = 50;

        textStamp1.HorizontalAlignment = HorizontalAlignment.Center;

        foreach (Page page in pdfDocument.Pages)
        {
            page.AddStamp(textStamp);
            page.AddStamp(textStamp1);
        }
        pdfDocument.Save(dataDir + "Watermark_18.5.pdf");

We hope this will be helpful. Please feel free to contact us if you need any further assistance.

Hi,

I prepared a test app (TextWatermark.zip (108.9 KB)) that tries to apply the lower (the one with bigger font size) text stamp dynamically so that it looks good on all page orientations and page sizes.

The general rule here is that the text stamp should be aligned to bottom at about 1/4 of page height, centered horizontally, with wrap on so that is breaks on as many lines as it needs (that requires a width to be set to page width - 100).

Please pay attention to the width of the text stamp. It will not span to the full width - 100 of the landscape page (page #2). It behaves as if once set, the width cannot be changed.

I have tried to add a new text stamp that is created for each page and that works but that comes with a considerable decrease in performance.

What am I missing?

Thank you!

@gwert

We have worked with the data shared by you and have been able to notice the problem when page size varies in a document. We have logged a ticket with ID PDFNET-44763 in our issue management system for further investigation and resolution. The ticket ID has been linked with this thread so that you will receive notification as soon as the ticket is resolved.

We are sorry for the inconvenience.

Hi,

Thank you for looking into adding watermarks using test stamps.

Is there any similar way (other than image watermark or text stamps) that is worth looking into?
Like using annotations?

Thank you!

@gwert

You can add watermark annotation to a PDF document by using below code snippet in your environment.

    Document pdf = new Document();
    Page page = pdf.Pages.Add();
    WatermarkAnnotation wa = new WatermarkAnnotation(page, new Rectangle(100, 500, 400, 600));
    Aspose.Pdf.Text.TextState ts = new Aspose.Pdf.Text.TextState();
    ts.ForegroundColor = Aspose.Pdf.Color.Blue;
    ts.Font = FontRepository.FindFont("Times New Roman");
    ts.FontSize = 32;
    wa.Opacity = 0.5;
    wa.SetTextAndState(new string [] {"TEST WATERMARK"} , ts);
    page.Annotations.Add(wa);
    pdf.Save(dataDir + "WatermarkAnnotation_18.5.pdf");

We hope this will be helpful. Please feel free to contact us if you need any further assistance.