2 ACCESSING IMAGE DATA

 2.1 Accessing an existing image
 2.2 Creating a new image
 2.3 Modifying images

The easiest way to understand IMG is to look at how simple example programs work. That’s what this section does. The examples are generally snippets of more complete programs that can be found in the directory /star/bin/examples/img (on non-Starlink machines replace /star with wherever you have the software installed). You are encouraged to copy and modify these for your own use.

SUN/101 also contains examples of programming techniques that you might want to to use with IMG. You should ideally read these two documents together, although this isn’t absolutely necessary.

2.1 Accessing an existing image

The first example is a complete program. It gets an existing image, works out its mean value and then writes it out:

        SUBROUTINE MEAN( ISTAT )                                [1]
  
  *  Access an input image.
        CALL IMG_IN( ’IN’, NX, NY, IP, ISTAT )                  [2]
  
  *  Derive the mean and write it out.
        CALL DOSTAT( %VAL( IP ), NX, NY, ISTAT )                [3]
  
  *  Free the input image.
        CALL IMG_FREE( ’IN’, ISTAT )                            [4]
        END
  
        SUBROUTINE DOSTAT( IMAGE, NX, NY, ISTAT )
        INCLUDE ’SAE_PAR’                                       [5]
        REAL IMAGE( NX, NY )                                    [6]
  
        IF ( ISTAT .NE. SAI__OK ) RETURN                        [7]
  
  *  Initialise the sum and loop over all elements of the image.
        SUM = 0.0
        DO 1 J = 1, NY
           DO 2 I = 1, NX
              SUM = SUM + IMAGE( I, J )
   2       CONTINUE
   1    CONTINUE
  
  *  Write out the mean value.
        WRITE( *, * ) ’Mean = ’, SUM / REAL( NX * NY )          [8]
  
        END

The following notes refer to the numbered statements:

(1)
Programs that use IMG should always have a main subroutine with an INTEGER argument. This subroutine should be named after the program and be stored in a file with the same name (mean and mean.f in this case). You should consider this subroutine as a replacement for the file that normally has a PROGRAM statement in it.
(2)
The call to ??x]]IMG_IN gets the input image. The image is associated with the “parameter” ’IN’ which usually means that you will be prompted for the name of an image data-file. The subroutine then returns the size of the image – NX × NY – and a pointer IP to its data (don’t panic – hold on for the next item).
(3)
A call to the subroutine DOSTAT, which performs the real work, is now made. Since any realistically useful program needs to be able to handle images of any size, a cheat is necessary – this is the %VAL(IP) argument. Basically, this makes the pointer to the image data, IP, look just like an array declaration in the calling routine (i.e. like say REAL IMAGE(NX,NY)). This isn’t standard Fortran, but should work on any machine that has IMG installed. Pointers are stored in INTEGER variables.
(4)
A call to IMG_FREE is made for each image parameter to tidy up before a program ends.
(5)
The INCLUDE statement in the subroutine DOSTAT inserts the contents of the file ‘SAE_PAR’. This defines some standard Fortran parameters for you, such as SAI__OK (note the double underscore). Include this file as standard as the parameters it defines are usually necessary.
(6)
The image is now available as an adjustable 2-dimensional array within the subroutine DOSTAT.
(7)
The value of the ISTAT argument is tested against SAI__OK at the start of DOSTAT. This is done in case an error has occurred earlier on (in which case ISTAT will not be equal to SAI__OK, so the remainder of DOSTAT will not execute).

Doing this means that the program will not crash if an earlier error results in (say) the IMAGE array containing rubbish, and it makes sure that you get a sensible error message at the end telling you what went wrong.

(8)
The calculation result is written out. In a more sophisticated program you might want to use routines from the MSG library (SUN/104) to do this.

To complete the program another file is required. This is an “interface” file (which should be named after the program but with a file extension of .ifl). It contains a description of each parameter associated with an image. The following will do for this example program:

  interface MEAN
     parameter IN
        prompt ’Input image’
     endparameter
  endinterface

The main point is that it is necessary to include a parameterendparameter statement for each input or output image. SUN/101 and SUN/115 describe numerous other parameter options if you need more sophisticated control.

Once you have the two files mean.f and mean.ifl you can compile and run the program by following the instructions in §6.

To recap: The most important IMG concepts to remember from this example are:

(1)
Images are associated with a label known as a “parameter”.
(2)
Image data is accessed by a “pointer” that needs to be passed to a subroutine using the %VAL mechanism.
(3)
It is necessary to call IMG_FREE to free images before the program ends.

2.2 Creating a new image

This second example (taken from the program flat.f in the example directory - see §2), shows how to create a new image and then write values to it:

  
  *  Create a new image.
        CALL IMG_NEW( ’OUT’, 416, 578, IP, ISTAT )              [1]
  
  *  Fill the array with the value 1.
        CALL DOFILL( %VAL( IP ), 416, 578, ISTAT )              [2]
  
  *  Free the image.
        CALL IMG_FREE( ’OUT’, ISTAT )                           [3]
        END
  
        SUBROUTINE DOFILL( IMAGE, NX, NY, ISTAT )
        INCLUDE ’SAE_PAR’
        REAL IMAGE( NX, NY )
        IF ( ISTAT .NE. SAI__OK ) RETURN
  
  *  Loop over all the elements of the image setting them to 1.0.
        DO 1 J = 1, NY
           DO 2 I = 1, NX
              IMAGE( I, J ) = 1.0
   2       CONTINUE
   1    CONTINUE
        END
  

The following notes refer to the numbered statements:
(1)
The call to ??x]]IMG_NEW creates the new image dataset (usually prompting you for a name). The image size in this example is 416 × 578 pixels.
(2)
The newly created image is passed to the subroutine DOFILL where all its elements are set to the value 1.0.
(3)
Calling IMG_FREE ensures that the output image is correctly freed (avoiding possible loss of the data you have written).

2.3 Modifying images

One of the most common things that programs do is modify an existing image or create an image that is a modification of an existing one. The examples shown here deal with both these cases.

2.3.1 Modifying an image

This snippet of Fortran shows an existing image being accessed so that it can be modified in place (that is, without creating a new copy):

  *  Access an existing image.
        CALL IMG_MOD( ’IN’, NX, NY, IP, ISTAT )
  
  *  Fill the image with a value.
        CALL DOFILL( %VAL( IP ), NX, NY, ISTAT )
  
  *  Free the image.
        CALL IMG_FREE( ’IN’, ISTAT )

2.3.2 Modifying a copy of an image

This example copies the input image first and then modifies the copy. This is essential if the input image needs to be kept. A complete program called add.f exists (see §2).

  *  Access an existing image.
        CALL IMG_IN( ’IN’, NX, NY, IPIN, ISTAT )
  
  *  Create a new output image by copying the input image.
        CALL IMG_OUT( ’IN’, ’OUT’, IPOUT, ISTAT )               [1]
  
  *  Modify the output image.
        CALL DOFILL( %VAL( IPOUT ), NX, NY, ISTAT )
  
  *  Free the input and output images.
        CALL IMG_FREE( ’*’, ISTAT )                             [2]

The following notes refer to the numbered statements:
(1)
The call to ??IMG_OUT creates a new output image associated with the parameter ’OUT’ by copying the one associated with the parameter ’IN’. It returns a pointer IPOUT for the output image data.
(2)
Notice that the names of the image parameters are not shown explicitly in this call to IMG_FREE. Using a ’*’ indicates that all known images should be freed.