                  The multi-file RIS interface
                  =============================

Contents:

 Introduction
 How to access files and images in the new interface
 "Name = value" attributes in the new interface
 Dealing with annotations in the new interface
 Work not yet completed, bugs, limitations
 A listing or routines
 Descriptions of GR routines
   File level interface
   Dataset Manipulation
   ID/Ref/Index Functions
   Interlace Request Functions
   LUT/Palette I/O Functions
   Special Element Functions
   Attribute Functions


Introduction
============
The new Generic Raster (GR) interface provides a set of functions for
manipulating raster images of all kinds.  This new interface is meant to
replace the older RIS8 and RIS24 interfaces, although these older
interfaces will continue to be supported.

Generic raster images are composed of "pixels" which can have multiple
components, including but not limited to 8-bit unsigned integers.  Each image
can have multiple palettes associated with it and other 'attributes' in the
same "name=value" style as the SD*() routines have.


The new GR interface was motivated by a number of needs:

o  The need for multi-file, multi-object access to raster images, allowing
users to keep open more than one file at a time, and to "attach" more than
one raster image at a time.

o  A need to further integrate the netCDF data-model with the HDF data-models.

o  A need for a more general framework for attributes within the RIS
data-model (allowing 'name = value' style metadata).

o  A need to be able to access subsamples and subsets of images.


IMPORTANT:  The added functionality represented by this new interface has
necessitated a change in how raster images are physically represented on
disk.   As a result programs using the old single-file RIS interfaces will
only be able to read the data out of files produced by the new interface.
The metadata / attributes will not be accessible.

The following chart represents what can be done with the various interfaces
available in HDF 4.0b1:

              old RIS-API    new GR-API

old RIS         CRW             CRW
HDF files

new RIS          r              CRW
HDF files

'R' means read, 'W' means write and 'C' means create.  Entries with dashes
'-' represent functionality which has not yet been implemented.  'r' stands
for the ability to only read the data, not the metadata.


Work not yet completed, bugs, limitations
===========================================

Misc. stuff left to do:
    Deal with special elements for images.
    GRrename for images.
    GRsetflags to suppress writing fill data and to suppress fillvalue attr.

Features not supported:
    Full support for multiple palettes with each RI.
    Support for named palettes with each RI.
    Support for palettes with non-standard formats.
    Deletion of attributes or images (would require changing the way index
        numbers are handled)

Other limitations:
   Currently the following design limitations are still in place:
   1 - Cannot have pixels or palette entries which contain mixed variable
        types, i.e. all the pixel/palette components must be of the same
        number type.
   2 - Currently all the components must be of valid HDF number types,
        fractional bytes (i.e. 6-bit components) or 'plain' multiple byte values
        are not handled, although they can be packed into the next larger
        sized number type in order to hold them.



How to access files and images in the new interface
======================================================


Here are the steps involved in accessing images in the new interface:

1. Open or create the file using Hopen.  This provides you with a file ID to
be used in step 2.

2. Activate the GR interface for the file with the file ID obtained from
step 1, using GRstart.  This provides you with a GR interface ID (GR ID).

3. Optionally obtain information about the raster images in the file and
global GR attributes using GRfileinfo.  Use the GR ID from step 2 to refer
to the image file.

4. Optionally find the index of a raster image, by name using
GRnametoindex, or by reference number using GRreftoindex.

5. Select for access an image with a given index, using GRselect for each
image.  Each call to GRselect returns a raster image ID (RI ID) for
subsequent accesses involving the corresponding image.

5. Access the image by its RI ID, using routines such as GRgetiminfo (to
get information about the image) and GRreadimage (to read all or part of an
image).

6. Terminate access to a given image using GRendaccess.

7. Terminate access to the GR interface for the file, using GRend.

8. Close the file using Hclose.

