Chapter 19: Transparency

Contents

19.1 PdfGState Object: Overview

19.1.1 PdfGState As a Graphics State Object

A graphics state is a central notion in the PDF format. The current graphics state is made up of many parameters affecting painting operations such as the current stroke and fill colors, line width, font, and many others. With AspPDF.NET, the graphics state is modified via various properties and methods of the PdfCanvas object such as SetFillColor or LineWidth. See Section 4.4 - Managing Graphics State for a detailed discussion of the graphics state.

As an alternative to setting individual parameters via separate operators, PDF also allows multiple parameters of the current graphics state to be modified in a single operation, via the graphics state object referred to in the PDF specifications as ExtGState. An instance of the graphics state object is created and populated with multiple parameters and then selected in a single step, and can be reused if necessary. While using the graphics state object seems redundant, there are in fact certain graphics state parameters that can only be specified via a graphics state object and not any other way. Transparency-related parameters are among those that require a graphics state object. As of Version 3.1, in order for AspPDF.NET to support transparency, its object model has been expanded to include a new object, PdfGState, which represents both a PDF ExtGState object, and a transparency group described in the following subsection.

An instance of the PdfGState object is created via the PdfDocument method CreateGState. This method expects a single argument, a PdfParam object or parameter string specifying various graphics state parameters including those related to transparency. To activate this PdfGState object, it is passed to the PdfCanvas method SetGState.

The following code snippet draws a semi-transparent text over a PDF page. The blend mode (BlendMode parameter) is set to Normal (1). Blend modes are covered in detail below. Both the stroke and fill transparency values (Alpha and FillAlpha parameters) are set to 0.2 (20%.)

PdfManager objPdf = new PdfManager();
PdfDocument objDoc = objPdf.OpenDocument(@"c:\path\doc.pdf");
PdfGState objGState = objDoc.CreateGState("BlendMode=1; Alpha=0.2; FillAlpha=0.2");
PdfPage objPage = objDoc.Pages[1];
objPage.Canvas.SetGState( objGState );
objPage.Canvas.DrawText( "DRAFT", "x=-40; y=170; angle=52; size=240; color=blue", objDoc.Fonts["Helvetica"] );
objDoc.Save( @"c:\path\out.pdf", false );

19.1.2 PdfGState As a Transparency Group Object

In addition to representing a graphics state object, the PdfGState object has also been assigned the task of representing a transparency group, an important entity in the PDF transparency model. Transparency groups are described in detail below.

To create a transparency group rather than a graphics state object, the CreateGState method must be called with the Group=True parameter. Other group-related parameters can be specified as well. When the Group parameter is set to True, all graphics state-related parameters are ignored. The instance of the PdfGState object representing a transparency group can then be assigned to a PdfGraphics or PdfPage object via the method SetGroup, for example:

...
PdfGState objGroup = objDoc.CreateGState("Group=True");
PdfGraphics objGraphics = objDoc.CreateGraphics("left=0; bottom=0; right=200; top=200");
objGraphics.SetGroup( Group );
...

The meaning of this code snippet will be explained below.

19.2 Blend Mode

From the Adobe PDF Reference: "The original Adobe imaging model paints objects (fills, strokes, text, and images) opaquely onto a page. The color of the page at any point is that of the topmost enclosing object, disregarding any previous objects it may overlap... Under the transparency imaging model, all of the objects on a page can potentially contribute to the result. Objects at a given point can be thought of as forming a transparency stack (or stack for short). The objects are arranged from bottom to top in the order in which they are specified. The color of the page at each point is determined by combining the colors of all enclosing objects in the stack according to compositing rules defined by the transparency model... A given object is composited with a backdrop. Ordinarily, the backdrop consists of the stack of all objects that have been specified previously. The result of compositing is then treated as the backdrop of the next object."

NOTE: A comprehensive description of the PDF Transparency Model is beyond the scope of this user manual. Please refer to the Adobe PDF Reference for detailed information on this complex subject.

Under the PDF transparency model, when an object is painted, its color and alpha values are combined with the current backdrop's color and alpha values to form a new current color and alpha values. The new values are computed according to the basic color compositing formula which takes into account the source color (Cs), backdrop color (Cb), source alpha (αs), backdrop alpha (αb), and a blend function B(Cb, Cs) which specifies how the source and backdrop colors are combined in the painting operation:

The blend function determines the blend mode of the painting operation and there are 16 pre-defined blend modes to choose from. For example, under the Normal blend mode the blend function is simply

B(Cb, Cs) = Cs

and under the Multiply mode it is

B(Cb, Cs) = Cb x Cs

The blend mode is specified via the BlendMode parameter of the PdfDocument.CreateGState method. The valid values are 1 to 16.

