A digital watermark is any auxiliary data embedded into a document used for subsequent identification. Watermarks may provide contextual support to an author's content, but are otherwise independent of that content. For example, stamping a page as "DRAFT" or "CONFIDENTIAL" imparts meaning beyond any text or drawings present on that page.
For sample code, refer to the AddWatermarkToPDFPage sample. See Samples and Demos.
PDF documents may express a digital watermark using any of the following techniques:
- Annotations: An interactive object associated with a location on the page that displays text or an image. A variety of types may be used including Text, Free text, or Rubber stamp.
- Page Graphics: Graphics may include text with specific style information and color, vector line art, sampled images or shading patterns. Content representing a watermark are inserted directly into the page's content stream, possibly indistinguishable from the original content. Graphics specifically intended for watermarks may be indicated using Optional Content Groups.
- Optional Content Groups (OCG): Collections of graphics in a PDF document can be selectively drawn or hidden by document authors or consumers. An OCG can indicate its graphics are intended as a watermark for printing.
- Pagination Artifacts: Tagged PDF documents distinguish between original content and artifacts of the layout process, including pagination artifacts such as header, footers, page numbers. Content may be specifically designated to be a watermark.
Most of these techniques can be accomplished using ImageGear, with varying complexity and completeness.
Annotations
ImageGear does not support creating or editing PDF annotations.
Page Graphics
Watermarks expressed as PDF page graphics are added using the ImageGear.Formats.PDF
namespace. This namespace provides classes for content editing modeled after graphics objects and operators described in the PDF Reference.
The following snippet demonstrates placing a 24-bpp RGB bitmap at the bottom left corner of a PDF page:
PDF support needs to be initialized first for this snippet to work. To get familiar with initializing IGNET, initializing PDF support, loading a PDF, saving a PDF, and terminating PDF support, refer to our samples on github.
Adjustments are required to successfully add images utilizing other pixel formats and color spaces in accordance to the image XObject discussion in the PDF reference.
C#
using System;
using System.IO;
using System.Windows.Forms;
using ImageGear.Core;
using ImageGear.Formats;
using ImageGear.Formats.PDF;
public static void AddRGB24ImageToPdfPage(ImGearPDFPage igPDFPage, ImGearPage igImage)
{
const Int32 BITS_PER_BYTE = 8;
try
{
// Acquire the PDF page content.
using (ImGearPDEContent content = igPDFPage.GetContent())
{
// Extract pixel data from RGB24 image.
Int32 strideInBytes = (igImage.DIB.Width * igImage.DIB.BitDepth + BITS_PER_BYTE - 1)
/ BITS_PER_BYTE;
Byte[] pixelData = new Byte[strideInBytes * igImage.DIB.Height];
for (int row = 0; row < igImage.DIB.Height; row++)
{
ImGearArrayRef raster = igImage.DIB.GetRaster(row);
Array.Copy((Byte[])raster.Content, raster.Offset, pixelData, row * strideInBytes,
strideInBytes);
}
// Create a DeviceRGB PDE Colorspace for RGB24 image.
ImGearPDEColorSpace igPDEColorSpace = new ImGearPDEColorSpace(
new ImGearPDFAtom("DeviceRGB"));
// Create a PDE Image attributes for image Form XObject
ImGearPDEImageAttrs igPDEImageAttrs = new ImGearPDEImageAttrs();
igPDEImageAttrs.Width = igImage.DIB.Width;
igPDEImageAttrs.Height = igImage.DIB.Height;
igPDEImageAttrs.Flags = ImGearPDEImageAttrFlags.EXTERNAL;
igPDEImageAttrs.BitsPerComponent = 8;
// Create a transform matrix that places the image at the bottom-left corner
// of the PDF page.
ImGearPDFFixedMatrix igPDETransformMatrix = new ImGearPDFFixedMatrix();
igPDETransformMatrix.A = ImGearPDF.DoubleToFixed(((double)igImage.DIB.Width));
igPDETransformMatrix.B = (int)ImGearPDFFixedValues.ZERO;
igPDETransformMatrix.C = (int)ImGearPDFFixedValues.ZERO;
igPDETransformMatrix.D = ImGearPDF.DoubleToFixed(((double)igImage.DIB.Height));
igPDETransformMatrix.H = (int)ImGearPDFFixedValues.ZERO;
igPDETransformMatrix.V = (int)ImGearPDFFixedValues.ZERO;
// Create a filter to compress RGB24 pixel data using the discrete cosine
// transform (DCT) technique based on the JPEG standard.
ImGearPDEFilterArray igPDEFilterArray = new ImGearPDEFilterArray();
ImGearPDFBasDict igDict = new ImGearPDFBasDict((ImGearPDFDocument)igPDFPage.Document,
false, 3);
igDict.PutInt(new ImGearPDFAtom("Columns"), false, igImage.DIB.Width);
igDict.PutInt(new ImGearPDFAtom("Rows"), false, igImage.DIB.Height);
igDict.PutInt(new ImGearPDFAtom("Colors"), false, 3);
ImGearPDEFilterSpec igPDEFilterSpec = new ImGearPDEFilterSpec();
igPDEFilterSpec.Name = new ImGearPDFAtom("DCTDecode");
igPDEFilterSpec.DecodeParams = igDict;
igPDEFilterSpec.EncodeParams = igDict;
igPDEFilterArray.AddSpec(igPDEFilterSpec);
// Create the PDE image.
using (ImGearPDEImage igPDEImage = new ImGearPDEImage(igPDEImageAttrs,
igPDETransformMatrix, ImGearPDEImageDataFlags.DECODED, igPDEColorSpace, null,
igPDEFilterArray, null, pixelData))
{
// Add the PDEImage to the PDF page graphics.
content.AddElement((int)ImGearPDEInsertElement.AFTER_LAST, igPDEImage);
igPDFPage.SetContent();
// Force refresh of PDF page content.
igPDFPage.ResetDisplayCache();
}
}
}
finally
{
// Release the PDF page content.
igPDFPage.ReleaseContent();
}
}
Refer to the AddWatermarkToPDFPage sample. See Samples and Demos.
See the PDF Reference topic "Graphics" for additional information.
See ImGearPDFFixedMatrix
Class for information about defining a transformation matrix.
Optional Content Groups
Watermark optional content can be added to PDF pages using the ImageGear.Formats.PDF
namespace, which provides classes for layer management.
Refer to Containers, Dictionaries, and Layers
for guidance on using the ImageGear.Formats.PDF
namespace to manage watermarks with Optional Content Groups (OCG).
To designate a watermark intended for printing, add an Optional Content Print Usage dictionary with Subtype name "Watermark" to that OCG, represented with an ImGearPDFLayer
object:
C#
// Create Print Usage dictionary
ImGearPDFBasDict igPrintUsageDict = new ImGearPDFBasDict( igPDFDocument, false, 2 );
igPrintUsageDict.PutName( new ImGearPDFAtom("Subtype"), false, new ImGearPDFAtom( "Watermark" ));
igPrintUsageDict.PutName( new ImGearPDFAtom("PrintState"), false, new ImGearPDFAtom( "ON" ));
// Add Print Usage dictionary to OCG group named "WatermarkLayer"
ImGearPDFLayer igWatermarkLayer = igPDFDocument.CreateLayer( "WatermarkLayer" );
igWatermarkLayer.SetUsageInfo( new ImGearPDFAtom("Print"), igPrintUsageDict );
See the PDF Reference topic "Making Graphical Content Optional" for additional information.
Pagination Artifacts
Watermarks expressed as Pagination Artifacts can be added using the ImageGear.Formats.PDF
namespace, which provides classes to create a marked-content sequence in accordance with the PDF Reference.
This usage is not demonstrated in any sample presently.
See the PDF Reference topic "Real Content and Artifacts" for additional information.