Notice that in the GR interface, images are identified in several ways.
Before an image is accessible ("attached"), it is identified by index,
name, and reference number. The index describes the relative position of
the image in the file. The name is a character string associated with the
image, and the reference number is a unique integer.  An image's name is
assigned by the program when it is created, and the reference number is
assigned by the HDF library when it is created. After an image is attached
, it is identified by an raster image identifier, or RI ID.

The following code fragment illustrates the steps involved in accessing the
image in a file and printing information about them.


    /* Open the file and initialize the GR interface */
    hdf_file_id=Hopen(TESTFILE,DFACC_RDWR,0);
    grid=GRstart(hdf_file_id);

    /* Obtain information about the images in the file */
    GRfileinfo(grid,&n_datasets,&n_attrs);

    /* Attach to each image and print information about it */
    for(i=0; i<n_datasets; i++)
      {
          riid=GRselect(grid,i);
          GRgetiminfo(riid,NULL,&ncomp,&nt,&il,dimsizes,&n_attrs);

          printf("%d: riid=%ld: ncomp=%ld, nt=%ld, il=%ld,
                    dim[0]=%ld, dim[1]=%ld, n_attrs=%ld\n",
                    i, riid, ncomp, nt, il, dimsizes[0],
                    dimsizes[1], n_attrs);

          /* Detach from the image */
          GRendaccess(riid);
      } /* end for */

    /* Shut down the GR interface and close the file */
    GRend(grid);
    Hclose(hdf_file_id);



"Name = value" attributes in the new interface
===============================================

Attributes of the form "name = value" were introduced in HDF 3.3, but at
that time they were available only for SDSs and files.  In HDF 4.0 we have
added the ability to attach local and global attributes to raster images
and raster image dimensions.

An attribute's "name" is a string, and "value" is the associated value or
values.  If an attribute contains more than one value, all values must be
of the same type.  For example the attribute 'valid_range' attribute might
be assigned values the maximum and minimum valid values for a given image.

Raster attributes can be "local" or "global."  A local raster image
attribute is one that applies to one raster image only. Global raster image
attributes apply to all of the images in a file.

Attributes for raster images are created by the routine GRsetattr.
Existing attributes are selected by giving an object pointer and an
attribute index.  The functions GRattrinfo, GRfindattr, and GRgetattr may
be used in combination to read attributes and their values.  GRattrinfo
gets the name , number type, and number of values for an attribute with a
given index.  GRfindattr gets the index of an attribute with a given name,
and GRreadattr reads the values associate with an attribute with a given
index.

The following example illustrates how to attach GR image attributes, and
also GR global (file) attributes.

    /* Open file and initialize the GR interface */
    hdf_file_id=Hopen(TESTFILE,DFACC_RDWR,0);
    grid=GRstart(hdf_file_id);

    /* Create a global attribute  -- applies to all rasters in the file */
    HDstrcpy(attr_name,"Test1");
    HDstrcpy(u8_attr,"Attribute value 1");
    GRsetattr(grid,attr_name,DFNT_UINT8,HDstrlen(u8_attr)+1,u8_attr);

    GRfileinfo(grid,&n_datasets,&n_attrs);

    /* select every image in the file, and
       assign a local attribute to each */
    for(i=0; i<n_datasets; i++)
      {
          /* Attach to image with index==i */
          riid=GRselect(grid,i);

          /* Create an attribute for the image */
          HDstrcpy(attr_name,"Image1");
          HDstrcpy(u8_attr,"Attribute value 1");
          GRsetattr(riid,attr_name,DFNT_UINT8,HDstrlen(u8_attr)+1,u8_attr);

          GRgetiminfo(riid,NULL,&ncomp,&nt,&il,dimsizes,&n_attrs);

          printf("%d: riid=%ld: ncomp=%ld, nt=%ld, il=%ld, dim[0]=%ld,
                  dim[1]=%ld, n_attrs=%ld\n",i,riid,ncomp,nt,il,
                  dimsizes[0], dimsizes[1],n_attrs);

                for(j=0; j<n_attrs; j++)
                  {
                    GRattrinfo(riid,j,attr_name,&nt,&ncomp);

                    GRgetattr(riid,j,u8_attr);
                    printf("Image #%d Attribute #%d: Name=%s, Value=%s\n",
                             i,j,attr_name,u8_attr);
                  } /* end for */

          /* Detach from the image */
          GRendaccess(riid);
      } /* end for */

    /* Shut down the GR interface */
    GRend(grid);

    /* Close the file */
    Hclose(hdf_file_id);



