Wednesday, January 21, 2004

Load And Print A Multipage TIFF From VB.NET

The .NET framework added a groovy wrapper for the GDI+ graphics library. One of the things that this has really helped me with in my job is the handling of TIFFs. In our VB6 applications I had to use a third party control (usually from LEAD) for loading, manipulating and finally printing TIFFs (the principal image format for our client base). No more! .NET has plenty of routines for handling every kind of image manipulation you can imagine: loading, rotating, printing, converting, and drawing. It's great.

When it came to the manipulation of multipage TIFFs, I found that the documentation wasn't easily understandable, and I only found little bits and pieces on the 'net for how to do it. I eventually pieced it all together into something workable, but I wanted to make it a little easier on you. So here's a class that loads and prints a multipage TIFF to the default printer.

Imports System

Imports System.Drawing
Imports System.Drawing.Imaging
Imports System.Drawing.Printing

Public Class PrintTiff

Private m_tiff As Drawing.Image
Private m_fd As FrameDimension

Public Sub New()

End Sub

' Sends a multi-page TIFF document to the default printer.
Public Function PrintTiffDocument(ByVal PathToTIFF As String) As String

Dim tiffDocument As New PrintDocument

' Load TIFF from file.
m_tiff = System.Drawing.Image.FromFile(PathToTIFF)

' Get the frame dimensions.
m_fd = New FrameDimension(m_tiff.FrameDimensionsList(0))

' Setup the print handler.
AddHandler tiffDocument.PrintPage, AddressOf PrintTiffPage

' Print the image.
' Throw all exceptions to caller.
End Try

End Function

' Print each page of the tiff to the printer.
Private Sub PrintTiffPage(ByVal sender As Object, ByVal e As PrintPageEventArgs)

Static pageNum As Int32 = 0

m_tiff.SelectActiveFrame(m_fd, pageNum)
e.Graphics.DrawImage(m_tiff, New PointF(0, 0))

pageNum += 1
If pageNum < m_tiff.GetFrameCount(m_fd) Then
e.HasMorePages = True
pageNum = 0
End If

End Sub

End Class


I'm not sure why, though I'm sure there's a good historic reason, but GDI+ refers to an image page as a "frame". So all of the methods with "frame" in the name are actually used in manipulating the pages. The PrintTiffPage needs a little bit of explaining, so here's what's happening there:

First of all, I keep the current page number in a static variable so that for each subsequent call the method knows which page to print (this number is reset to zero once the image has been completely printed). The SelectActiveFrame() method sets the page number that is the current page for the TIFF (starting with zero). You have to have a FrameDimension object for the TIFF to pass to this method. After selecting the page to print, I draw the page onto the printer using the DrawImage method. I put the page in the upper-left corner of the printer. Finally, if there are any pages left to print, I set the event flag indicating this is the case, otherwise I reset the page number to zero so the next call to the PrintTiffDocument() method will start on the first page.

Questions or comments? Email me!