.NET에서 PDF 문서 페이지에 워터마크 추가하기

블로그 카테고리: PDF.NET

2020/09/11

"워터마크"는 기존 문서 내용 앞에 나타나는 텍스트 또는 이미지입니다. 예를 들어, 민감한 정보가 포함된 PDF 페이지에 "기밀" 워터마크를 적용할 수 있습니다.

VintaSoft PDF .NET Plug-in의 "PDF Reader+Writer" 버전은 PDF 문서 페이지에 워터마크를 추가하는 기능을 제공합니다.

PDF 문서의 텍스트와 겹치지 않도록 워터마크는 "곱하기(Multiply)" 색상 혼합 모드로 추가해야 합니다.
하나의 워터마크 리소스가 문서의 모든 페이지에 사용되어 최적의 크기로 PDF를 생성합니다.
래스터 이미지 또는 벡터 PDF 문서를 워터마크로 정의할 수 있습니다.

다음은 PDF 문서에 워터마크를 추가하는 C# 코드입니다.
// 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();
    }
}     


다음은 워터마크가 추가된 모든 페이지가 포함된 PDF 문서의 예입니다. testDocument_marked.pdf.