Image Display with IDL

IDL provides many tools for displaying, modifying and analyzing images. The topics in this section are meant to get you started with a basic set of tools. We will enlarge this toolbox as we go along in the course. The topics of this section are:

Reading Image Data [TOP]

Image data can be read from files in several formats. For example, if you have an image named scene.png in a directory then you can read it by supplying the path to the image to the Read_png procedure. If the directory is named myimages on the C drive then you could read the image into an array named image by executing the command

IDL> Read_png,'C:\myimages\scene.png',image

IDL provides routines of the form Read_xxx to read a number of image formats. Look in the IDL Help index for further information. The supported formats in IDL version 5.2 include: BMP, DICOM, GIF, JPEG, PICT, PNG, PPM, SRF, TIFF. Each procedure has keyword parameters to set.

Beginning with version 5.3, IDL provides a generic image-reading routine called READ_IMAGE. It can be used as either a procedure or a function. To be most effective, it can be used with the QUERY_IMAGE function, which can provide information about an image before a read attempt is made.

I find it handy to use the Dialog_Pickfile function to help me pick the full name of the image file. This has the added advantage that it will construct a full file name for whatever machine is being used. If you are looking for images with a particular name pattern, you can use the filter keyword. For example, to pick an image of type png you can do the following:

IDL> fname=Dialog_Pickfile(FILTER='*.png')
IDL> ok=Query_Image(fname,info)

The variable OK will equal 1 if the image file can be read and 0 if it cannot be read. the variable INFO is a structure that contains information about the image in the file. You can find out what fields are in the structure by using HELP.


Suppose that we had picked the file fname='peppers.png'. Then the info structure would be as shown below.

** Structure <1583200>, 7 tags, length=40, data length=36, refs=1:
   CHANNELS        LONG                 1
   DIMENSIONS      LONG      Array[2]
   HAS_PALETTE     INT              1
   IMAGE_INDEX     LONG                 0
   NUM_IMAGES      LONG                 1
   PIXEL_TYPE      INT              1
   TYPE            STRING    'PNG'

The image has a palette. That means that the image array contains the indexes for the palette. To display the image we will need to use the palette information to set up the color system. Both the image array and the color palette can be read by the READ_IMAGE function.

IDL> image=Read_Image(fname,rr,gg,bb)
IDL> Device,DECOMPOSED=0 ;Tell IDL to use indexed color system
IDL> TVLCT,rr,gg,bb ;Sets up the internal palette
IDL> Window,1,XSIZE=info.dimensions[0],YSIZE=info.dimensions[1]
IDL> TV,image 

This image uses color tables. We will also look at an example that uses true color. Color tables are discussed below.

Setting up display windows [TOP]

The image display procedures, TV and TVSCL that are discussed below will display an image in the active window or open a new window if there is no active window. This is ok if it is what you want. However, the result may be a window of the wrong size or location on the screen. To make a window of the right size, you have to find out the size of the image and then open a window of that size.

The image array image that was read above is two-dimensional. You can find the image size and open a window that it fits with the following commands:

IDL> imSize=SIZE(image)

If you want to open or resize a window with a particular window index n then use the command

IDL> WINDOW,n,XSIZE=imSize[1],YSIZE=imSize[2]

If the window is open, then this command also erases the contents.

You can control the position of a window on the screen by using the XPOS and YPOS keyword parameters. For more information see IDL Help.

Displaying byte arrays [TOP]

IDL uses two commands to display image data on the screen: TV and TVSCL. These procedures use the same arguments and keywords and differ only in that TVSCL scales the image into the intensity range of the display device, while TV displays the image directly. They have the form:

TV, image [, X, Y]
TVSCL, image [, X, Y]

where A is a 2D array and X and Y are optional location parameters. If they are used, they determine the offset of the image origin from the corner of the window. Other parameters are available, as described in IDL Help.

If one issues the command

IDL> TV,image

then the image will be displayed in the current window. If there is no open window, then one with the default window size will be opened. If you want to put the image into a window of the same size, then you need to find out the size of the image and open a window to match it. You could do this manually by finding the size with the Help command and then typing the parameters into the Window procedure. However, you will often want to automate the process so you can put it into a program. To do that, use Query_Image function or the Size procedure. An example of the use of Size is:

IDL> imSize=SIZE(image)
IDL> Window,/FREE,XSIZE=imSize[1],YSIZE=imSize[2]
IDL> TV,image

