Writing a Raster Image to an HDF File


The following sections detail how a user may utilize the HDF library and the GR API within a computer program to write a raster image in HDF. As a teaching tool, this tutorial will concentrate on using the FORTRAN programming language. However, examples of the appropriate C code will also be given for certain steps.


Previous Main Topic

Next Main Topic

Return to Main Topics

Does the current version of HDF support your computer platform?

As outlined in Section 4, the HDF library can not be run on just any available computer platform or operating system. Before downloading the HDF library software, the user should make sure that the current release of HDF supports his/her computer and operating system. Otherwise, the user will be unable to work with the HDF library and files. There is also a possibility that previous releases of HDF may support the Users computer platform while the latest version does not. In this event, the user may wish to obtain the earlier software.

Return to top

Downloading and Installing of the HDF library 

The HDF library and software is public domain software and available free to all users. The library and code can be downloaded from the (NCSA anonymous ftp server). Directions on how to install the HDF library can also be found at this location.

Return to top

Are all libraries and programs properly linked and compiled?

In order to run the HDF software, the library and the needed application routines and programs must first be properly compiled and linked. As of the current release of HDF (4.1r3), four separate libraries must be compiled and linked. These are the libmfhdf.a, libdf.a, libjpeg.a, and libz.a libraries. Provided below are examples of the command(s) that can be used for this action. It must be noted that the order in which the libraries are linked is important and should not vary from the order shown below:

For C programs:

  1. cc -o <your program> <your program>.c \
  2. -I<pathf for hdf include directory> \
  3. -L<path for hdf libraries> -lmfhdf -ldf -ljpeg -lz

For FORTRAN programs:

  1. f77 -o <your program> <your program>.f \
  2. -I<path for hdf include directory> \
  3. -L<path for hdf libraries> -lmfhdf -ldf -ljpeg -lz

For the various commands needed to link and compile the HDF library on each individual platform, please see Section 4 "Compiling the HDF library".

Return to top

Writing a short program to write a raster image in HDF

Return

Select a programming language

As mentioned previously, the HDF library and programs can only be run by using either the C or FORTRAN programming language. This choice is up to the user depending on availability and the language he or she feels most familiar and comfortable with. All routines within the GR API begin with either the "GR" prefix (C) or the "mg" (FORTRAN) prefix. Examples of the routines/code used to open, read, write, etc.. raster images ar given in the following sections.

Return to Top

Make sure all include files are in place

In section 4 - The HDF Library: Software and Hardware , it was noted that a series of standard HDF definitions and declarations of file access codes (i.e. read, write, etc.) and data types (i.e. integer, character) must be included within the programs that the user writes to utilize the various application routines. In the C programs, this is accomplished simply by adding the line #include "hdf.h" at the beginning of the program. This line effectively includes all the needed constants and definitions from the HDF software. When writing FORTRAN programs, this may also be done by simply adding an include statement that brings in only the needed definitions and declarations (constants.f) from the hdf.h header file. This is done by the following code: "include constants.f". However, all FORTRAN compilers (particularly the older ones) do not support the use of include statements. In this event, the user must type in/declare all the constants and definitions found in the constants.f file. It is advised that all declarations, whether through include statements or not, should be done at the beginning of the program.

Example:

FORTRAN:

      C DFACC_RDONLY is defined in hdf.h
C if not available for FORTRAN then add
Parameter (DFACC_RDONLY=1)

C:

#include "hdf.h"
main()

Return

 

Make all variable and parameter declarations

As with any program, the scientist/user should declare and initialize all variables and parameters at the beginning of the program. This includes all variables and arguments that will be used by the HDF commands to follow. The variable and parameter declarations needed for each call will be provided in the example boxes of the individual steps. These statements always belong at the top of the program.

Return

Open file containing existing non-HDF data set and store in array

Before writing any data into HDF, the actual data first has to be accessed within the program. As is normally done in non-HDF applications, the file containing the data that the user wishes to convert into HDF must first be opened. After opening the file, the user reads and stores the data for the image into a multi-dimensional array that can be accessed by the HDF commands.

For the purpose of this tutorial, the non-HDF data set will be read from an existing file called image.dat into a multi-dimensional real array called rimage(XL,YL) where XL= 10 and YL = 10.