Dealing with annotations in the new interface
================================================

The new GR interface allows you to reference rasters explicitly, by "GR
id".  A GR id is different from its reference number.  Since annotation
routines attach annotations to objects by reference number, there needs to
be a mechanism for determining the reference number of a raster image,
given its id. This is made possible by the addition of the routine
GRidtoref.

A similar problem occurs when going the other way.  For example, a call to
DFANlabellist returns the reference numbers of objects that are
annotated.  If those objects are RISs (i.e. they have the tag DFTAG_RIG),
we need to map the reference numbers to the corresponding images.  For
this, a two-step process is required.  You can use the function
GRreftoindex to get the index, or position, of the dataset that has a
certain reference number, then you use the routine GRselect to get the id
for the image in that position.


A listing or routines
======================

File/Interface Functions:
int32 GRstart(int32 hdf_file_id)
    - Initializes the GR interface for a particular file. Returns a 'grid' to
        specify the GR group to operate on.
intn GRfileinfo(int32 grid, int32 *n_datasets, int32 *n_attrs)
    - Returns information about the datasets and "global" attributes for the
        GR interface.
intn GRend(int32 grid)
    - Terminates multi-file GR access for a file.

Image I/O Functions:
int32 GRcreate(int32 grid,char *name,int32 ncomp,int32 nt,int32 il,int32
dimsizes[2])
    - Defines a raster image in a file.  Returns a 'riid' to work with the new
        raster image.
int32 GRselect(int32 grid,int32 index)
    - Selects an existing RI to operate on.
int32 GRnametoindex(int32 grid,char *name)
    - Maps a RI name to an index which is returned.
intn GRgetiminfo(int32 riid,char *name,int32 *ncomp,int32 *nt,int32
*il,int32 dimsizes[2],int32 *n_attr)
    - Gets information about an RI which has been selected/created.
intn GRwriteimage(int32 riid,int32 start[2],int32 stride[2],int32
count[2],VOIDP data)
    - Writes image data to an RI.  Partial dataset writing and subsampling is
        allowed, but only with the dimensions of the dataset (ie. no UNLIMITED
        dimension support)
intn GRreadimage(int32 riid,int32 start[2],int32 stride[2],int32
count[2],VOIDP data)
    - Read image data from an RI.  Partial reads and subsampling are allowed.
intn GRendaccess(int32 riid)
    - End access to an RI.

Dimension Functions:
int32 GRgetdimid(int32 riid,int32 index)
    - Get a dimension id ('dimid') for an RI to assign atrributes to. [Later]
intn GRsetdimname(int32 dimid,char *name)
    - Set the name of a dimension. [Later]
int32 GRdiminfo(int32 dimid,char *name,int32 *size,int32 *n_attr)
    - Get information about the dimensions attributes and size. [Later]

ID/Ref/Index Functions:
uint16 GRidtoref(int32 riid)
    - Maps an riid to a reference # for annotating or including in a Vgroup.
int32 GRreftoindex(int32 hdf_file_id,uint16 ref)
    - Maps the reference # of an RI into an index which can be used with
        GRselect.

Interlace Request Functions:
intn GRreqlutil(int32 riid,intn il)
    - Request that the next LUT read from an RI have a particular interlace.
intn GRreqimageil(int32 riid,intn il)
    - Request that the image read from an RI have a particular interlace.

LUT/Palette I/O Functions:
int32 GRgetlutid(int32 riid,int32 index)
    - Get a palette id ('palid') for an RI.
intn GRgetlutinfo(int32 riid,int32 *ncomp,int32 *nt,int32 *il,int32 *nentries)
    - Gets information about a palette.