The following table summarizes all the available blend modes and their effects when the picture of a duck is painted on top of the picture of a rainbow.

Name
BlendMode
Effect
Name
BlendMode
Effect
Normal
1
Multiply
2
Screen
3
Overlay
4
Darken
5
Lighten
6
ColorDodge
7
ColorBurn8
8
HardLight
9
SoftLight
10
Difference11
11
Exclusion
12
Hue
13
Saturation
14
Color
15
Luminosity
16

19.3 Transparency Groups

19.3.1 Groups: Overview

One or more consecutive objects in a stack can be collected together into a transparency group, or simply group. The group as a whole can have various properties that modify the compositing behavior of objects within the group and their interactions with its backdrop. An additional blend mode and alpha can also be associated with the group as a whole and used when compositing it with its backdrop. Groups can be nested within other groups.

With AspPDF.NET, a transparency group is implemented by a PdfGraphics object linked to a PdfGState object representing a group, as follows:

PdfGState objGroup = objDoc.CreateGState("Group=true; <other parameters>");
PdfGraphics objGraph = objDoc.CreateGraphics("<list of parameters>");
objGraph.SetGroup( objGroup );

The following four images demonstrate the effects of transparency grouping. In the upper two figures, three colored circles are painted as independent objects with no grouping. At the upper left, the three objects are painted opaquely; each completely replaces its backdrop (including previously painted objects) with its own color. At the upper right, the same three independent objects are painted with an opacity of 0.5, causing them to composite with each other and with the gray and white background. In the lower two figures, the three objects are combined as a transparency group. At the lower-left, the individual objects have an opacity of 1.0 within the group, but the group as a whole is painted in the Normal blend mode (BlendMode=1) with an opacity of 0.5 (FillAlpha=0.5). At the lower right, the objects have an opacity of 0.5 within the group and thus compose with each other. The group as a whole is painted against the backdrop with an opacity of 1.0 but in a different blend mode, HardLight (BlendMode=9), producing a different visual effect.

Below is the corresponding AspPDF.NET script:

PdfDocument objDoc;
PdfPage objPage;

void Page_Load(Object Source, EventArgs E)
{
  // Common part: draw background
  PdfManager objPdf = new PdfManager();
  objDoc = objPdf.CreateDocument();
  objPage = objDoc.Pages.Add();

  objPage.Canvas.SetFillColor(0.8f, 0.8f, 0.8f);
  objPage.Canvas.FillRect(0, 0, objPage.Width / 2, objPage.Height);
  objPage.Canvas.SetFillColor(1, 1, 1);
  objPage.Canvas.FillRect(objPage.Width / 2, 0, objPage.Width, objPage.Height);

  objPage.Canvas.SaveState();
  objPage.Canvas.SetCTM(1, 0, 0, 1, 206, 600);
  UpperLeft();
  objPage.Canvas.RestoreState();

  objPage.Canvas.SaveState();
  objPage.Canvas.SetCTM(1, 0, 0, 1, 206, 400);
  UpperRight();
  objPage.Canvas.RestoreState();

  objPage.Canvas.SaveState();
  objPage.Canvas.SetCTM(1, 0, 0, 1, 206, 200);
  LowerLeft();
  objPage.Canvas.RestoreState();

  objPage.Canvas.SaveState();
  objPage.Canvas.SetCTM(1, 0, 0, 1, 206, 0);
  LowerRight();
  objPage.Canvas.RestoreState();

  // Save document, the Save method returns generated file name
  string strFilename = objDoc.Save(Server.MapPath("transp.pdf"), false);
  lblResult.Text = "Success! Download your PDF file <A HREF=" + strFilename + ">here</A>";
}

void UpperLeft()
{
  PdfGraphics objCirc1 = objDoc.CreateGraphics("left=0; bottom=0; right=100; top=100");
  objCirc1.Canvas.SetFillColor(1, 0, 0);
  objCirc1.Canvas.FillEllipse(50, 50, 50, 50);

  PdfGraphics objCirc2 = objDoc.CreateGraphics("left=0; bottom=0; right=100; top=100");
  objCirc2.Canvas.SetFillColor(1, 1, 0);
  objCirc2.Canvas.FillEllipse(50, 50, 50, 50);

  PdfGraphics objCirc3 = objDoc.CreateGraphics("left=0; bottom=0; right=100; top=100");
  objCirc3.Canvas.SetFillColor(0, 0, 1);
  objCirc3.Canvas.FillEllipse(50, 50, 50, 50);

  PdfGraphics objGraph = objDoc.CreateGraphics("left=0; bottom=0; right=200; top=200");
  objGraph.Canvas.DrawGraphics(objCirc1, "x=25; y=28");
  objGraph.Canvas.DrawGraphics(objCirc2, "x=50; y=71");
  objGraph.Canvas.DrawGraphics(objCirc3, "x=75; y=28");

  objPage.Canvas.DrawGraphics(objGraph, "x=0; y=0");
}