Example:

FORTRAN:

        real rimage(10,10)
XL = 10
YL = 10
Open(unit=15, file='image.dat',form='formatted')
Do I=1,XL
Do j=1,YL
Read(15,25)rwind(I,J)
Enddo
Enddo

Return

Open new HDF file and initialize access to the GR interface

Unlike the SD API (SDstart/sfstart), this is a two-step process because all interfaces other tan the SD API must use Hopen/Hclose to open/close HDF files. A description of the Hopen/Hclose command is provided in section 2.3 of the HDF4.1r3 Users Guide. This two-step process accomplishes the following:

This is done by the following code:

	file_id=hopen(filename, access_mode,n_dds_block) (FORTRAN)
gr_id = mgstart(file_id)

or

	file_id = Hopen(filename, access_mode,n_dds_block);   (C)
gr_id = GRstart(file_id);

where the gr_id command must follow the file_id command and:

	file_id = HDF file id returned by the Hopen/hopen command
gr_id = Gr interface id returned by the mgstart/GRstart command
filename = the name of the new HDF file (character string)
access_mode = Type of access required for this file
n_dds_block = number of data descriptors in a data descriptor block (new file)

All available options for the access-mode argument are defined in the hdf.h header file mentioned previously and need only to be identified for all C and most FORTRAN operations. All options begin with the prefix "DFACC_" and include:

	DFACC_CREATE (File Creation Access)
DFACC_RDONLY (Read Access)
DFACC_RDWR (Read and Write Access)

As mentioned previously, these definitions are stated in the hdf.h header file.

In the event that the user's FORTRAN compiler can not handle include statements such as those found in the hdf.h header file, the DFACC_ variable must be defined, along with its assigned value, at the beginning of the program. This is done by a code line such as:

	parameter (DFACC_RDONLY = 1) (For FORTRAN only)

For the purpose of this tutorial, the new HDF file will be called image.hdf.

Example:

FORTRAN:

        integer*4 file_id, gr_id, mgstart, hopen
parameter (DFACC_CREATE = 4)
file_id = hopen(image.hdf, DFACC_CREATE,16)
gr_id = mgstart(file_id)

C:

	#include "hdf.h"
/* Includes all the access_mode definintions */
int32 gr_id, file_id, Hopen;
file_id = Hopen(image.hdf, DFACC_CREATE,16);
gr_id+GRstart(file_id);

Return

Define a new HDF raster image

After initializing the GR interface and opening and assigning a file id (file_id) and interface id (gr_id), the next step is to define a new HDF raster image to which the existing non-HDF data will be written. This is done by the following code:

	ri_id = mgcreat(gr_id,name,n_comps,data_type,interlace_mode,dim_sizes) (FORTRAN)
or
ri_id = GRcreate(gr_id,name,n_comps,data_type,interlace_mode,dim_sizes); ( C )

(It should be noted that mgselct/GRselect may also be used to write to a previously defined HDF data set.)

where

	gr_id = the GR interface id created in the previous step (mgstart/GRstart)
ri_id = HDF raster image identifier returned by the mgcreat/GRcreate command
name = name of new raster image (in ASCII character string)
n_comps = number of pixel components in the raster image (integer > 1)
data_type = data type of image data
interlace_mode = interlacing used to write the the image (0,1,2)
0 = MFGR_INTERLACE_PIXEL(pixel interlacing)
1 = MFGR_INTERLACE_LINE(line interlacing)
2 = MFGR_INTERLACE_COMP(component interlacing)

This argument always takes the form of DFNT_X, where X is the data type to be used. A list of all the data types supported by the API can be found in the HDF User's Guide. For most of the data types, 8,16,32 and 64-bit types are supported. A few of the available options are provided below:

 


HDF Data Type Description
DFNT_FLOAT32 32 bit floating point real
DFNT_DOUBLE double precision reals
DFNT_CHAR8 8 bit character type
DFNT_UCHAR8 8 bit unsigned character type
DFNT_INT16 16 bit integer type
DFNT_UINT16 16 bit unsigned integer type
DFNT_NINT16 16 bit native integer
DFNT_NUINT16 16 bit native unsigned integer
DFNT_NFLOAT32 32 bit native floating point real