intn GRwritelut(int32 riid,int32 ncomps,int32 nt,int32 il,int32
nentries,VOIDP data)
    - Writes out a palette for an RI.
intn GRreadlut(int32 palid,VOIDP data)
    - Reads a palette from an RI.

Special Element Functions:
int32 GRsetexternalfile(int32 riid,char *filename,int32 offset)
    - Makes the image data of an RI into an external element special element.
intn GRsetaccesstype(int32 riid,uintn accesstype)
    - Sets the access for an RI to be either serial or parallel I/O.
intn GRsetcompress(int32 riid,int32 comp_type,comp_info *cinfo)
    - Makes the image data of an RI into a compressed special element.

Attribute Functions:
intn GRsetattr(int32 dimid|riid|grid,char *name,int32 attr_nt,int32
count,VOIDP data)
    - Write an attribute for an object.
int32 GRattrinfo(int32 dimid|riid|grid,int32 index,char *name,int32
*attr_nt,int32 *count)
    - Get attribute information for an object.
intn GRgetattr(int32 dimid|riid|grid,int32 index,VOIDP data)
    - Read an attribute for an object.
int32 GRfindattr(int32 dimid|riid|grid,char *name)
    - Get the index of an attribute with a given name for an object.



Routine Descriptions
====================

Most of the routines in the GR interface return a status value of type intn
(native integers).  If the status is equal to SUCCEED the routine completed
successfully.  If it is equal to FAIL an error occurred, information about
the error may be available by calling HEprint(filestream, 0).  SUCCEED and
FAIL are defined in hdf.h for C users and in constant.i for Fortran
programs.

All IDs (hdf_file_id, grid, riid) are int32 quantities.

Prototypes for these functions can be found in the file hproto.h

Routines that can be called from C are all of the form GRxxx

More details about all the routines below can be found in the HDF reference
manual.


File level interface:
=====================

These routines initialize and de-initialize the GR interface, and provide
information about the raster images in a file.

GRstart
-------
    Initialize the GR*() interface for a given HDF file.
 USAGE
    int32 GRstart(hdf_file_id)
        int32 hdf_file_id;          IN: file ID from Hopen
 RETURNS
    Return grid (GR ID) on success, or FAIL
 DESCRIPTION
    Initializes the GR*() interface to operate on the HDF file which was
    specified by hdf_file_id.  This routine must be called before any further
    GR*() routines are called for a file.

GRfileinfo
----------
    Report high-level information about the GR*() interface for a given file.
 USAGE
    intn GRfileinfo(grid, n_datasets, n_attrs)
        int32 grid;                 IN: GR ID to get information about
        int32 *n_datasets;          OUT: the # of GR datasets in a file
        int32 *n_attrs;             OUT: the # of "global" GR attributes
 RETURNS
    SUCCEED/FAIL
 DESCRIPTION
    Reports general information about the number of datasets and "global"
    attributes for the GR interface.  This routine is generally used to find
    the range of acceptable indices for GRselect calls.


GRend
-----
    Terminate the GR*() interface for a given HDF file.
 USAGE
    intn GRend(grid)
        int32 grid;          IN: GR ID from GRstart
 RETURNS
    SUCCEED/FAIL

 DESCRIPTION
    Terminates access to the GR*() interface for a file.


DataSet Manipulation
=====================

GRcreate
--------
    Create a new raster image.

 USAGE
    int32 GRcreate(grid, name, ncomp, nt, il, dimsizes)
        int32 grid;         IN: GR ID from GRstart
        char *name;         IN: Name of raster image to create
        int32 ncomp;        IN: Number of components in image
        int32 nt;           IN: Number type of each component
        int32 il;           IN: Interlace of the components in the image
        int32 dimsizes[2];  IN: Dimensions of the new image

 RETURNS
    A valid riid (Raster-Image ID) on success, or FAIL.

 DESCRIPTION
    Creates a new raster image in a file.

ASSUMPTIONS
    All components must be the same number-type.


