Stamping Like Acrobat

I have a pdf file I want to use as a stamp. I’m not sure what the best approach is. Should I convert it to an image and draw it on the document? or what is the best method so it looks and acts like a stamp that acrobat would apply.

Hi Dave and sorry for the late response.

Here is a code snippet that shows how to create a custom stamp annotation:

using System;
using System.IO;
using GemBox.Pdf.Annotations;
using GemBox.Pdf.Content;

namespace GemBox.Pdf.Test.Quick
{
    static partial class Program
    {
        static void Main()
        {
            var desktop = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);

            // For this code snippet, the PDF file to use as a stamp will be simply a copy of the input PDF file.
            File.Copy(Path.Combine(desktop, "Reading.pdf"), Path.Combine(desktop, "ReadingStamp.pdf"), overwrite: true);

            using (var document = PdfDocument.Load(Path.Combine(desktop, "Reading.pdf")))
            {
                PdfForm stampForm;

                // Convert first page of the PDF file you want to use as a stamp to a form.
                using (var stampDocument = PdfDocument.Load(Path.Combine(desktop, "ReadingStamp.pdf")))
                    stampForm = stampDocument.Pages[0].ConvertToForm(document);

                // Use stampForm.SetBoundingBox() and stampForm.Transform if you want to crop or transform (for example, scale) stamp form.

                var page = document.Pages[0];

                var boundingBox = stampForm.BoundingBox;

                // Add the Unknown (custom) stamp annotation whose size is 25% of the input PDF file page size.
                var stampAnnotation = page.Annotations.AddStamp(100, 200, boundingBox.Width / 4, boundingBox.Height / 4, PdfStampIcon.Unknown);

                // Set the appearance of the Stamp annotation.
                stampAnnotation.Appearance.Set(stampForm);

                document.Save(Path.Combine(desktop, "ReadingStamped.pdf"));
            }
        }
    }
}

The next code snippet shows how to create a predefined stamp annotation (dynamic stamp is used because it is the most complex):

using System;
using System.Globalization;
using System.IO;
using GemBox.Pdf.Annotations;

namespace GemBox.Pdf.Test.Quick
{
    static partial class Program
    {
        static void Main()
        {
            var desktop = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);

            using (var document = PdfDocument.Load(Path.Combine(desktop, "Reading.pdf")))
            {
                var page = document.Pages[0];

                // Add the DynamicApproved stamp annotation with default size.
                var stampAnnotation = page.Annotations.AddStamp(100, 200, 0, 0, PdfStampIcon.DynamicApproved);

                // Adjust dynamic parts of the stamp annotation appearance.
                stampAnnotation.Appearance.Name = "John Doe";
                stampAnnotation.Appearance.Date = new DateTimeOffset(2023, 2, 14, 12, 0, 0, new TimeSpan(0, 0, 0));
                stampAnnotation.Appearance.DateFormatProvider = new CultureInfo("en-US");

                document.Save(Path.Combine(desktop, "ReadingStamped.pdf"));
            }
        }
    }
}

Previous versions of GemBox.Pdf didn’t support Stamp annotations but it was possible to create them via low-level API.

Here is a code snippet that shows how to do it:

using System;
using System.IO;
using GemBox.Pdf.Content;
using GemBox.Pdf.Objects;

namespace GemBox.Pdf.Test.Quick
{
    static partial class Program
    {
        static void Main()
        {
            var desktop = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);

            // For this code snippet, the PDF file to use as a stamp will be simply a copy of the input PDF file.
            File.Copy(Path.Combine(desktop, "Reading.pdf"), Path.Combine(desktop, "ReadingStamp.pdf"), overwrite: true);

