Chapter 5: Image and Graphics Objects

Contents

5.1 PdfImage Object

AspPDF is capable of placing arbitrary images on a PDF document. It supports images in BMP, GIF, JPEG, PNG and TIFF formats. To display an image on a canvas, the method Canvas.DrawImage should be used. This method expects two arguments, an instance of the PdfImage object and a parameter object (or parameter string).

A PdfImage object is created via PdfDocument's OpenImage method which takes an image path as an argument. PdfImage can also be created via the OpenImageBinary method which opens an image from memory. Once an instance of PdfImage is created, it can be displayed multiple times across a PDF document.

The following code segment displays the image painting.jpg three times on a page with various scaling factors:

Set Pdf = Server.CreateObject("Persits.Pdf")
Set Doc = Pdf.CreateDocument
Set Page = Doc.Pages.Add

Set Image = Doc.OpenImage( Server.MapPath( "painting.jpg") )

Set Param = Pdf.CreateParam

For i = 1 To 3
   Param("x") = (Page.Width - Image.Width / i) / 2
   Param("y") = Page.Height - Image.Height * i / 2 - 200
   Param("ScaleX") = 1 / i
   Param("ScaleY") = 1 / i

   Page.Canvas.DrawImage Image, Param
Next

Filename = Doc.Save( Server.MapPath("image.pdf"), False )
IPdfManager objPdf = new PdfManager();
IPdfDocument objDoc = objPdf.CreateDocument(Missing.Value);
IPdfPage objPage = objDoc.Pages.Add(Missing.Value, Missing.Value, Missing.Value);

IPdfImage objImage = objDoc.OpenImage( Server.MapPath( "painting.jpg"), Missing.Value );

IPdfParam objParam = objPdf.CreateParam(Missing.Value);

for( int i = 1; i <=3; i++ )
{
   objParam["x"].Value = (objPage.Width - objImage.Width / i) / 2.0f;
   objParam["y"].Value = objPage.Height - objImage.Height * i / 2.0f - 200;
   objParam["ScaleX"].Value = 1.0f / i;
   objParam["ScaleY"].Value = 1.0f / i;

   objPage.Canvas.DrawImage( objImage, objParam );
}

String strFilename = objDoc.Save( Server.MapPath("image.pdf"), false );

Here, we pass four arguments to the DrawImage method: X, Y, ScaleX and ScaleY. X and Y are required: they specify the coordinates of the lower-left corner of the image being displayed.

ScaleX and ScaleY are optional: they specify scaling factors along the X and Y coordinates. Both arguments are 1 by default, which means the image size on the page (in user coordinates) will be equal to its pixel size, provided that the image resolution is the standard 72 dots per inch (dpi). For example, if a 72dpi image is 360 x 216 pixels and the ScaleX/ScaleY arguments are not specified, the image will occupy 360 x 216 units of space, or 5" x 3". A 300dpi image with the same pixel size will only occupy 1.2" x .72".

You can optionally specify a rotation Angle (in degrees) by which the image will be rotated counter-clockwise around its lower-left corner.

Click on the links below to run this code sample:

The Doc.OpenImageBinary method does the same as OpenImage but it opens an image from a memory array as opposed to disk. This method can be used if the image being opened is stored in a database table as a blob:

Set Image = Doc.OpenImageBinary( rs("image_blob").Value )

5.2.1 Image-to-PDF Conversion

The PdfImage properties ResolutionX and ResolutionY (introduced by AspPDF 1.1) enable conversion of GIF, JPEG, BMP, PNG and TIFF images to one-page PDF documents with the size and resolution of the original image fully preserved. These properties return the dot-per-inch (DPI) resolutions of an image along the X and Y coordinates. For GIF, PNG and BMP images, these values are always 72 dpi, the resolution of JPEG and TIFF images may vary and usually ranges from 72 to 600 dpi.

The following code fragment converts an arbitrary image into a one-page PDF document with the page size calculated based on the size and resolution of the image being converted:

...
Set Image = Doc.OpenImage(Server.MapPath( "atlanticocean.tif" ) )

' Add empty page. Page size is based on resolution and size of image
Width = Image.Width * 72 / Image.ResolutionX
Height = Image.Height * 72 / Image.ResolutionY
Set Page = Doc.Pages.Add( Width, Height )

' Draw image
Page.Canvas.DrawImage Image, "x=0, y=0"
...
...
// Open image from file
IPdfImage objImage = objDoc.OpenImage(Server.MapPath( "atlanticocean.tif" ), Missing.Value );