GRselect
--------
    Select a raster image to operate on.
 USAGE
    int32 GRselect(grid,index)
        int32 grid;          IN: GR ID from GRstart
        int32 index;         IN: Which raster image to select (indexed from 0)
 RETURNS
    A valid riid (Raster-Image ID) on success, or FAIL.

 DESCRIPTION
    Selects a raster image from the file to work on.  This ID is needed for
    all operations on the image dataset, including reading/writing data,
    annotations, etc.



GRnametoindex
-------------
    Map a raster image name to an index.
 USAGE
    int32 GRnametoindex(grid,name)
        int32 grid;          IN: GR ID from GRstart
        char *name;          IN: Name of raster image to search for
 RETURNS
    A valid index on success, or FAIL.

 DESCRIPTION
    Searches for a raster image based on the name provided.  This routine
    maps from names of raster images to indices inside the GR group.

GRgetiminfo
-----------
    Gets information about a raster image.

 USAGE
    intn GRgetiminfo(riid,name,ncomp,nt,il,dimsizes,n_attr)
        int32 riid;         IN: RI ID from GRselect/GRcreate
        char *name;         OUT: name of raster image
        int32 *ncomp;       OUT: number of components in image
        int32 *nt;          OUT: number type of components
        int32 *il;          OUT: interlace of the image
        int32 *dimsizes;    OUT: size of each dimension
        int32 *n_attr;      OUT: the number of attributes for the image

 RETURNS
    SUCCEED/FAIL

 DESCRIPTION
    Looks up information about an image which has been selected or created
    with the GR routines.  Each of the parameters can be NULL, in which case
    that piece of information will not be retrieved.

GRwriteimage
------------
    Writes raster data to an image

 USAGE
    intn GRwriteimage(riid,start,stride,edge,data)
        int32 riid;         IN: RI ID from GRselect/GRcreate
        int32 start[2];     IN: array containing the offset in the image of the
                                image data to write out
        int32 stride[2];    IN: array containing interval of data being written
                                along each edge.  strides of 0 are illegal
                                (and generate an error)
                                ie. stride of 1 in each dimension means
                                writing contiguous data, stride of 2 means
                                writing every other element out along an edge.
        int32 count[2];     IN: number of elements to write out along each edge.
        VOIDP data;         IN: pointer to the data to write out.

 RETURNS
    SUCCEED/FAIL

 DESCRIPTION
    Writes image data to an RI.  Partial dataset writing and subsampling is
        allowed, but only within the dimensions of the dataset (ie. no UNLIMITED
        dimension support)

 ASSUMPTIONS
    If the stride parameter is set to NULL, a stride of 1 will be assumed.


GRreadimage
-----------
    Read raster data for an image

 USAGE
    intn GRreadimage(riid,start,stride,edge,data)
        int32 riid;         IN: RI ID from GRselect/GRcreate
        int32 start[2];     IN: array containing the offset in the image of the
                                image data to read in
        int32 stride[2];    IN: array containing interval of data being read
                                along each edge.  strides of 0 are illegal
                                (and generate an error)
                                ie. stride of 1 in each dimension means
                                reading contiguous data, stride of 2 means
                                reading every other element out along an edge.
        int32 count[2];     IN: number of elements to read in along each edge.
        VOIDP data;         IN: pointer to the data to read in.

 RETURNS
    SUCCEED/FAIL

 DESCRIPTION
    Read image data from an RI.  Partial dataset reading and subsampling is
        allowed.

ASSUMPTIONS
    If the stride parameter is set to NULL, a stride of 1 will be assumed.



GRendaccess
-----------
    End access to an RI.

 USAGE
    intn GRendaccess(riid)
        int32 riid;         IN: RI ID from GRselect/GRcreate

 RETURNS
    SUCCEED/FAIL

 DESCRIPTION
    End access to an RI.  Further attempts to access the RI ID will result in
    an error.


Dimension Functions
===================
(these have not been completed)


ID/Ref/Index Functions
======================

