Agrega una marca de agua a las páginas de un documento PDF en .NET

Categoría del blog: PDF.NET

11.09.2020

Una "marca de agua" es un texto o una imagen que aparece delante del contenido del documento. Por ejemplo, podría aplicar una marca de agua "Confidencial" a páginas PDF con información confidencial. La edición

"PDF Reader+Writer" del Plugin VintaSoft PDF .NET permite añadir marcas de agua a las páginas de un documento PDF.

Para no superponer el texto del documento PDF, la marca de agua debe agregarse en el modo de fusión de colores "Multiplicar".
Se utiliza una marca de agua para todas las páginas del documento para crear un PDF con un tamaño óptimo.
Una imagen rasterizada o un documento PDF vectorial se puede definir como marca de agua.

A continuación, se muestra código en C# que permite agregar una marca de agua a un documento PDF:
// The project, which uses this code, must have references to the following assemblies:
// - Vintasoft.Imaging
// - Vintasoft.Imaging.Pdf

/// <summary>
/// Adds the watermark image to the PDF document.
/// </summary>
/// <param name="inPdfFilename">The filename of input PDF document.</param>
/// <param name="outPdfFilename">The filename of output PDF document.</param>
/// <param name="watermarkImageFilename">The filename of watermark image.</param>
public static void AddWatermarkToPdfDocument(string inPdfFilename, string outPdfFilename, string watermarkImageFilename)
{
    AddWatermarkToPdfDocument(inPdfFilename, outPdfFilename, watermarkImageFilename, 0.25f, new Vintasoft.Imaging.PaddingF(0.1f), false);
}

/// <summary>
/// Adds the watermark image to the PDF document.
/// </summary>
/// <param name="inPdfFilename">The filename of input PDF document.</param>
/// <param name="outPdfFilename">The filename of output PDF document.</param>
/// <param name="watermarkImageFilename">The filename of watermark image.</param>
/// <param name="watermarkImageAlpha">The watermark image alpha.</param>
/// <param name="watermarkImagePadding">The watermark image padding.</param>
/// <param name="ignorePageRotation">Indicates that value of Vintasoft.Imaging.Pdf.Tree.PdfPage.Rotate property should be ignored.</param>
public static void AddWatermarkToPdfDocument(
    string inPdfFilename,
    string outPdfFilename,
    string watermarkImageFilename, 
    float watermarkImageAlpha,
    Vintasoft.Imaging.PaddingF watermarkImagePadding,
    bool ignorePageRotation)
{
    // check watermark padding
    if (watermarkImagePadding.Horizontal < 0 || watermarkImagePadding.Vertical < 0)
        throw new System.ArgumentOutOfRangeException("watermarkImagePadding");

    // open PDF document
    using (Vintasoft.Imaging.Pdf.PdfDocument document = new Vintasoft.Imaging.Pdf.PdfDocument(inPdfFilename))
    {
        // create "watermark" resource
        Vintasoft.Imaging.Pdf.Tree.PdfResource watermakResource;
        using (Vintasoft.Imaging.VintasoftImage watermarkImage = new Vintasoft.Imaging.VintasoftImage(watermarkImageFilename))
        {
            // if watermarkImage is PDF page
            if (watermarkImage.SourceInfo.DecoderName == "Pdf")
            {
                // create form resource based on PDF page
                Vintasoft.Imaging.Pdf.Tree.PdfPage page = Vintasoft.Imaging.Pdf.PdfDocumentController.GetPageAssociatedWithImage(watermarkImage);
                watermakResource = new Vintasoft.Imaging.Pdf.Tree.PdfFormXObjectResource(document, page);
            }
            else
            {
                // create watermark image resource with JPEG compression
                Vintasoft.Imaging.Pdf.PdfCompression watermarkResourceCompression = Vintasoft.Imaging.Pdf.PdfCompression.Jpeg;
                watermakResource = new Vintasoft.Imaging.Pdf.Tree.PdfImageResource(document, watermarkImage, watermarkResourceCompression);
            }
        }

        // for each page in PDF document
        foreach (Vintasoft.Imaging.Pdf.Tree.PdfPage page in document.Pages)
        {
            // add watermark on PDF page
            AddWatermarkToPdfPage(page, watermakResource, watermarkImagePadding, watermarkImageAlpha, ignorePageRotation);
        }

        // pack PDF document to an output file
        document.Pack(outPdfFilename);
    }
}