// Add empty page. Page size is based on resolution and size of image
float fWidth = objImage.Width * 72.0f / objImage.ResolutionX;
float fHeight = objImage.Height * 72.0f / objImage.ResolutionY;
IPdfPage objPage = objDoc.Pages.Add( fWidth, fHeight, Missing.Value );

// Draw image
objPage.Canvas.DrawImage( objImage, "x=0, y=0" );
...

5.2 Masking and Transparency

Usually, an image completely covers an area it occupies. All portions of the image, whether black, white, gray or color, completely obscure any marks that may previously have existed in the same place on the page.

However, it is possible to crop, or "mask out" the background of an image and then place the masked image on a different background, allowing the existing background to show through the masked areas. Two masking methods are available: explicit masking using a separate image, and color key masking.

5.2.1 Explicit Masking

This method requires a separate monochrome image which serves as an image mask. Such an image can be created using the Microsoft Paint application (included in all versions of Windows). Copy an image you need masked into Paint, change its attribute to Black and White, then save it as a monochrome bitmap. White areas of the bitmap will mask out the corresponding pixels of the image being masked.

An image is masked as follows:

1. The monochrome mask image is opened with OpenImage/OpenImageBinary, then its IsMask property is set to True.

2. The image to be masked is opened with OpenImage/OpenImageBinary also, then its SetImageMask method is called and the image object obtained in Step 1 is passed as an argument.

The following code sample takes the image exclam.gif and its monochrome bitmap mask exclam.bmp, and places the image on top of a drawing to demonstrate that the existing background is showing through the masked areas.

...
Set ImageMask = Doc.OpenImage( Server.MapPath( "exclam.bmp") )
ImageMask.IsMask = True ' Mark this image object as a mask

Set Image = Doc.OpenImage( Server.MapPath( "exclam.gif") )
Image.SetImageMask ImageMask

Page.Canvas.DrawImage Image, "x=10, y=550"
...
...
IPdfImage objImageMask = objDoc.OpenImage( Server.MapPath( "exclam.bmp"), Missing.Value );
objImageMask.IsMask = true; // Mark this image object as a mask

IPdfImage objImage = objDoc.OpenImage( Server.MapPath( "exclam.gif"), Missing.Value );
objImage.SetImageMask( objImageMask );
objPage.Canvas.DrawImage( objImage, "x=10, y=550" );
...

Click on the links below to run this code sample:

5.2.2 Color Key Masking

An alternative way to mask an image is by specifying a range of colors to mask. All samples (a PDF term roughly equivalent to "pixels") of the image with color components falling within the specified range are masked (not painted).

A color range is an array of 2 x N integers where N is the number of color components per sample. N is 3 for RGB images, 4 for CMYK images, and 1 for monochrome bitmaps.

Each integer in the array must be between 0 and 2 BitsPerComponent - 1. The BitsPerComponent value may be 1, 2, 4, or 8 depending on the image. Use PdfImage properties ComponentsPerSample and BitsPerComponent to know exactly what these values are for your image.

To specify a color key mask, the PdfImage provides the method SetColorMask which takes a parameter object (or parameter string) as an argument. The parameters in the parameter object must be named Min1, Max1, Min2, Max2, ..., MinN, MaxN.

For example, the image exclam.gif used in the previous section is a GIF, so its ComponentsPerSample is 3 and BitsPerComponent is 8. To set a mask, we need to specify three ranges, or 6 integers each between 0 and 255. Therefore, to mask the white and light gray areas of this image, we may use the following code:

Image.SetColorMask "Min1=250;Max1=255; Min2=250;Max2=255; Min3=250;Max3=255"

Here, we specify three ranges for each of the R, G, and B color components. The ranges are between 250 and 255 which corresponds to white and very light gray.

5.2.3 GIF Transparency Support

Starting with Version 1.6.0.3, AspPDF provides full transparency support for GIF images. The transparent areas of GIF images are automatically masked.

The effect of the GIF transparency support is illustrated by the picture below. A transparent GIF icon was drawn on a yellow background with an AspPDF version prior to 1.6.0.3 (left) and with version 1.6.0.3 (right).

5.2.4 PNG Transparency Support

Starting with version 1.6.0.2, AspPDF supports Portable Network Graphics format also known as PNG. AspPDF fully supports both the PNG Alpha Channel and simple transparency. PNG transparency support is fully automatic, i.e. no additional coding is needed to display an alpha- or transparency-enabled PNG image.

5.2.5 TIFF Transparency Support

As of Version 3.4.0.11, AspPDF supports alpha information contained in TIFF images the same way as with PNG images.

5.3 PdfGraphics Object

Sometimes, a composite graphics object comprised of drawings, text and images, such as a company's logo and slogan on a background, needs to be displayed in multiple places and on multiple pages within a PDF document, possibly with various scaling factors.

