Libraries and Packages: The VOS Interface

2.3 Accessing Images -- imio

Procedures in the sf imio library allow an SPP application to read and write IRAF images. IRAF supports several different image formats, including old IRAF, (OIF format), GEIS or STSDAS (STF format) and PROS (QPOE format). However, the same imio procedures are used regardless of the specific format of the image so the formats are transparent to the applications program. The details of decoding the image files are buried in the kernels beneath the applications level of imio. The user specifies the format type when specifying the image names as input or output to the task. The imtype cl environment variable also may be used to specify the default image type. A specific image name extension overrides the value of imtype. The imio interface supports images of up to seven dimensions. In a sense, all images are multidimensional, with the higher, unused axis lengths set to one. An n dimensional image may therefore be accessed by a program coded to operate upon an m dimensional image.


To access an image, you must first open it using the immap() function.

Table 2.8: Image I/O Functions.

This returns a pointer type variable that is the address of the image descriptor structure. The immap() function has three arguments. The first argument is the image filename, passed as a string, the second is a mode specifying how to access the image. It is an integer usually passed as a symbolic constant parameter. The access mode argument may be one of the following symbolic parameters:

Table 2.9: Access Mode Parameters.

The third argument is the pointer to another image, already opened with another immap() call. It is used only if the access mode is NEW_COPY and specifies a template image. The header of the template image will be copied to the header of the new image, but not the pixel values. That is, the structure of the new output image will be similar to the existing image, but the pixels will be different.

imunmap() releases any dynamically allocated memory used for file and I/O buffers. Note that imio refers to images by the header filename, regardless of the format of the image. Therefore, if you do specify an extension on the image filename in a call to immap(), use the header file extension, not the pixel file.

Table 2.10: Image Formats.

For example,

im = immap ("taurus.imh", READ_ONLY, 0) 
You may omit the extension, in which case imio will interpret the filename as an image header. If there is only one image with the specified root name, then it will open that one, regardless of the image format. If there are two images with the same root but different extensions (different image formats), imio will open the one in OIF (IRAF) format.

Of course, it is usually up to the user to specify a filename. You need not append an extension unless you wish to force a particular format, or if you wish to use a non-standard extension. If the task creates an image from scratch (using NEW_IMAGE, not copying an existing image) there is an additional way to control the image format. The cl environment variable imtype specifies the image format if there is no extension to the output image filename.

Image data are passed from imio procedures to the application via pointers in dynamically allocated memory. These imio procedures comprise families of calls to read and write the pixel data. Each pointer typed function returns a pointer to dynamically allocated memory containing the specified part of the image.

Arbitrary Line I/O

These procedures read image data one line at a time. They allocate a block of memory containing the pixels and return the memory pointer as the function value.

Table 2.11: Image Line I/O Functions.

All of the above procedures are implemented for the usual SPP numeric data types: short, int, long, real, double, and complex. That is, the procedure name represents the data type of the SPP buffer that holds the image pixels, not necessarily the data type of the image file. The returned pointer type function value is a pointer to memory allocated by memio for the line of pixels from the image. This differs from the image file descriptor (imp above), which is a pointer to a structure containing the attributes of the image as a whole. The pixel data may be passed to another procedure via the Mem[] construct.

You need not explicitly deallocate memory allocated by any imio procedure. However, you should call imunmap() for any images opened with immap(). This will flush I/O buffers and free allocated memory.

Note that the output (imp...()) procedures as well as the input (img...()) procedures return a pointer to dynamic memory. The pixels are written to the file when the output buffer is full; in some cases, not until the image is closed, or when flushed explicitly. When writing to an output image, your procedure fills the buffer associated with the pointer and then calls the imp...() procedure.

Example 2.12 is a simple example of copying one image into another using arbitrary line I/O.

Line by Line I/O

Another family of procedures returns a pointer to a line of an image, progressing through adjacent lines with each successive call. These differ from the previous family in that those allow a particular line to be read in random order. These procedures return the next line in order.

Table 2.12: Line by Line I/O.

