The following is a simple example of how to create a new NDF data structure from scratch, in this case starting with image data read from an unformatted sequential Fortran file. This is typical of how the NDF-based half of a format conversion application (designed to read data from another format into an NDF) might look. This example could be modified to read other formats by appropriately replacing the routine which reads the data from the file.
In this example, use has been made of the FIO_ package (SUN/143) to allocate a Fortran I/O unit. Some moderately elaborate error reporting is also illustrated; this gives helpful error messages in response to I/O errors and a final contextual report at the end of the application.
SUBROUTINE READIMG( STATUS )
*+
* Name:
* READIMG
* Purpose:
* Read an image into an NDF.
* Description:
* This routine reads a 2-dimensional real image into an NDF data
* structure from an unformatted sequential Fortran file. The image
* data are assumed to be stored one line per record in the file.
* ADAM Parameters:
* FILE = LITERAL (Read)
* Name of the input file.
* NDF = NDF (Write)
* The output NDF data structure.
* NX = INTEGER (Read)
* Number of pixels per image line.
* NY = INTEGER (Read)
* Number of lines in the image.
*-
* Type Definitions:
IMPLICIT NONE ! No implicit typing
* Global Constants:
INCLUDE 'SAE_PAR' ! Standard SAE constants
INCLUDE 'FIO_PAR' ! Define FIO__SZFNM constant
* Status:
INTEGER STATUS ! Global status
* Local Variables:
CHARACTER * ( FIO__SZFNM ) FILE ! Input file name
INTEGER DIM( 2 ) ! Image dimension sizes
INTEGER EL ! Number of mapped values
INTEGER INDF ! NDF identifier
INTEGER IOERR ! I/O error status
INTEGER IOUNIT ! Fortran I/O unit number
INTEGER PNTR( 1 ) ! Pointer to mapped values
*.
* Check inherited global status.
IF ( STATUS .NE. SAI__OK ) RETURN
* Obtain the name of the input file and allocate an I/O unit on which
* to open it.
CALL PAR_GET0C( 'FILE', FILE, STATUS )
CALL FIO_GUNIT( IOUNIT, STATUS )
IF ( STATUS .NE. SAI__OK ) GO TO 99
* Open the file, trapping and reporting any errors.
OPEN( FILE = FILE, UNIT = IOUNIT, STATUS = 'OLD',
: FORM = 'UNFORMATTED', IOSTAT = IOERR )
IF ( IOERR .NE. 0 ) THEN
STATUS = SAI__ERROR
CALL ERR_FIOER( 'MESSAGE', IOERR )
CALL FIO_REP( IOUNIT, FILE, IOERR,
: 'Unable to open file ^FNAME on Fortran unit ^UNIT - ' //
: '^MESSAGE', STATUS )
GO TO 99
END IF
* Obtain the dimension sizes of the image to be read and check the
* values obtained for validity.
CALL PAR_GET0I( 'NX', DIM( 1 ), STATUS )
CALL PAR_GET0I( 'NY', DIM( 2 ), STATUS )
IF ( STATUS .NE. SAI__OK ) GO TO 99
IF ( ( DIM( 1 ) .LT. 1 ) .OR. ( DIM( 2 ) .LT. 1 ) ) THEN
STATUS = SAI__ERROR
CALL ERR_REP( 'READIMG_BADDIM',
: 'Image dimensions must be positive.', STATUS )
GO TO 99
END IF
* Create an output NDF of the correct size and map its data array as
* _REAL values for writing.
CALL NDF_CREP( 'NDF', '_REAL', 2, DIM, INDF, STATUS )
CALL NDF_MAP( INDF, 'Data', '_REAL', 'WRITE', PNTR, EL, STATUS )
* Read the image values from the input file into the mapped array.
CALL READIT( IOUNIT, DIM( 1 ), DIM( 2 ), %VAL( PNTR( 1 ) ),
: STATUS )
* Annul the NDF identifier, close the input file and deallocate the I/O
* unit.
99 CONTINUE
CALL NDF_ANNUL( INDF, STATUS )
CLOSE( UNIT = IOUNIT )
CALL FIO_PUNIT( IOUNIT, STATUS )
* If an error occurred, then report contextual information.
IF ( STATUS .NE. SAI__OK ) THEN
CALL ERR_REP( 'READIMG_ERR',
: 'READIMG: Error reading an image into an NDF from a ' //
: 'Fortran file.', STATUS )
END IF
END
SUBROUTINE READIT( IOUNIT, NX, NY, ARRAY, STATUS )
*+
* Name:
* READIT
* Purpose:
* Read an image from a file.
* Invocation:
* CALL READIT( IOUNIT, NX, NY, ARRAY, STATUS )
* Description:
* The routine reads a real image from an unformatted sequential
* Fortran file, one image line per record.
* Arguments:
* IOUNIT = INTEGER (Given)
* The Fortran I/O unit on which to read the (previously opened)
* file.
* NX = INTEGER (Given)
* Number of pixels per image line.
* NY = INTEGER (Given)
* Number of lines in the image.
* ARRAY( NX, NY ) = REAL (Returned)
* The image array to be read.
* STATUS = INTEGER (Given and Returned)
* The global status.
*-
* Type Definitions:
IMPLICIT NONE ! No implicit typing
* Global Constants:
INCLUDE 'SAE_PAR' ! Standard SAE constants
INCLUDE 'FIO_PAR' ! Define FIO__SZFNM constant
* Arguments Given:
INTEGER IOUNIT
INTEGER NX
INTEGER NY
* Arguments Returned:
REAL ARRAY( NX, NY )
* Status:
INTEGER STATUS ! Global status
* Local Variables:
CHARACTER * ( FIO__SZFNM ) FILE ! File name
INTEGER IGNORE ! Enquire status (ignored)
INTEGER IOERR ! I/O error status
INTEGER IX ! Loop counter for image pixels
INTEGER IY ! Loop counter for image lines
*.
* Check inherited global status.
IF ( STATUS .NE. SAI__OK ) RETURN
* Read each line of the image from the file, trapping any errors.
DO 1 IY = 1, NY
READ( IOUNIT, IOSTAT = IOERR ) ( ARRAY( IX, IY ), IX= 1, NX )
* If an error occurred, then make a helpful error report and abort.
IF ( IOERR .NE. 0 ) THEN
STATUS = SAI__ERROR
CALL ERR_FIOER( 'MESSAGE', IOERR )
CALL FIO_REP( IOUNIT, ' ', IOERR,
: 'Error reading file ^FNAME on Fortran unit '^UNIT - ' //
: '^MESSAGE', STATUS )
GO TO 99
END IF
1 CONTINUE
* Jump to here if an error occurs.
99 CONTINUE
END
The following is an example ADAM interface file (readimg.ifl) for the application above.
interface READIMG
parameter FILE # Input file name
position 1
type LITERAL
prompt 'Input file'
endparameter
parameter NDF # Output NDF
position 4
prompt 'Output NDF'
endparameter
parameter NX # Number of pixels per line
position 2
type _INTEGER
prompt 'X dimension of image'
endparameter
parameter NY # Number of lines in image
position 3
type _INTEGER
prompt 'Y dimension of image'
endparameter
endinterface