GRidtoref
---------
    Maps an RI ID to a reference # for annotating or including in a Vgroup.

 USAGE
    uint16 GRidtoref(riid)
        int32 riid;         IN: RI ID from GRselect/GRcreate

 RETURNS
    A valid reference # on success or FAIL

 DESCRIPTION
    Maps an riid to a reference # for annotating or including in a Vgroup.


GRreftoindex
------------
    Maps the reference # of an RI into an index which can be used with GRselect.

 USAGE
    int32 GRreftoindex(grid,ref)
        int32 grid;         IN: GR ID from GRstart
        uint16 ref;         IN: reference number of raster image to map to index

 RETURNS
    A valid index # on success or FAIL

 DESCRIPTION
    Maps the reference # of an RI into an index which can be used with GRselect.


Interlace Request Functions
===========================


GRreqlutil
----------
    Request that the next LUT read from an RI have a particular interlace.

 USAGE
    intn GRreqlutil(riid,il)
        int32 riid;         IN: RI ID from GRselect/GRcreate
        intn il;            IN: interlace for next LUT.  From the following
                                values (found in mfgr.h):
                      MFGR_INTERLACE_PIXEL      - pixel interlacing
                      MFGR_INTERLACE_LINE       - line interlacing
                      MFGR_INTERLACE_COMPONENT  - component/plane interlacing

 RETURNS
    SUCCEED/FAIL

 DESCRIPTION
    Request that the next LUT read from an RI have a particular interlace.



GRreqimageil
------------
    Request that the image read from an RI have a particular interlace.

 USAGE
    intn GRreqimageil(riid,il)
        int32 riid;         IN: RI ID from GRselect/GRcreate
        intn il;            IN: interlace for next RI.  From the following
                                values (found in mfgr.h):
                      MFGR_INTERLACE_PIXEL      - pixel interlacing
                      MFGR_INTERLACE_LINE       - line interlacing
                      MFGR_INTERLACE_COMPONENT  - component/plane interlacing

 RETURNS
    SUCCEED/FAIL

 DESCRIPTION
    Request that the image read from an RI have a particular interlace.




LUT/Palette I/O Functions
=========================

GRgetlutid
----------
    Get a LUT id ('lutid') for an RI.

 USAGE
    int32 GRgetlutid(riid,index)
        int32 riid;         IN: RI ID from GRselect/GRcreate
        int32 lut_index;    IN: Which LUT image to select (indexed from 0)

 RETURNS
    Valid LUT ID on success, FAIL on failure

 DESCRIPTION
    Get a LUT id ('lutid') for accessing LUTs in an RI.

 GLOBAL VARIABLES
 COMMENTS, BUGS, ASSUMPTIONS
    Currently only supports one LUT per image, at index 0 and LUTID==RIID.




intn GRgetlutinfo(int32 riid,int32 *ncomp,int32 *nt,int32 *il,int32 *nentries)
    - Gets information about a palette.



GRwritelut
----------
    Writes out a LUT for an RI.

 USAGE
    intn GRwritelut(riid,name,ncomps,nt,il,nentries,data)
        int32 lutid;        IN: LUT ID from GRgetlutid
        char *name;         IN: name of LUT image
        int32 ncomp;        IN: number of components in LUT
        int32 nt;           IN: number type of components
        int32 il;           IN: interlace of the LUT
        int32 nentries;     IN: the number of entries for the LUT
        VOIDP data;         IN: LUT data to write out

 RETURNS
    SUCCEED/FAIL

 DESCRIPTION
    Writes out a LUT for an RI.


GRreadlut
---------
    Reads a LUT from an RI.

 USAGE
    intn GRreadlut(lutid,data)
        int32 lutid;        IN: LUT ID from GRgetlutid
        VOIDP data;         IN: buffer for LUT data read in

 RETURNS
    SUCCEED/FAIL

 DESCRIPTION
    Reads a LUT from an RI.




Special Element Functions
=========================