The image that is displayed may not look like what you expect because the range of values may not match the color table or because the image color table was different than the current color table. Information about the range of colors in the color table is stored in the system variable !D.N_Colors. One can rescale the image to match the color table by use of the BytScl function.

IDL> imSize=SIZE(image)
IDL> Window,/FREE,XSIZE=imSize[1],YSIZE=imSize[2]
IDL> scImage=BytScl(image,TOP=!D.N_Colors-1)
IDL> TV,scimage

scImage is a new array of the same size as image but with a range of values from 0 to !D.N_Colors.

You can accomplish the same rescaling by using the TVSCL procedure. The image displayed with the following commands will look the same as that displayed with those above.

IDL> imSize=SIZE(image)
IDL> Window,/FREE,XSIZE=imSize[1],YSIZE=imSize[2]
IDL> TVSCL,image

The TVSCL procedure provides a quick way to display an image so that you will get good contrast. However, scaling the image yourself and displaying it with TV will give you greater control.

The TV and TVSCL procedures do not give you any control of the color appearance of a displayed image. To do that you have to use the tools that control the color pallette.

Using color tables [TOP]

IDL displays images in either 8-bit or 24-bit color. Here we will discuss image display with 8-bit color, which is also called indexed color. The simplest way to understand indexed color is to run the procedure XPALETTE in IDL. This will bring up a window that displays the current color table and that enables you to change colors. Click here to see an example.

Indexed color makes use of three color channels, called Red, Green and Blue. A displayed color is composed of a mixture of the three colors. Each color index corresponds to a particular mixture. The three graphs in the left column of the XPALETTE window show the [r,g,b] mixture for each index.

The number of available indexes on a particular computer is provided by the system variable, !D.N_COLORS. This value is displayed at the top of the center column in the window, and shows 236 colors available in this example. The controls in the XPALETTE window enable you to manipulate the color table. The procedure is simple to follow if you first click on the help button while running XPALETTE. The color table itself is displayed on the right. It is a 16x16 array. You can use the tools to change the color table. The index slider at the top shows that the cursor is on color index 168.

IDL has a number of predefined color tables. These can be loaded by using the LOADCT procedure. For example, LOADCT,3 would load the RED TEMPERATURE color table. This happens to be the color table displayed in the example. You can load any of the predefined color tables in XPALETTE by using the Predefined button. The available color tables are listed below. These color tables are most useful when doing graphics.
0 B-W LINEAR 14 STEPS 28 Hardcandy
2 GRN-RED-BLU-WHT 16 Haze 30 Ocean
3 RED TEMPERATURE 17 Blue - Pastel - Red 31 Peppermint
4 BLUE/GREEN/RED/YELLOW 18 Pastels 32 Plasma
5 STD GAMMA-II 19 Hue Sat Lightness 1 33 Blue-Red
6 PRISM 20 Hue Sat Lightness 2 34 Rainbow
7 RED-PURPLE 21 Hue Sat Value 1 35 Blue Waves
8 GREEN/WHITE LINEAR 22 Hue Sat Value 2 36 Volcano
9 GRN/WHT EXPONENTIAL 23 Purple-Red + Stripes 37 Waves
10 GREEN-PINK 24 Beach 38 Rainbow18
11 BLUE-RED 25 Mac Style 39 Rainbow + white
12 16 LEVEL 26 Eos A 40 Rainbow + black
13 RAINBOW 27 Eos B    

IDL provides a number of functions to work with color tables. LOADCT,n causes the color table with index n to be loaded. By default, the color table will be one of those in the list above. However, you can construct your own color table by a process described in IDL Help.

The procedure TVLCT,R,G,B,\GET loads the current color table into the variables R, G and B. You can then manipulate these variables to change the color table. For example, the following code segment will reverse the color table.

IDL> LOADCT,3 ;Load the Red Temperature color table
IDL> TVLCT,R,G,B,/GET ;Put the table into IDL variables
IDL> TVLCT,RR,GG,BB ;Load the reversed colors

If you are working on an 8-bit display, then the changes in the color table should immediately affect all of the open graphics windows. (The situation is different if you are using a device that is set up to display 24-bit color, where the displayed windows are not affected when the color table is changed. To apply a new color table with a 24-bit display you then need to redisplay the image.)

ReaReading information from image displays [TOP]

Suppose that an image has been displayed in a window and that you want to get information about the brightness or color at points or regions in an image. To do that it is handy to be able to interact with the display. The CURSOR procedure can be used to support that interaction.