This family of procedures is implemented for the usual SPP numeric data types: short, int, long, real, double, and complex. The functions return the buffer pointer in an argument, bufptr, not in the function value as the previous procedures. These procedures return a completion status as the function value which may be tested for EOF. The argument v is a long array containing indexes of the line to read. This should be initialized to ones. After each call to imgnlT() it is updated to contain the index of the next line. See the example below.

This family of procedures is useful for operating on an image line by line, without regard for the absolute size or even the dimensionality of the image. Because of the buffering of image input and output and a certain amount of asynchronous I/O, substantially more efficient code can result. Example 2.13 demonstrates line by line image I/O by copying an image to a new image. Note that the procedure works the same regardless of the dimensionality and data type of the images. Another, more complete example, can be found in Appendix B.

General Sections

These procedures return a pointer to dynamically allocated memory containing the pixels from an arbitrary section of an image. Note the difference from line-by-line I/O, in which the returned memory always represents a single line of an image, regardless of the dimensionality. These procedures may return a multi-dimensional section.

Table 2.13: Image Section Memory I/O Functions.

All of the above procedures are implemented for the usual SPP numeric data types: short, int, long, real, double, and complex. imggsT() differs from the other procedures in that the same arguments may be used for images of any dimension. The vectors vs and ve describe the range of elements in the section.

Miscellaneous Procedures

There are a few additional procedures providing miscellaneous capabilities.

Table 2.14: Miscellaneous Image I/O Functions.

The last three procedures parse a fully qualified image filename into its components. The terms image, section, and cluster refer to separate fragments of a fully qualified image name. The image section is a string enclosed by square brackets specifying some subraster of an image, for example, [100:125,200:450]. The image name is the filename and group member number (applicable to STF images) without the image section, and the cluster is the filename only. Example 2.14 should clarify this nomenclature. Image sections will be explained in greater detail (See "Image Sections" on page 74.)

Note that imacces() tests only whether an image name is valid, not if the image exists. However, if the image includes an image section, then imacces() will test for its existence.

Header Parameters

Image headers describe the format of an image and permit arbitrary parameters to be carried with the pixel data. The image database interface is the imio interface to the database containing the image headers. The first, fixed format, part of the image header contains the standard fields in binary and is fixed in size. This is followed by the user area, a string buffer containing a sequence of variable length, newline delimited FITS format keyword=value header cards. When an image is opened a large user area is allocated to permit the addition of new parameters without filling up the buffer. When the header is subsequently updated on disk only as much disk space is used as is needed to store the actual header.

Images comprise keyword parameters in an image header in addition to the pixel values. These header keywords describe the fundamental properties of the image such as its size and data type. In addition, they represent other pertinent information such as the instrument, date, world coordinate transformation, or any other data thought useful by the originator of the data. See "Standard Fields" on page 72 for an explanation of the standard parameters available for every image.

Table 2.15: Image Header Parameter Functions.

In each procedure, the name of the parameter is specified as a character string (keyword here), sometimes referred to as a field. The procedures imgetT(), imputT(), and imaddT() are implemented for the SPP data types bool, char, short, int, long, real, and double. The argument imp is a pointer type reference to the image returned by immap().

New parameters will typically be added to the image header with either one of the typed imadd() procedures or with the lower level imaddf() procedure. The former procedures permit the parameter to be created and the value initialized all in one call, while the latter only creates the parameter. In addition, the typed imadd() procedures may be used to update the values of existing parameters, i.e., it is not considered an error if the parameter already exists. The principal limitation of the typed procedures is that they may only be used to add or set parameters of a standard data type.

The value of any parameter may be fetched with one of the imgetT() functions. Be careful not to confuse imgets() with imgstr() (or imputs() with impstr()) when fetching or storing the string value of a field. Fully automatic type conversion is provided. Any field may be read or written as a string, and the usual type conversions are permitted for the numeric data types.

The imaccf() function may be used to determine whether a field exists. Fields are deleted with imdelf(). It is an error to attempt to delete a nonexistent field. The following example (Example 2.15) illustrates handling of image header parameters. The character string field can take the name of any existing keyword in the image header, e.g., DATE_OBS or i_naxis1.