void UpperRight()
{
  PdfGraphics objCirc1 = objDoc.CreateGraphics("left=0; bottom=0; right=100; top=100");
  objCirc1.Canvas.SetFillColor(1, 0, 0);
  objCirc1.Canvas.FillEllipse(50, 50, 50, 50);

  PdfGraphics objCirc2 = objDoc.CreateGraphics("left=0; bottom=0; right=100; top=100");
  objCirc2.Canvas.SetFillColor(1, 1, 0);
  objCirc2.Canvas.FillEllipse(50, 50, 50, 50);

  PdfGraphics objCirc3 = objDoc.CreateGraphics("left=0; bottom=0; right=100; top=100");
  objCirc3.Canvas.SetFillColor(0, 0, 1);
  objCirc3.Canvas.FillEllipse(50, 50, 50, 50);

  PdfGraphics objGraph = objDoc.CreateGraphics("left=0; bottom=0; right=200; top=200");
  PdfGState objGState = objDoc.CreateGState("BlendMode=1; FillAlpha=0.5");
  objGraph.Canvas.SetGState(objGState);
  objGraph.Canvas.DrawGraphics(objCirc1, "x=25; y=28");
  objGraph.Canvas.DrawGraphics(objCirc2, "x=50; y=71");
  objGraph.Canvas.DrawGraphics(objCirc3, "x=75; y=28");

  objPage.Canvas.DrawGraphics(objGraph, "x=0; y=0");
}

void LowerLeft()
{
  PdfGraphics objCirc1 = objDoc.CreateGraphics("left=0; bottom=0; right=100; top=100");
  objCirc1.Canvas.SetFillColor(1, 0, 0);
  objCirc1.Canvas.FillEllipse(50, 50, 50, 50);

  PdfGraphics objCirc2 = objDoc.CreateGraphics("left=0; bottom=0; right=100; top=100");
  objCirc2.Canvas.SetFillColor(1, 1, 0);
  objCirc2.Canvas.FillEllipse(50, 50, 50, 50);

  PdfGraphics objCirc3 = objDoc.CreateGraphics("left=0; bottom=0; right=100; top=100");
  objCirc3.Canvas.SetFillColor(0, 0, 1);
  objCirc3.Canvas.FillEllipse(50, 50, 50, 50);

  PdfGState objGroup = objDoc.CreateGState("Group=true");
  PdfGraphics objGraph = objDoc.CreateGraphics("left=0; bottom=0; right=200; top=200");
  objGraph.SetGroup(objGroup);
  objGraph.Canvas.DrawGraphics(objCirc1, "x=25; y=28");
  objGraph.Canvas.DrawGraphics(objCirc2, "x=50; y=71");
  objGraph.Canvas.DrawGraphics(objCirc3, "x=75; y=28");

  PdfGState objGState = objDoc.CreateGState("BlendMode=1; FillAlpha=0.5");
  objPage.Canvas.SetGState(objGState);
  objPage.Canvas.DrawGraphics(objGraph, "x=0; y=0");
}

void LowerRight()
{
  PdfGState objGState = objDoc.CreateGState("BlendMode=1; FillAlpha=0.5");

  PdfGraphics objCirc1 = objDoc.CreateGraphics("left=0; bottom=0; right=100; top=100");
  objCirc1.Canvas.SetGState(objGState);
  objCirc1.Canvas.SetFillColor(1, 0, 0);
  objCirc1.Canvas.FillEllipse(50, 50, 50, 50);

  PdfGraphics objCirc2 = objDoc.CreateGraphics("left=0; bottom=0; right=100; top=100");
  objCirc2.Canvas.SetGState(objGState);
  objCirc2.Canvas.SetFillColor(1, 1, 0);
  objCirc2.Canvas.FillEllipse(50, 50, 50, 50);

  PdfGraphics objCirc3 = objDoc.CreateGraphics("left=0; bottom=0; right=100; top=100");
  objCirc3.Canvas.SetGState(objGState);
  objCirc3.Canvas.SetFillColor(0, 0, 1);
  objCirc3.Canvas.FillEllipse(50, 50, 50, 50);

  PdfGState objGroup = objDoc.CreateGState("Group=true");
  PdfGraphics objGraph = objDoc.CreateGraphics("left=0; bottom=0; right=200; top=200");
  objGraph.SetGroup(objGroup);
  objGraph.Canvas.DrawGraphics(objCirc1, "x=25; y=28");
  objGraph.Canvas.DrawGraphics(objCirc2, "x=50; y=71");
  objGraph.Canvas.DrawGraphics(objCirc3, "x=75; y=28");

  PdfGState objGState2 = objDoc.CreateGState("BlendMode=9; FillAlpha=1");
  objPage.Canvas.SetGState(objGState2);
  objPage.Canvas.DrawGraphics(objGraph, "x=0; y=0");
}
Dim objDoc As PdfDocument
Dim objPage As PdfPage