The CURSOR procedure reads the position of the interactive graphics cursor of the current graphics device. It enables the graphic cursor on the device, optionally waits for the user to move it and/or click a mouse button, and then reports the cursor position.

The procedure has two positional parameters to return the cursor position, and a number of keyword parameters. For example, if you would like to click the mouse at a point in an image and return the pixel location you could use the command


The result will be returned when you click down. You can also have a value returned on an up-click or when the mouse moves. The above command will give X and Y in device (pixel) coordinates. If you would like to have them in normalized coordinates, then set the NORMAL keyword instead of the DEVICE keyword. You can also get the position in data coordinates, useful with plotted information, by setting the DATA keyword.

The prococedure, SAMPLE_CLICK prints the coordinates and image value each time you click the left mouse button. It quits when you click the right mouse button. Look up !MOUSE.BUTTON in IDL Help for more mouse information. The FORMAT statement is used to control the appearance of the printed output.

;SAMPLE_CLICK,Q uses the mouse cursor to show values of an array Q that
;has been displayed in a window. Left click in the image to print the
;coordinates and the value. Right-click to end the procedure. It is assumed
;that the window is sized to fit the array image.

	PRINT,FORMAT='("POSITION=[",I3,",",I3,"], VALUE=",I3)',X,Y,Q[X,Y]

The SAMPLE_CLICK procedure is very useful for finding points of interest in an image. You can then use other procedures such as PLOT or SURFACE to look at the information in the image array with graphical tools.

Resizing images [TOP]

Images are just arrays, so we can use IDL array selection and resizing tools to change the size of an image. We will assume here that the array image is two-dimensional and that its dimensions are Dx by Dy.

You can select a portion of the image by using command

IDL> A=image[x1:x2,y1:y2]

where the region of interest is defined by the indices (x1,x2,y1,y2). This array will have size Ax=x2-x1+1, Ay=y2-y1+1. The objects inside the region will not change in size.

If we change the scale of an image we need to calculate the values of pixels on a new grid. This can be done with the REBIN and CONGRID functions.

The REBIN function resizes a vector or array by stretching or compressing it in each dimension. The new dimensions must be integral multiples or factors of the original dimensions. The expansion or compression of each dimension is independent of the others, so that each dimension can be expanded or compressed by a different value. If Dx is the number of columns in the original and Tx is the number of columns in the target, then let f=Dx/Tx. Then f must be an integer if Tx<Dx (compression) or 1/f must be an integer if Tx>Dx (expansion). The same must be true in the row dimension.

The CONGRID function can be used to resize an image to resize an array without the restriction of scaling by an integer factor. It uses interpolation, so is not as fast as REBIN.

As an example, let A be a 3x3 array that is expanded to a 9x9 array by the two methods. Look carefully at the patterns used to create the new pixels.


Note: The result AD=REBIN(A,9,9,/SAMPLE) yields the same result 
as the statement AC=CONGRID(A,9,9). Either can be used when the
dimensions of the new array are integer multiples of the original.
You may want to test the above statement. Results are listed below.
   0   1   2
   3   4   5
   6   7   8
   0   0   0   1   1   1   2   2   2
   1   1   1   2   2   2   3   3   3
   2   2   2   3   3   3   4   4   4
   3   3   3   4   4   4   5   5   5
   4   4   4   5   5   5   6   6   6
   5   5   5   6   6   6   7   7   7
   6   6   6   7   7   7   8   8   8
   6   6   6   7   7   7   8   8   8
   6   6   6   7   7   7   8   8   8
   0   0   0   1   1   1   2   2   2
   0   0   0   1   1   1   2   2   2
   0   0   0   1   1   1   2   2   2
   3   3   3   4   4   4   5   5   5
   3   3   3   4   4   4   5   5   5
   3   3   3   4   4   4   5   5   5
   6   6   6   7   7   7   8   8   8
   6   6   6   7   7   7   8   8   8
   6   6   6   7   7   7   8   8   8

   0   0   0   1   1   1   2   2   2
   0   0   0   1   1   1   2   2   2
   0   0   0   1   1   1   2   2   2
   3   3   3   4   4   4   5   5   5
   3   3   3   4   4   4   5   5   5
   3   3   3   4   4   4   5   5   5
   6   6   6   7   7   7   8   8   8
   6   6   6   7   7   7   8   8   8
   6   6   6   7   7   7   8   8   8