Similar to the DFACC_ argument, all data types are defined in hdf.h. Once again, for FORTRAN compilers unable to access these include files, the DFNT_ argument, and its' assigned value, must be defined at the beginning of the program using code like this:

	parameter (DFNT_INT16 = 22) (taken from constants.f within the hdf.h file)

dim_sizes = An array defining the size of each dimension of the data array (integer)

This variable is best specified with the other variable declarations at the top of the program. In FORTRAN, an example for a 2-D, 10 X 10 array would be:

	dimsizes(1) = 10 (FORTRAN)
dimsizes (2) = 10

or

	dimsizes[0] = 10; ( C )
dimsizes[1] = 10;

 

Example:

FORTRAN:
integer*4 DFNT_INT16
integer ri_id
integer dim_sizes(2), mgcreat
XL = 10
YL = 10
data_type = DFNT_16
n_comps = 2
interlace_mode = MFGR_INTERLACE_PIXEL
dim_sizes(1) = XL
dim_sizes(2) = YL
ri_id = mgcreat(gr_id, image, n_comps, data_type, interlace_mode, dim_sizes)
C:
int32 ri_id;
int32 dim_sizes[2],;
XL = 10;
YL = 10;
dim_sizes[0] = YL;
dim_sizes[1] = XL;
ri_id = GRcreate(gr_id, image, n_comps, data_type, interlace_mode, dim_sizes);

Return

Write existing data array to a new image array in a created HDF file

After initializing the GR API and defining the new HDF file and new HDF raster image to be written to, the next step is to actually write the existing non-HDF data into the HDF file by using the GRwriteimage (mgwrimg) command. This command is used to write either all or part of the existing 2-dimensional image array (termed a "slab") into the ri_id array with the same number of dimensions. In addition, the size of each dimension of the data "slab" must be the same or smaller then the corresponding dimension of the ri_id. The GRwriteimage/mgwrimg command is used in the following fashion:

	ret=mgwrimg (ri_id, start, stride, edges, data) (FORTRAN)

or

	ret=GRwriteimage (ri_id, start, stride, edges, data); ( C )

 

(It should be noted that there are two versions of the write routine in FORTRAN, "mgwrimg" is used for numeric data while "mgwcimg" is used for writing character data.)

where

	ri_id = the raster image id determined and returned by using SDcreate (sfcreate)
start = An array which identifies where in the file that the writing will begin

The start array identifies the starting location or position where the writing of the data "slab" will begin. This array must have the same number of dimensions as the image. The declaration of the start variables can be done at the top of the program or just preceding the call of the mgwrimg (GRwriteimage) command. As an example, to write the existing data set to the beginning of a new 2-dimensional image, the following must be specified:

	start(1) = 0 (FORTRAN)
start(2) = 0

Or

	start[0] = 0; ( C )
start[1] = 0;

For a 2-D image, the first element of start specifies the offset from the beginning of the array along the fastest changing dimenasion (1st in FORTRAN, 2nd in C) while the secind element specifies an offset from the beginning of the array along the 2nd fastest changing dimension (2nd in FORTRAN, 1st in C).As an example, if start(1)=1 and start(2)=2 then;

	In FORTRAN, the starting location is the 2nd row and 3rd column
In C, the starting location is the 2nd row and 3rd column.

stride = An array specifying the interval between written values in each dimension

The stride argument specifies, for each dimension, the interval between consecutive written values of the data set. In other words, how many array locations are skipped with each writing of the data? Like the start array, the stride argument is predefined before calling the sfwdata (SDwritedata) command, either directly before the call or at the top of the program.

If the user does not wish to skip any array locations in a new 2-dimensional SDS, the following is to be declared:

	stride(1) = 1 (FORTRAN)
stride(2) = 1

or

	stride(0) = 1; ( C )
stride(1) = 1;

However, if the user wishes to skip every other X (dimension 1) location, the following would be used:

	stride(1) = 2 (FORTRAN)
stride(2) = 1

Or

	stride(0) = 2; ( C )
stride(1) = 1;

edge = An array defining the number of data values to be written in each dimension. In plain terms, this argument defines the size of the data slab (all or part of the data) to be written to the new array and each dimension.