Sub Page_Load(ByVal Source As Object, ByVal E As EventArgs)
  ' Common part: draw background
  Dim objPdf As PdfManager = New PdfManager()
  objDoc = objPdf.CreateDocument()
  objPage = objDoc.Pages.Add()

  objPage.Canvas.SetFillColor(0.8f, 0.8f, 0.8f)
  objPage.Canvas.FillRect(0, 0, objPage.Width / 2, objPage.Height)
  objPage.Canvas.SetFillColor(1, 1, 1)
  objPage.Canvas.FillRect(objPage.Width / 2, 0, objPage.Width, objPage.Height)

  objPage.Canvas.SaveState()
  objPage.Canvas.SetCTM(1, 0, 0, 1, 206, 600)
  UpperLeft()
  objPage.Canvas.RestoreState()

  objPage.Canvas.SaveState()
  objPage.Canvas.SetCTM(1, 0, 0, 1, 206, 400)
  UpperRight()
  objPage.Canvas.RestoreState()

  objPage.Canvas.SaveState()
  objPage.Canvas.SetCTM(1, 0, 0, 1, 206, 200)
  LowerLeft()
  objPage.Canvas.RestoreState()

  objPage.Canvas.SaveState()
  objPage.Canvas.SetCTM(1, 0, 0, 1, 206, 0)
  LowerRight()
  objPage.Canvas.RestoreState()

  ' Save document, the Save method returns generated file name
  Dim strFilename As String = objDoc.Save(Server.MapPath("transp.pdf"), False)
  lblResult.Text = "Success! Download your PDF file <A HREF=" + strFilename + ">here</A>"
End Sub

Sub UpperLeft()
  Dim objCirc1 As PdfGraphics = objDoc.CreateGraphics("left=0; bottom=0; right=100; top=100")
  objCirc1.Canvas.SetFillColor(1, 0, 0)
  objCirc1.Canvas.FillEllipse(50, 50, 50, 50)

  Dim objCirc2 As PdfGraphics = objDoc.CreateGraphics("left=0; bottom=0; right=100; top=100")
  objCirc2.Canvas.SetFillColor(1, 1, 0)
  objCirc2.Canvas.FillEllipse(50, 50, 50, 50)

  Dim objCirc3 As PdfGraphics = objDoc.CreateGraphics("left=0; bottom=0; right=100; top=100")
  objCirc3.Canvas.SetFillColor(0, 0, 1)
  objCirc3.Canvas.FillEllipse(50, 50, 50, 50)

  Dim objGraph As PdfGraphics = objDoc.CreateGraphics("left=0; bottom=0; right=200; top=200")
  objGraph.Canvas.DrawGraphics(objCirc1, "x=25; y=28")
  objGraph.Canvas.DrawGraphics(objCirc2, "x=50; y=71")
  objGraph.Canvas.DrawGraphics(objCirc3, "x=75; y=28")

  objPage.Canvas.DrawGraphics(objGraph, "x=0; y=0")
End Sub

Sub UpperRight()
  Dim objCirc1 As PdfGraphics = objDoc.CreateGraphics("left=0; bottom=0; right=100; top=100")
  objCirc1.Canvas.SetFillColor(1, 0, 0)
  objCirc1.Canvas.FillEllipse(50, 50, 50, 50)

  Dim objCirc2 As PdfGraphics = objDoc.CreateGraphics("left=0; bottom=0; right=100; top=100")
  objCirc2.Canvas.SetFillColor(1, 1, 0)
  objCirc2.Canvas.FillEllipse(50, 50, 50, 50)

  Dim objCirc3 As PdfGraphics = objDoc.CreateGraphics("left=0; bottom=0; right=100; top=100")
  objCirc3.Canvas.SetFillColor(0, 0, 1)
  objCirc3.Canvas.FillEllipse(50, 50, 50, 50)

  Dim objGraph As PdfGraphics = objDoc.CreateGraphics("left=0; bottom=0; right=200; top=200")
  Dim objGState As PdfGState = objDoc.CreateGState("BlendMode=1; FillAlpha=0.5")
  objGraph.Canvas.SetGState(objGState)
  objGraph.Canvas.DrawGraphics(objCirc1, "x=25; y=28")
  objGraph.Canvas.DrawGraphics(objCirc2, "x=50; y=71")
  objGraph.Canvas.DrawGraphics(objCirc3, "x=75; y=28")

  objPage.Canvas.DrawGraphics(objGraph, "x=0; y=0")