/// <summary>
/// Adds the watermark image to the PDF page.
/// </summary>
/// <param name="page">The PDF page.</param>
/// <param name="watermarkResource">The PDF resource that contains watermark.</param>
/// <param name="watermarkImagePadding">The watermark image padding.</param>
/// <param name="watermarkImageAlpha">The watermark image alpha.</param>
/// <param name="ignorePageRotation">Indicates that value of Vintasoft.Imaging.Pdf.Tree.PdfPage.Rotate property should be ignored.</param>
public static void AddWatermarkToPdfPage(
    Vintasoft.Imaging.Pdf.Tree.PdfPage page,
    Vintasoft.Imaging.Pdf.Tree.PdfResource watermarkResource,
    Vintasoft.Imaging.PaddingF watermarkImagePadding,
    float watermarkImageAlpha,
    bool ignorePageRotation)
{
    Vintasoft.Imaging.Pdf.Tree.PdfImageResource watermarkImageResource = watermarkResource as Vintasoft.Imaging.Pdf.Tree.PdfImageResource;
    Vintasoft.Imaging.Pdf.Tree.PdfFormXObjectResource watermarkFormResource = watermarkResource as Vintasoft.Imaging.Pdf.Tree.PdfFormXObjectResource;

    // gets the size of watermark resource
    System.Drawing.SizeF watermarkResourceSize;
    if (watermarkImageResource != null)
        watermarkResourceSize = new System.Drawing.SizeF(watermarkImageResource.Width, watermarkImageResource.Height);
    else
        watermarkResourceSize = new System.Drawing.SizeF(watermarkFormResource.BoundingBox.Width, watermarkFormResource.BoundingBox.Height);

    // create PDF graphics from PDF page and specify that graphics must clear and add new content
    using (Vintasoft.Imaging.Pdf.Drawing.PdfGraphics graphics = Vintasoft.Imaging.Pdf.Drawing.PdfGraphics.FromPage(page))
    {
        // get mediabox of PDF page
        System.Drawing.RectangleF pageMediaBox = page.MediaBox;

        // if watermark image must be rotated
        if (!ignorePageRotation && page.Rotate != 0)
        {
            // rotate padding
            watermarkImagePadding.Rotate(page.Rotate);
        }

        // calculate watermark rectangle
        System.Drawing.RectangleF watermarkRect = new System.Drawing.RectangleF(
            pageMediaBox.X + watermarkImagePadding.Left * pageMediaBox.Width,
            pageMediaBox.Y + watermarkImagePadding.Bottom * pageMediaBox.Height,
            pageMediaBox.Width - watermarkImagePadding.Horizontal * pageMediaBox.Width,
            pageMediaBox.Height - watermarkImagePadding.Vertical * pageMediaBox.Height);
        float scale = System.Math.Min(watermarkRect.Width / watermarkResourceSize.Width, watermarkRect.Height / watermarkResourceSize.Height);
        System.Drawing.RectangleF watermarkImageRect = new System.Drawing.RectangleF(
            watermarkRect.X + (watermarkRect.Width - watermarkResourceSize.Width * scale) / 2,
            watermarkRect.Y + (watermarkRect.Height - watermarkResourceSize.Height * scale) / 2,
            watermarkResourceSize.Width * scale,
            watermarkResourceSize.Height * scale);

        // create graphics state parameters
        Vintasoft.Imaging.Pdf.Tree.PdfGraphicsStateParameters gsParams = new Vintasoft.Imaging.Pdf.Tree.PdfGraphicsStateParameters(page.Document);
        // set blending mode to "Multiply"
        gsParams.BlendMode = Vintasoft.Imaging.Pdf.Tree.GraphicsStateBlendMode.Multiply;
        // set alpha transparency
        gsParams.AlphaForNonStrokingOperations = watermarkImageAlpha;

        // save graphics state
        graphics.SaveGraphicsState();

        // set graphics state parameters
        graphics.SetGraphicsStateParameters(gsParams);

        // if watermark image must be rotated
        if (!ignorePageRotation && page.Rotate != 0)
        {
            // apply rotation to the PdfGraphics
            Vintasoft.Imaging.AffineMatrix matrix = new Vintasoft.Imaging.AffineMatrix();
            matrix.RotateAt(
                page.Rotate,
                watermarkImageRect.X + watermarkImageRect.Width / 2,
                watermarkImageRect.Y + watermarkImageRect.Height / 2);
            graphics.MultiplyTransform(matrix);
        }

        // if watermark is an image
        if (watermarkImageResource != null)
            // draw watermark image
            graphics.DrawImage(watermarkImageResource, watermarkImageRect);
        else
            // draw watermark form
            graphics.DrawForm(watermarkFormResource, watermarkImageRect);

        // restore graphics state
        graphics.RestoreGraphicsState();
    }
}     


A continuación, se muestra un ejemplo de un documento PDF cuya página contiene la marca de agua: testDocument_marked.pdf.