edge must be specified for each dimension and can not be larger then the entire length of the newly defined (from mgcreat/GRcreate) array it is being written to.

The edge is affected by the stride. If stride = 2, then the edge will need to be divided by two, because it will be writing to every other location along a dimension.

Similar to stride and start, the edge argument needs to be defined prior to the calling of the mrwrimg (GRwriteimage) command, whether it be at the top of the program or directly before the routine call.

As an example, most often, the user will wish to write the entire non-HDF data set into a new array that starts from the beginning and does not contain any missing data or blanks. For a 2-dimensional array of 10X10, read and stored into the data array "image", this can be done, in FORTRAN, by:

	start(1) = 0
start(2) = 0
stride(1) = 1
stride(2) = 1
edge(1) = 10
edge(2) = 10
retn = mgwrimg(ri_id, start, stride, edge, image)

Or in C by:

	start[0] = 0;
start[1] = 0;
stride[0] = 1;
stride[1] = 1;
edge[0] = 10;
edge[1] = 10;
retn = GRwriteimage(ri_id, start, stride, edge, image);

data = The array or buffer of data to be written

The file containing this data should be opened at the beginning of the program and the data read in and stored into the necessary arrays before beginning the HDF operations.

Example:

FORTRAN:

        integer start(2), edges(2), stride(2)
integer retn, XL, YL
integer sfwdata
c Define the location, pattern and size of data set that
c will be written to.
XL = 10
YL = 10
start(1) = 0
start(2) = 0
edge(1) = XL
edge(2) = YL
stride(1) = 1
stride(2) = 1
c write the data
retn = mgwrimg(ri_id, start, stride, edge, image)

C: int32 retn;
int32 start[2], edges[2], stride[2];
XL = 10;
YL = 10;
/*Define the location, pattern and size of the dataset*/
For (i=0; i<rank; i++) {
start[i] = 0;
edge[i] = dims[i];
edge(0) = 10;
edge(1) = 10;
/* Write the stored data to "image". The 5th argument must be explicitly cast to
a generic pointer to conform to the API definition for GRwriteimage */
retn = GRwriteimage(ri_id, start, NULL, edges, (VCIDP)image);

 

Return

Optional operation: Provide metadata (attributes) for HDF files or raster images

The mechanism for providing attrributes for a raster image within the GR API is similar to that for the SD API and scientific data sets.Using the general attribute routines for user-defined attributes described in section 7, attributes can be written and attached to the file itself and the raster image in question. This is not required, but up to the choice of the user.

After opening the file or image, the GRsetattr(mgsnatt) routine can be used to either create new attributes for a new file/image or modify the attributes for an existing and already named file/image:

	GRsetattr (obj_id,attr_name, data_type, n_values, attr_value);        ( C)
mgsnatt(obj_id, attr_name, data_type, n_values, attr_value) (FORTRAN)

where

	obj_id = GR interface (Gr_id) or raster image (ri_id) identifier
attr_name = ASCII string containing the name of the attribute
data_type = data type of attribute values (i.e., DFNT_INT32)
n_values = total number values/characters in the attribute
attr_value = text string or label

After setting/writing the attributes, the user must terminate access to the data array (using the GRendaccess/mgendacc commands) and the file and GR interface (using the GRend/mgend commands).

FORTRAN:

        file_id=hopen(image.hdf,DFACC_CREATE,16)
gr_id = mgstart(file_id)
retn = mgsattr(gr_id, "Contents of file", DFNT_CHAR8, 16, "wind images")

C:

file_id=Hopen(image.hdf,DFACC_CREATE,16)
gr_id=GRstart (file_id);
retn= GRsetattr (gr_id, "Contents of file", DFNT_CHAR8, 16, "wind_images ");

 

Return

Terminate / close access to all files, data sets, and APIs

After writing the data to the new GR image within the new HDF file, it is necessary to terminate or close access to the raster imager(ri), the GR interface and the HDF file itself in order to prevent any possible loss of data. This is done by the following:

	retn = mgendac(ri_id) (FORTRAN)
retn = mgend(gr_id)
retn = Hclose(file_id)

or

	retn = GRendaccess(ri_id); ( C )
retn = GRend(gr_id)
retn = hclose(file_id)

Return

Execute program

Execute like a normal FORTRAN or C program.

Return