End Sub

Sub LowerLeft()
  Dim objCirc1 As PdfGraphics = objDoc.CreateGraphics("left=0; bottom=0; right=100; top=100")
  objCirc1.Canvas.SetFillColor(1, 0, 0)
  objCirc1.Canvas.FillEllipse(50, 50, 50, 50)

  Dim objCirc2 As PdfGraphics = objDoc.CreateGraphics("left=0; bottom=0; right=100; top=100")
  objCirc2.Canvas.SetFillColor(1, 1, 0)
  objCirc2.Canvas.FillEllipse(50, 50, 50, 50)

  Dim objCirc3 As PdfGraphics = objDoc.CreateGraphics("left=0; bottom=0; right=100; top=100")
  objCirc3.Canvas.SetFillColor(0, 0, 1)
  objCirc3.Canvas.FillEllipse(50, 50, 50, 50)

  Dim objGroup As PdfGState = objDoc.CreateGState("Group=true")
  Dim objGraph As PdfGraphics = objDoc.CreateGraphics("left=0; bottom=0; right=200; top=200")
  objGraph.SetGroup(objGroup)
  objGraph.Canvas.DrawGraphics(objCirc1, "x=25; y=28")
  objGraph.Canvas.DrawGraphics(objCirc2, "x=50; y=71")
  objGraph.Canvas.DrawGraphics(objCirc3, "x=75; y=28")

  Dim objGState As PdfGState = objDoc.CreateGState("BlendMode=1; FillAlpha=0.5")
  objPage.Canvas.SetGState(objGState)
  objPage.Canvas.DrawGraphics(objGraph, "x=0; y=0")
End Sub

Sub LowerRight()
  Dim objGState As PdfGState = objDoc.CreateGState("BlendMode=1; FillAlpha=0.5")

  Dim objCirc1 As PdfGraphics = objDoc.CreateGraphics("left=0; bottom=0; right=100; top=100")
  objCirc1.Canvas.SetGState(objGState)
  objCirc1.Canvas.SetFillColor(1, 0, 0)
  objCirc1.Canvas.FillEllipse(50, 50, 50, 50)

  Dim objCirc2 As PdfGraphics = objDoc.CreateGraphics("left=0; bottom=0; right=100; top=100")
  objCirc2.Canvas.SetGState(objGState)
  objCirc2.Canvas.SetFillColor(1, 1, 0)
  objCirc2.Canvas.FillEllipse(50, 50, 50, 50)

  Dim objCirc3 As PdfGraphics = objDoc.CreateGraphics("left=0; bottom=0; right=100; top=100")
  objCirc3.Canvas.SetGState(objGState)
  objCirc3.Canvas.SetFillColor(0, 0, 1)
  objCirc3.Canvas.FillEllipse(50, 50, 50, 50)

  Dim objGroup As PdfGState = objDoc.CreateGState("Group=true")
  Dim objGraph As PdfGraphics = objDoc.CreateGraphics("left=0; bottom=0; right=200; top=200")
  objGraph.SetGroup(objGroup)
  objGraph.Canvas.DrawGraphics(objCirc1, "x=25; y=28")
  objGraph.Canvas.DrawGraphics(objCirc2, "x=50; y=71")
  objGraph.Canvas.DrawGraphics(objCirc3, "x=75; y=28")

  Dim objGState2 As PdfGState = objDoc.CreateGState("BlendMode=9; FillAlpha=1")
  objPage.Canvas.SetGState(objGState2)
  objPage.Canvas.DrawGraphics(objGraph, "x=0; y=0")
End Sub

Click the links below to run this code sample:

19.3.2 Isolated and Knockout Groups

An isolated group is one whose elements are composited onto a fully transparent initial backdrop rather than onto the group's backdrop. The resulting source color and object alpha for the group are therefore independent of the group backdrop. The only interaction with the group backdrop occurs when the group's computed color and alpha are then composited with it.

In a knockout group, each individual element is composited with the group's initial backdrop rather than with the stack of preceding elements in the group. Each object overwrites (knocks out) the effects of any earlier elements it overlaps within the same group. At any given point, only the topmost object enclosing the point contributes to the result color and opacity of the group as a whole.

By default, a group created with the Doc.CreateGState("Group=True") method is neither isolated nor knockout. To make a group an isolated or knockout one, or both, the parameters Isolated and/or Knockout must be set to True, for example:

PdfGState objGroup = objDoc.CreateGState("Group=True; Isolated=True; Knockout=True");

