Coyote's Guide to IDL Programming

Color Switching in PostScript

QUESTION: It looks like my background and foreground colors were switched in my PostScript output. How come?

ANSWER: PostScript drawing and background colors are switched so that a plot with a black background and white lettering on your display will have a white background and black lettering in PostScript.

In IDL, the drawing color index is represented by the system variable !P.COLOR. This typically is a number that corresponds to one less than the number of colors you are using in your IDL session. That is, !P.COLOR = !D.TABLE_SIZE-1. The background color index is in the system variable !P.BACKGROUND and is typically set to 0.

When you make the PostScript device the current device, the !P.COLOR index is set to 0 and the !P.BACKGROUND index is set to 255. With most of the color tables distributed with IDL this results in a white plot on a black background on your display and a black plot on a white background for PostScript.

You can change the color loaded in the !P.COLOR color index, or you can draw in some other color by using the COLOR keyword on a graphics command. For example, if you always want to draw in a green color no matter whether on the display or in a PostScript file, you can do something like this:

   IF !D.NAME EQ 'PS' THEN TVLCT, 0, 255, 0, 255 ELSE $
      TVLCT, 0, 255, 0, 0
   PLOT, data

Or, you could load the green color in some other index, say color index 100, and draw in green on both the display and in the PostScript file, like this:

   TVLCT, 0, 255, 0, 100
   PLOT, data, COLOR=100

(Be aware that you can only draw in color in PostScript if the COLOR keyword is set to 1 and the BITS_PER_PIXEL keyword is set to 8 for the PostScript device. And if you send color PostScript output to a gray-scale printer, the colors are represented by dithering the lines, resulting in a broken or dotted appearance.)

Many people divide their color table up into what might be called "data colors" and "drawing colors". For example, if I wanted to center an image in a graphics window with a red box around it and a green title above it, I might do something like this:

   dataColors = !D.TABLE_SIZE-2
   redColor = !D.TABLE_SIZE-2
   greenColor = !D.TABLE_SIZE-1
   LOADCT, 5, NCOLORS=datacolors
   TVLCT, [255, 0], [0, 255], [0,0], !D.TABLE_SIZE-2 ; Red and Green.
   TV, BYTSCL(image, TOP=datacolors-1), XSIZE=0.8, YSIZE=0.8, $
      0.1, 0.1, /NORMAL
   PLOTS, [0.1, 0.1, 0.9, 0.9, 0.9], [0.1, 0.9, 0.9, 0.1, 0.1], /NORMAL, $
      THICK=3, COLOR=redColor
   XYOUTS, 0.5, 0.95, 'Image Title', ALIGNMENT=0.5, /NORMAL, $
      SIZE=2.0, Color=greenColor

If you work with colors this way, your PostScript output is nearly always identical to what you see on your display. A good rule of thumb I always use, if I want PostScript output that is identical to display output, is to never use the color indices at the top or the bottom of the color table.

Working with PostScript background colors is somewhat different. I mentioned earlier that the !P.BACKGROUND system variable is set to 255 when you make the PostScript device active. But it doesn't matter what color you load into color index 255, you still get a white background on your PostScript plot! In other words, the color you load into index 255 can be used for other things (I used it in the code above for a green drawing color), but it doesn't affect the background color of the plot. For example, if I wanted to use the two drawing colors I loaded above to draw a red plot on a green background, I could type this:

   PLOT, data, BACKGROUND=greenColor, COLOR=redColor

I would get what I expect on the display, but I would get a red plot on a white background in PostScript.

There is only one way to get a background color different from white in a PostScript file, and that is essentially to draw an image of a single color in the PostScript window. I like to use POLYFILL for this purpose, like this:

   POLYFILL, [1,1,0,0,1], [1,0,0,1,1], /NORMAL, COLOR=greenColor
   PLOT, data, COLOR=redColor, /NOERASE

Another way would be to use the TV command like this:

   image = REPLICATE(greenColor, 2, 2)
   PLOT, data, COLOR=redColor, /NOERASE

Web Coyote's Guide to IDL Programming