Invisible if css is enabled, don't click

Printing multi-frame Tiff images in VB.NET to a certain printer tray

A part of work I was asked to create a simple program that prints a multi-frame Tiff image from the file system to a (user-definable) printer and specific tray and to add some fun the ability to specify which page to start on and the ability to skip X number of pages between.

This is a edge case and finding the information was a huge task, while I do program VB.NET some (I know and use at least four languages,) I am mainly a web app programmer so I don’t know much about image manipulation and printing, I feared I would be heading into Win32 API land and flash backs of my days as a VB6 programmer came flooding back.

Luckily it wasn’t that hard, getting the correct information and merging it together was 95% of my battle. Following the jump will reveal the secrets.

This is a console application that I built, so it required me to add the System.Drawing reference so I could access it’s namespace. You will need the following namespaces to work:

  1. Imports System.Drawing
  2. Imports System.Drawing.Printing
  3. Imports System.Drawing.Imaging

We need to declare a few global variables. I know I know, global variables are bad mmmkay. It leaves a bad taste in my mouth too, but it makes things easier, if you have a better way I’d like to know.

This is a console app and it takes commandline arguments so the we declare the main subroutine as such:

  1. Sub Main()
  2. Main(Environment.getCommandLineArgs())
  3. End Sub

I suppose you could handle the command line args right in this subroutine but I like to overload it and make look like a normal command line app would. So now we create the meat of our program.

  1. Private Sub Main(byVal args() as string)
  2. ‘Initialize variables
  3. Dim tray As String = ""
  4. Dim printer As String = ""
  5. Dim filepath As String = ""
  6. Dim ps As PaperSource
  7. Dim trayfound As Boolean = False
  8. start = 1
  9. skip = 1
  10. Dim parameter(1), arg As String
  11. ‘iterate through the commandline arguements
  12. For Each arg In args
  13. ‘VB.NET sends the program name as one of the args so we need to check for that
  14. ‘and we don’t was superfluous args, just the ones that start with our switch delimiter
  15. If (arg.IndexOf("-") = 0) Then
  16. parameter(0) = arg.Substring(0, arg.IndexOf(":"))  ‘The switch
  17. parameter(1) = arg.Substring(arg.IndexOf(":") + 1, arg.Length - arg.IndexOf(":") - 1) ‘The value
  18. Select parameter(0)
  19. Case "-file"
  20. filepath = parameter(1)
  21. Case "-p"
  22. printer = parameter(1)
  23. Case "-start"
  24. start = parameter(1)
  25. Case "-step"
  26. skip = parameter(1)
  27. Case "-tray"
  28. ‘tray names can contain spaces so    they need to be enclosed in quotes
  29. ‘to prevent it from getting split up as VB.Net Args are space delimited
  30. tray = parameter(1).Replace("""", "")
  31. End Select
  32. ‘Load the tiff image
  33. tiffImage = Image.FromFile(filepath)
  34. ‘Create an instance of a PrintDocument
  35. printDoc = New PrintDocument()
  36. ‘If the printer switch wasn’t specified it will use the computer’s default printer
  37. If (printer <> "") Then
  38. printDoc.PrinterSettings.PrinterName = printer
  39. End If
  40. ‘If the user wants to print to a specific tray we will need to iterate through the printers
  41. ‘Trays to find the appropriate one and then reassign the PrintDocs default settings
  42. If  tray <> "" Then
  43. For Each ps In printDoc.PrinterSettings.PaperSources
  44. If ps.SourceName = tray Then
  45. printDoc.DefaultPageSettings.PaperSource = ps
  46. trayfound = True
  47. Exit For
  48. End If
  49. Next
  50. End If
  51. ‘Now that everything is in order we can begin the print
  52. printDoc.Print()
  53. End If
  54. End For
  55. End Sub

Just a note on the above code, I left out a lot of error checking, so make sure you do proper checking or the code will probably fail if you don’t have all the switches properly entered.

Now for the Counter Intuitive part of the code. This is a little confusing and I will explain it after.

  1. Private Sub printDoc_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles printDoc.PrintPage
  2. tiffImage.SelectActiveFrame(FrameDimension.Page, start - 1)
  3. start += skip
  4. e.Graphics.DrawImage(tiffImage, 0, 0)
  5. If (start < tiffImage.GetFrameCount(FrameDimension.Page)) Then
  6. e.HasMorePages = True
  7. Else
  8. e.HasMorePages = False
  9. End If
  10. End Sub

When printDoc.Print() is called it triggers it’s PrintPage event, we select a page in our image and set it as the active frame (generally the first image in the multi-frame tiff, but it could start anywhere.) Then we increment the next page to be selected by the step specified by the user (or default of 1 page.) We then send the active frame to “e.graphics” via it’s drawImage method. My image is standard 8×11 inches so I set the top right corner to 0×0 so it fits the entire page, you may want to place a smaller image in the center of your document so you will have to do your own math to change this. Finally we check to see if there are any more frames in the Tiff image that we will need to print, if there is we set a flag that there are more pages to print and as a result the printDoc.PrintPages event is triggered again and this is why we needed global variables the next page runs through this process again and start is incremented again, etc. If you think of it as a Do While loop it’s much easier to understand.

I hope this helps some people out there looking for this sort of functionality as it took me about 5 hours to piece this simple bit of code together from various forums, tips and MSDN reference.

Technorati Tags: , , , , , , ,

Popularity: 86% [?]

Related Posts

One Response to “Printing multi-frame Tiff images in VB.NET to a certain printer tray”

  1. jaredmcateer.com » Blog Archive » Printing multi-frame Tiff images in VB.NET with multiple orientations Says:

    [...] is a continuation of “Printing multi-frame Tiff images in VB.NET to a certain printer tray.” A problem came up that I hadn’t accounted for and my client came back to me. I was [...]

Leave a Reply

We did not invent the algorithm. The algorithm killed Jeeves. The algorithm constantly finds Jesus. This is not the algorithm. This is close.