The following images demonstrate the isolated and knockout effects for a group consisting of four overlapping circles in a light gray color. The circles are painted within the group with opacity 1.0 in the Multiply blend mode (BlendMode=2). The group itself is painted against its backdrop in the Normal blend mode (BlendMode=1). In the top row, the group is isolated and thus does not interact with the rainbow backdrop. In the bottom row, the group is non-isolated and composites with the backdrop. In the left column, the four overlapping circles are defined as a knockout group and therefore do not composite with each other within the group. In the right column, the circles form a non-knockout group and thus do composite with each other.

 KnockoutNon-knockout
Isolated
Non-isolated

Below is the corresponding AspPDF.NET script:

PdfDocument objDoc;
PdfPage objPage;
PdfManager objPdf;
PdfGState objGState;
PdfGState objGState2;
PdfImage objImage;

void Page_Load(Object Source, EventArgs E)
{
  // Common part: draw background
  objPdf = new PdfManager();
  objDoc = objPdf.CreateDocument();
  objPage = objDoc.Pages.Add();

  // Rainbow background image
  objImage = objDoc.OpenImage(Server.MapPath("19_rainbow.png"));

  objGState = objDoc.CreateGState("blendmode=2");
  objGState2 = objDoc.CreateGState("blendmode=1");

  DrawCircles(600, true, true);
  DrawCircles(400, true, false);
  DrawCircles(200, false, true);
  DrawCircles(0, false, false);

  // Save document, the Save method returns generated file name
  string strFilename = objDoc.Save(Server.MapPath("groups.pdf"), false);
  lblResult.Text = "Success! Download your PDF file <A HREF=" + strFilename + ">here</A>";
}

// Y-shift, isolated flag, knockout flag
void DrawCircles(int Y, bool Isolated, bool Knockout)
{
  PdfGraphics objGraph = objDoc.CreateGraphics("left=0; bottom=0; right=200; top=200");

  // Create a circle graphics
  PdfGraphics objCircle = objDoc.CreateGraphics("left=0; bottom=0; right=100; top=100");
  objCircle.Canvas.SetFillColor(0.7f, 0.7f, 0.7f);
  objCircle.Canvas.FillEllipse(50, 50, 50, 50);

  // Parameter object for group creation
  PdfParam objParam = objPdf.CreateParam();
  objParam["Group"] = 1; // true
  if (Isolated) objParam["Isolated"] = 1;
  if (Knockout) objParam["Knockout"] = 1;
  PdfGState objGroup = objDoc.CreateGState(objParam);

  objGraph.SetGroup(objGroup);
  objGraph.Canvas.SetGState(objGState);
  objGraph.Canvas.DrawGraphics(objCircle, "x=25; y=28");
  objGraph.Canvas.DrawGraphics(objCircle, "x=75; y=28");
  objGraph.Canvas.DrawGraphics(objCircle, "x=25; y=78");
  objGraph.Canvas.DrawGraphics(objCircle, "x=75; y=78");

  objPage.Canvas.SaveState();

  objPage.Canvas.DrawImage(objImage, "x=0, y=" + Y);

  objPage.Canvas.SetGState(objGState2);
  objPage.Canvas.DrawGraphics(objGraph, "x=0; y=" + Y);

  objPage.Canvas.RestoreState();
}
Dim objDoc As PdfDocument
Dim objPage As PdfPage
Dim objPdf As PdfManager
Dim objGState As PdfGState
Dim objGState2 As PdfGState
Dim objImage As PdfImage

Sub Page_Load(ByVal Source As Object, ByVal E As EventArgs)
  ' Common part: draw background
  objPdf = new PdfManager()
  objDoc = objPdf.CreateDocument()
  objPage = objDoc.Pages.Add()

  ' Rainbow background image
  objImage = objDoc.OpenImage(Server.MapPath("19_rainbow.png"))

  objGState = objDoc.CreateGState("blendmode=2")
  objGState2 = objDoc.CreateGState("blendmode=1")

  DrawCircles(600, true, true)
  DrawCircles(400, true, false)
  DrawCircles(200, false, true)
  DrawCircles(0, false, false)

  ' Save document, the Save method returns generated file name
  Dim strFilename As string = objDoc.Save(Server.MapPath("groups.pdf"), false)
  lblResult.Text = "Success! Download your PDF file <A HREF=" + strFilename + ">here</A>"
End Sub