PDF specifications describe such self-contained, complex entities under the name Form XObjects but to avoid confusion with interactive forms described in Chapter 11, AspPDF refers to them as graphics objects.

5.3.1 PdfGraphics Object Overview

AspPDF provides support for graphics entities via the PdfGraphics object creatable via PdfDocument's CreateGraphics method. A graphics object has a fixed size specified at creation time, but it can be scaled and rotated when displayed via the Cavas.DrawGraphics method, the same way as an image.

PdfGraphics has an associated PdfCanvas object accessible via the Canvas property much the same way as PdfPage. Therefore, a graphics object may contain drawings, images, text and other graphics objects.

PdfGraphics objects may be used stand-alone to help display repetitive graphics entities. They can also be used to define the appearance of annotations and form fields described in later chapters.

The code sample below creates an instance of PdfGraphics, draws a mathematically defined shape on it, and also draws a string of text. After that, the graphics is drawn on the page multiple times with rotation around the center of the page.

...
Set Graphics = Doc.CreateGraphics("Left=0,Bottom = 0;Right=100;Top=100")

With Graphics.Canvas
   .DrawRect 1, 1, 99, 99
   .MoveTo 50, 90
   For i = 0 to 628
      .LineTo 40 * sin(i / 25) + 50, 40 * cos(i / 20) + 50
   Next
   .Fill

   .DrawText "AspPDF Rules!", "x=20, y=12; size=8", doc.Fonts("Courier")
End With

Set Param = Pdf.CreateParam

For angle = 0 To 330 step 30
   Param("x") = 306 + 150 * cos( angle / 360 * 6.28 )
   Param("y") = 396 + 150 * sin( angle / 360 * 6.28 )
   Param("Angle") = Angle

   Page.Canvas.DrawGraphics Graphics, Param
Next
...
...
IPdfGraphics objGraphics = objDoc.CreateGraphics("Left=0,Bottom=0;Right=100;Top=100");

objGraphics.Canvas.DrawRect( 1, 1, 99, 99 );
objGraphics.Canvas.MoveTo( 50, 90 );
for( int i = 0; i <= 628; i++ )
{
   objGraphics.Canvas.LineTo( (float)(40 * Math.Sin(i / 25.0) + 50), (float)(40 * Math.Cos(i / 20.0) + 50) );
}
objGraphics.Canvas.Fill( Missing.Value );

objGraphics.Canvas.DrawText( "AspPDF Rules!", "x=20, y=12; size=8", objDoc.Fonts["Courier", Missing.Value] );

IPdfParam objParam = objPdf.CreateParam(Missing.Value);

for(int angle = 0; angle <= 330; angle +=30 )
{
   objParam["x"].Value = (float)(306+150.0*Math.Cos(angle/360.0*6.28 ) );
   objParam["y"].Value = (float)(396+150.0*Math.Sin(angle/360.0*6.28 ) );
   objParam["Angle"].Value = angle;

   objPage.Canvas.DrawGraphics( objGraphics, objParam );
}
...

Click on the links below to run this code sample:

5.3.2 Tiling Patterns

Update: As of Version 3.5, there is a more versatile way to create patterns, via the PdfDocument.CreatePattern method. This functionality is described in Section 16.5 - Patterns and Shadings.

A tiling pattern consists of a small graphical figure called a pattern cell. Filling an area with the pattern replicates the cell vertically and horizontally within this area.

Starting with Version 1.6, AspPDF supports tiling patterns via the method PdfCanvas.FillWithPattern which expects an instance of the PdfGraphics object representing the pattern cell to be used. The 2nd optional argument, EvenOdd, is the same as in the PdfCanvas.Fill method. To designate an instance of the PdfGraphics object as a pattern cell, the CreateGraphics method must be called with the parameter Pattern=true.

The following code snippet fills a circular area with a pattern consisting of a single small image:

Set Image = Doc.OpenImage("c:\path\airplane_icon.gif")
Set Graph = Doc.CreateGraphics("left=0; bottom=0; right=42;top=45; pattern=true;")
Graph.Canvas.DrawImage Image, "x=0, y=0"

' Create path, fill it with the pattern
Page.Canvas.AddEllipse 300, 200, 100, 100
Page.Canvas.FillWithPattern Graph
...

5.3.3 Creating Graphics from Pages

As of Version 2.3, a PdfGraphics object can be created from the page of another existing document and then drawn on this document one or more times with shifting, scaling and rotation applied, if necessary. This functionality is provided via the method PdfDocument.CreateGraphicsFromPage and described in detail in Section 9.6 - Drawing Other Documents' Pages.