GRsetexternalfile
-----------------
    Makes the image data of an RI into an external element special element.

 USAGE
    intn GRsetexternalfile(riid,filename,offset)
        int32 riid;         IN: RI ID from GRselect/GRcreate
        char *filename;     IN: name of the external file
        int32 offset;       IN: offset in the external file to store the image

 RETURNS
    SUCCEED/FAIL

 DESCRIPTION
    Makes the image data of an RI into an external element special element.
        Cause the actual data for a dataset to be stored in an
        external file.  This can only be done once for any given
        dataset and it is the user's responsibility to make sure the
        external datafile is transported when the "header" file is
        moved.  The offset is the number of byte from the beginning of
        the file where the data should be stored.  This routine can
        only be called on HDF 3.3 files (i.e. calling on an XDR-based
        netCDF file that was opened with the multi-file interface will
        fail).





GRsetaccesstype
---------------
    Sets the access for an RI to be either serial or parallel I/O.

 USAGE
    intn GRsetaccesstype(riid,accesstype)
        int32 riid;         IN: RI ID from GRselect/GRcreate
        uintn accesstype;   IN: access type for image data, from the following
                                values:
                                    DFACC_SERIAL - for serial access
                                    DFACC_PARALLEL - for parallel access

 RETURNS
    SUCCEED/FAIL

 DESCRIPTION
    Sets the access for an RI to be either serial or parallel I/O.




GRsetcompress
-------------
    Compressed the image data of an RI.

 USAGE
    intn GRsetcompress(riid,comp_type,cinfo)
        int32 riid;         IN: RI ID from GRselect/GRcreate
        int32 comp_type;    IN: type of compression, from list in hcomp.h
        comp_info *cinfo;   IN: compression specific information

 RETURNS
    SUCCEED/FAIL

 DESCRIPTION
    Compressed the image data of an RI.
    (Makes the image data of an RI into a compressed special element)




Attribute Functions
===================

GRsetattr
---------
    Write an attribute for an object.

 USAGE
    intn GRsetattr(dimid|riid|grid,name,attr_nt,count,data)
        int32 dimid|riid|grid;  IN: DIM|RI|GR ID
        char *name;             IN: name of attribute
        int32 attr_nt;          IN: number-type of attribute
        int32 count;            IN: number of entries of the attribute
        VOIDP data;             IN: attribute data to write

 RETURNS
    SUCCEED/FAIL

 DESCRIPTION
    Write an attribute for an object (function will figure out ID type).

 GLOBAL VARIABLES
 COMMENTS, BUGS, ASSUMPTIONS
    Currently does not allow changing NT of an existing attribute.




GRattrinfo
----------
    Get attribute information for an object.

 USAGE
    intn GRattrinfo(dimid|riid|grid,index,name,attr_nt,count)
        int32 dimid|riid|grid;  IN: DIM|RI|GR ID
        int32 index;            IN: index of the attribute for info
        char *name;             OUT: name of attribute
        int32 attr_nt;          OUT: number-type of attribute
        int32 count;            OUT: number of entries of the attribute

 RETURNS
    SUCCEED/FAIL

 DESCRIPTION
    Get attribute information for an object.




GRgetattr
---------
    Read an attribute for an object.

 USAGE
    intn GRgetattr(dimid|riid|grid,index,data)
        int32 dimid|riid|grid;  IN: DIM|RI|GR ID
        int32 index;            IN: index of the attribute for info
        VOIDP data;             OUT: data read for attribute

 RETURNS
    SUCCEED/FAIL

 DESCRIPTION
    Read an attribute for an object.




GRfindattr
----------
    Get the index of an attribute with a given name for an object.

 USAGE
    int32 GRfindattr(int32 dimid|riid|grid,char *name)
        int32 dimid|riid|grid;  IN: DIM|RI|GR ID
        char *name;             IN: name of attribute to search for

 RETURNS
    Valid index for an attribute on success, FAIL on failure

 DESCRIPTION
    Get the index of an attribute with a given name for an object.