' Y-shift, isolated flag, knockout flag
Sub DrawCircles(Y As Integer, Isolated As Boolean, Knockout As Boolean)
  Dim objGraph As PdfGraphics = objDoc.CreateGraphics("left=0; bottom=0; right=200; top=200")

  ' Create a circle graphics
  Dim objCircle As PdfGraphics = objDoc.CreateGraphics("left=0; bottom=0; right=100; top=100")
  objCircle.Canvas.SetFillColor(0.7f, 0.7f, 0.7f)
  objCircle.Canvas.FillEllipse(50, 50, 50, 50)

  ' Parameter object for group creation
  Dim objParam As PdfParam = objPdf.CreateParam()
  objParam("Group") = 1 ' true
  If Isolated Then objParam("Isolated") = 1
  If Knockout Then objParam("Knockout") = 1
  Dim objGroup As PdfGState = objDoc.CreateGState(objParam)

  objGraph.SetGroup(objGroup)
  objGraph.Canvas.SetGState(objGState)
  objGraph.Canvas.DrawGraphics(objCircle, "x=25; y=28")
  objGraph.Canvas.DrawGraphics(objCircle, "x=75; y=28")
  objGraph.Canvas.DrawGraphics(objCircle, "x=25; y=78")
  objGraph.Canvas.DrawGraphics(objCircle, "x=75; y=78")

  objPage.Canvas.SaveState()

  objPage.Canvas.DrawImage(objImage, "x=0, y=" + Y.ToString())

  objPage.Canvas.SetGState(objGState2)
  objPage.Canvas.DrawGraphics(objGraph, "x=0, y=" + Y.ToString())

  objPage.Canvas.RestoreState()
End Sub

Click the links below to run this code sample:

19.4 Soft Masks

Any PDF compositing operation can be subject to a soft mask, or alpha mask, which is a graphics object that serves as the source of variable opacity for the objects being drawn. The word soft emphasizes that the mask value at a given point is not limited to just 0.0 or 1.0 but can take on intermediate fractional values as well. A soft mask is activated by linking it to a graphics state object, and then activating that object.

For a graphics object to act like a soft mask, it has to be associated with a transparency group. The soft mask values (opacity) can be derived either from the group's alpha values or from the group's luminosity values. In the latter case, the transparency group must be associated with a color space so that the luminocity could be properly calculated.

With AspPDF.NET, a soft mask is created by creating an instance of the PdfGraphics object and associating it with a transparency group via the PdfGraphics.SetGroup method. The PdfGraphics object is then associated with a graphics state object via the PdfGState.SetSoftMask method. The SetSoftMask method expects two arguments: an instance of the PdfGraphics object and a parameter list. The optional Alpha parameter specifies whether the soft mask is to be derived from the group's alpha values (if set to True) or luminocity values (if set to False or omitted). The optional backdrop color for the group can also be specified via the C1, C2, ..., Cn color components (black by default.)

Note that if Alpha is False or omitted, the transparency group associated with this PdfGraphics object must be assigned a color space via the SetColorSpace method.

The following example uses a soft mask defined by a black and white image to create a drop shadow for a logo:

Below is the corresponding AspPDF.NET script:

PdfManager objPdf = new PdfManager();
PdfDocument objDoc = objPdf.CreateDocument();
PdfPage objPage = objDoc.Pages.Add();

// Main Logo
PdfGraphics objLogo = objDoc.CreateGraphics("left=0; bottom=0; right=128; top=206");

objLogo.Canvas.SetParams("FillColor=#313570");
objLogo.Canvas.MoveTo(6, 177);
objLogo.Canvas.LineTo(48, 201);
objLogo.Canvas.LineTo(113, 162);
objLogo.Canvas.LineTo(113, 86);
objLogo.Canvas.LineTo(70, 62);
objLogo.Canvas.LineTo(70, 137);
objLogo.Canvas.ClosePath();
objLogo.Canvas.Fill();

objLogo.Canvas.SetParams("FillColor=#5B88B1");
objLogo.Canvas.MoveTo(61, 5);
objLogo.Canvas.LineTo(61, 130);
objLogo.Canvas.LineTo(20, 106);
objLogo.Canvas.LineTo(20, 30);
objLogo.Canvas.ClosePath();
objLogo.Canvas.Fill();

// Transparency group to be used with the soft mask
PdfGState objGroup = objDoc.CreateGState("Group=true");
// Required as we use luminocity for soft mask
objGroup.SetColorSpace( objDoc.CreateColorSpace("DeviceRGB"));

// Soft mask based on an image to be used as alpha
PdfImage objImage = objDoc.OpenImage(Server.MapPath("19_alpha.png"));
PdfGraphics objSM = objDoc.CreateGraphics("left=0; bottom=0; right=128; top=206");
objSM.Canvas.DrawImage( objImage, "x=0; y=0" );

// Associate the soft mask with a transparency group
objSM.SetGroup( objGroup );

