Coyote's Guide to IDL Programming

Positioning Graphics with the PRINTER Device

QUESTION: I am having a difficult time printing to the PRINTER device from IDL. The origin of the printed graphic is always halfway down the page (instead of at the bottom where I'd like it). The returned size is correct, but I can't get the thing to print on the whole page. What am I doing wrong?

ANSWER: Well, a couple of things are going wrong here. First of all the default "window" on the output page is set so that in portrait mode the "plot" will show up in a 5 x 7 inch window on top of the page. Why the top and not centered? Uh, you will have to ask RSI.

You can see the default offsets and window sizes by typing this. Here is what I see on my machine with my default HP printer:

     IDL> Set_Plot, 'PRINTER'
     IDL> Help, /Device

   Available Graphics Devices: CGM HP METAFILE NULL PCL PRINTER PS WIN Z
   Current graphics device: PRINTER
      Printer : hp deskjet 990c series
      Orientation: Portrait
      Scale Factor: 1
      Resolution: 600 dots per inch
      Current Font: Arial,	Current TrueType Font: 
      Size (X,Y): (17.78,12.7) cm., (7,5) in.
      Offset (X,Y): (1.905,12.7) cm., (0.75,5) in.

If you want to center the graphic output, you will have to calculate the proper offsets and sizes to do that. I do this by calling my program PSWindow, like this:

     keywords = PSWindow()
     Set_Plot, 'PRINTER'
     Device, _Extra=keywords

PSWindow returns a structure with fields that are appropriate for setting the PostScript or PRINTER devices. The keywords are set to values that center the graphic output on the page in such a way as to preserve the aspect ratio of the current graphics window. In other words, what you see on the PRINTER output should be nearly identical to what you see in your current graphics window.

     IDL> Help, keywords
  ** Structure PSWINDOW_STRUCT, 7 tags, length=24:
     XSIZE           FLOAT           5.95000
     YSIZE           FLOAT           4.25892
     XOFFSET         FLOAT           1.27500
     YOFFSET         FLOAT           3.37054
     INCHES          INT              1
     PORTRAIT        INT              1
     LANDSCAPE       INT              0

It's just a little bit more complicated than this, of course. Because I've found it is impossible to change the printer orientation (i.e., landscape to portrait, or visa versa) at the same time I am setting the sizes and offsets.

If I'm trying to print in landscape mode, I usually do something like this, which gets the printer oriented properly by setting the Landscape (or Portrait) keyword independently of the other settings I am trying to configure.

     keywords = PSWindow(/Printer, /Landscape)
     Set_Plot, 'PRINTER'
     Device, Landscape = keywords.landscape
     Device, _Extra=keywords

Note, too, that unlike printing to a PostScript file, the point by which offsets is calculated stays in the lower-left corner of the page, no matter how the page is rotated. (Nice, but that is why there is a Printer keyword to PSWindow. It has to know how to sort out landscape offsets.)

To just add one more complication, the point at which the printer offsets are calculated is not the very corner of the page, as it is in PostScript. Offsets are calculated from the point on the paper that can actually print. This point varies from printer to printer, so there is no fool-proof way of absolutely centering output on a PRINTER page. On my printer the offsets are calculated from the point at (0.25, 0.25) inches, so I have to add this "fudge factor" to the size and offsets returned from PSWindow, like this:

     keywords = PSWindow(Fudge=0.25, /Printer)
     Set_Plot, 'PRINTER'
     Device, _Extra=keywords

(Note that the sizes and offsets returned by PSWindow are in inches unless the CM keyword is set to specify everything in centimeters. Also, if you use an A4 page size, you want to use the PAGESIZE keyword, too.)

Anyway, you can see this all in operation in the program PrintWindow. This program is designed to send the contents of a graphics window directly to the printer. The output will have the same aspect ratio as the display window and will be centered on the output page. It is really no different from sending an image to the printer, so it should be directly relevant to you.

[Return to IDL Programming Tips]