Table 2.16: Image File I/O Functions Handling Templates.

The field name list procedures imofnl[su](), imgnfn(), and imcfnl() procedures are similar to the fio file template facilities, except that the @file notation is not supported. The template is expanded upon an image header rather than a directory. Unsorted lists are the most useful for image header fields. If sorting is enabled each comma delimited pattern in the template is sorted separately, rather than globally sorting the entire template after expansion. Minimum match is permitted when expanding the template, another difference from file templates. Only actual, full length field names are placed in the output list.

Standard Fields

The imio database interface, described above, may be used to access any field of the image header, including the standard fields shown in Table 2.17, existing for every image. In addition, there may be other parameters unique to the particular image.

Table 2.17: Standard Header Keywords.

The names of the standard fields share an i_ prefix to reduce the possibility of collisions with user field names, to identify the standard fields in sorted listings, to allow use of pattern matching to discriminate between the standard fields and user fields, and so on. The i_ prefix may be omitted provided the resultant name does not match the name of a user parameter. It is however recommended that the full name be used in all applications software.

You will need to use the include file <imhdr.h> when dealing with image headers. This defines macros for standard image header parameters dealing with fundamental characteristics of the image such as the size, data type, etc. Several header parameters are available via the imio structure defined by <imhdr.h>. Others may be accessed through the imio database procedures. Parameters may be read or written. If a parameter does not exist, it must be created. Example 2.16 is a fragment of code that finds the size of the image, the number of pixels per line and the number of lines. Since the keyword values in Table 2.17 are accessible through the <imhdr.h> structure, they can be used to get keyword values from an image using the hedit task.

Image Sections

A fundamental feature of imio is the capability to treat a subset of an image identically to an entire image. The image filename as passed to immap() may include an image section which specifies what part of the image to read. The image section facility greatly increases the flexibility of the imio interface. Image sections are specified as part of the image name input to immap(), and are not visible to the applications program, which sees a somewhat smaller image, or an image of lesser dimensionality. Some examples are shown below. In addition, see "World Coordinates -- mwcs" on page 129 describing the mwcs world coordinate system library.

Table 2.18: Image Section Syntax.

Image Name Templates

The filename template
package of procedures permits the use of wildcards or nested lists of image filenames. The functionality and calling sequences are similar to those of the fio filename template package (see "Filename Templates" on page 101).

An image template is expanded into a list of image names or image sections with imtopen(). The list is not globally sorted, however sublists generated by pattern matching are sorted before appending the sublist to the final list. The number of images or image sections in a list is given by imtlen(). Images are read sequentially from the list with imtgetim(), which returns EOF when the end of the list is reached. The list may be rewound with imtrew(). An image template list should be closed with imtclose() to return the buffers used to store the list and its descriptor.

Table 2.19: Image Template Functions.

Note that the int function imgetim() returns EOF upon attempting to read at the end of file. Otherwise, it returns the number of characters in the image name.

Example 2.17 is the top level procedure for the IRAF images.imcopy task in images$imutil/t_imcopy.x. It demonstrates handling image name templates. Some comments have been added to clarify the code.

Table 2.8: - Image I/O Functions.
Table 2.9: - Access Mode Parameters.
Table 2.10: - Image Formats.
Arbitrary Line I/O
Table 2.11: - Image Line I/O Functions.
Line by Line I/O
Table 2.12: - Line by Line I/O.
General Sections
Table 2.13: - Image Section Memory I/O Functions.
Miscellaneous Procedures
Table 2.14: - Miscellaneous Image I/O Functions.
Header Parameters
Table 2.15: - Image Header Parameter Functions.
Table 2.16: - Image File I/O Functions Handling Templates.
Standard Fields
Table 2.17: - Standard Header Keywords.
Image Sections
Table 2.18: - Image Section Syntax.
Image Name Templates
Table 2.19: - Image Template Functions.

Generated with CERN WebMaker