// Drop Shadow. Uses GState object with a soft mask
PdfGState objGState = objDoc.CreateGState("fillalpha=0.5");
objGState.SetSoftMask( objSM, "alpha=false" );
PdfGraphics objShadow = objDoc.CreateGraphics("left=0; bottom=0; right=128; top=206");

objShadow.Canvas.SetGState( objGState );
objShadow.Canvas.SetFillColor( 0.2f, 0.2f, 0.2f ); // gray
objShadow.Canvas.FillRect( 0, 0, 128, 206 );

// Draw shadow with an offset
objPage.Canvas.DrawGraphics( objShadow, "x=110; y=490" );

// Draw logo
objPage.Canvas.DrawGraphics( objLogo, "x=100; y=500" );

// Save document, the Save method returns generated file name
string strFilename = objDoc.Save( Server.MapPath("dropshadow.pdf"), false );
Dim objPdf As PdfManager = New PdfManager()
Dim objDoc As PdfDocument = objPdf.CreateDocument()
Dim objPage As PdfPage = objDoc.Pages.Add()

' Main Logo
Dim objLogo As PdfGraphics = objDoc.CreateGraphics("left=0; bottom=0; right=128; top=206")

objLogo.Canvas.SetParams("FillColor=#313570")
objLogo.Canvas.MoveTo(6, 177)
objLogo.Canvas.LineTo(48, 201)
objLogo.Canvas.LineTo(113, 162)
objLogo.Canvas.LineTo(113, 86)
objLogo.Canvas.LineTo(70, 62)
objLogo.Canvas.LineTo(70, 137)
objLogo.Canvas.ClosePath()
objLogo.Canvas.Fill()

objLogo.Canvas.SetParams("FillColor=#5B88B1")
objLogo.Canvas.MoveTo(61, 5)
objLogo.Canvas.LineTo(61, 130)
objLogo.Canvas.LineTo(20, 106)
objLogo.Canvas.LineTo(20, 30)
objLogo.Canvas.ClosePath()
objLogo.Canvas.Fill()

' Transparency group to be used with the soft mask
Dim objGroup As PdfGState = objDoc.CreateGState("Group=true")
' Required as we use luminocity for soft mask
objGroup.SetColorSpace(objDoc.CreateColorSpace("DeviceRGB"))

' Soft mask based on an image to be used as alpha
Dim objImage As PdfImage = objDoc.OpenImage(Server.MapPath("19_alpha.png"))
Dim objSM As PdfGraphics = objDoc.CreateGraphics("left=0; bottom=0; right=128; top=206")
objSM.Canvas.DrawImage(objImage, "x=0; y=0")

' Associate the soft mask with a transparency group
objSM.SetGroup(objGroup)

' Drop Shadow. Uses GState object with a soft mask
Dim objGState As PdfGState = objDoc.CreateGState("fillalpha=0.5")
objGState.SetSoftMask(objSM, "alpha=false")
Dim objShadow As PdfGraphics = objDoc.CreateGraphics("left=0; bottom=0; right=128; top=206")

objShadow.Canvas.SetGState(objGState)
objShadow.Canvas.SetFillColor(0.2F, 0.2F, 0.2F) ' gray
objShadow.Canvas.FillRect(0, 0, 128, 206)

' Draw shadow with an offset
objPage.Canvas.DrawGraphics(objShadow, "x=110; y=490")

' Draw logo
objPage.Canvas.DrawGraphics(objLogo, "x=100; y=500")

' Save document, the Save method returns generated file name
Dim strFilename As String = objDoc.Save(Server.MapPath("dropshadow.pdf"), False)

19.5 Miscellaneous Features

19.5.1 Page Groups

In all the transparency group-related examples of this chapter, a group was implemented by a PdfGraphics object. A group can also be represented by a PdfPage object as a whole, in the exact same manner. To have a page represent a group, the method PdfPage.SetGroup must be called, for example:

PdfGState objGroup = objDoc.CreateGState("Group=True; Isolated=True");
PdfPage objPage = objDoc.Pages.Add();
objPage.SetGroup( objGroup );

19.5.2 Other Graphics State Parameters

In addition to the BlendMode, Alpha and FillAlpha parameters described above, the CreateGState method also accepts the following parameters (all optional):

  • AlphaIsShape (Boolean) - specifies whether the current soft mask and alpha constant are to be interpreted as shape (True) or opacity values (False).
  • TextKnockout (Boolean) - determines the behavior of overlapping glyphs within a text object.
  • Overprint (Boolean) - specifies whether to apply overprint for all stroking operations.
  • FillOverprint (Boolean) - specifies whether to apply overprint for all painting operations other than stroking.
  • OverprintMode (integer) - specifies the overprint mode which determines how to interpret a tint value of 0.0 in a CMYK color space.