            using (var document = PdfDocument.Load(Path.Combine(desktop, "Reading.pdf")))
            {
                PdfForm stampForm;

                // Convert first page of the PDF file you want to use as a stamp to a form.
                using (var stampDocument = PdfDocument.Load(Path.Combine(desktop, "ReadingStamp.pdf")))
                    stampForm = stampDocument.Pages[0].ConvertToForm(document);

                // Use stampForm.SetBoundingBox() and stampForm.Transform if you want to crop or transform (for example, scale) stamp form.

                var page = document.Pages[0];

                // Get or add the underlying Annots array to the page object via low-level API.
                var annots = page.Annotations.GetOrAddArray();

                // Create Stamp annotation dictionary.
                var stampAnnot = PdfDictionary.Create(
                    new PdfDictionaryEntry("Subtype", PdfName.Create("Stamp")),
                    new PdfDictionaryEntry("Rect", PdfArray.Create(PdfNumber.Create(100), PdfNumber.Create(200), PdfNumber.Create(300), PdfNumber.Create(400))),
                    new PdfDictionaryEntry("P", page.GetDictionary().Indirect));

                // Set the Print flag.
                // See https://opensource.adobe.com/dc-acrobat-sdk-docs/standards/pdfstandards/pdf/PDF32000_2008.pdf#page=393
                stampAnnot.Add(PdfName.Create("F"), PdfInteger.Create(1 << (3 - 1)));

                // Add Stamp annotation dictionary to the Annots array as an indirect object.
                annots.Add(PdfIndirectObject.Create(stampAnnot));

                // Access the last annotation via high-level API.
                var stampAnnotation = page.Annotations[page.Annotations.Count - 1];

                // Set the appearance of the Stamp annotation.
                stampAnnotation.Appearance.Set(stampForm);

                document.Save(Path.Combine(desktop, "ReadingStamped.pdf"));
            }
        }
    }
}

The file used in these code snippets you can download from our example Read text from PDF files with C# / VB.NET applications

Regards,
Stipo

Hello, Thanks for the snippet. I managed to make that work but for some reason it will not print with the document. I’ve searched for a setting but can’t seem to find the right combination to get it to print.

Thanks.
Dave

Hi Dave!

You must set the Print flag in the annotation’s Flags entry (the F entry).

Please see the updated code snippet from my previous answer.

Regards,
Stipo

Thank you Stipo, I never would have found that without your help. I wish I knew more about this stuff.

Thanks to you and Mario for the great support!

Hi stipo, using your 1st sample code block works well. However, I have observed the following:
Open the resulting document in Adobe Reader. With the mouse over the 1st page, right click. The context menu that comes up, looks like this:

RightClick1

If you click the Properties option in that menu, this comes up :

StampProperties

So its like the Stamp is “active”, and the user can see its properties, and edit them via Adobe Reader etc.

Is it possible to make the stamp not editable ?
e.g. so ideally (if technically possible), when I right click on the 1st page, I will see the standard context menu, like:

Thanks

Hi,

There are two ways to disable editing of stamp properties:

  1. Lock the annotation:
    stampAnnotation.Locked = true;

Users can still unlock it via Adobe Reader user interface.

  1. Make the annotation read-only (currently possible only via low-level API):
// Set the ReadOnly flag.
// See https://opensource.adobe.com/dc-acrobat-sdk-docs/standards/pdfstandards/pdf/PDF32000_2008.pdf#page=393
var stampAnnotationDictionary = stampAnnotation.GetDictionary();
var fName = PdfName.Create("F");
int f = 0;
if(stampAnnotationDictionary.TryGetValue(fName, out PdfBasicObject fValue))
{
    if (fValue.ObjectType == PdfBasicObjectType.IndirectObject)
        fValue = ((PdfIndirectObject)fValue).Value;

    f = ((PdfInteger)fValue).Value;
}
stampAnnotationDictionary[fName] = PdfInteger.Create(f | (1 << (7 - 1)));

Users can still view stamp annotation properties but cannot edit them via Adobe Reader user interface.

The only way to disable annotation right-click context menu is to flatten the annotation (draw it directly in the page’s content) and remove it from the page’s annotation collection:

page.Content.DrawAnnotation(stampAnnotation);
page.Annotations.Remove(stampAnnotation);

Regards,
Stipo

Thanks Stipo, I ended up flattening the annotation, which worked great.