1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2  * Copyright by The HDF Group.                                               *
3  * Copyright by the Board of Trustees of the University of Illinois.         *
4  * All rights reserved.                                                      *
5  *                                                                           *
6  * This file is part of HDF.  The full HDF copyright notice, including       *
7  * terms governing use, modification, and redistribution, is contained in    *
8  * the COPYING file, which can be found at the root of the source code       *
9  * distribution tree, or in https://support.hdfgroup.org/ftp/HDF/releases/.  *
10  * If you do not have access to either file, you may request a copy from     *
11  * help@hdfgroup.org.                                                        *
12  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
13 
14 /* $Id$ */
15 
16 /*
17 FILE
18     mfgr.c
19 
20 PURPOSE
21     Multi-file access to "generic" raster images
22 
23 REMARKS
24     These functions perform manipulate "generic" raster images.  These
25     raster images are composed of "pixels" which can have multiple
26     components of data-types other than 8-bit unsigned integers.  Each
27     image can have multiple palettes associated with it and other 'attributes'
28     in the same "name=value" style as the SD*() routines have.
29 
30 DESIGN
31         These routines are modeled loosely after the previous single-file
32     DFGR*() routines and the current SD*() routines.  There is a table of
33     pointers to sets of raster images stored in the files which have been
34     initialized, similar to the current Vgroup/Vdata implementation.  The table
35     contains entries for each file which contain pointers to set of information
36     about the "global" attributes (for this interface) and to the set of raster
37     images in the file.
38         Each set of information for each file is stored in memory using
39     the tbbt*() routines.
40         Each raster image (RI) in the file will be stored in one Vgroup which
41     will contain all the RIs created as well as the "global" raster attributes.
42         Each RI in the file will be stored as a Vgroup containing the image data
43     for each RI as well as the palettes and dataset attributes for that image.
44     Also, each RI Vgroup will have a corresponding RIG created with it and
45     maintained in parallel, for backward compatibility.
46 
47 BUGS/LIMITATIONS
48    Currently the following design limitations are still in place:
49    1 - Cannot have pixels or palette entries which contain mixed variable
50         types, ie. all the pixel/palette components must be of the same
51         number type.
52    2 - Currently all the components must be of valid HDF number types,
53         fractional bytes (ie. 6-bit components) or 'plain' multiple byte values
54         are not handled, although they can be packed into the next larger
55         sized number type in order to hold them.
56 
57 EXPORTED ROUTINES
58 
59 File/Interface Functions:
60 int32 GRstart(int32 hdf_file_id)
61     - Initializes the GR interface for a particular file. Returns a 'grid' to
62         specify the GR group to operate on.
63 intn GRfileinfo(int32 grid, int32 *n_datasets, int32 *n_attrs)
64     - Returns information about the datasets and "global" attributes for the
65         GR interface.
66 intn GRend(int32 grid)
67     - Terminates multi-file GR access for a file.
68 
69 Image I/O Functions:
70 int32 GRcreate(int32 grid,char *name,int32 ncomp,int32 nt,int32 il,int32 dimsizes[2])
71     - Defines a raster image in a file.  Returns a 'riid' to work with the new
72         raster image.
73 int32 GRselect(int32 grid,int32 index)
74     - Selects an existing RI to operate on.
75 int32 GRnametoindex(int32 grid,char *name)
76     - Maps a RI name to an index which is returned.
77 intn GRgetiminfo(int32 riid,char *name,int32 *ncomp,int32 *nt,int32 *il,int32 dimsizes[2],int32 *n_attr)
78     - Gets information about an RI which has been selected/created.
79 intn GRgetnluts(int32 riid)
80     - Get the number of palettes (LUTs) for an image
81 intn GRwriteimage(int32 riid,int32 start[2],int32 stride[2],int32 count[2],void * data)
82     - Writes image data to an RI.  Partial dataset writing and subsampling is
83         allowed, but only with the dimensions of the dataset (ie. no UNLIMITED
84         dimension support)
85 intn GRreadimage(int32 riid,int32 start[2],int32 stride[2],int32 count[2],void * data)
86     - Read image data from an RI.  Partial reads and subsampling are allowed.
87 intn GRendaccess(int32 riid)
88     - End access to an RI.
89 
90 Dimension Functions:
91 int32 GRgetdimid(int32 riid,int32 index)
92     - Get a dimension id ('dimid') for an RI to assign atrributes to. [Later]
93 intn GRsetdimname(int32 dimid,char *name)
94     - Set the name of a dimension. [Later]
95 int32 GRdiminfo(int32 dimid,char *name,int32 *size,int32 *n_attr)
96     - Get information about the dimensions attributes and size. [Later]
97 
98 ID/Ref/Index Functions:
99 uint16 GRidtoref(int32 riid)
100     - Maps an riid to a reference # for annotating or including in a Vgroup.
101 int32 GRreftoindex(int32 hdf_file_id,uint16 ref)
102     - Maps the reference # of an RI into an index which can be used with
103         GRselect.
104 
105 Interlace Request Functions:
106 intn GRreqlutil(int32 riid,intn il)
107     - Request that the next LUT read from an RI have a particular interlace.
108 intn GRreqimageil(int32 riid,intn il)
109     - Request that the image read from an RI have a particular interlace.
110 
111 LUT/Palette I/O Functions:
112 int32 GRgetlutid(int32 riid,int32 index)
113     - Get a palette id ('palid') for an RI.
114 uint16 GRluttoref(int32 lutid)
115     - Maps a lutid to a reference # for annotating of including in a Vgroup.
116 intn GRgetlutinfo(int32 lutid,int32 *ncomp,int32 *nt,int32 *il,int32 *nentries)
117     - Gets information about a palette.
118 intn GRwritelut(int32 lutid,int32 ncomps,int32 nt,int32 il,int32 nentries,void * data)
119     - Writes out a palette for an RI.
120 intn GRreadlut(int32 palid,void * data)
121     - Reads a palette from an RI.
122 
123 Special Element Functions:
124 int32 GRsetexternalfile(int32 riid,char *filename,int32 offset)
125     - Makes the image data of an RI into an external element special element.
126 intn GRsetaccesstype(int32 riid,uintn accesstype)
127     - Sets the access for an RI to be either serial or parallel I/O.
128 intn GRsetcompress(int32 riid,comp_coder_t comp_type,comp_info *cinfo)
129     - Makes the image data of an RI into a compressed special element.
130 intn GRgetcompress(int32 riid,comp_coder_t* comp_type,comp_info *cinfo)
131     - Retrieves the compression information of a raster image's data.
132 intn GRgetcompinfo(int32 riid,comp_coder_t* comp_type,comp_info *cinfo)
133     - Retrieves the compression information of a raster image's data.
134       Will replace GRgetcompress in the future.
135 
136 Attribute Functions:
137 intn GRsetattr(int32 dimid|riid|grid,char *name,int32 attr_nt,int32 count,void * data)
138     - Write an attribute for an object.
139 int32 GRattrinfo(int32 dimid|riid|grid,int32 index,char *name,int32 *attr_nt,int32 *count)
140     - Get attribute information for an object.
141 intn GRgetattr(int32 dimid|riid|grid,int32 index,void * data)
142     - Read an attribute for an object.
143 int32 GRfindattr(int32 dimid|riid|grid,char *name)
144     - Get the index of an attribute with a given name for an object.
145 
146 Chunking Functions:
147      GRsetchunk     -- make GR a chunked GR
148      GRgetchunkinfo -- get Info on GR
149      GRwritechunk   -- write the specified chunk to the GR
150      GRreadchunk    -- read the specified chunk to the GR
151      GRsetchunkcache -- maximum number of chunks to cache
152 
153 LOCAL ROUTINES
154 intn GRIil_convert(const void * inbuf,gr_interlace_t inil,void * outbuf,
155         gr_interlace_t outil,int32 dims[2],int32 ncomp,int32 nt);
156     - Copy a pixel buffer from one interlace to another.
157 
158 AUTHOR
159    Quincey Koziol
160 
161 MODIFICATION HISTORY
162    10/20/95  - Starting writing specs & coding prototype
163     3/ 8/96  - Modifications to remove compiled limits on the # of files
164  */
165 
166 #define MFGR_MASTER
167 #include "hdf.h"
168 #include "hlimits.h"
169 
170 #ifdef H4_HAVE_LIBSZ          /* we have the library */
171 #include "szlib.h"
172 #endif
173 
174 /* Local pre-processor macros */
175 #define XDIM    0
176 #define YDIM    1
177 
178 /*
179    * --------------------------------------------------------------------
180    * PRIVATE  data structure and routines.
181    * --------------------------------------------------------------------
182  */
183 static TBBT_TREE *gr_tree=NULL;
184 
185 /* Whether we've installed the library termination function yet for this interface */
186 PRIVATE intn library_terminate = FALSE;
187 
188 typedef struct image_info_struct {
189     uint16 grp_tag,grp_ref;         /* tag/ref of the group the image is in */
190     uint16 img_tag,img_ref;         /* tag/ref of the image itself */
191     uint16 aux_ref;                 /* ref of aux. info about an image */
192     int32 offset;                   /* offset of the image data */
193 } imginfo_t;
194 
195 PRIVATE intn GRIupdatemeta(int32 hdf_file_id,ri_info_t *img_ptr);
196 
197 PRIVATE intn GRIupdateRIG(int32 hdf_file_id,ri_info_t *img_ptr);
198 
199 PRIVATE intn GRIupdateRI(int32 hdf_file_id,ri_info_t *img_ptr);
200 
201 PRIVATE intn GRIup_attr_data(int32 hdf_file_id,at_info_t *attr_ptr);
202 
203 PRIVATE intn GRIstart(void);
204 
205 PRIVATE intn GRIgetaid(ri_info_t *img_ptr, intn acc_perm);
206 
207 PRIVATE intn GRIisspecial_type(int32 file_id, uint16 tag, uint16 ref);
208 
209 /*--------------------------------------------------------------------------
210  NAME
211     rigcompare
212  PURPOSE
213     Compare two B-tree keys for equality.
214  USAGE
215     intn rigcompare(k1, k2, cmparg)
216         void * k1, k2;               IN: ptrs to the keys for the tree elements
217         intn cmparg;                IN/OUT: unused
218  RETURNS
219     Returns negative for k2>k1, positive for k2<k1 and 0 for k2=k1
220  DESCRIPTION
221     Similar to memcmp function, this routine just compares tree keys for
222     greater/equal/lesser status.
223  GLOBAL VARIABLES
224  COMMENTS, BUGS, ASSUMPTIONS
225 
226   *** Only called by B-tree routines, should _not_ be called externally ***
227 
228  EXAMPLES
229  REVISION LOG
230 --------------------------------------------------------------------------*/
rigcompare(void * k1,void * k2,intn cmparg)231 intn rigcompare(void * k1, void * k2, intn cmparg)
232 {
233     /* shut compiler up */
234     cmparg = cmparg;
235 
236     return ((intn) ((*(int32 *) k1) - (*(int32 *) k2)));    /* valid for integer keys */
237 }   /* rigcompare */
238 
239 /* ---------------------------- GRIgrdestroynode ------------------------- */
240 /*
241    Frees B-Tree gr_info_t nodes
242 
243    *** Only called by B-tree routines, should _not_ be called externally ***
244  */
245 VOID
GRIgrdestroynode(void * n)246 GRIgrdestroynode(void * n)
247 {
248     gr_info_t      *gr_ptr=(gr_info_t *)n;
249 
250     /* clear out the tbbt's */
251     tbbtdfree(gr_ptr->grtree, GRIridestroynode, NULL);
252     tbbtdfree(gr_ptr->gattree, GRIattrdestroynode, NULL);
253 
254     HDfree(gr_ptr);
255 }   /* GRIgrdestroynode */
256 
257 /*--------------------------------------------------------------------------
258  NAME
259     GRIattrdestroynode
260  PURPOSE
261     Frees B-Tree attribute nodes.
262  USAGE
263     VOID GRIattrdestroynode(n)
264         void * n;               IN: ptr to the attr node to delete
265  RETURNS
266     none
267  DESCRIPTION
268     Called internally by the tbbt*() routines, this routine is used when
269     deleting trees.
270  GLOBAL VARIABLES
271  COMMENTS, BUGS, ASSUMPTIONS
272 
273   *** Only called by B-tree routines, should _not_ be called externally ***
274 
275  EXAMPLES
276  REVISION LOG
277 --------------------------------------------------------------------------*/
GRIattrdestroynode(void * n)278 VOID GRIattrdestroynode(void * n)
279 {
280     at_info_t *at_ptr=(at_info_t *)n;
281 
282     if(at_ptr->name!=NULL)
283         HDfree(at_ptr->name);
284     if(at_ptr->data!=NULL)
285         HDfree(at_ptr->data);
286 
287     HDfree(at_ptr);
288 }   /* GRIattrdestroynode */
289 
290 /*--------------------------------------------------------------------------
291  NAME
292     GRIridestroynode
293  PURPOSE
294     Frees B-Tree raster-image nodes.
295  USAGE
296     VOID GRIridestroynode(n)
297         void * n;               IN: ptr to the attr node to delete
298  RETURNS
299     none
300  DESCRIPTION
301     Called internally by the tbbt*() routines, this routine is used when
302     deleting trees.
303  GLOBAL VARIABLES
304  COMMENTS, BUGS, ASSUMPTIONS
305 
306   *** Only called by B-tree routines, should _not_ be called externally ***
307 
308  EXAMPLES
309  REVISION LOG
310 --------------------------------------------------------------------------*/
GRIridestroynode(void * n)311 VOID GRIridestroynode(void * n)
312 {
313     ri_info_t *ri_ptr=(ri_info_t *)n;
314 
315     if(ri_ptr->name!=NULL)
316         HDfree(ri_ptr->name);
317     if(ri_ptr->ext_name!=NULL)
318         HDfree(ri_ptr->ext_name);
319     tbbtdfree(ri_ptr->lattree, GRIattrdestroynode, NULL);
320     if(ri_ptr->fill_value!=NULL)
321         HDfree(ri_ptr->fill_value);
322 
323     HDfree(ri_ptr);
324 }   /* GRIridestroynode */
325 
326 /* -------------------------- Get_grfile ------------------------ */
327 /*
328    Looks in the TBBT gr_tree for the file ID of a file.
329    Returns a pointer to the gr_info_t for that file on success, otherwise NULL.
330  */
331 PRIVATE gr_info_t *
Get_grfile(HFILEID f)332 Get_grfile(HFILEID f)
333 {
334     void * *t;       /* vfile_t pointer from tree */
335     int32 key=(int32)f;
336 
337     t = (void **)tbbtdfind(gr_tree, &key, NULL);
338     return((gr_info_t *)(t==NULL ? NULL : *t));
339 } /* end Get_grfile() */
340 
341 /*--------------------------------------------------------------------------
342  NAME
343     GRIisspecial_type
344  PURPOSE
345     Returns the special type if the given element is special.
346  USAGE
347     intn GRIisspecial_type(file_id, tag, ref)
348         int32 file_id;    IN: file id
349         uint16 tag;    IN: tag of the element
350         uint16 ref;    IN: ref of the element
351  RETURNS
352     Special type:
353   SPECIAL_LINKED
354   SPECIAL_EXT
355   SPECIAL_COMP
356   SPECIAL_VLINKED
357   SPECIAL_CHUNKED
358   SPECIAL_BUFFERED
359   SPECIAL_COMPRAS
360     or 0 if the element is not special element.
361  DESCRIPTION
362     Called internally by the GRIget_image_list to allow a chunked or
363     linked-block element to proceed eventhough its offset is 0.
364  GLOBAL VARIABLES
365  COMMENTS, BUGS, ASSUMPTIONS
366 
367   *** Only called by library routines, should _not_ be called externally ***
368 
369  EXAMPLES
370  REVISION LOG
371 --------------------------------------------------------------------------*/
372 PRIVATE intn
GRIisspecial_type(int32 file_id,uint16 tag,uint16 ref)373 GRIisspecial_type(int32 file_id, uint16 tag, uint16 ref)
374 {
375     CONSTR(FUNC, "GRIisspecial_type");
376     accrec_t* access_rec=NULL;/* access element record */
377     int32     aid;
378     intn      ret_value=0;
379 
380     /* clear error stack */
381     HEclear();
382 
383     /* start read access on the access record of the data element, which
384        is being inquired for its special information */
385     aid = Hstartread(file_id, tag, ref);
386 
387     /* get the access_rec pointer */
388     access_rec = HAatom_object(aid);
389     if (access_rec == NULL) HGOTO_ERROR(DFE_ARGS, FAIL);
390 
391     /* only return the valid special code, anything else return 0 */
392     switch (access_rec->special)
393     {
394   case SPECIAL_LINKED:
395   case SPECIAL_EXT:
396   case SPECIAL_COMP:
397   case SPECIAL_VLINKED:
398   case SPECIAL_CHUNKED:
399   case SPECIAL_BUFFERED:
400   case SPECIAL_COMPRAS:
401       ret_value = access_rec->special;
402       break;
403   default:
404       ret_value = 0;
405     } /* switch */
406 
407     if (Hendaccess(aid)== FAIL)
408         HERROR(DFE_CANTENDACCESS);
409 done:
410   if(ret_value == FAIL)
411     { /* Error condition cleanup */
412   /* end access to the aid if it's been accessed */
413   if (aid != 0)
414       if (Hendaccess(aid)== FAIL)
415     HERROR(DFE_CANTENDACCESS);
416     } /* end if */
417 
418   /* Normal function cleanup */
419   return ret_value;
420 }   /* GRIisspecial_type */
421 
422 /* -------------------------- New_grfile ------------------------ */
423 /*
424    Creates gr_info_t structure and adds it to the tree
425    Returns a pointer to the gr_info_t for that file on success, otherwise NULL.
426  */
427 PRIVATE gr_info_t *
New_grfile(HFILEID f)428 New_grfile(HFILEID f)
429 {
430     gr_info_t *g;
431 
432     /* Allocate the gr_info_t structure */
433     if (NULL == (g = (gr_info_t *) HDcalloc(1,sizeof(gr_info_t))))
434       return(NULL);
435 
436     /* Assign the file ID & insert into the tree */
437     g->hdf_file_id=f;
438     tbbtdins(gr_tree, g, NULL);    /* insert the vg instance in B-tree */
439 
440     return(g);
441 } /* end New_grfile() */
442 
443 /* -------------------------- Store_imginfo ------------------------ */
444 /*
445    Stores information into the image_info_struct.
446 
447    Added to refactor repeated code. -BMR, Jun 7, 2015
448  */
449 PRIVATE void
Store_imginfo(imginfo_t * imginfo,uint16 grp_tag,uint16 grp_ref,uint16 img_tag,uint16 img_ref)450 Store_imginfo(
451         imginfo_t *imginfo,
452         uint16 grp_tag,
453         uint16 grp_ref,
454         uint16 img_tag,
455         uint16 img_ref)
456 {
457     imginfo->grp_tag=(uint16)grp_tag;
458     imginfo->grp_ref=(uint16)grp_ref;
459     imginfo->img_tag=(uint16)img_tag;
460     imginfo->img_ref=(uint16)img_ref;
461 } /* end Store_imginfo() */
462 
463 /* -------------------------- Get_oldimgs ------------------------ */
464 /*
465    Find all images of tag searched_tag in the file and store their
466    information in the list of image_info_structs.  The stored information
467    include the image's tag/ref, DFTAG_NULL/DFREF_WILDCARD for the group's
468    tag/ref, and the image's offset in the file.
469 
470    Returns the number of images on success, or NULL, otherwise.
471 
472    Added to refactor repeated code. -BMR, Jul 13, 2015
473  */
474 PRIVATE intn
Get_oldimgs(int32 file_id,imginfo_t * img_info,uint16 searched_tag)475 Get_oldimgs(int32 file_id, imginfo_t *img_info, uint16 searched_tag)
476 {
477     uint16 find_tag, find_ref;
478     int32 find_off, find_len;
479     intn num_imgs = 0;
480     imginfo_t *ptr = img_info;
481 
482     find_tag = find_ref = 0;
483     find_off = find_len = 0;
484 
485     while (Hfind(file_id, searched_tag, DFREF_WILDCARD, &find_tag, &find_ref, &find_off, &find_len, DF_FORWARD) == SUCCEED)
486     {
487         /* DFTAG_NULL is passed in for parent group because old images don't
488            have group structure. */
489         Store_imginfo(ptr, DFTAG_NULL, DFREF_WILDCARD, find_tag, find_ref);
490         ptr->offset = find_off;   /* store offset */
491         num_imgs++;
492         ptr++;
493     }   /* end while */
494     return num_imgs;
495 } /* end Get_oldimgs() */
496 
497 /* -------------------------- Init_diminfo ------------------------ */
498 /*
499    Initializes the dimension information.
500 
501    Added to refactor repeated code. -BMR, Apr 23, 2015
502  */
503 PRIVATE void
Init_diminfo(dim_info_t * dim_info)504 Init_diminfo(dim_info_t *dim_info)
505 { /* Init_diminfo */
506     dim_info->dim_ref = DFREF_WILDCARD;
507     dim_info->xdim = 256;
508     dim_info->ydim = 1;
509     dim_info->ncomps = 3;
510     dim_info->nt = DFNT_UINT8;
511     dim_info->file_nt_subclass = DFNTF_HDFDEFAULT;
512     dim_info->il = MFGR_INTERLACE_PIXEL;
513     dim_info->nt_tag = DFTAG_NULL;
514     dim_info->nt_ref = DFREF_WILDCARD;
515     dim_info->comp_tag = DFTAG_NULL;
516     dim_info->comp_ref = DFREF_WILDCARD;
517 } /* end Init_diminfo */
518 
519 /* -------------------------- Decode_diminfo ------------------------ */
520 /*
521    Decodes dimension information.
522 
523    The parameter *p points to a buffer containing the data read from the
524    file.  The data is the previously encoded dimension information.
525 
526    Added to refactor repeated code. -BMR, Apr 23, 2015
527  */
528 PRIVATE void
Decode_diminfo(uint8 * p,dim_info_t * dim_info)529 Decode_diminfo(uint8 *p, dim_info_t *dim_info)
530 {
531     int16 int16var;  /* temp var */
532 
533     INT32DECODE(p, dim_info->xdim);
534     INT32DECODE(p, dim_info->ydim);
535     UINT16DECODE(p, dim_info->nt_tag);
536     UINT16DECODE(p, dim_info->nt_ref);
537     INT16DECODE(p, int16var);
538     dim_info->ncomps = (int32)int16var;
539     INT16DECODE(p, dim_info->il);
540     UINT16DECODE(p, dim_info->comp_tag);
541     UINT16DECODE(p, dim_info->comp_ref);
542 } /* Decode_diminfo */
543 
544 /*--------------------------------------------------------------------------
545  NAME
546     GRIget_image_list
547  PURPOSE
548     Find all the unique raster images in the file
549  USAGE
550     intn GRIget_image_list(hdf_file_id,gr_info)
551         int32 hdf_file_id;          IN: file ID from Hopen
552         gr_info_t *gr_info;         IN: # of unique images found
553  RETURNS
554     Return SUCCEED/FAIL
555  DESCRIPTION
556     Sifts through all the images in a file and compiles a list of all the
557     unique ones.
558  GLOBAL VARIABLES
559  COMMENTS, BUGS, ASSUMPTIONS
560    o Count the maximum number of possible raster images in the file
561    o Search through the file for raster images
562       - Look for RI8s
563       - Look for RIGs
564       - Look for an RI Vgroup, then read in RIs & "global" attributes.
565    o Eliminate duplicate images
566    o Throw all the remaining RI8s, RIGs, and RIs into an internal table with
567       appropriate information about each of them
568  EXAMPLES
569  REVISION LOG
570 --------------------------------------------------------------------------*/
GRIget_image_list(int32 file_id,gr_info_t * gr_ptr)571 static intn GRIget_image_list(int32 file_id,gr_info_t *gr_ptr)
572 {
573     CONSTR(FUNC, "GRIget_image_list");
574     uint16      gr_ref;         /* ref # of the Vgroup containing new-style RIs */
575     intn        curr_image;     /* current image gathering information about */
576     intn        nimages;        /* total number of potential images */
577     intn        noldimages;     /* count of old imgs returned by Get_oldimgs */
578     int32       nri, nci, nri8, nci8, nii8, nvg;   /* number of RIs, CIs, RI8s, CI8s & II8s & Vgroups */
579     uint16      find_tag, find_ref;     /* storage for tag/ref pairs found */
580     int32       find_off, find_len;     /* storage for offset/lengths of tag/refs found */
581     imginfo_t *img_info;        /* image info list */
582     intn        i, j;           /* local counting variable */
583     intn        ret_value = SUCCEED;
584 
585     HEclear();
586 
587     /* In a completely psychotic file, there could be RIGs with no corresponding
588        RI8s and also RI8s with no corresponding RIGs, so assume the worst
589        case and then run through them all to eliminate matched pairs */
590     nri = Hnumber(file_id, DFTAG_RI);     /* count the number of RI and CIs */
591     if (nri == FAIL)
592         HGOTO_ERROR(DFE_INTERNAL, FAIL);
593     nci = Hnumber(file_id, DFTAG_CI);     /* count the number of RI and CIs */
594     if (nci == FAIL)
595         HGOTO_ERROR(DFE_INTERNAL, FAIL);
596     nri8 = Hnumber(file_id, DFTAG_RI8);     /* add the number of RI8, CI8s and II8s */
597     if (nri8 == FAIL)
598         HGOTO_ERROR(DFE_INTERNAL, FAIL);
599     nci8 = Hnumber(file_id, DFTAG_CI8);
600     if (nci8 == FAIL)
601         HGOTO_ERROR(DFE_INTERNAL, FAIL);
602     nii8 = Hnumber(file_id, DFTAG_II8);
603     if (nii8 == FAIL)
604         HGOTO_ERROR(DFE_INTERNAL, FAIL);
605     nvg = Hnumber(file_id, RI_TAG);
606     if (nvg == FAIL)
607         HGOTO_ERROR(DFE_INTERNAL, FAIL);
608     nimages = (intn) (nri + nci + nri8 + nci8 + nii8 + nvg);
609 
610     /* if there are no images just close the file and get out */
611     if (nimages == 0)
612       {
613         ret_value = (SUCCEED);
614         goto done;
615       }
616 
617     /* Get space to store the image offsets */
618     if ((img_info = (imginfo_t *) HDmalloc(nimages * sizeof(imginfo_t))) == NULL)
619         HGOTO_ERROR(DFE_NOSPACE, FAIL);
620     HDmemset(img_info, 0, (size_t)nimages * sizeof(imginfo_t));
621 
622     /* search through the GR group for raster images & global attributes */
623     curr_image = 0;
624     if((gr_ref=(uint16)Vfind(file_id,GR_NAME))!=0)
625     {
626         int32       gr_key;         /* Vgroup key of the GR Vgroup */
627 
628         gr_ptr->gr_ref=gr_ref; /* squirrel this away for later use */
629         if((gr_key=Vattach(file_id,(int32)gr_ref,"r"))!=FAIL)
630         {
631             int32 nobjs=Vntagrefs(gr_key); /* The number of objects in the Vgroup */
632             int32 img_key;  /* Vgroup key of an image */
633             int32 grp_tag,grp_ref;  /* a tag/ref in the Vgroup */
634             int32 img_tag,img_ref;  /* image tag/ref in the Vgroup */
635             char textbuf[VGNAMELENMAX + 1];    /* buffer to store the name in */
636 
637             for(i=0; i<nobjs; i++)
638             {
639                 if(Vgettagref(gr_key,i,&grp_tag,&grp_ref)==FAIL)
640                     continue;
641 
642                 switch(grp_tag)
643                 {
644                     case DFTAG_VG:  /* should be an image */
645                         if((img_key=Vattach(file_id,grp_ref,"r"))!=FAIL)
646                         {
647                             if(Vgetclass(img_key,textbuf)!=FAIL)
648                             {
649                                 if(!HDstrcmp(textbuf,RI_NAME))
650                                 { /* it is an image, get the image's tag/ref */
651                                     for(j=0; j<Vntagrefs(img_key); j++)
652                                     {
653                                         if(Vgettagref(img_key,j,&img_tag,&img_ref)==FAIL)
654                                             continue;
655                                         /* Make sure the tag is correct, then
656                                            store the image's info and the
657                                            tag/ref of the vgroup that represents
658                                            the image into image_info_struct and
659                                            increment image count */
660                                         if(img_tag==DFTAG_RI || img_tag==DFTAG_CI)
661                                         {
662                                             Store_imginfo(&img_info[curr_image], grp_tag, grp_ref, img_tag, img_ref);
663                                             img_info[curr_image].offset = Hoffset(file_id, (uint16)img_tag, (uint16)img_ref);     /* store offset */
664                                             curr_image++;
665                                             break;
666                                         } /* end if */
667                                     } /* end for */
668                                 } /* end if */
669                             } /* end if */
670                             Vdetach(img_key);
671                         } /* end if */
672                         break; /* case DFTAG_VG, an image */
673 
674                     case DFTAG_VH:  /* must be a "global" attribute */
675                     {
676                         at_info_t *new_attr;  /* attr to add to the set of global attrs */
677                         int32 at_key;         /* VData key for the attribute */
678 
679                         if((new_attr=(at_info_t *)HDmalloc(sizeof(at_info_t)))==NULL)
680                             HGOTO_ERROR(DFE_NOSPACE,FAIL);
681                         new_attr->ref=(uint16)grp_ref;
682                         new_attr->index=gr_ptr->gattr_count;
683                         new_attr->data_modified=FALSE;
684                         new_attr->new_at=FALSE;
685                         new_attr->data=NULL;
686 
687                         /* Open the vdata to read the attr's info */
688                         if((at_key=VSattach(file_id,(int32)grp_ref,"r"))!=FAIL)
689                         {
690                             char *fname;
691 
692                             /* Make certain the attribute only has one field */
693                             if(VFnfields(at_key)!=1)
694                             {
695                                 VSdetach(at_key);
696                                 HDfree(new_attr);
697                                 break;
698                             } /* end if */
699                             new_attr->nt=VFfieldtype(at_key,0);
700                             new_attr->len=VFfieldorder(at_key,0);
701                             if(new_attr->len==1)
702                                 new_attr->len=VSelts(at_key);
703 
704                             /* Get the name of the attribute */
705                             if((fname=VFfieldname(at_key,0))==NULL)
706                             {
707                                 sprintf(textbuf,"Attribute #%d",(int)new_attr->index);
708                                 if((new_attr->name=(char *)HDmalloc(HDstrlen(textbuf)+1))==NULL)
709                                 {
710                                     VSdetach(at_key);
711                                     HDfree(new_attr);
712                                     HGOTO_ERROR(DFE_NOSPACE,FAIL);
713                                 } /* end if */
714                                 HDstrcpy(new_attr->name,textbuf);
715                             } /* end if */
716                             else
717                             {
718                                 if((new_attr->name=(char *)HDmalloc(HDstrlen(fname)+1))==NULL)
719                                 {
720                                     VSdetach(at_key);
721                                     HDfree(new_attr);
722                                     HGOTO_ERROR(DFE_NOSPACE,FAIL);
723                                 } /* end if */
724                                 HDstrcpy(new_attr->name,fname);
725                             } /* end else */
726 
727                             /* insert the attr instance in B-tree */
728                             tbbtdins(gr_ptr->gattree, new_attr, NULL);
729 
730                             VSdetach(at_key);
731                         } /* end if */
732 
733                         /* increment the number of GR global attributes */
734                         gr_ptr->gattr_count++;
735                     } /* end case DFTAG_VH, a global attribute */
736                     break;
737 
738                     default:
739                         break;
740                 } /* end switch */
741             } /* end for */
742             Vdetach(gr_key);
743         } /* end if */
744     } /* end if */
745 
746     /* Get information about the RIGs in the file */
747     find_tag = find_ref = 0;
748     while (Hfind(file_id, DFTAG_RIG, DFREF_WILDCARD, &find_tag, &find_ref, &find_off, &find_len, DF_FORWARD) == SUCCEED)
749       {
750           uint16      elt_tag, elt_ref;   /* tag/ref of items in a RIG */
751           int32       group_id;       /* group ID for looking at RIG's */
752 
753           /* read RIG into memory */
754           if ((group_id = DFdiread(file_id, DFTAG_RIG, find_ref)) == FAIL)
755               HGOTO_ERROR(DFE_INTERNAL, FAIL);
756           elt_tag = elt_ref = 0;    /* initialize bogus tag/ref */
757           while (DFdiget(group_id, &elt_tag, &elt_ref)!=FAIL)
758             {   /* get next tag/ref */
759                 if (elt_tag == DFTAG_CI || elt_tag == DFTAG_RI)
760                   {
761                       if (elt_tag != DFTAG_NULL && elt_ref != DFREF_NONE) /* make certain we found an image */
762                         {     /* store the information about the image */
763                             Store_imginfo(&img_info[curr_image], DFTAG_RIG, find_ref, elt_tag, elt_ref);
764                             img_info[curr_image].offset = Hoffset(file_id, elt_tag, elt_ref);     /* store offset */
765                             curr_image++;
766                         }     /* end if */
767                   } /* end if */
768             } /* end while */
769       } /* end while */
770 
771     /* go through the RI8s */
772     noldimages = Get_oldimgs(file_id, &img_info[curr_image], DFTAG_RI8);
773     curr_image = curr_image + noldimages;
774 
775     /* go through the CI8s */
776     noldimages = Get_oldimgs(file_id, &img_info[curr_image], DFTAG_CI8);
777     curr_image = curr_image + noldimages;
778 
779     /* go through the II8s */
780     noldimages = Get_oldimgs(file_id, &img_info[curr_image], DFTAG_II8);
781     curr_image = curr_image + noldimages;
782 
783     /* Eliminate duplicate images by using the offset of the image data */
784     /* Here's a table for how the images will be eliminated: */
785     /*
786                                     img_info[i].grp_tag
787                                     VG              RIG             NULL(RI8)
788                                +-----------------+-----------------+--------+
789                             VG | j=NULL          | i=NULL          | i=NULL |
790                                |                 | j.aux=i.grp_ref |        |
791                                +-----------------+-----------------+--------+
792     img_info[j].grp_tag     RIG| j=NULL          | j=NULL          | i=NULL |
793                                | i.aux=j.grp_ref |                 |        |
794                                +-----------------+-----------------+--------+
795                       NULL(RI8)| j=NULL          | j=NULL          | j=NULL |
796                                +-----------------+-----------------+--------+
797     */
798 
799     for (i = 0; i < curr_image; i++)
800     {     /* go through the images looking for duplicates */
801         if(img_info[i].img_tag!=DFTAG_NULL)
802             for (j = i+1; j < curr_image; j++)
803             {
804                 /* if their refs are different, they're not duplicate, skip */
805                 if(img_info[i].img_ref == img_info[j].img_ref)
806                     if(img_info[j].img_tag!=DFTAG_NULL)
807                     {
808                         /* If the element is special, get its type, to allow
809                            linked block or chunked images to go into the if
810                            statement below in order for the duplicate image be
811                            eliminated - bug #814, BMR Feb, 2005 */
812                         intn special_type = GRIisspecial_type(file_id,img_info[i].img_tag,img_info[i].img_ref);
813 
814                         if (((img_info[i].offset!= INVALID_OFFSET && img_info[i].offset!=0)
815                                 && img_info[i].offset == img_info[j].offset) ||
816                              (img_info[i].offset==0
817                                 && (special_type == SPECIAL_LINKED ||
818                                     special_type == SPECIAL_CHUNKED)))
819                         {
820                             /* eliminate the oldest tag from the match */
821                             switch(img_info[i].img_tag)
822                             {
823                               case DFTAG_RI:
824                               case DFTAG_CI: /* Newer style raster image, found in RIG & Vgroup */
825                                   if(img_info[j].grp_tag==DFTAG_RIG)
826                                   {
827                                       img_info[j].img_tag=DFTAG_NULL;
828                                       if(img_info[i].grp_tag==DFTAG_VG)
829                                           img_info[i].aux_ref=img_info[j].grp_ref;
830                                   } /* end if */
831                                   else
832                                   {
833                                       if(img_info[i].grp_tag==DFTAG_VG)
834                                           img_info[j].img_tag=DFTAG_NULL;
835                                       else
836                                       {
837                                           img_info[j].img_tag=DFTAG_NULL;
838                                           if(img_info[i].grp_tag==DFTAG_RIG)
839                                               img_info[j].aux_ref=img_info[i].grp_ref;
840                                       } /* end else */
841                                   } /* end else */
842                                   break;
843 
844                               case DFTAG_RI8:
845                               case DFTAG_CI8:
846                               case DFTAG_II8: /* Eldest style raster image, no grouping */
847                                   if(img_info[j].img_tag!=DFTAG_RI8 && img_info[j].img_tag!=DFTAG_CI8 && img_info[j].img_tag!=DFTAG_II8)
848                                       img_info[i].img_tag=DFTAG_NULL;
849                                   else
850                                       img_info[j].img_tag=DFTAG_NULL;
851                                   break;
852 
853                               default:
854                                   /* an image which was eliminated from the list of images */
855                                   break;
856                             } /* end switch */
857                         } /* end if */
858                     } /* end if */
859             } /* end for */
860     } /* end for go through the images looking for duplicates */
861 
862     /* Ok, now sort through the file for information about each image found */
863     for(i=0; i<curr_image; i++)
864     {
865         if(img_info[i].img_tag!=DFTAG_NULL)
866         {
867             switch(img_info[i].grp_tag)
868             {
869               case DFTAG_VG: /* New style raster image, found in a Vgroup */
870               {
871                   ri_info_t *new_image; /* ptr to the image to read in */
872                   int32 img_key;            /* Vgroup key of an image */
873                   int32 img_tag,img_ref;    /* image tag/ref in the Vgroup */
874                   char textbuf[VGNAMELENMAX + 1];    /* buffer to store the name in */
875                   uint8 ntstring[4];        /* buffer to store NT info */
876                   uint8 GRtbuf[64];         /* local buffer for reading RIG info */
877 
878                   if((img_key=Vattach(file_id,(int32)img_info[i].grp_ref,"r"))!=FAIL)
879                   {
880                       uint16 name_len;
881                       if((new_image=(ri_info_t *)HDmalloc(sizeof(ri_info_t)))==NULL)
882                       {
883                           HDfree(img_info);   /* free offsets */
884                           Hclose(file_id);
885                           HGOTO_ERROR(DFE_NOSPACE,FAIL);
886                       } /* end if */
887 
888                       /* Initialize all the fields in the image structure to zeros */
889                       HDmemset(new_image,0,sizeof(ri_info_t));
890 
891                       /* Get the name of the image */
892                       if(Vgetnamelen(img_key,&name_len)==FAIL)
893                           name_len = 20; /* for "Raster Image #%d" */
894                       if((new_image->name=(char *)HDmalloc(name_len+1))==NULL)
895                           HGOTO_ERROR(DFE_NOSPACE,FAIL);
896                       if(Vgetname(img_key,new_image->name)==FAIL)
897                           sprintf(new_image->name,"Raster Image #%d",(int)i);
898 
899                       /* Initialize the local attribute tree */
900                       new_image->lattr_count = 0;
901                       new_image->lattree = tbbtdmake(rigcompare, sizeof(int32), TBBT_FAST_INT32_COMPARE);
902                       if (new_image->lattree == NULL)
903                           HGOTO_ERROR(DFE_NOSPACE, FAIL);
904                       new_image->ri_ref=img_info[i].grp_ref;
905                       if(img_info[i].aux_ref!=0)
906                           new_image->rig_ref=img_info[i].aux_ref;
907                       else
908                           new_image->rig_ref=DFREF_WILDCARD;
909 
910                       for(j=0; j<Vntagrefs(img_key); j++)
911                       {
912                           if(Vgettagref(img_key,j,&img_tag,&img_ref)==FAIL)
913                               continue;
914 
915                           /* parse this tag/ref pair */
916                           switch(img_tag)
917                           {
918                             case DFTAG_RI:    /* Regular image data */
919                                 new_image->img_tag=(uint16)img_tag;
920                                 new_image->img_ref=(uint16)img_ref;
921                                 if(SPECIALTAG(new_image->img_tag)==TRUE)
922                                 {
923                                     new_image->use_buf_drvr=1;
924                                 }
925                                 break;
926 
927                             case DFTAG_CI:    /* Compressed image data */
928                                 new_image->img_tag=(uint16)img_tag;
929                                 new_image->img_ref=(uint16)img_ref;
930                                 new_image->use_buf_drvr=1;
931                                 new_image->use_cr_drvr=1;
932                                 break;
933 
934                             case DFTAG_LUT:   /* Palette */
935                                 new_image->lut_tag=(uint16)img_tag;
936                                 new_image->lut_ref=(uint16)img_ref;
937 
938                                 /* Fill in some default palette dimension info, in case there isn't a DFTAG_LD for this palette */
939                                 if(new_image->lut_dim.dim_ref==0)
940 				    Init_diminfo(&(new_image->lut_dim));
941                                 break;
942 
943                             case DFTAG_LD:    /* Palette dimensions */
944 {
945                                 uint8 *p = GRtbuf;
946                                 if (Hgetelement(file_id, (uint16)img_tag, (uint16)img_ref, GRtbuf) != FAIL)
947 				    Decode_diminfo(p, &(new_image->lut_dim));
948                                 else
949                                     HGOTO_ERROR(DFE_READERROR, FAIL);
950 
951                                 /* read NT */
952                                 if (Hgetelement(file_id, new_image->lut_dim.nt_tag, new_image->lut_dim.nt_ref, ntstring) == FAIL)
953                                     HGOTO_ERROR(DFE_READERROR, FAIL);
954 
955                                 /* check for any valid NT */
956                                 if (ntstring[1] == DFNT_NONE)
957                                     break;
958 
959                                 /* set NT info */
960                                 new_image->lut_dim.dim_ref = (uint16)img_ref;
961                                 new_image->lut_dim.nt = (int32)ntstring[1];
962                                 new_image->lut_dim.file_nt_subclass = (int32)ntstring[3];
963                                 if ((new_image->lut_dim.file_nt_subclass != DFNTF_HDFDEFAULT)
964                                     && (new_image->lut_dim.file_nt_subclass!= DFNTF_PC)
965                                     && (new_image->lut_dim.file_nt_subclass!= DFKgetPNSC(new_image->lut_dim.nt, DF_MT)))
966                                     break; /* unknown subclass */
967                                 if (new_image->lut_dim.file_nt_subclass!= DFNTF_HDFDEFAULT)
968                                 {     /* if native or little endian */
969                                     if (new_image->lut_dim.file_nt_subclass!= DFNTF_PC)   /* native */
970                                         new_image->lut_dim.nt |= DFNT_NATIVE;
971                                     else  /* little endian */
972                                         new_image->lut_dim.nt |= DFNT_LITEND;
973                                 }     /* end if */
974 }
975                                 break;
976 
977                             case DFTAG_ID:    /* Image description info */
978                             {
979                                 uint8 *p = GRtbuf;
980                                 at_info_t *new_attr;  /* attr to add to the local attr set */
981                                 if (Hgetelement(file_id, (uint16)img_tag, (uint16)img_ref, GRtbuf) != FAIL)
982 				    Decode_diminfo(p, &(new_image->img_dim));
983                                 else
984                                     HGOTO_ERROR(DFE_READERROR, FAIL);
985 
986                                 /* read NT */
987                                 if (Hgetelement(file_id, new_image->img_dim.nt_tag, new_image->img_dim.nt_ref, ntstring) == FAIL)
988                                     HGOTO_ERROR(DFE_READERROR, FAIL);
989 
990                                 /* check for any valid NT */
991                                 if (ntstring[1] == DFNT_NONE)
992                                     break;
993 
994                                 /* set NT info */
995                                 new_image->img_dim.dim_ref=(uint16)img_ref;
996                                 new_image->img_dim.nt = (int32)ntstring[1];
997                                 new_image->img_dim.file_nt_subclass = (int32)ntstring[3];
998                                 if ((new_image->img_dim.file_nt_subclass != DFNTF_HDFDEFAULT)
999                                     && (new_image->img_dim.file_nt_subclass!= DFNTF_PC)
1000                                     && (new_image->img_dim.file_nt_subclass!= DFKgetPNSC(new_image->img_dim.nt, DF_MT)))
1001                                     break; /* unknown subclass */
1002                                 if (new_image->img_dim.file_nt_subclass!= DFNTF_HDFDEFAULT)
1003                                 {     /* if native or little endian */
1004                                     if (new_image->img_dim.file_nt_subclass!= DFNTF_PC)   /* native */
1005                                         new_image->img_dim.nt |= DFNT_NATIVE;
1006                                     else  /* little endian */
1007                                         new_image->img_dim.nt |= DFNT_LITEND;
1008                                 }     /* end if */
1009                             } /* end case DFTAG_ID */
1010 
1011                             case DFTAG_VH:    /* Attribute information */
1012                             {
1013                                 at_info_t *new_attr;  /* attr to add to the local attr set */
1014                                 int32 at_key;         /* VData key for the attribute */
1015 
1016                                 if((new_attr=(at_info_t *)HDmalloc(sizeof(at_info_t)))==NULL)
1017                                     HGOTO_ERROR(DFE_NOSPACE,FAIL);
1018                                 new_attr->ref=(uint16)img_ref;
1019                                 new_attr->index=new_image->lattr_count;
1020                                 new_attr->data_modified=FALSE;
1021                                 new_attr->new_at=FALSE;
1022                                 new_attr->data=NULL;
1023                                 if((at_key=VSattach(file_id,(int32)img_ref,"r"))!=FAIL)
1024                                 {
1025                                     char *fname;
1026 
1027                                     /* Make certain the attribute only has one field */
1028                                     if(VFnfields(at_key)!=1)
1029                                     {
1030                                         VSdetach(at_key);
1031                                         HDfree(new_attr);
1032                                         break;
1033                                     } /* end if */
1034                                     new_attr->nt=VFfieldtype(at_key,0);
1035                                     new_attr->len=VFfieldorder(at_key,0);
1036                                     if(new_attr->len==1)
1037                                         new_attr->len=VSelts(at_key);
1038 
1039                                     /* Get the name of the attribute */
1040                                     if((fname=VFfieldname(at_key,0))==NULL)
1041                                     {
1042                                         sprintf(textbuf,"Attribute #%d",(int)new_attr->index);
1043                                         if((new_attr->name=(char *)HDmalloc(HDstrlen(textbuf)+1))==NULL)
1044                                         {
1045                                             VSdetach(at_key);
1046                                             HDfree(new_attr);
1047                                             HGOTO_ERROR(DFE_NOSPACE,FAIL);
1048                                         } /* end if */
1049                                         HDstrcpy(new_attr->name,textbuf);
1050                                     } /* end if */
1051                                     else
1052                                     {
1053                                         if((new_attr->name=(char *)HDmalloc(HDstrlen(fname)+1))==NULL)
1054                                         {
1055                                             VSdetach(at_key);
1056                                             HDfree(new_attr);
1057                                             HGOTO_ERROR(DFE_NOSPACE,FAIL);
1058                                         } /* end if */
1059                                         HDstrcpy(new_attr->name,fname);
1060                                     } /* end else */
1061 
1062                                     tbbtdins(new_image->lattree, new_attr, NULL);    /* insert the attr instance in B-tree */
1063 
1064                                     VSdetach(at_key);
1065                                 } /* end if */
1066 
1067                                 new_image->lattr_count++;
1068 
1069                                 break;
1070                             } /* end case DFTAG_VH */
1071 
1072                             default:          /* Unknown tag */
1073                                 break;
1074                           } /* end switch */
1075                       } /* end for */
1076 
1077                       new_image->index=gr_ptr->gr_count;
1078                       new_image->gr_ptr=gr_ptr; /* point up the tree */
1079                       tbbtdins(gr_ptr->grtree, new_image, NULL);    /* insert the new image into B-tree */
1080                       gr_ptr->gr_count++;
1081                       Vdetach(img_key);
1082                   } /* end if */
1083               } /* end case DFTAG_VG */
1084               break;
1085 
1086               case DFTAG_RIG:   /* Older style raster image, found in RIG */
1087               {
1088                   int32       GroupID;
1089                   uint16      elt_tag, elt_ref;
1090                   ri_info_t *new_image; /* ptr to the image to read in */
1091                   char textbuf[VGNAMELENMAX + 1];    /* buffer to store the name in */
1092                   uint8 ntstring[4];        /* buffer to store NT info */
1093                   uint8 GRtbuf[64];         /* local buffer for reading RIG info */
1094 
1095                   /* read RIG into memory */
1096                   if ((GroupID = DFdiread(file_id, DFTAG_RIG, img_info[i].grp_ref)) == FAIL)
1097                       HGOTO_ERROR(DFE_READERROR, FAIL);
1098 
1099                   if((new_image=(ri_info_t *)HDmalloc(sizeof(ri_info_t)))==NULL)
1100                   {
1101                       HDfree(img_info);   /* free offsets */
1102                       Hclose(file_id);
1103                       HGOTO_ERROR(DFE_NOSPACE,FAIL);
1104                   } /* end if */
1105 
1106                   /* Initialize all the fields in the image structure to zeros */
1107                   HDmemset(new_image,0,sizeof(ri_info_t));
1108 
1109                   /* Get the name of the image */
1110                   sprintf(textbuf,"Raster Image #%d",(int)i);
1111                   if((new_image->name=(char *)HDmalloc(HDstrlen(textbuf)+1))==NULL)
1112                       HGOTO_ERROR(DFE_NOSPACE,FAIL);
1113                   HDstrcpy(new_image->name,textbuf);
1114                   new_image->name_generated = TRUE;
1115 
1116                   /* Initialize the local attribute tree */
1117                   new_image->lattree = tbbtdmake(rigcompare, sizeof(int32), TBBT_FAST_INT32_COMPARE);
1118                   if (new_image->lattree == NULL)
1119                       HGOTO_ERROR(DFE_NOSPACE, FAIL);
1120                   new_image->ri_ref=DFREF_WILDCARD;
1121                   new_image->rig_ref=img_info[i].grp_ref;
1122 
1123                   while (DFdiget(GroupID, &elt_tag, &elt_ref)!=FAIL)
1124                   {     /* get next tag/ref */
1125                       switch (elt_tag)
1126                       {   /* process tag/ref */
1127                         case DFTAG_RI:    /* regular image data */
1128                             new_image->img_tag=elt_tag;
1129                             new_image->img_ref=elt_ref;
1130                             if(SPECIALTAG(new_image->img_tag)==TRUE)
1131                             {
1132                                 new_image->use_buf_drvr=1;
1133                             } /* end if */
1134                             break;
1135 
1136                         case DFTAG_CI:    /* compressed image data */
1137                             new_image->img_tag=elt_tag;
1138                             new_image->img_ref=elt_ref;
1139                             new_image->use_buf_drvr=1;
1140                             new_image->use_cr_drvr=1;
1141                             break;
1142 
1143                         case DFTAG_LUT:   /* Palette */
1144                             new_image->lut_tag=elt_tag;
1145                             new_image->lut_ref=elt_ref;
1146 
1147                             /* Fill in some default palette dimension info, in
1148 			       case there isn't a DFTAG_LD for this palette */
1149                             if(new_image->lut_dim.dim_ref==0)
1150                             {
1151 				    Init_diminfo(&(new_image->lut_dim));
1152                             } /* end if */
1153                             break;
1154 
1155                         case DFTAG_LD:    /* Palette dimensions */
1156 {
1157                             uint8 *p = GRtbuf;
1158                             if (Hgetelement(file_id, elt_tag, elt_ref, GRtbuf) != FAIL)
1159 				Decode_diminfo(p, &(new_image->lut_dim));
1160                             else
1161                             {
1162                                 DFdifree(GroupID);
1163                                 HGOTO_ERROR(DFE_READERROR, FAIL);
1164                             }
1165 
1166                             /* read NT */
1167                             if (Hgetelement(file_id, new_image->lut_dim.nt_tag, new_image->lut_dim.nt_ref, ntstring) == FAIL)
1168                             {
1169                                 DFdifree( GroupID );
1170                                 HGOTO_ERROR(DFE_READERROR, FAIL);
1171                             }
1172 
1173                             /* check for any valid NT */
1174                             if (ntstring[1] == DFNT_NONE)
1175                                 break;
1176 
1177                             /* set NT info */
1178                             new_image->lut_dim.dim_ref = elt_ref;
1179                             new_image->lut_dim.nt = (int32)ntstring[1];
1180                             new_image->lut_dim.file_nt_subclass = (int32)ntstring[3];
1181                             if ((new_image->lut_dim.file_nt_subclass != DFNTF_HDFDEFAULT)
1182                                 && (new_image->lut_dim.file_nt_subclass!= DFNTF_PC)
1183                                 && (new_image->lut_dim.file_nt_subclass!= DFKgetPNSC(new_image->lut_dim.nt, DF_MT)))
1184                                 break; /* unknown subclass */
1185                             if (new_image->lut_dim.file_nt_subclass!= DFNTF_HDFDEFAULT)
1186                             {     /* if native or little endian */
1187                                 if (new_image->lut_dim.file_nt_subclass!= DFNTF_PC)   /* native */
1188                                     new_image->lut_dim.nt |= DFNT_NATIVE;
1189                                 else  /* little endian */
1190                                     new_image->lut_dim.nt |= DFNT_LITEND;
1191                             }     /* end if */
1192                             break;
1193 }
1194                         case DFTAG_ID:    /* Image description info */
1195                           {
1196                             uint8 *p = GRtbuf;
1197                             if (Hgetelement(file_id, elt_tag, elt_ref, GRtbuf) != FAIL)
1198 				Decode_diminfo(p, &(new_image->img_dim));
1199                             else
1200                             {
1201                                 DFdifree( GroupID );
1202                                 HGOTO_ERROR(DFE_GETELEM, FAIL);
1203                             }
1204 
1205                             /* read NT */
1206                             if (Hgetelement(file_id, new_image->img_dim.nt_tag, new_image->img_dim.nt_ref, ntstring) == FAIL)
1207                             {
1208                                 DFdifree( GroupID );
1209                                 HGOTO_ERROR(DFE_GETELEM, FAIL);
1210                             }
1211 
1212                             /* check for any valid NT */
1213                             if (ntstring[1] == DFNT_NONE)
1214                                 break;
1215 
1216                             /* set NT info */
1217                             new_image->img_dim.dim_ref=elt_ref;
1218                             new_image->img_dim.nt = (int32)ntstring[1];
1219                             new_image->img_dim.file_nt_subclass = (int32)ntstring[3];
1220                             if ((new_image->img_dim.file_nt_subclass != DFNTF_HDFDEFAULT)
1221                                 && (new_image->img_dim.file_nt_subclass!= DFNTF_PC)
1222                                 && (new_image->img_dim.file_nt_subclass!= DFKgetPNSC(new_image->img_dim.nt, DF_MT)))
1223                                 break; /* unknown subclass */
1224                             if (new_image->img_dim.file_nt_subclass!= DFNTF_HDFDEFAULT)
1225                             {     /* if native or little endian */
1226                                 if (new_image->img_dim.file_nt_subclass!= DFNTF_PC)   /* native */
1227                                     new_image->img_dim.nt |= DFNT_NATIVE;
1228                                 else  /* little endian */
1229                                     new_image->img_dim.nt |= DFNT_LITEND;
1230                             }     /* end if */
1231                             break;
1232                           }
1233                         default:    /* ignore unknown tags */
1234                             break;
1235                       } /* end switch */
1236                   } /* end while */
1237                   new_image->index=gr_ptr->gr_count;
1238                   new_image->gr_ptr=gr_ptr; /* point up the tree */
1239                   tbbtdins(gr_ptr->grtree, new_image, NULL);    /* insert the new image into B-tree */
1240                   gr_ptr->gr_count++;
1241               } /* end case DFTAG_RIG */
1242               break;
1243 
1244               case DFTAG_NULL:  /* Eldest style raster image, no grouping */
1245               {
1246                   ri_info_t *new_image; /* ptr to the image to read in */
1247                   char textbuf[VGNAMELENMAX + 1];    /* buffer to store the name in */
1248                   uint8 GRtbuf[64];         /* local buffer for reading RIG info */
1249 
1250                   if((new_image=(ri_info_t *)HDmalloc(sizeof(ri_info_t)))==NULL)
1251                   {
1252                       HDfree(img_info);   /* free offsets */
1253                       Hclose(file_id);
1254                       HGOTO_ERROR(DFE_NOSPACE,FAIL);
1255                   } /* end if */
1256 
1257                   /* Initialize all the fields in the image structure to zeros */
1258                   HDmemset(new_image,0,sizeof(ri_info_t));
1259 
1260                   /* Get the name of the image */
1261                   sprintf(textbuf,"Raster Image #%d",(int)i);
1262                   if((new_image->name=(char *)HDmalloc(HDstrlen(textbuf)+1))==NULL)
1263                       HGOTO_ERROR(DFE_NOSPACE,FAIL);
1264                   HDstrcpy(new_image->name,textbuf);
1265                   new_image->name_generated = TRUE;
1266 
1267                   /* Initialize the local attribute tree */
1268                   new_image->lattree = tbbtdmake(rigcompare, sizeof(int32), TBBT_FAST_INT32_COMPARE);
1269                   if (new_image->lattree == NULL)
1270                       HGOTO_ERROR(DFE_NOSPACE, FAIL);
1271                   new_image->ri_ref=DFREF_WILDCARD;
1272                   new_image->rig_ref=DFREF_WILDCARD;
1273 
1274                   /* Get tag/ref for image */
1275                   new_image->img_tag=img_info[i].img_tag;
1276                   new_image->img_ref=img_info[i].img_ref;
1277 
1278                   /* Get dimension information for this 8-bit image */
1279 
1280 		  /* Initialize dim info to default */
1281 		  Init_diminfo(&(new_image->img_dim));
1282 
1283 		  /* Reassign valid values */
1284                   if (Hgetelement(file_id, DFTAG_ID8, new_image->img_ref, GRtbuf) != FAIL)
1285                   {
1286                       uint8      *p;
1287                       uint16      u;
1288 
1289                       p = GRtbuf;
1290                       UINT16DECODE(p, u);
1291                       new_image->img_dim.xdim=(int32)u;
1292                       UINT16DECODE(p, u);
1293                       new_image->img_dim.ydim=(int32)u;
1294                       new_image->img_dim.ncomps=1;
1295                   }   /* end if */
1296                   else
1297                       HGOTO_ERROR(DFE_GETELEM, FAIL);
1298 
1299                   /* Get palette information */
1300                   if(Hexist(file_id, DFTAG_IP8, new_image->img_ref)==SUCCEED)
1301                   {
1302                       new_image->lut_tag=DFTAG_IP8;
1303                       new_image->lut_ref=new_image->img_ref;
1304 
1305                       /* set palette dimensions too */
1306 		      Init_diminfo(&(new_image->lut_dim));
1307                   } /* end if */
1308                   else
1309                       new_image->lut_tag=new_image->lut_ref=DFREF_WILDCARD;
1310 
1311                   new_image->index=gr_ptr->gr_count;
1312                   new_image->gr_ptr=gr_ptr; /* point up the tree */
1313                   tbbtdins(gr_ptr->grtree, new_image, NULL);    /* insert the new image into B-tree */
1314                   gr_ptr->gr_count++;
1315               } /* end case DFTAG_NULL */
1316               break;
1317 
1318               default: /* an image which was eliminated from the list of images */
1319                   break;
1320             } /* end switch */
1321         } /* end if */
1322     } /* end for */
1323 
1324     HDfree(img_info);   /* free image info structures */
1325 
1326 done:
1327   if(ret_value == FAIL)
1328     { /* Error condition cleanup */
1329 
1330     } /* end if */
1331 
1332   /* Normal function cleanup */
1333 
1334   return ret_value;
1335 } /* end GRIget_image_list() */
1336 
1337 /*--------------------------------------------------------------------------
1338  NAME
1339     GRIil_convert
1340  PURPOSE
1341     Convert a buffer from one interlace to another.
1342  USAGE
1343     intn GRIil_convert(inbuf,inil,outbuf,outil,dims,ncomp,nt)
1344         const void * inbuf;          IN: input buffer
1345         gr_interlace_t inil;        IN: input buffer's interlace scheme
1346         void * outbuf;               IN: output buffer
1347         gr_interlace_t outil;       IN: output buffer's requested interlace scheme
1348         int32 dims[2];              IN: dimensions of the buffers
1349         int32 ncomp;                IN: both buffer's number of components per pixel
1350         int32 nt;                   IN: both buffer's pixel number-type
1351  RETURNS
1352     Returns SUCCEED/FAIL
1353  DESCRIPTION
1354     This routine converts between PIXEL, LINE & COMPONENT interlacing schemes.
1355     All data written to the disk is written in PIXEL interlacing and converted
1356     to/from the user's buffers.
1357  GLOBAL VARIABLES
1358  COMMENTS, BUGS, ASSUMPTIONS
1359     This routine does no parameter checking, it's assumed to be done at a
1360     higher layer.
1361 
1362     This routine also does not handle the case where the inbuf==outbuf, i.e.
1363     switching the interlace 'in-place'.  More work would be required to enable
1364     this to be done.
1365  EXAMPLES
1366  REVISION LOG
1367 --------------------------------------------------------------------------*/
GRIil_convert(const void * inbuf,gr_interlace_t inil,void * outbuf,gr_interlace_t outil,int32 dims[2],int32 ncomp,int32 nt)1368 intn GRIil_convert(const void * inbuf,gr_interlace_t inil,void * outbuf,
1369         gr_interlace_t outil,int32 dims[2],int32 ncomp,int32 nt)
1370 {
1371     CONSTR(FUNC, "GRIil_convert");    /* for HERROR */
1372     intn ret_value=SUCCEED;
1373     uintn pixel_size=(uintn)DFKNTsize((nt|DFNT_NATIVE)&(~DFNT_LITEND))*(uintn)ncomp;
1374     uintn comp_size=(uintn)DFKNTsize((nt|DFNT_NATIVE)&(~DFNT_LITEND));
1375     const void * *in_comp_ptr=NULL;    /* an array of pointers to each input component */
1376     void * *out_comp_ptr=NULL;   /* an array of pointers to each output component */
1377     int32 *in_pixel_add=NULL;   /* an array of increments for each input pixel moved */
1378     int32 *out_pixel_add=NULL;  /* an array of increments for each output pixel moved */
1379     int32 *in_line_add=NULL;    /* an array of increments for each input line moved */
1380     int32 *out_line_add=NULL;   /* an array of increments for each output line moved */
1381     intn i,j,k;       /* local counting variables */
1382 
1383     if(inil==outil)     /* check for trivial input=output 'conversion' */
1384         HDmemcpy(outbuf,inbuf,(size_t)dims[XDIM]*(size_t)dims[YDIM]*(size_t)pixel_size);
1385     else
1386       {
1387           /* allocate pixel pointer arrays */
1388           if((in_comp_ptr=HDmalloc(sizeof(void *)*(size_t)ncomp))==NULL)
1389               HGOTO_ERROR(DFE_NOSPACE, FAIL);
1390           if((out_comp_ptr=HDmalloc(sizeof(void *)*(size_t)ncomp))==NULL)
1391               HGOTO_ERROR(DFE_NOSPACE, FAIL);
1392 
1393           /* allocate pixel increment arrays */
1394           if((in_pixel_add=HDmalloc(sizeof(int32)*(size_t)ncomp))==NULL)
1395               HGOTO_ERROR(DFE_NOSPACE, FAIL);
1396           if((out_pixel_add=HDmalloc(sizeof(int32)*(size_t)ncomp))==NULL)
1397               HGOTO_ERROR(DFE_NOSPACE, FAIL);
1398 
1399           /* allocate line increment arrays */
1400           if((in_line_add=HDmalloc(sizeof(int32)*(size_t)ncomp))==NULL)
1401               HGOTO_ERROR(DFE_NOSPACE, FAIL);
1402           if((out_line_add=HDmalloc(sizeof(int32)*(size_t)ncomp))==NULL)
1403               HGOTO_ERROR(DFE_NOSPACE, FAIL);
1404 
1405           /* Set up the input buffer pointers and adders */
1406           switch(inil)
1407             {
1408                 case MFGR_INTERLACE_PIXEL:
1409                     for(i=0; i<ncomp; i++)
1410                       {
1411                         in_comp_ptr[i]=((const uint8 *)inbuf)+(size_t)i*comp_size;
1412                         in_pixel_add[i]=(int32)pixel_size;
1413                         in_line_add[i]=0;
1414                       } /* end for */
1415                     break;
1416 
1417                 case MFGR_INTERLACE_LINE:
1418                     for(i=0; i<ncomp; i++)
1419                       {
1420                         in_comp_ptr[i]=((const uint8 *)inbuf)+(size_t)i*(size_t)dims[XDIM]*comp_size;
1421                         in_pixel_add[i]=(int32)comp_size;
1422                         in_line_add[i]=(int32)((size_t)(ncomp-1)*(size_t)dims[XDIM]*comp_size);
1423                       } /* end for */
1424                     break;
1425 
1426                 case MFGR_INTERLACE_COMPONENT:
1427                     for(i=0; i<ncomp; i++)
1428                       {
1429                         in_comp_ptr[i]=((const uint8 *)inbuf)+(size_t)i*(size_t)dims[YDIM]*(size_t)dims[XDIM]*comp_size;
1430                         in_pixel_add[i]=(int32)comp_size;
1431                         in_line_add[i]=0;
1432                       } /* end for */
1433                     break;
1434 
1435                 default:
1436                     HGOTO_ERROR(DFE_ARGS, FAIL);
1437             } /* end switch */
1438 
1439           /* Set up the output buffer pointers and adders */
1440           switch(outil)
1441             {
1442                 case MFGR_INTERLACE_PIXEL:
1443                     for(i=0; i<ncomp; i++)
1444                       {
1445                         out_comp_ptr[i]=((uint8 *)outbuf)+(size_t)i*comp_size;
1446                         out_pixel_add[i]=(int32)pixel_size;
1447                         out_line_add[i]=0;
1448                       } /* end for */
1449                     break;
1450 
1451                 case MFGR_INTERLACE_LINE:
1452                     for(i=0; i<ncomp; i++)
1453                       {
1454                         out_comp_ptr[i]=((uint8 *)outbuf)+(size_t)i*(size_t)dims[XDIM]*comp_size;
1455                         out_pixel_add[i]=(int32)comp_size;
1456                         out_line_add[i]=(int32)((size_t)(ncomp-1)*(size_t)dims[XDIM]*comp_size);
1457                       } /* end for */
1458                     break;
1459 
1460                 case MFGR_INTERLACE_COMPONENT:
1461                     for(i=0; i<ncomp; i++)
1462                       {
1463                         out_comp_ptr[i]=((uint8 *)outbuf)+(size_t)i*(size_t)dims[YDIM]*(size_t)dims[XDIM]*comp_size;
1464                         out_pixel_add[i]=(int32)comp_size;
1465                         out_line_add[i]=0;
1466                       } /* end for */
1467                     break;
1468 
1469                 default:
1470                     HGOTO_ERROR(DFE_ARGS, FAIL);
1471             } /* end switch */
1472 
1473         /* now just push pixels from one buffer to another */
1474         for(i=0; i<dims[YDIM]; i++)
1475           {
1476               for(j=0; j<dims[XDIM]; j++)
1477                 {
1478                     for(k=0; k<ncomp; k++)
1479                       {
1480                           HDmemcpy(out_comp_ptr[k],in_comp_ptr[k],comp_size);
1481                           out_comp_ptr[k]=((uint8 *)out_comp_ptr[k])+out_pixel_add[k];
1482                           in_comp_ptr[k]=((const uint8 *)in_comp_ptr[k])+in_pixel_add[k];
1483                       } /* end for */
1484                 } /* end for */
1485 
1486               /* wrap around the end of the line of pixels */
1487               /* (only necessary if one of the buffers is in 'line' interlace) */
1488               if(inil==MFGR_INTERLACE_LINE || outil==MFGR_INTERLACE_LINE)
1489                   for(k=0; k<ncomp; k++)
1490                     {
1491                         out_comp_ptr[k]=((uint8 *)out_comp_ptr[k])+out_line_add[k];
1492                         in_comp_ptr[k]=((const uint8 *)in_comp_ptr[k])+in_line_add[k];
1493                     } /* end for */
1494           } /* end for */
1495       } /* end else */
1496 
1497 done:
1498   if(ret_value == FAIL)
1499     { /* Error condition cleanup */
1500 
1501     } /* end if */
1502 
1503   /* Normal function cleanup */
1504 
1505     /* Free arrays allocated during this routine */
1506     /* (common for both error and normal returns) */
1507     if(in_comp_ptr!=NULL)
1508         HDfree((void*)in_comp_ptr);
1509     if(out_comp_ptr!=NULL)
1510         HDfree(out_comp_ptr);
1511     if(in_pixel_add!=NULL)
1512         HDfree(in_pixel_add);
1513     if(out_pixel_add!=NULL)
1514         HDfree(out_pixel_add);
1515     if(in_line_add!=NULL)
1516         HDfree(in_line_add);
1517     if(out_line_add!=NULL)
1518         HDfree(out_line_add);
1519 
1520   return ret_value;
1521 } /* end GRIil_convert() */
1522 
1523 /*--------------------------------------------------------------------------
1524  NAME
1525     GRstart
1526  PURPOSE
1527     Initialize the GR*() interface for a given HDF file.
1528  USAGE
1529     int32 GRstart(hdf_file_id)
1530         int32 hdf_file_id;          IN: file ID from Hopen
1531  RETURNS
1532     Return grid on success or FAIL
1533  DESCRIPTION
1534     Initializes the GR*() interface to operate on the HDF file which was
1535     specified by hdf_file_id.  This routine must be called before any further
1536     GR*() routines are called for a file.
1537 
1538  GLOBAL VARIABLES
1539  COMMENTS, BUGS, ASSUMPTIONS
1540  EXAMPLES
1541  REVISION LOG
1542 --------------------------------------------------------------------------*/
GRstart(int32 hdf_file_id)1543 int32 GRstart(int32 hdf_file_id)
1544 {
1545     CONSTR(FUNC, "GRstart");    /* for HERROR */
1546     gr_info_t *gr_ptr;          /* ptr to the new GR information for a file */
1547     int32  ret_value = SUCCEED;
1548 
1549     /* clear error stack and check validity of file id */
1550     HEclear();
1551 
1552     /* Perform global, one-time initialization */
1553     if (library_terminate == FALSE)
1554         if(GRIstart()==FAIL)
1555             HGOTO_ERROR(DFE_CANTINIT, FAIL);
1556 
1557     /* check the validity of the file ID */
1558     if(!HDvalidfid(hdf_file_id))
1559         HGOTO_ERROR(DFE_ARGS, FAIL);
1560 
1561     /* Check if GR file tree has been allocated */
1562     if (gr_tree == NULL)
1563       {
1564           if ((gr_tree = tbbtdmake(rigcompare, sizeof(int32), TBBT_FAST_INT32_COMPARE)) == NULL)
1565               HGOTO_ERROR(DFE_NOSPACE, FAIL);
1566 
1567           /* Initialize the atom groups for GRs and RIs */
1568           HAinit_group(GRIDGROUP,GRATOM_HASH_SIZE);
1569           HAinit_group(RIIDGROUP,GRATOM_HASH_SIZE);
1570       } /* end if */
1571 
1572     /* Grab the existing gr_info_t structure first, otherwise create a new one */
1573     if ((gr_ptr = Get_grfile(hdf_file_id)) == NULL)
1574         if ((gr_ptr = New_grfile(hdf_file_id)) == NULL)
1575             HGOTO_ERROR(DFE_FNF, FAIL);
1576 
1577     if (gr_ptr->access==0)
1578       {
1579         /* Fire up the Vset interface */
1580         if(Vstart(hdf_file_id)==FAIL)
1581             HGOTO_ERROR(DFE_CANTINIT,FAIL);
1582 
1583         /* Initialize the starting information for the interface */
1584         gr_ptr->hdf_file_id=hdf_file_id;
1585         gr_ptr->gr_ref=DFREF_WILDCARD;
1586         gr_ptr->gr_count=0;
1587         gr_ptr->grtree = tbbtdmake(rigcompare, sizeof(int32), TBBT_FAST_INT32_COMPARE);
1588         if (gr_ptr->grtree == NULL)
1589             HGOTO_ERROR(DFE_NOSPACE, FAIL);
1590         gr_ptr->gr_modified=0;
1591 
1592         gr_ptr->gattr_count=0;
1593         gr_ptr->gattree = tbbtdmake(rigcompare, sizeof(int32), TBBT_FAST_INT32_COMPARE);
1594         if (gr_ptr->gattree == NULL)
1595             HGOTO_ERROR(DFE_NOSPACE, FAIL);
1596         gr_ptr->gattr_modified=0;
1597         gr_ptr->attr_cache=GR_ATTR_THRESHHOLD;
1598 
1599         /* Go get all the images and attributes in the file */
1600         if(GRIget_image_list(hdf_file_id,gr_ptr)==FAIL)
1601             HGOTO_ERROR(DFE_INTERNAL,FAIL);
1602       } /* end else */
1603     gr_ptr->access++;
1604 
1605     /* Return handle to the GR interface to the user */
1606     ret_value=HAregister_atom(GRIDGROUP,gr_ptr);
1607 
1608 
1609 done:
1610   if(ret_value == FAIL)
1611     { /* Error condition cleanup */
1612 
1613     } /* end if */
1614 
1615   /* Normal function cleanup */
1616   return ret_value;
1617 } /* end GRstart() */
1618 
1619 /*--------------------------------------------------------------------------
1620  NAME
1621     GRfileinfo
1622  PURPOSE
1623     Report high-level information about the GR*() interface for a given file.
1624  USAGE
1625     intn GRfileinfo(grid, n_datasets, n_attrs)
1626         int32 grid;                 IN: GR ID to get information about
1627         int32 *n_datasets;          OUT: the # of GR datasets in a file
1628         int32 *n_attrs;             OUT: the # of "global" GR attributes
1629  RETURNS
1630     SUCCEED/FAIL
1631  DESCRIPTION
1632     Reports general information about the number of datasets and "global"
1633     attributes for the GR interface.  This routine is generally used to find
1634     the range of acceptable indices for GRselect calls.
1635  GLOBAL VARIABLES
1636  COMMENTS, BUGS, ASSUMPTIONS
1637  EXAMPLES
1638  REVISION LOG
1639 --------------------------------------------------------------------------*/
GRfileinfo(int32 grid,int32 * n_datasets,int32 * n_attrs)1640 intn GRfileinfo(int32 grid,int32 *n_datasets,int32 *n_attrs)
1641 {
1642     CONSTR(FUNC, "GRfileinfo");    /* for HERROR */
1643     gr_info_t *gr_ptr;          /* ptr to the GR information for a file */
1644     intn  ret_value = SUCCEED;
1645 
1646     /* clear error stack and check validity of file id */
1647     HEclear();
1648 
1649     /* check the validity of the GR ID */
1650     if (HAatom_group(grid)!=GRIDGROUP)
1651         HGOTO_ERROR(DFE_ARGS, FAIL);
1652 
1653     /* locate GR's object in hash table */
1654     if (NULL == (gr_ptr = (gr_info_t *) HAatom_object(grid)))
1655         HGOTO_ERROR(DFE_GRNOTFOUND, FAIL);
1656 
1657     /* Get the number of datasets & global attributes from the memory structures */
1658     if(n_datasets!=NULL)
1659         *n_datasets=gr_ptr->gr_count;
1660     if(n_attrs!=NULL)
1661         *n_attrs=gr_ptr->gattr_count;
1662 
1663 
1664 done:
1665   if(ret_value == FAIL)
1666     { /* Error condition cleanup */
1667 
1668     } /* end if */
1669 
1670   /* Normal function cleanup */
1671   return ret_value;
1672 } /* end GRfileinfo() */
1673 
1674 /*--------------------------------------------------------------------------
1675  NAME
1676     GRIupdatemeta
1677  PURPOSE
1678     Internal routine to update the meta-data for an image
1679  USAGE
1680     intn GRIupdatemeta(hdf_file_id,img_ptr)
1681         int32 hdf_file_id;          IN: the file ID for the HDF file.
1682         ri_info_t *img_ptr;         IN: pointer to the image info for the
1683                                         image to write.
1684  RETURNS
1685     SUCCEED/FAIL
1686 
1687  DESCRIPTION
1688     Write out the meta-information about an image (& palette) to an HDF file.
1689 
1690  GLOBAL VARIABLES
1691  COMMENTS, BUGS, ASSUMPTIONS
1692     Shared by both GRIupdateRIG() and GRIupdateRI() calls.
1693  EXAMPLES
1694  REVISION LOG
1695 --------------------------------------------------------------------------*/
GRIupdatemeta(int32 hdf_file_id,ri_info_t * img_ptr)1696 PRIVATE intn GRIupdatemeta(int32 hdf_file_id,ri_info_t *img_ptr)
1697 {
1698     CONSTR(FUNC, "GRIupdatemeta");   /* for HERROR */
1699     uint8 GRtbuf[64];   /* local buffer for reading RIG info */
1700     uint8 ntstring[4];  /* temporary storage for the number type information */
1701     uint8 *p;           /* temporary pointer into buffer */
1702     intn  ret_value = SUCCEED;
1703 
1704     HEclear();
1705     if (!HDvalidfid(hdf_file_id) || img_ptr==NULL)
1706         HGOTO_ERROR(DFE_ARGS, FAIL);
1707 
1708     /* Weird test below to allow for tag/ref values of zero.  (I'll spare */
1709     /*  everyone my rant about why DFTAG_NULL should have been made zero */
1710     /*  instead of one... QAK) */
1711     if(img_ptr->img_dim.nt_tag<=(uint16)DFTAG_NULL)
1712         img_ptr->img_dim.nt_tag=DFTAG_NT;
1713     if(img_ptr->img_dim.nt_ref==DFREF_WILDCARD)
1714         img_ptr->img_dim.nt_ref=Htagnewref(hdf_file_id,img_ptr->img_dim.nt_tag);
1715 
1716     /* Write out the raster image's number-type record */
1717     ntstring[0] = DFNT_VERSION;     /* version */
1718     ntstring[1] = (uint8)img_ptr->img_dim.nt;       /* type */
1719     ntstring[2] = (uint8)(DFKNTsize(img_ptr->img_dim.nt)*8); /* width: RIG data is 8-bit chars */
1720     ntstring[3] = DFNTC_BYTE;       /* class: data are numeric values */
1721     if (Hputelement(hdf_file_id, img_ptr->img_dim.nt_tag,
1722             img_ptr->img_dim.nt_ref, ntstring, (int32) 4) == FAIL)
1723         HGOTO_ERROR(DFE_PUTELEM, FAIL);
1724 
1725     /* Check for a palette with this image */
1726     if(img_ptr->lut_ref!=DFREF_WILDCARD)
1727       {
1728           /* Write out the palette number-type */
1729           if(img_ptr->lut_dim.nt_tag<=(uint16)DFTAG_NULL)
1730               img_ptr->lut_dim.nt_tag=DFTAG_NT;
1731           if(img_ptr->lut_dim.nt_ref==DFREF_WILDCARD)
1732               img_ptr->lut_dim.nt_ref=Htagnewref(hdf_file_id,img_ptr->lut_dim.nt_tag);
1733           ntstring[0] = DFNT_VERSION;     /* version */
1734           ntstring[1] = DFNT_UCHAR;       /* type */
1735           ntstring[2] = 8;                /* width: RIG data is 8-bit chars */
1736           ntstring[3] = DFNTC_BYTE;       /* class: data are numeric values */
1737           if (Hputelement(hdf_file_id, img_ptr->lut_dim.nt_tag,
1738                   img_ptr->lut_dim.nt_ref, ntstring, (int32)4) == FAIL)
1739               HGOTO_ERROR(DFE_PUTELEM, FAIL);
1740 
1741           /* Write out the palette dimensions */
1742           p = GRtbuf;
1743           INT32ENCODE(p, img_ptr->lut_dim.xdim);
1744           INT32ENCODE(p, img_ptr->lut_dim.ydim);
1745           UINT16ENCODE(p, img_ptr->lut_dim.nt_tag);
1746           UINT16ENCODE(p, img_ptr->lut_dim.nt_ref);
1747           INT16ENCODE(p, img_ptr->lut_dim.ncomps);
1748 /* Currently all data is written out in 'pixel' interlace, so force the */
1749 /* interlace stored on disk to match, instead of the interlacing that the */
1750 /* user created the image with. -QAK  */
1751 #ifdef LATER
1752           INT16ENCODE(p, img_ptr->lut_dim.il);
1753 #else /* LATER */
1754           INT16ENCODE(p, (int16)MFGR_INTERLACE_PIXEL);
1755 #endif /* LATER */
1756           UINT16ENCODE(p, img_ptr->lut_dim.comp_tag);
1757           UINT16ENCODE(p, img_ptr->lut_dim.comp_ref);
1758           if(img_ptr->lut_dim.dim_ref==DFREF_WILDCARD)
1759               img_ptr->lut_dim.dim_ref=Htagnewref(hdf_file_id,DFTAG_LD);
1760           if (Hputelement(hdf_file_id, DFTAG_LD, img_ptr->lut_dim.dim_ref, GRtbuf, (int32)(p-GRtbuf)) == FAIL)
1761               HGOTO_ERROR(DFE_PUTELEM, FAIL);
1762       } /* end if */
1763 
1764     /* Write out the image dimensions */
1765     p = GRtbuf;
1766     INT32ENCODE(p, img_ptr->img_dim.xdim);
1767     INT32ENCODE(p, img_ptr->img_dim.ydim);
1768     UINT16ENCODE(p, img_ptr->img_dim.nt_tag);
1769     UINT16ENCODE(p, img_ptr->img_dim.nt_ref);
1770     INT16ENCODE(p, img_ptr->img_dim.ncomps);
1771 /* Currently all data is written out in 'pixel' interlace, so force the */
1772 /* interlace stored on disk to match, instead of the interlacing that the */
1773 /* user created the image with. -QAK  */
1774 #ifdef LATER
1775     INT16ENCODE(p, img_ptr->img_dim.il);
1776 #else /* LATER */
1777     INT16ENCODE(p, (int16)MFGR_INTERLACE_PIXEL);
1778 #endif /* LATER */
1779     UINT16ENCODE(p, img_ptr->img_dim.comp_tag);
1780     UINT16ENCODE(p, img_ptr->img_dim.comp_ref);
1781     if(img_ptr->img_dim.dim_ref==DFREF_WILDCARD)
1782         img_ptr->img_dim.dim_ref=Htagnewref(hdf_file_id,DFTAG_ID);
1783     if (Hputelement(hdf_file_id, DFTAG_ID, img_ptr->img_dim.dim_ref, GRtbuf, (int32)(p-GRtbuf)) == FAIL)
1784         HGOTO_ERROR(DFE_PUTELEM, FAIL);
1785 
1786 done:
1787   if(ret_value == FAIL)
1788     { /* Error condition cleanup */
1789 
1790     } /* end if */
1791 
1792   /* Normal function cleanup */
1793 
1794   return ret_value;
1795 } /* end GRIupdatemeta() */
1796 
1797 /*--------------------------------------------------------------------------
1798  NAME
1799     GRIupdateRIG
1800  PURPOSE
1801     Internal routine to update the RIG for an image
1802  USAGE
1803     intn GRIupdateRIG(hdf_file_id,img_ptr)
1804         int32 hdf_file_id;          IN: the file ID for the HDF file.
1805         ri_info_t *img_ptr;         IN: pointer to the image info for the
1806                                         image to write.
1807  RETURNS
1808     SUCCEED/FAIL
1809 
1810  DESCRIPTION
1811     Write out the RIG structure to an HDF file.
1812 
1813  GLOBAL VARIABLES
1814  COMMENTS, BUGS, ASSUMPTIONS
1815  EXAMPLES
1816  REVISION LOG
1817 --------------------------------------------------------------------------*/
GRIupdateRIG(int32 hdf_file_id,ri_info_t * img_ptr)1818 PRIVATE intn GRIupdateRIG(int32 hdf_file_id,ri_info_t *img_ptr)
1819 {
1820     CONSTR(FUNC, "GRIupdateRIG");   /* for HERROR */
1821     int32 GroupID;      /* RIG id for group interface */
1822     intn   ret_value = SUCCEED;
1823 
1824     HEclear();
1825     if (!HDvalidfid(hdf_file_id) || img_ptr==NULL)
1826         HGOTO_ERROR(DFE_ARGS, FAIL);
1827 
1828     /* Don't write out a RIG, unless it is compatible with the older RIGS */
1829     /*  which already exist.  This is to guarantee compatibility with older */
1830     /*  software, both application and in the library */
1831     if(img_ptr->img_dim.nt!=DFNT_UINT8 || (img_ptr->img_dim.ncomps!=1
1832             && img_ptr->img_dim.ncomps!=3))
1833       {
1834         ret_value =(SUCCEED); /* lie and say it's ok - QAK */
1835         goto done;
1836       }
1837 
1838     /* Write out the image/palette meta-information */
1839     if (GRIupdatemeta(hdf_file_id,img_ptr)==FAIL)
1840         HGOTO_ERROR(DFE_INTERNAL, FAIL);
1841 
1842     /* Write out the RIG itself */
1843     if ((GroupID = DFdisetup(6)) == FAIL)    /* max 6 tag/refs in set */
1844         HGOTO_ERROR(DFE_GROUPSETUP, FAIL);
1845 
1846     /* add image dimension tag/ref to RIG */
1847     if (DFdiput(GroupID, DFTAG_ID, (uint16) img_ptr->img_dim.dim_ref) == FAIL)
1848         HGOTO_ERROR(DFE_PUTGROUP, FAIL);
1849 
1850     /* add image data tag/ref to RIG */
1851     if (DFdiput(GroupID, img_ptr->img_tag, img_ptr->img_ref) == FAIL)
1852         HGOTO_ERROR(DFE_PUTGROUP, FAIL);
1853 
1854     /* Check if we should write palette information */
1855     if(img_ptr->lut_ref!=DFREF_WILDCARD)
1856       {
1857           /* add palette dimension tag/ref to RIG */
1858           if (DFdiput(GroupID, DFTAG_LD, (uint16) img_ptr->lut_dim.dim_ref) == FAIL)
1859               HGOTO_ERROR(DFE_PUTGROUP, FAIL);
1860 
1861           /* add palette data tag/ref to RIG */
1862           if (DFdiput(GroupID, img_ptr->lut_tag, img_ptr->lut_ref) == FAIL)
1863               HGOTO_ERROR(DFE_PUTGROUP, FAIL);
1864       } /* end if */
1865 
1866     /* write out RIG */
1867     if(img_ptr->rig_ref==DFTAG_WILDCARD)
1868         img_ptr->rig_ref=Htagnewref(hdf_file_id,DFTAG_RIG);
1869     if(DFdiwrite(hdf_file_id, GroupID, DFTAG_RIG, img_ptr->rig_ref)==FAIL)
1870         HGOTO_ERROR(DFE_GROUPWRITE, FAIL);
1871 
1872 done:
1873   if(ret_value == FAIL)
1874     { /* Error condition cleanup */
1875 
1876     } /* end if */
1877 
1878   /* Normal function cleanup */
1879 
1880   return ret_value;
1881 } /* end GRIupdateRIG() */
1882 
1883 /*--------------------------------------------------------------------------
1884  NAME
1885     GRIupdateRI
1886  PURPOSE
1887     Internal routine to update the RI Vgroup for an image
1888  USAGE
1889     intn GRIupdateRI(hdf_file_id,img_ptr)
1890         int32 hdf_file_id;          IN: the file ID for the HDF file.
1891         ri_info_t *img_ptr;         IN: pointer to the image info for the
1892                                         image to write.
1893  RETURNS
1894     SUCCEED/FAIL
1895 
1896  DESCRIPTION
1897     Write out the RI Vgroup to an HDF file.
1898 
1899  GLOBAL VARIABLES
1900  COMMENTS, BUGS, ASSUMPTIONS
1901  EXAMPLES
1902  REVISION LOG
1903 --------------------------------------------------------------------------*/
GRIupdateRI(int32 hdf_file_id,ri_info_t * img_ptr)1904 PRIVATE intn GRIupdateRI(int32 hdf_file_id,ri_info_t *img_ptr)
1905 {
1906     CONSTR(FUNC, "GRIupdateRI");   /* for HERROR */
1907     int32 GroupID;      /* RI vgroup id */
1908     intn  ret_value = SUCCEED;
1909     int32 temp_ref;     /* used to hold the returned value from a function
1910                                 that may return a ref or a FAIL - BMR */
1911 
1912 
1913     HEclear();
1914     if (!HDvalidfid(hdf_file_id) || img_ptr==NULL)
1915         HGOTO_ERROR(DFE_ARGS, FAIL);
1916 
1917     /* Write out the image/palette meta-information */
1918     if (GRIupdatemeta(hdf_file_id,img_ptr)==FAIL)
1919         HGOTO_ERROR(DFE_INTERNAL, FAIL);
1920 
1921     /* Write out the RI Vgroup itself */
1922     if ((GroupID = Vattach(hdf_file_id,(img_ptr->ri_ref!=DFREF_WILDCARD ?
1923             img_ptr->ri_ref : -1),"w")) == FAIL)
1924         HGOTO_ERROR(DFE_CANTATTACH, FAIL);
1925 
1926     /* grab the ref. # of the new Vgroup */
1927     if(img_ptr->ri_ref==DFREF_WILDCARD)
1928     {
1929     /* due to uint16 type of ref, check return value of VQueryref
1930          and assign it to ri_ref only when it's not FAIL - BMR */
1931     temp_ref = VQueryref (GroupID);
1932     if(temp_ref == FAIL)
1933         HGOTO_ERROR(DFE_BADREF,FAIL);
1934     img_ptr->ri_ref = (uint16)temp_ref;
1935     }
1936 
1937     /* Set the name of the RI */
1938     if(img_ptr->name!=NULL)
1939         if(Vsetname(GroupID,img_ptr->name)==FAIL)
1940             HGOTO_ERROR(DFE_BADVSNAME,FAIL);
1941 
1942     /* Set the class of the RI group */
1943     if(Vsetclass(GroupID,RI_NAME)==FAIL)
1944         HGOTO_ERROR(DFE_BADVSNAME,FAIL);
1945 
1946     /* add image dimension tag/ref to RIG */
1947     if (Vaddtagref(GroupID, DFTAG_ID, (int32)img_ptr->img_dim.dim_ref) == FAIL)
1948         HGOTO_ERROR(DFE_CANTADDELEM, FAIL);
1949 
1950     /* If we don't have a tag for the image, just use DFTAG_RI for now */
1951     if(img_ptr->img_tag==DFTAG_NULL)
1952         img_ptr->img_tag=DFTAG_RI;
1953 
1954     /* If we don't have a ref for the image, generate a new one */
1955     if(img_ptr->img_ref==DFREF_WILDCARD) {
1956         int32 temp_aid;
1957 
1958         /* Assign reference number for image */
1959         img_ptr->img_ref=Htagnewref(hdf_file_id,img_ptr->img_tag);
1960 
1961         /* Make certain that the tag/ref pair is allocated in the file */
1962         if((temp_aid=Hstartaccess(hdf_file_id,img_ptr->img_tag,img_ptr->img_ref,DFACC_WRITE))==FAIL)
1963             HGOTO_ERROR(DFE_CANTADDELEM, FAIL);
1964         Hendaccess(temp_aid);
1965     } /* end if */
1966 
1967     /* add image data tag/ref to RIG */
1968     if (Vaddtagref(GroupID, (int32)img_ptr->img_tag, (int32)img_ptr->img_ref) == FAIL)
1969         HGOTO_ERROR(DFE_CANTADDELEM, FAIL);
1970 
1971     /* Check if we should write palette information */
1972     if(img_ptr->lut_ref!=DFREF_WILDCARD)
1973       {
1974           /* add palette dimension tag/ref to RIG */
1975           if (Vaddtagref(GroupID, DFTAG_LD, (int32)img_ptr->lut_dim.dim_ref) == FAIL)
1976               HGOTO_ERROR(DFE_CANTADDELEM, FAIL);
1977 
1978           /* add palette data tag/ref to RIG */
1979           if (Vaddtagref(GroupID, (int32)img_ptr->lut_tag, (int32)img_ptr->lut_ref) == FAIL)
1980               HGOTO_ERROR(DFE_CANTADDELEM, FAIL);
1981       } /* end if */
1982 
1983     /* write out RIG */
1984     if(Vdetach(GroupID)==FAIL)
1985         HGOTO_ERROR(DFE_CANTDETACH, FAIL);
1986 
1987 done:
1988   if(ret_value == FAIL)
1989     { /* Error condition cleanup */
1990 
1991     } /* end if */
1992 
1993   /* Normal function cleanup */
1994 
1995   return ret_value;
1996 } /* end GRIupdateRI() */
1997 
1998 /*--------------------------------------------------------------------------
1999  NAME
2000     GRIup_attr_data
2001  PURPOSE
2002     Internal routine to update/create the attribute data
2003  USAGE
2004     intn GRIup_attr_data(hdf_file_id,attr_ptr)
2005         int32 hdf_file_id;          IN: the file ID for the HDF file.
2006         at_info_t *attr_ptr;        IN: pointer to the attribute info for the
2007                                         attr. to write.
2008  RETURNS
2009     SUCCEED/FAIL
2010 
2011  DESCRIPTION
2012     Write out the data for an attribute to an HDF file.
2013 
2014  GLOBAL VARIABLES
2015  COMMENTS, BUGS, ASSUMPTIONS
2016  EXAMPLES
2017  REVISION LOG
2018 --------------------------------------------------------------------------*/
GRIup_attr_data(int32 hdf_file_id,at_info_t * attr_ptr)2019 PRIVATE intn GRIup_attr_data(int32 hdf_file_id,at_info_t *attr_ptr)
2020 {
2021     CONSTR(FUNC, "GRIup_attr_data");   /* for HERROR */
2022     intn   ret_value = SUCCEED;
2023 
2024     HEclear();
2025     if (!HDvalidfid(hdf_file_id) || attr_ptr==NULL)
2026         HGOTO_ERROR(DFE_ARGS, FAIL);
2027 
2028     /* Write out the attribute data */
2029     if (attr_ptr->ref==DFREF_WILDCARD)  /* create a new attribute */
2030       {
2031         if((attr_ptr->ref=(uint16)VHstoredata(hdf_file_id,attr_ptr->name,attr_ptr->data,
2032                 attr_ptr->len,attr_ptr->nt,RIGATTRNAME,RIGATTRCLASS))==(uint16)FAIL)
2033             HGOTO_ERROR(DFE_VSCANTCREATE,FAIL);
2034         attr_ptr->new_at=TRUE;
2035       } /* end if */
2036     else    /* update an existing one */
2037       {
2038         int32 AttrID;       /* attribute Vdata id */
2039 
2040         if((AttrID=VSattach(hdf_file_id,(int32)attr_ptr->ref,"w"))==FAIL)
2041             HGOTO_ERROR(DFE_CANTATTACH,FAIL);
2042         if(VSsetfields(AttrID,attr_ptr->name)==FAIL)
2043           {
2044             VSdetach(AttrID);
2045             HGOTO_ERROR(DFE_BADFIELDS,FAIL);
2046           } /* end if */
2047         if(VSwrite(AttrID,attr_ptr->data,attr_ptr->len,FULL_INTERLACE)==FAIL)
2048           {
2049             VSdetach(AttrID);
2050             HGOTO_ERROR(DFE_VSWRITE,FAIL);
2051           } /* end if */
2052         if(VSdetach(AttrID)==FAIL)
2053             HGOTO_ERROR(DFE_CANTDETACH,FAIL);
2054       } /* end else */
2055 
2056 done:
2057   if(ret_value == FAIL)
2058     { /* Error condition cleanup */
2059 
2060     } /* end if */
2061 
2062   /* Normal function cleanup */
2063 
2064   return ret_value;
2065 } /* end GRIup_attr_data() */
2066 
2067 /*--------------------------------------------------------------------------
2068  NAME
2069     GRend
2070  PURPOSE
2071     Terminate the GR*() interface for a given HDF file.
2072  USAGE
2073     intn GRend(grid)
2074         int32 grid;          IN: GR ID from GRstart
2075  RETURNS
2076     SUCCEED/FAIL
2077 
2078  DESCRIPTION
2079     Terminates access to the GR*() interface for a specific file.
2080 
2081  GLOBAL VARIABLES
2082  COMMENTS, BUGS, ASSUMPTIONS
2083  EXAMPLES
2084  REVISION LOG
2085 --------------------------------------------------------------------------*/
GRend(int32 grid)2086 intn GRend(int32 grid)
2087 {
2088     CONSTR(FUNC, "GRend");      /* for HERROR */
2089     int32 hdf_file_id;          /* HDF file ID */
2090     int32 GroupID;              /* VGroup ID for the GR group */
2091     gr_info_t *gr_ptr;          /* ptr to the GR information for this grid */
2092     filerec_t *file_rec;        /* File record */
2093     void *      *t1;
2094     intn   ret_value = SUCCEED;
2095     int32 temp_ref;     /* used to hold the returned value from a function
2096                                 that may return a ref or a FAIL - BMR */
2097 
2098 
2099     /* clear error stack and check validity of file id */
2100     HEclear();
2101 
2102     /* check the validity of the GR ID */
2103     if (HAatom_group(grid)!=GRIDGROUP)
2104         HGOTO_ERROR(DFE_ARGS, FAIL);
2105 
2106     /* locate GR's object in hash table */
2107     if (NULL == (gr_ptr = (gr_info_t *) HAatom_object(grid)))
2108         HGOTO_ERROR(DFE_GRNOTFOUND, FAIL);
2109 
2110     if (--gr_ptr->access)
2111         HGOTO_DONE(SUCCEED);
2112 
2113     hdf_file_id=gr_ptr->hdf_file_id;
2114     file_rec = HAatom_object(hdf_file_id);
2115 
2116     if(((file_rec->access)&DFACC_WRITE)!=0)
2117       {
2118         /* Check if the GR group exists, and create it if not */
2119         if(gr_ptr->gr_ref==DFREF_WILDCARD)
2120           {
2121             if((GroupID=Vattach(gr_ptr->hdf_file_id,-1,"w"))==FAIL)
2122                 HGOTO_ERROR(DFE_CANTATTACH,FAIL);
2123 
2124             /* due to uint16 type of ref, check return value of VQueryref
2125                 then assign it to gr_ref only when it's not FAIL */
2126             temp_ref = VQueryref(GroupID);
2127             if(temp_ref == FAIL)
2128                 HGOTO_ERROR (DFE_NOVALS,FAIL);
2129             gr_ptr->gr_ref = (uint16)temp_ref;
2130             if(Vsetname(GroupID,GR_NAME)==FAIL)
2131                 HGOTO_ERROR(DFE_BADVSNAME,FAIL);
2132             if(Vsetclass(GroupID,GR_NAME)==FAIL)
2133                 HGOTO_ERROR(DFE_BADVSNAME,FAIL);
2134           } /* end if */
2135         else
2136           {
2137             if((GroupID=Vattach(gr_ptr->hdf_file_id,(int32)gr_ptr->gr_ref,"w"))==FAIL)
2138                 HGOTO_ERROR(DFE_CANTATTACH,FAIL);
2139           } /* end else */
2140 
2141         /* Write out the information for RIs which have been changed */
2142         if(gr_ptr->gr_modified==TRUE && gr_ptr->gr_count>0)
2143           {
2144               void *      *t2;
2145               ri_info_t *img_ptr;   /* ptr to the image */
2146 
2147               if (NULL == (t2 = (void **)tbbtfirst((TBBT_NODE *) * (gr_ptr->grtree))))
2148                 {
2149                     HGOTO_ERROR(DFE_NOTINTABLE, FAIL);
2150                 } /* end if */
2151               else
2152                   img_ptr = (ri_info_t *) * t2;   /* get actual pointer to the ri_info_t */
2153 
2154               /* cycle through all of the images in memory */
2155               while (t2!=NULL)
2156                 {
2157                     /* check if the image data has been modified */
2158                     if(img_ptr->data_modified==TRUE)
2159                       {
2160                         /* do nothing currently, we are synchronously updating the image data */
2161                           img_ptr->data_modified=FALSE;
2162                       } /* end if */
2163 
2164                     /* check if the image meta-info has been modified */
2165                     if(img_ptr->meta_modified==TRUE)
2166                       {
2167                           /* Test if the tag/ref pair has been assigned yet */
2168                           if(img_ptr->img_tag==DFTAG_NULL || img_ptr->img_ref==DFREF_WILDCARD)
2169                             {
2170                               img_ptr->img_tag=DFTAG_RI;
2171                             } /* end if */
2172 
2173                           /* write out the RI/RIG information again */
2174                           if(GRIupdateRIG(gr_ptr->hdf_file_id,img_ptr)==FAIL)
2175                               HGOTO_ERROR(DFE_INTERNAL, FAIL);
2176                           if(GRIupdateRI(gr_ptr->hdf_file_id,img_ptr)==FAIL)
2177                               HGOTO_ERROR(DFE_INTERNAL, FAIL);
2178                           img_ptr->meta_modified=FALSE;
2179                       } /* end if */
2180 
2181                     /* check if the local attributes has been modified */
2182                     if(img_ptr->attr_modified==TRUE && img_ptr->lattr_count>0)
2183                       {
2184                           void *      *t3;
2185                           at_info_t *attr_ptr;   /* ptr to the attribute */
2186 
2187                           if (NULL == (t3 = (void **)tbbtfirst((TBBT_NODE *) * (img_ptr->lattree))))
2188                             {
2189                                 HGOTO_ERROR(DFE_NOTINTABLE, FAIL);
2190                             } /* end if */
2191                           else
2192                               attr_ptr = (at_info_t *) * t3;   /* get actual pointer to the at_info_t */
2193 
2194                           /* cycle through all of the local attributes in memory */
2195                           while (t3!=NULL)
2196                             {
2197                                 /* check if the attribute data has been modified */
2198                                 if(attr_ptr->data_modified==TRUE)
2199                                   {
2200                                       if(GRIup_attr_data(gr_ptr->hdf_file_id,attr_ptr)==FAIL)
2201                                           HGOTO_ERROR(DFE_INTERNAL, FAIL);
2202                                       attr_ptr->data_modified=FALSE;
2203                                   } /* end if */
2204 
2205                                 /* check if the attribute was added to the group */
2206                                 if(attr_ptr->new_at==TRUE)
2207                                   {
2208                                       int32 lGroupID;  /* ID of the Vgroup */
2209 
2210                                       if((lGroupID=Vattach(gr_ptr->hdf_file_id,(int32)img_ptr->ri_ref,"w"))==FAIL)
2211                                           HGOTO_ERROR(DFE_CANTATTACH,FAIL);
2212                                       if(Vaddtagref(lGroupID,ATTR_TAG,(int32)attr_ptr->ref)==FAIL)
2213                                           HGOTO_ERROR(DFE_CANTADDELEM,FAIL);
2214                                       if(Vdetach(lGroupID)==FAIL)
2215                                           HGOTO_ERROR(DFE_CANTDETACH,FAIL);
2216                                       attr_ptr->new_at=FALSE;
2217                                   } /* end if */
2218 
2219                                 /* get the next local attribute in the tree/list */
2220                                 if (NULL != (t3 = (void **)tbbtnext((TBBT_NODE *) t3)))     /* get the next node in the tree */
2221                                     attr_ptr = (at_info_t *) * t3;     /* get actual pointer to the at_info_t */
2222                             } /* end while */
2223                           img_ptr->attr_modified=FALSE;
2224                       } /* end if */
2225 
2226                     /* Check if the RI is already in the GR, add it if not */
2227                     if(Vinqtagref(GroupID,RI_TAG,(int32)img_ptr->ri_ref)==FALSE)
2228                         if(Vaddtagref(GroupID,RI_TAG,(int32)img_ptr->ri_ref)==FAIL)
2229                             HGOTO_ERROR(DFE_CANTADDELEM,FAIL);
2230 
2231                     /* get the next image in the tree/list */
2232                     if (NULL != (t2 = (void **)tbbtnext((TBBT_NODE *) t2)))     /* get the next node in the tree */
2233                         img_ptr = (ri_info_t *) * t2;     /* get actual pointer to the ri_info_t */
2234                 } /* end while */
2235           } /* end if */
2236 
2237         /* Write out the information for the global attributes which have been changed */
2238         if(gr_ptr->gattr_modified==TRUE && gr_ptr->gattr_count>0)
2239           {
2240               void *      *t2;
2241               at_info_t *attr_ptr;   /* ptr to the attribute */
2242 
2243               if (NULL == (t2 = (void **)tbbtfirst((TBBT_NODE *) * (gr_ptr->gattree))))
2244                 {
2245                     HGOTO_ERROR(DFE_NOTINTABLE, FAIL);
2246                 } /* end if */
2247               else
2248                   attr_ptr = (at_info_t *) * t2;   /* get actual pointer to the at_info_t */
2249 
2250               /* cycle through all of the global attributes in memory */
2251               while (t2!=NULL)
2252                 {
2253                     /* check if the attribute data has been modified */
2254                     if(attr_ptr->data_modified==TRUE)
2255                       {
2256                         if(GRIup_attr_data(gr_ptr->hdf_file_id,attr_ptr)==FAIL)
2257                             HGOTO_ERROR(DFE_INTERNAL, FAIL);
2258                         attr_ptr->data_modified=FALSE;
2259 
2260                         /* check if the attribute was a new attribute */
2261                         if(attr_ptr->new_at==TRUE)
2262                           {
2263                             if(Vaddtagref(GroupID,ATTR_TAG,(int32)attr_ptr->ref)==FAIL)
2264                                 HGOTO_ERROR(DFE_CANTADDELEM,FAIL);
2265                             attr_ptr->new_at=FALSE;
2266                           } /* end if */
2267                       } /* end if */
2268 
2269                     /* get the next global attribute in the tree/list */
2270                     if (NULL != (t2 = (void **)tbbtnext((TBBT_NODE *) t2)))     /* get the next node in the tree */
2271                         attr_ptr = (at_info_t *) * t2;     /* get actual pointer to the at_info_t */
2272                 } /* end while */
2273             gr_ptr->gattr_modified=FALSE;
2274           } /* end if */
2275 
2276         /* Let go of the GR Vgroup */
2277         if(Vdetach(GroupID)==FAIL)
2278             HGOTO_ERROR(DFE_CANTDETACH,FAIL);
2279       } /* end if */
2280 
2281     /* Free all the memory we've allocated */
2282     tbbtdfree(gr_ptr->grtree, GRIridestroynode, NULL);
2283     tbbtdfree(gr_ptr->gattree, GRIattrdestroynode, NULL);
2284 
2285     /* Close down the entry for this file in the GR tree */
2286     /* Find the node in the tree */
2287     if (( t1 = (void **)tbbtdfind(gr_tree, &hdf_file_id, NULL)) == NULL)
2288         HGOTO_DONE(FAIL);
2289 
2290     /* Delete the node and free the gr_info_t stucture */
2291     tbbtrem((TBBT_NODE **) gr_tree, (TBBT_NODE *) t1, NULL);
2292     HDfree(gr_ptr);
2293 
2294     /* Close down the Vset routines we started */
2295     if(Vend(hdf_file_id)==FAIL)
2296         HGOTO_ERROR(DFE_CANTSHUTDOWN,FAIL);
2297 
2298     if (NULL == HAremove_atom(grid))
2299         HGOTO_ERROR(DFE_INTERNAL, FAIL);
2300 
2301 done:
2302   if(ret_value == FAIL)
2303     { /* Error condition cleanup */
2304 
2305     } /* end if */
2306 
2307   /* Normal function cleanup */
2308   return ret_value;
2309 } /* end GRend() */
2310 
2311 /*--------------------------------------------------------------------------
2312  NAME
2313     GRselect
2314  PURPOSE
2315     Select a raster image to operate on.
2316  USAGE
2317     int32 GRselect(grid,index)
2318         int32 grid;          IN: GR ID from GRstart
2319         int32 index;         IN: Which raster image to select (indexed from 0)
2320  RETURNS
2321     A valid riid (Raster-Image ID) on success, or FAIL.
2322 
2323  DESCRIPTION
2324     Selects a raster image from the file to work on.  This ID is needed for
2325     all operations on the image dataset, including reading/writing data,
2326     annotations, etc.
2327 
2328  GLOBAL VARIABLES
2329  COMMENTS, BUGS, ASSUMPTIONS
2330  EXAMPLES
2331  REVISION LOG
2332 --------------------------------------------------------------------------*/
GRselect(int32 grid,int32 index)2333 int32 GRselect(int32 grid,int32 index)
2334 {
2335     CONSTR(FUNC, "GRselect");   /* for HERROR */
2336     gr_info_t *gr_ptr;          /* ptr to the GR information for this grid */
2337     ri_info_t *ri_ptr;          /* ptr to the image to work with */
2338     void * *t;                   /* temp. ptr to the image found */
2339     int32  ret_value = SUCCEED;
2340 
2341     /* clear error stack and check validity of file id */
2342     HEclear();
2343 
2344     /* check the validity of the GR ID */
2345     if (HAatom_group(grid)!=GRIDGROUP)
2346         HGOTO_ERROR(DFE_ARGS, FAIL);
2347 
2348     /* locate GR's object in hash table */
2349     if (NULL == (gr_ptr = (gr_info_t *) HAatom_object(grid)))
2350         HGOTO_ERROR(DFE_GRNOTFOUND, FAIL);
2351 
2352     /* check the index range validity */
2353     if(!VALIDRIINDEX(index,gr_ptr))
2354         HGOTO_ERROR(DFE_ARGS, FAIL);
2355 
2356     if((t = (void **)tbbtdfind(gr_ptr->grtree, &index, NULL))==NULL)
2357         HGOTO_ERROR(DFE_RINOTFOUND,FAIL);
2358     ri_ptr=(ri_info_t *)*t;
2359 
2360     ri_ptr->access++;
2361 
2362     ret_value=HAregister_atom(RIIDGROUP,ri_ptr);
2363 
2364 done:
2365   if(ret_value == FAIL)
2366     { /* Error condition cleanup */
2367 
2368     } /* end if */
2369 
2370   /* Normal function cleanup */
2371   return ret_value;
2372 } /* end GRselect() */
2373 
2374 /*--------------------------------------------------------------------------
2375  NAME
2376     GRcreate
2377 
2378  PURPOSE
2379     Create a new raster image.
2380 
2381  USAGE
2382     int32 GRcreate(grid, name, ncomp, nt, il, dimsizes)
2383         int32 grid;         IN: GR ID from GRstart
2384         char *name;         IN: Name of raster image to create
2385         int32 ncomp;        IN: Number of components in image
2386         int32 nt;           IN: Number type of each component
2387         int32 il;           IN: Interlace of the components in the image
2388         int32 dimsizes[2];  IN: Dimensions of the new image
2389 
2390  RETURNS
2391     A valid riid (Raster-Image ID) on success, or FAIL.
2392 
2393  DESCRIPTION
2394     Creates a new raster image in a file.
2395 
2396  GLOBAL VARIABLES
2397  COMMENTS, BUGS, ASSUMPTIONS
2398     All components must be the same number-type.
2399 
2400  EXAMPLES
2401  REVISION LOG
2402 --------------------------------------------------------------------------*/
GRcreate(int32 grid,const char * name,int32 ncomp,int32 nt,int32 il,int32 dimsizes[2])2403 int32 GRcreate(int32 grid,const char *name,int32 ncomp,int32 nt,int32 il,int32 dimsizes[2])
2404 {
2405     CONSTR(FUNC, "GRcreate");   /* for HERROR */
2406     int32 GroupID;              /* ID of the Vgroup created */
2407     gr_info_t *gr_ptr;          /* ptr to the GR information for this grid */
2408     ri_info_t *ri_ptr;          /* ptr to the image to work with */
2409     int32    ret_value = SUCCEED;
2410     int32 temp_ref;     /* used to hold the returned value from a function
2411                                 that may return a ref or a FAIL - BMR */
2412 
2413     /* clear error stack */
2414     HEclear();
2415 
2416     /* check the validity of the args */
2417     if (HAatom_group(grid)!=GRIDGROUP || name==NULL || ncomp<1
2418             || (il!=MFGR_INTERLACE_PIXEL && il!=MFGR_INTERLACE_LINE
2419             && il!=MFGR_INTERLACE_COMPONENT) || dimsizes==NULL
2420             || dimsizes[0]<=0 || dimsizes[1]<=0)
2421         HGOTO_ERROR(DFE_ARGS, FAIL);
2422 
2423     /* locate GR's object in hash table */
2424     if (NULL == (gr_ptr = (gr_info_t *) HAatom_object(grid)))
2425         HGOTO_ERROR(DFE_GRNOTFOUND, FAIL);
2426 
2427     /* Allocate space for the new image information */
2428     if((ri_ptr=(ri_info_t *)HDmalloc(sizeof(ri_info_t)))==NULL)
2429         HGOTO_ERROR(DFE_NOSPACE,FAIL);
2430     HDmemset(ri_ptr,0,sizeof(ri_info_t));
2431 
2432     /* Allocate space for the name and copy it */
2433     if((ri_ptr->name=(char *)HDmalloc(HDstrlen(name)+1))==NULL)
2434         HGOTO_ERROR(DFE_NOSPACE,FAIL);
2435     HDstrcpy(ri_ptr->name,name);
2436 
2437     /* Assign image information */
2438     ri_ptr->index=gr_ptr->gr_count;
2439 #ifdef OLD_WAY
2440     ri_ptr->ri_ref=DFREF_WILDCARD;
2441 #else /* OLD_WAY */
2442     if ((GroupID = Vattach(gr_ptr->hdf_file_id,-1,"w")) == FAIL)
2443         HGOTO_ERROR(DFE_CANTATTACH, FAIL);
2444     /* due to uint16 type of ref, check return value of VQueryref
2445          and assign it to ri_ref only when it's not FAIL - BMR */
2446     temp_ref = VQueryref(GroupID);
2447     if(temp_ref == FAIL)
2448         HGOTO_ERROR(DFE_BADREF, FAIL);
2449     ri_ptr->ri_ref = (uint16)temp_ref;
2450     if(Vdetach(GroupID)==FAIL)
2451         HGOTO_ERROR(DFE_CANTDETACH, FAIL);
2452 #endif /* OLD_WAY */
2453     ri_ptr->rig_ref=DFREF_WILDCARD;
2454     ri_ptr->gr_ptr=gr_ptr;
2455     ri_ptr->img_dim.dim_ref=DFREF_WILDCARD;
2456     ri_ptr->img_dim.xdim=dimsizes[XDIM];
2457     ri_ptr->img_dim.ydim=dimsizes[YDIM];
2458     ri_ptr->img_dim.ncomps=ncomp;
2459     ri_ptr->img_dim.nt=nt;
2460     ri_ptr->img_dim.file_nt_subclass=DFNTF_HDFDEFAULT;
2461     ri_ptr->img_dim.il=(gr_interlace_t)il;
2462     ri_ptr->img_dim.nt_tag=ri_ptr->img_dim.nt_ref=DFREF_WILDCARD;
2463     ri_ptr->img_dim.comp_tag=ri_ptr->img_dim.comp_ref=DFREF_WILDCARD;
2464     ri_ptr->img_tag=ri_ptr->img_ref=DFREF_WILDCARD;
2465     ri_ptr->img_aid=0;
2466     ri_ptr->acc_perm=0;
2467     ri_ptr->lut_tag=ri_ptr->lut_ref=DFREF_WILDCARD;
2468     ri_ptr->im_il=MFGR_INTERLACE_PIXEL;
2469     ri_ptr->lut_il=MFGR_INTERLACE_PIXEL;
2470     ri_ptr->data_modified=FALSE;
2471     ri_ptr->meta_modified=TRUE;
2472     ri_ptr->attr_modified=FALSE;
2473     ri_ptr->lattr_count=0;
2474     ri_ptr->lattree = tbbtdmake(rigcompare, sizeof(int32), TBBT_FAST_INT32_COMPARE);
2475     if(ri_ptr->lattree==NULL)
2476         HGOTO_ERROR(DFE_NOSPACE, FAIL);
2477     ri_ptr->use_buf_drvr=FALSE;
2478     ri_ptr->use_cr_drvr=FALSE;
2479     ri_ptr->comp_img=FALSE;
2480     ri_ptr->ext_img=FALSE;
2481     ri_ptr->acc_img=FALSE;
2482     ri_ptr->fill_img=TRUE;
2483     ri_ptr->fill_value=NULL;
2484     ri_ptr->store_fill=FALSE;
2485     ri_ptr->access++;
2486 
2487     /* insert the new image in the global image tree */
2488     tbbtdins(gr_ptr->grtree, ri_ptr, NULL);    /* insert the new image into B-tree */
2489 
2490     /* indicate that the GR info has changed */
2491     gr_ptr->gr_modified=TRUE;
2492     gr_ptr->gr_count++;
2493 
2494     ret_value=HAregister_atom(RIIDGROUP,ri_ptr);
2495 
2496 done:
2497   if(ret_value == FAIL)
2498     { /* Error condition cleanup */
2499 
2500     } /* end if */
2501 
2502   /* Normal function cleanup */
2503   return ret_value;
2504 } /* end GRcreate() */
2505 
2506 /*--------------------------------------------------------------------------
2507  NAME
2508     GRnametoindex
2509  PURPOSE
2510     Map a raster image name to an index.
2511  USAGE
2512     int32 GRnametoindex(grid,name)
2513         int32 grid;          IN: GR ID from GRstart
2514         char *name;          IN: Name of raster image to search for
2515  RETURNS
2516     A valid index on success, or FAIL.
2517 
2518  DESCRIPTION
2519     Searches for a raster image based on the name provided.  This routine
2520     maps from names of raster images to indices inside the GR group.
2521 
2522  GLOBAL VARIABLES
2523  COMMENTS, BUGS, ASSUMPTIONS
2524  EXAMPLES
2525  REVISION LOG
2526 --------------------------------------------------------------------------*/
GRnametoindex(int32 grid,const char * name)2527 int32 GRnametoindex(int32 grid,const char *name)
2528 {
2529     CONSTR(FUNC, "GRnametoindex");   /* for HERROR */
2530     gr_info_t *gr_ptr;          /* ptr to the GR information for this grid */
2531     ri_info_t *ri_ptr;          /* ptr to the image to work with */
2532     void * *t;                   /* temp. ptr to the image found */
2533     int32   ret_value = SUCCEED;
2534 
2535     /* clear error stack and check validity of file id */
2536     HEclear();
2537 
2538     /* check the validity of the GR ID */
2539     if (HAatom_group(grid)!=GRIDGROUP || name==NULL)
2540         HGOTO_ERROR(DFE_ARGS, FAIL);
2541 
2542     /* locate GR's object in hash table */
2543     if (NULL == (gr_ptr = (gr_info_t *) HAatom_object(grid)))
2544         HGOTO_ERROR(DFE_GRNOTFOUND, FAIL);
2545 
2546     if((t = (void **)tbbtfirst((TBBT_NODE *)* (gr_ptr->grtree)))==NULL)
2547         HGOTO_ERROR(DFE_RINOTFOUND,FAIL);
2548     do {
2549         ri_ptr=(ri_info_t *)*t;
2550         if(ri_ptr!=NULL && HDstrcmp(ri_ptr->name,name)==0)  /* ie. the name matches */
2551             HGOTO_DONE(ri_ptr->index);
2552     } while((t= (void **)tbbtnext((TBBT_NODE *)t))!=NULL);
2553 
2554     ret_value = (FAIL);
2555 
2556 done:
2557   if(ret_value == FAIL)
2558     { /* Error condition cleanup */
2559 
2560     } /* end if */
2561 
2562   /* Normal function cleanup */
2563   return ret_value;
2564 } /* end GRnametoindex() */
2565 
2566 /*--------------------------------------------------------------------------
2567  NAME
2568     GRgetiminfo
2569 
2570  PURPOSE
2571     Gets information about a raster image.
2572 
2573  USAGE
2574     intn GRgetiminfo(riid,name,ncomp,nt,il,dimsizes,n_attr)
2575         int32 riid;         IN: RI ID from GRselect/GRcreate
2576         char *name;         OUT: name of raster image
2577         int32 *ncomp;       OUT: number of components in image
2578         int32 *nt;          OUT: number type of components
2579         int32 *il;          OUT: interlace of the image
2580         int32 *dimsizes;    OUT: size of each dimension
2581         int32 *n_attr;      OUT: the number of attributes for the image
2582 
2583  RETURNS
2584     SUCCEED/FAIL
2585 
2586  DESCRIPTION
2587     Looks up information about an image which has been selected or created
2588     with the GR routines.  Each of the parameters can be NULL, in which case
2589     that piece of information will not be retrieved.
2590 
2591  GLOBAL VARIABLES
2592  COMMENTS, BUGS, ASSUMPTIONS
2593  EXAMPLES
2594  REVISION LOG
2595 --------------------------------------------------------------------------*/
GRgetiminfo(int32 riid,char * name,int32 * ncomp,int32 * nt,int32 * il,int32 dimsizes[2],int32 * n_attr)2596 intn GRgetiminfo(int32 riid,char *name,int32 *ncomp,int32 *nt,int32 *il,
2597     int32 dimsizes[2],int32 *n_attr)
2598 {
2599     CONSTR(FUNC, "GRgetiminfo");   /* for HERROR */
2600     ri_info_t *ri_ptr;          /* ptr to the image to work with */
2601     intn  ret_value = SUCCEED;
2602 
2603     /* clear error stack and check validity of args */
2604     HEclear();
2605 
2606     /* check the validity of the RI ID */
2607     if (HAatom_group(riid)!=RIIDGROUP)
2608         HGOTO_ERROR(DFE_ARGS, FAIL);
2609 
2610     /* locate RI's object in hash table */
2611     if (NULL == (ri_ptr = (ri_info_t *) HAatom_object(riid)))
2612         HGOTO_ERROR(DFE_RINOTFOUND, FAIL);
2613 
2614     if(name!=NULL)
2615         HDstrcpy(name, ri_ptr->name);
2616 
2617     if(ncomp!=NULL)
2618         *ncomp=ri_ptr->img_dim.ncomps;
2619 
2620     if(nt!=NULL)
2621         *nt=ri_ptr->img_dim.nt;
2622 
2623     if(il!=NULL)
2624         *il=(int32)ri_ptr->img_dim.il;
2625 
2626     if(dimsizes!=NULL)
2627       {
2628           dimsizes[0]=ri_ptr->img_dim.xdim;
2629           dimsizes[1]=ri_ptr->img_dim.ydim;
2630       } /* end if */
2631 
2632     if(n_attr!=NULL)
2633         *n_attr=ri_ptr->lattr_count;
2634 
2635 done:
2636   if(ret_value == FAIL)
2637     { /* Error condition cleanup */
2638 
2639     } /* end if */
2640 
2641   /* Normal function cleanup */
2642   return ret_value;
2643 } /* end GRgetiminfo() */
2644 
2645 /*--------------------------------------------------------------------------
2646  NAME
2647     GRgetnluts
2648 
2649  PURPOSE
2650     Get the number of palettes (LUTs) for an image
2651 
2652  USAGE
2653     intn GRgetnluts(riid)
2654         int32 riid;         IN: RI ID from GRselect/GRcreate
2655 
2656  RETURNS
2657     The number of palettes on success, FAIL (-1) on failure
2658 
2659  DESCRIPTION
2660     Determines the number of palettes for an image (0 or 1 for now).  In the
2661     future, if multiple palettes are supported, this function may return
2662     values greater than 1.
2663 
2664  GLOBAL VARIABLES
2665  COMMENTS, BUGS, ASSUMPTIONS
2666  EXAMPLES
2667  REVISION LOG
2668 --------------------------------------------------------------------------*/
GRgetnluts(int32 riid)2669 intn GRgetnluts(int32 riid)
2670 {
2671     CONSTR(FUNC, "GRgetnluts");   /* for HERROR */
2672     ri_info_t *ri_ptr;          /* ptr to the image to work with */
2673     intn  ret_value = FAIL;
2674 
2675     /* clear error stack and check validity of args */
2676     HEclear();
2677 
2678     /* check the validity of the RI ID */
2679     if (HAatom_group(riid)!=RIIDGROUP)
2680         HGOTO_ERROR(DFE_ARGS, FAIL);
2681 
2682     /* locate LUT's object in hash table */
2683     if (NULL == (ri_ptr = (ri_info_t *) HAatom_object(riid)))
2684         HGOTO_ERROR(DFE_RINOTFOUND, FAIL);
2685 
2686     if(ri_ptr->lut_ref==DFREF_WILDCARD) /* check for no palette defined currently */
2687         ret_value=0;
2688     else        /* we've got a valid palette currently */
2689         ret_value=1;
2690 
2691 done:
2692   if(ret_value == FAIL)
2693     { /* Error condition cleanup */
2694 
2695     } /* end if */
2696 
2697   /* Normal function cleanup */
2698     return ret_value;
2699 } /* end GRgetnluts() */
2700 
2701 /*--------------------------------------------------------------------------
2702  NAME
2703     GRwriteimage
2704 
2705  PURPOSE
2706     Writes raster data to an image
2707 
2708  USAGE
2709     intn GRwriteimage(riid,start,stride,edge,data)
2710         int32 riid;         IN: RI ID from GRselect/GRcreate
2711         int32 start[2];     IN: array containing the offset in the image of the
2712                                 image data to write out
2713         int32 stride[2];    IN: array containing interval of data being written
2714                                 along each edge.  strides of 0 are illegal
2715                                 (and generate an error)
2716                                 ie. stride of 1 in each dimension means
2717                                 writing contiguous data, stride of 2 means
2718                                 writing every other element out along an edge.
2719         int32 count[2];     IN: number of elements to write out along each edge.
2720         void * data;         IN: pointer to the data to write out.
2721 
2722  RETURNS
2723     SUCCEED/FAIL
2724 
2725  DESCRIPTION
2726     Writes image data to an RI.  Partial dataset writing and subsampling is
2727         allowed, but only within the dimensions of the dataset (ie. no UNLIMITED
2728         dimension support)
2729 
2730  GLOBAL VARIABLES
2731  COMMENTS, BUGS, ASSUMPTIONS
2732     If the stride parameter is set to NULL, a stride of 1 will be assumed.
2733 
2734  EXAMPLES
2735  REVISION LOG
2736 --------------------------------------------------------------------------*/
GRwriteimage(int32 riid,int32 start[2],int32 in_stride[2],int32 count[2],void * data)2737 intn GRwriteimage(int32 riid,int32 start[2],int32 in_stride[2],int32 count[2],void * data)
2738 {
2739     CONSTR(FUNC, "GRwriteimage");   /* for HERROR */
2740     int32 hdf_file_id;          /* HDF file ID */
2741     int32 stride[2];            /* pointer to the stride array */
2742     gr_info_t *gr_ptr;          /* ptr to the GR information for this grid */
2743     ri_info_t *ri_ptr;          /* ptr to the image to work with */
2744     intn solid_block=FALSE;     /* whether the image data is a solid block of data */
2745     intn whole_image=FALSE;     /* whether we are writing out the whole image */
2746     void * *img_data;            /* pointer to the converted image data to write */
2747     uintn pixel_mem_size,       /* size of a pixel in memory */
2748         pixel_disk_size;        /* size of a pixel on disk */
2749     uint16 scheme;  /* compression scheme used for JPEG images */
2750     uint32     comp_config;
2751     comp_coder_t comp_type;
2752     comp_info cinfo;
2753     intn status=FAIL;
2754     intn convert=FALSE;         /* true if machine NT != NT to be written */
2755     uint8 platnumsubclass;      /* class of this NT for this platform */
2756     intn new_image=FALSE;       /* whether we are writing a new image out */
2757     intn switch_interlace=FALSE;/* whether the memory interlace needs to be switched around */
2758     intn ret_value = SUCCEED;
2759 
2760     /* clear error stack and check validity of args */
2761     HEclear();
2762 
2763     /* check the basic validity of the args (stride is OK to be NULL) */
2764     if (HAatom_group(riid)!=RIIDGROUP || start==NULL /* || in_stride==NULL */ || count==NULL
2765             || data==NULL)
2766         HGOTO_ERROR(DFE_ARGS, FAIL);
2767 
2768     /* Get the correct parameters into the stride array */
2769     if(in_stride==NULL)
2770           stride[XDIM]=stride[YDIM]=1;
2771     else
2772       {
2773           stride[XDIM]=in_stride[XDIM];
2774           stride[YDIM]=in_stride[YDIM];
2775       } /* end else */
2776 
2777     /* Sanity check the start, stride, and count args */
2778     if((start[XDIM]<0 || start[YDIM]<0) || (stride[XDIM]<1 || stride[YDIM]<1)
2779             || (count[XDIM]<1 || count[YDIM]<1))
2780         HGOTO_ERROR(DFE_BADDIM, FAIL);
2781 
2782     /* locate RI's object in hash table */
2783     if (NULL == (ri_ptr = (ri_info_t *) HAatom_object(riid)))
2784         HGOTO_ERROR(DFE_RINOTFOUND, FAIL);
2785     gr_ptr=ri_ptr->gr_ptr;
2786     hdf_file_id=gr_ptr->hdf_file_id;
2787 
2788     comp_type = COMP_CODE_NONE;
2789     scheme = ri_ptr->img_dim.comp_tag;
2790     if (scheme == DFTAG_JPEG5 || scheme == DFTAG_GREYJPEG5
2791             || scheme==DFTAG_JPEG || scheme==DFTAG_GREYJPEG)
2792     {
2793         comp_type = COMP_CODE_JPEG;
2794         cinfo.jpeg.quality = 0;
2795         cinfo.jpeg.force_baseline = 0;
2796     }
2797     else if (scheme == DFTAG_IMC)
2798     { /* coder no longer supported */
2799         HGOTO_ERROR(DFE_BADCODER,FAIL);
2800     }
2801     else
2802     {
2803         /* use lower-level routine to get the compression information */
2804         status = HCPgetcompinfo(ri_ptr->gr_ptr->hdf_file_id,
2805                         ri_ptr->img_tag, ri_ptr->img_ref,
2806                         &comp_type, &cinfo);
2807 	if (status == FAIL)
2808             HGOTO_ERROR(DFE_INTERNAL,FAIL);
2809     }
2810     if (comp_type != COMP_CODE_NONE)
2811     {
2812         /* Check that the compression encoder is available */
2813         HCget_config_info(comp_type, &comp_config);
2814         if ((comp_config & (COMP_DECODER_ENABLED|COMP_ENCODER_ENABLED)) == 0) {
2815             /* coder not present?? */
2816              HGOTO_ERROR(DFE_BADCODER,FAIL);
2817         }
2818         if ((comp_config & COMP_ENCODER_ENABLED) == 0) {
2819             /* encoder not present?? */
2820              HGOTO_ERROR(DFE_NOENCODER,FAIL);
2821         }
2822     }
2823 
2824     if(stride[XDIM]==1 && stride[YDIM]==1)
2825       { /* solid block of data */
2826           solid_block=TRUE;
2827           if((start[XDIM]==0 && start[YDIM]==0) && (count[XDIM]==ri_ptr->img_dim.xdim
2828                 && count[YDIM]==ri_ptr->img_dim.ydim))
2829               whole_image=TRUE;
2830           else
2831               whole_image=FALSE;
2832       } /* end if */
2833     else /* block of data spread out with strides */
2834           solid_block=FALSE;
2835 
2836     if(ri_ptr->img_dim.il!=MFGR_INTERLACE_PIXEL)
2837         switch_interlace=TRUE;
2838 
2839     /* Get the size of the pixels in memory and on disk */
2840     pixel_mem_size=(uintn)(ri_ptr->img_dim.ncomps*DFKNTsize((ri_ptr->img_dim.nt | DFNT_NATIVE) & (~DFNT_LITEND)));
2841     pixel_disk_size=(uintn)(ri_ptr->img_dim.ncomps*DFKNTsize(ri_ptr->img_dim.nt));
2842 
2843     /* Get number-type and conversion information */
2844     platnumsubclass = (uint8)DFKgetPNSC(ri_ptr->img_dim.nt & (~DFNT_LITEND), DF_MT);
2845     convert = (ri_ptr->img_dim.file_nt_subclass != platnumsubclass) ||
2846   (pixel_mem_size != pixel_disk_size);  /* is conversion necessary? */
2847 
2848     if(convert || switch_interlace==TRUE)
2849       {   /* convert image data to HDF disk format */
2850           /* Allocate space for the conversion buffer */
2851           if((img_data=HDmalloc(pixel_disk_size*(size_t)count[XDIM]*(size_t)count[YDIM]))==NULL)
2852               HGOTO_ERROR(DFE_NOSPACE,FAIL);
2853 
2854           if(switch_interlace==TRUE)
2855             {
2856               void * pixel_buf;  /* buffer for the pixel interlaced data */
2857 
2858               /* Allocate space for the conversion buffer */
2859               if((pixel_buf=HDmalloc(pixel_mem_size*(size_t)count[XDIM]*(size_t)count[YDIM]))==NULL)
2860                   HGOTO_ERROR(DFE_NOSPACE,FAIL);
2861 
2862               GRIil_convert(data,ri_ptr->img_dim.il,pixel_buf,MFGR_INTERLACE_PIXEL,
2863                   count,ri_ptr->img_dim.ncomps,ri_ptr->img_dim.nt);
2864 
2865               /* convert the pixel data into the HDF disk format */
2866               DFKconvert(pixel_buf,img_data,ri_ptr->img_dim.nt,
2867                   ri_ptr->img_dim.ncomps*count[XDIM]*count[YDIM],DFACC_WRITE,0,0);
2868 
2869               HDfree(pixel_buf);
2870             } /* end if */
2871           else /* convert the pixel data into the HDF disk format */
2872               DFKconvert(data,img_data,ri_ptr->img_dim.nt,
2873                   ri_ptr->img_dim.ncomps*count[XDIM]*count[YDIM],DFACC_WRITE,0,0);
2874       } /* end if */
2875     else /* no conversion necessary, just use the user's buffer */
2876         img_data=data;
2877 
2878     if(ri_ptr->img_tag==DFTAG_NULL || ri_ptr->img_ref==DFREF_WILDCARD)
2879         new_image=TRUE;
2880     else {
2881         /* Check if the actual image data is in the file yet, or if just the tag & ref are known */
2882         if(Hlength(ri_ptr->gr_ptr->hdf_file_id,ri_ptr->img_tag,ri_ptr->img_ref)>0)
2883             new_image=FALSE;
2884         else
2885             new_image=TRUE;
2886     } /* end else */
2887 
2888     if(GRIgetaid(ri_ptr,DFACC_WRITE)==FAIL)
2889         HGOTO_ERROR(DFE_INTERNAL,FAIL);
2890 
2891     if(whole_image==TRUE)
2892       { /* write the whole image out */
2893 #ifdef OLD_WAY
2894         if(new_image==TRUE)
2895           { /* Create the tag/ref for the new image */
2896               ri_ptr->img_tag=DFTAG_RI;
2897               ri_ptr->img_ref=Htagnewref(hdf_file_id,ri_ptr->img_tag);
2898           } /* end if */
2899         if(Hputelement(hdf_file_id,ri_ptr->img_tag,ri_ptr->img_ref,
2900                 (uint8 *)img_data,(int32)pixel_disk_size*count[XDIM]*count[YDIM])==FAIL)
2901             HGOTO_ERROR(DFE_PUTELEM,FAIL);
2902 #else /* OLD_WAY */
2903         /* Make certain we are at the beginning */
2904         if(Hseek(ri_ptr->img_aid,0,DF_START)==FAIL)
2905             HGOTO_ERROR(DFE_SEEKERROR,FAIL);
2906 
2907         /* Write the entire image out */
2908         if(Hwrite(ri_ptr->img_aid,(int32)pixel_disk_size*count[XDIM]*count[YDIM],
2909                 (uint8 *)img_data)==FAIL)
2910             HGOTO_ERROR(DFE_WRITEERROR,FAIL);
2911 #endif /* OLD_WAY */
2912       } /* end if */
2913     else
2914       { /* write only part of the image out */
2915           int32 img_offset; /* current offset in the image data */
2916           void * tmp_data;   /* temp. pointer to the image data to write */
2917           intn fill_image=FALSE;  /* whether to create fill values, etc. */
2918           void * fill_line=NULL;   /* array containing the fill pixels for an entire line of the image */
2919           int32 fill_lo_size=0,   /* number of bytes in the "low" block */
2920               fill_hi_size=0,     /* number of bytes in the "high" block */
2921               fill_line_size=0;   /* number of bytes in the "line" block */
2922 
2923           img_offset=((ri_ptr->img_dim.xdim*start[YDIM])+start[XDIM])*(int32)pixel_disk_size;
2924 
2925           /* check if this is a new image, and if we need to write fill pixels */
2926           if(new_image==TRUE && ri_ptr->fill_img==TRUE)
2927             { /* create fill value arrays for various blocks */
2928                 void * fill_pixel; /* converted value for the filled pixel */
2929                 int32 at_index;   /* attribute index for the fill value */
2930 
2931                 if((fill_pixel=HDmalloc(pixel_disk_size))==NULL)
2932                     HGOTO_ERROR(DFE_NOSPACE,FAIL);
2933 
2934                 /* create correct disk version of fill pixel */
2935                 if(ri_ptr->fill_value!=NULL)
2936                   {
2937                       DFKconvert(ri_ptr->fill_value,fill_pixel,
2938                           ri_ptr->img_dim.nt,ri_ptr->img_dim.ncomps,
2939                           DFACC_WRITE,0,0);
2940                   } /* end if */
2941                 else  /* create default pixel fill value of all zero components */
2942                   {
2943                     /* Try to find a fill value attribute */
2944                     if((at_index=GRfindattr(riid,FILL_ATTR))!=FAIL)
2945                       { /* Found a fill value attribute */
2946                           if((ri_ptr->fill_value=HDmalloc(pixel_mem_size))==NULL)
2947                               HGOTO_ERROR(DFE_NOSPACE,FAIL);
2948                           if(GRgetattr(riid,at_index,ri_ptr->fill_value)==FAIL)
2949                               HGOTO_ERROR(DFE_BADATTR,FAIL);
2950                           DFKconvert(ri_ptr->fill_value,fill_pixel,
2951                               ri_ptr->img_dim.nt,ri_ptr->img_dim.ncomps,
2952                               DFACC_WRITE,0,0);
2953                       } /* end if */
2954                     else
2955                         HDmemset(fill_pixel,0,pixel_disk_size);
2956                   } /* end else */
2957 
2958                 /* check for "low" pixel runs */
2959                 if(start[XDIM]>0)
2960                     fill_lo_size=(int32)pixel_disk_size*start[XDIM];
2961 
2962                 /* check for "high" pixel runs */
2963                 if((start[XDIM]+((count[XDIM]-1)*stride[XDIM])+1)<ri_ptr->img_dim.xdim)
2964                     fill_hi_size=(int32)pixel_disk_size*(ri_ptr->img_dim.xdim-
2965                         (start[XDIM]+((count[XDIM]-1)*stride[XDIM])+1));
2966 
2967                 /* create the "line" pixel block */
2968                 /* allocate space for the "line" block */
2969                 fill_line_size=(int32)pixel_disk_size*ri_ptr->img_dim.xdim;
2970                 if((fill_line=HDmalloc(fill_line_size))==NULL)
2971                       HGOTO_ERROR(DFE_NOSPACE,FAIL);
2972                 HDmemfill(fill_line,fill_pixel,pixel_disk_size,(uint32)ri_ptr->img_dim.xdim);
2973 
2974                 fill_image=TRUE;  /* set flag to write out fill pixels */
2975                 ri_ptr->store_fill=TRUE;  /* set flag to store fill value attribute */
2976 
2977                 /* Get rid of the fill pixel */
2978                 if(ri_ptr->fill_value==NULL)
2979                     ri_ptr->fill_value=fill_pixel;
2980                 else
2981                     HDfree(fill_pixel);
2982             } /* end if */
2983 
2984           tmp_data=img_data;
2985           if(solid_block==TRUE)
2986             {   /* write out runs of data in the image */
2987                 int32 pix_len;    /* length of current row's pixel run */
2988                 intn i;           /* temporary loop variable */
2989 
2990                 pix_len=(int32)pixel_disk_size*count[XDIM];
2991 
2992                 if(fill_image==TRUE)
2993                   {   /* surround the block to write with fill values */
2994                       /* write out lines "below" the block */
2995                       if(start[YDIM]>0)
2996                         { /* fill in the lines leading up the block */
2997                           for(i=0; i<start[YDIM]; i++)
2998                               if(Hwrite(ri_ptr->img_aid,fill_line_size,fill_line)==FAIL)
2999                                   HGOTO_ERROR(DFE_WRITEERROR,FAIL);
3000                         } /* end if */
3001 
3002                       /* write prelude of low pixels */
3003                       if(fill_lo_size>0)
3004                           if(Hwrite(ri_ptr->img_aid,fill_lo_size,fill_line)==FAIL)
3005                               HGOTO_ERROR(DFE_WRITEERROR,FAIL);
3006 
3007                       /* write out the block */
3008                       for(i=0; i<count[YDIM]; i++)
3009                         {
3010                             if(Hwrite(ri_ptr->img_aid,pix_len,tmp_data)==FAIL)
3011                                 HGOTO_ERROR(DFE_WRITEERROR,FAIL);
3012 
3013                             /* This next write wraps around the high side */
3014                             /* of the block and writes the next low side */
3015                             /* at the same time. */
3016                             if((fill_hi_size+fill_lo_size)>0
3017                                     && i<(count[YDIM]-1))
3018                                 if(Hwrite(ri_ptr->img_aid,(fill_hi_size+fill_lo_size),fill_line)==FAIL)
3019                                     HGOTO_ERROR(DFE_WRITEERROR,FAIL);
3020                             tmp_data=(void *)((char *)tmp_data+pix_len);
3021                         } /* end for */
3022 
3023                       /* Finish the last chunk of high side fill values */
3024                       if(fill_hi_size>0)
3025                           if(Hwrite(ri_ptr->img_aid,fill_hi_size,fill_line)==FAIL)
3026                               HGOTO_ERROR(DFE_WRITEERROR,FAIL);
3027 
3028                       /* write out lines "above" the block */
3029                       if((start[YDIM]+((count[YDIM]-1)*stride[YDIM])+1)
3030                           <ri_ptr->img_dim.ydim)
3031                         {
3032                           for(i=start[YDIM]+((count[YDIM]-1)*stride[YDIM])+1;
3033                                   i<ri_ptr->img_dim.ydim; i++)
3034                               if(Hwrite(ri_ptr->img_aid,fill_line_size,fill_line)==FAIL)
3035                                   HGOTO_ERROR(DFE_WRITEERROR,FAIL);
3036                         } /* end if */
3037                   } /* end if */
3038                 else
3039                   {   /* don't worry about fill values */
3040                       for(i=0; i<count[YDIM]; i++)
3041                         {
3042                             if(Hseek(ri_ptr->img_aid,img_offset,DF_START)==FAIL)
3043                                 HGOTO_ERROR(DFE_SEEKERROR,FAIL);
3044                             if(Hwrite(ri_ptr->img_aid,pix_len,tmp_data)==FAIL)
3045                                 HGOTO_ERROR(DFE_WRITEERROR,FAIL);
3046                             img_offset+=(int32)pixel_disk_size*ri_ptr->img_dim.xdim;
3047                             tmp_data=(void *)((char *)tmp_data+pix_len);
3048                         } /* end for */
3049                   } /* end else */
3050             } /* end if */
3051           else
3052             {   /* sub-sampling, seek to each data element and write it out */
3053                 intn i,j,k;       /* temporary loop variables */
3054                 int32 fill_stride_size=0; /* # of pixels in the stride block */
3055                 intn fill_xdim=FALSE, /* whether to fill in the X dimension */
3056                     fill_ydim=FALSE;  /* whether to fill in the Y dimension */
3057 
3058                 /* check if we need to insert fill pixels between strides */
3059                 if(fill_image==TRUE)
3060                   {   /* create the "stride" pixel block */
3061                       if(stride[XDIM]>1)
3062                         {
3063                           /* allocate space for the "stride" block */
3064                           fill_stride_size=(int32)pixel_disk_size*(stride[XDIM]-1);
3065                           fill_xdim=TRUE;
3066                         } /* end if */
3067                       if(stride[YDIM]>1)
3068                           fill_ydim=TRUE;
3069 
3070                       /* write fills and sub-sampled data */
3071 
3072                       /* write out lines "below" the block */
3073                       if(start[YDIM]>0)
3074                         { /* fill in the lines leading up the block */
3075                           for(i=0; i<start[YDIM]; i++)
3076                             {
3077                               if(Hwrite(ri_ptr->img_aid,fill_line_size,fill_line)==FAIL)
3078                                   HGOTO_ERROR(DFE_WRITEERROR,FAIL);
3079                             } /* end for */
3080                         } /* end if */
3081 
3082                       /* write prelude of low pixels */
3083                       if(fill_lo_size>0)
3084                         {
3085                           if(Hwrite(ri_ptr->img_aid,fill_lo_size,fill_line)==FAIL)
3086                               HGOTO_ERROR(DFE_WRITEERROR,FAIL);
3087                         } /* end if */
3088 
3089                       for(i=0; i<count[YDIM]; i++)
3090                         {
3091                             for(j=0; j<count[XDIM]; j++)
3092                               {
3093                                 if(Hwrite(ri_ptr->img_aid,(int32)pixel_disk_size,tmp_data)==FAIL)
3094                                     HGOTO_ERROR(DFE_WRITEERROR,FAIL);
3095                                 if(fill_xdim==TRUE && j<(count[XDIM]-1))
3096                                   {
3097                                     if(Hwrite(ri_ptr->img_aid,fill_stride_size,fill_line)==FAIL)
3098                                         HGOTO_ERROR(DFE_WRITEERROR,FAIL);
3099                                   } /* end if */
3100                                 tmp_data=(void *)((char *)tmp_data+pixel_disk_size);
3101                               } /* end for */
3102 
3103                             /* Fill in the y-dim stride lines */
3104                             if(fill_ydim==TRUE)
3105                                 for(k=1; k<stride[YDIM]; k++)
3106                                   {
3107                                     if(Hwrite(ri_ptr->img_aid,fill_line_size,fill_line)==FAIL)
3108                                         HGOTO_ERROR(DFE_WRITEERROR,FAIL);
3109                                   } /* end for */
3110 
3111                             /* This next write wraps around the high side */
3112                             /* of the block and writes the next low side */
3113                             /* at the same time. */
3114                             if((fill_hi_size+fill_lo_size)>0
3115                                     && i<(count[YDIM]-1))
3116                               {
3117                                 if(Hwrite(ri_ptr->img_aid,(fill_hi_size+fill_lo_size),fill_line)==FAIL)
3118                                     HGOTO_ERROR(DFE_WRITEERROR,FAIL);
3119                               } /* end if */
3120                         } /* end for */
3121 
3122                       /* Finish the last chunk of high side fill values */
3123                       if(fill_hi_size>0)
3124                         {
3125                           if(Hwrite(ri_ptr->img_aid,fill_hi_size,fill_line)==FAIL)
3126                               HGOTO_ERROR(DFE_WRITEERROR,FAIL);
3127                         } /* end if */
3128 
3129                   } /* end if */
3130                 else
3131                   {   /* don't worry about fill values */
3132                     int32 stride_add; /* amount to add for stride amount */
3133 
3134                     stride_add=(int32)pixel_disk_size*stride[XDIM];
3135 
3136                       for(i=0; i<count[YDIM]; i++)
3137                         {
3138                             int32 local_offset;
3139 
3140                             local_offset=img_offset;
3141                             for(j=0; j<count[XDIM]; j++)
3142                               {
3143                                 if(Hseek(ri_ptr->img_aid,local_offset,DF_START)==FAIL)
3144                                     HGOTO_ERROR(DFE_SEEKERROR,FAIL);
3145                                 if(Hwrite(ri_ptr->img_aid,(int32)pixel_disk_size,tmp_data)==FAIL)
3146                                     HGOTO_ERROR(DFE_WRITEERROR,FAIL);
3147                                 local_offset+=stride_add;
3148                                 tmp_data=(void *)((char *)tmp_data+pixel_disk_size);
3149                               } /* end for */
3150 
3151                             img_offset+=ri_ptr->img_dim.xdim*stride[YDIM]*(int32)pixel_disk_size;
3152                         } /* end for */
3153                   } /* end else */
3154             } /* end else */
3155 
3156           if(fill_line!=NULL)     /* free the fill-value pixels if we used 'em */
3157               HDfree(fill_line);
3158 
3159       } /* end else */
3160     ri_ptr->data_modified=TRUE;
3161 
3162     /* if we've allocated a temporary buffer, free it */
3163     if(convert || switch_interlace==TRUE)
3164         HDfree(img_data);
3165 
3166     /* mark the image as being modified */
3167     ri_ptr->data_modified=TRUE;
3168     gr_ptr->gr_modified=TRUE;
3169 
3170 done:
3171   if(ret_value == FAIL)
3172     { /* Error condition cleanup */
3173 
3174     } /* end if */
3175 
3176   /* Normal function cleanup */
3177   return ret_value;
3178 } /* end GRwriteimage() */
3179 
3180 /*--------------------------------------------------------------------------
3181  NAME
3182     GRreadimage
3183 
3184  PURPOSE
3185     Read raster data for an image
3186 
3187  USAGE
3188     intn GRreadimage(riid,start,stride,edge,data)
3189         int32 riid;         IN: RI ID from GRselect/GRcreate
3190         int32 start[2];     IN: array containing the offset in the image of the
3191                                 image data to read in
3192         int32 stride[2];    IN: array containing interval of data being read
3193                                 along each edge.  strides of 0 are illegal
3194                                 (and generate an error)
3195                                 ie. stride of 1 in each dimension means
3196                                 reading contiguous data, stride of 2 means
3197                                 reading every other element out along an edge.
3198         int32 count[2];     IN: number of elements to read in along each edge.
3199         void * data;         IN: pointer to the data to read in.
3200 
3201  RETURNS
3202     SUCCEED/FAIL
3203 
3204  DESCRIPTION
3205     Read image data from an RI.  Partial dataset reading and subsampling is
3206         allowed.
3207 
3208  GLOBAL VARIABLES
3209  COMMENTS, BUGS, ASSUMPTIONS
3210     If the stride parameter is set to NULL, a stride of 1 will be assumed.
3211 
3212  EXAMPLES
3213  REVISION LOG
3214 --------------------------------------------------------------------------*/
GRreadimage(int32 riid,int32 start[2],int32 in_stride[2],int32 count[2],void * data)3215 intn GRreadimage(int32 riid,int32 start[2],int32 in_stride[2],int32 count[2],void * data)
3216 {
3217     CONSTR(FUNC, "GRreadimage");   /* for HERROR */
3218     int32 hdf_file_id;          /* HDF file ID */
3219     gr_info_t *gr_ptr;          /* ptr to the GR information for this grid */
3220     ri_info_t *ri_ptr;          /* ptr to the image to work with */
3221     int32 stride[2];            /* pointer to the stride array */
3222     intn solid_block=FALSE;     /* whether the image data is a solid block of data */
3223     intn whole_image=FALSE;     /* whether we are reading in the whole image */
3224     intn image_data=FALSE;      /* whether there is actual image data or not */
3225     void * *img_data;           /* pointer to the converted image data to write */
3226     uintn pixel_disk_size;      /* size of a pixel on disk */
3227     uintn pixel_mem_size;       /* size of a pixel in memory */
3228     intn convert;               /* true if machine NT != NT to be written */
3229     uint8 platnumsubclass;      /* class of this NT for this platform */
3230     uint16 scheme;  /* compression scheme used for JPEG images */
3231     uint32     comp_config;
3232     comp_coder_t comp_type;
3233     comp_info cinfo;
3234     intn status=FAIL;
3235     intn  ret_value = SUCCEED;
3236 
3237     /* clear error stack and check validity of args */
3238     HEclear();
3239 
3240     /* check the basic validity of the args (stride is OK to be NULL) */
3241     if (HAatom_group(riid)!=RIIDGROUP || start==NULL /* || in_stride==NULL */ || count==NULL
3242             || data==NULL)
3243         HGOTO_ERROR(DFE_ARGS, FAIL);
3244 
3245     /* Get the correct parameters into the stride array */
3246     if(in_stride==NULL)
3247           stride[XDIM]=stride[YDIM]=1;
3248     else
3249       {
3250           stride[XDIM]=in_stride[XDIM];
3251           stride[YDIM]=in_stride[YDIM];
3252       } /* end else */
3253 
3254     /* Sanity check the start, stride, and count args */
3255     if((start[XDIM]<0 || start[YDIM]<0) || (stride[XDIM]<1 || stride[YDIM]<1)
3256             || (count[XDIM]<1 || count[YDIM]<1))
3257         HGOTO_ERROR(DFE_BADDIM, FAIL);
3258 
3259     /* locate RI's object in hash table */
3260     if (NULL == (ri_ptr = (ri_info_t *) HAatom_object(riid)))
3261         HGOTO_ERROR(DFE_RINOTFOUND, FAIL);
3262     gr_ptr=ri_ptr->gr_ptr;
3263     hdf_file_id=gr_ptr->hdf_file_id;
3264 
3265     comp_type = COMP_CODE_NONE;
3266     scheme = ri_ptr->img_dim.comp_tag;
3267     if (scheme == DFTAG_JPEG5 || scheme == DFTAG_GREYJPEG5
3268             || scheme==DFTAG_JPEG || scheme==DFTAG_GREYJPEG)
3269     {
3270 	comp_type = COMP_CODE_JPEG;
3271 	cinfo.jpeg.quality = 0;
3272 	cinfo.jpeg.force_baseline = 0;
3273     }
3274     /* Catch old images to avoid going into HCPgetcompinfo */
3275     else if (scheme == DFTAG_RLE) /* old image */
3276         comp_type = COMP_CODE_RLE;
3277     else if (scheme == DFTAG_IMC) /* old image */
3278         comp_type = COMP_CODE_IMCOMP;
3279     else
3280     {
3281 	/* use lower-level routine to get the compression information */
3282 	status = HCPgetcompinfo(hdf_file_id, ri_ptr->img_tag, ri_ptr->img_ref,
3283                         &comp_type, &cinfo);
3284 	if (status == FAIL)
3285             HGOTO_ERROR(DFE_INTERNAL,FAIL);
3286     }
3287     if (comp_type != COMP_CODE_NONE &&
3288 	comp_type != COMP_CODE_RLE &&
3289 	comp_type != COMP_CODE_IMCOMP)
3290     {   /* This is reading, why do we need encoder? -BMR */
3291 	/* Check that the compression encoder is available */
3292 	HCget_config_info(comp_type, &comp_config);
3293 	if ((comp_config & (COMP_DECODER_ENABLED|COMP_ENCODER_ENABLED)) == 0)
3294 	{ /* coder not present?? */
3295 	    HGOTO_ERROR(DFE_BADCODER,FAIL);
3296 	}
3297 	if ((comp_config & COMP_DECODER_ENABLED) == 0)
3298 	{ /* decoder not present?? */
3299 	    HGOTO_ERROR(DFE_NOENCODER,FAIL);
3300 	}
3301     }
3302     if(stride[XDIM]==1 && stride[YDIM]==1)
3303     { /* solid block of data */
3304 	solid_block=TRUE;
3305 	if ((start[XDIM]==0 && start[YDIM]==0)
3306 	 && (count[XDIM]==ri_ptr->img_dim.xdim
3307 	  && count[YDIM]==ri_ptr->img_dim.ydim))
3308 	    whole_image=TRUE;
3309 	else
3310 	    whole_image=FALSE;
3311       } /* end if */
3312     else /* block of data spread out with strides */
3313         solid_block=FALSE;
3314 
3315     /* Get the size of the pixels in memory and on disk */
3316     pixel_disk_size=(uintn)(ri_ptr->img_dim.ncomps*DFKNTsize(ri_ptr->img_dim.nt));
3317     pixel_mem_size=(uintn)(ri_ptr->img_dim.ncomps*DFKNTsize((ri_ptr->img_dim.nt | DFNT_NATIVE) & (~DFNT_LITEND)));
3318 
3319     /* Get number-type and conversion information */
3320     platnumsubclass = (uint8)DFKgetPNSC(ri_ptr->img_dim.nt & (~DFNT_LITEND), DF_MT);
3321     convert = (pixel_disk_size != pixel_mem_size) || (ri_ptr->img_dim.file_nt_subclass != platnumsubclass);  /* is conversion necessary? */
3322 
3323     /* Check if the image data is in the file */
3324     if(ri_ptr->img_tag==DFTAG_NULL || ri_ptr->img_ref==DFREF_WILDCARD)
3325         image_data=FALSE;
3326     else
3327     {
3328         /* Check if the actual image data is in the file yet, or if just the
3329 	   tag & ref are known */
3330         if(Hlength(hdf_file_id,ri_ptr->img_tag,ri_ptr->img_ref)>0)
3331             image_data=TRUE;
3332         else
3333             image_data=FALSE;
3334     } /* end else */
3335 
3336     if(image_data==FALSE)
3337       { /* Fake an image for the user by using the pixel fill value */
3338           void * fill_pixel;         /* converted value for the filled pixel */
3339           int32 at_index;
3340 
3341           if((fill_pixel=HDmalloc(pixel_mem_size))==NULL)
3342               HGOTO_ERROR(DFE_NOSPACE,FAIL);
3343 
3344           /* Try to find a fill value attribute */
3345           if((at_index=GRfindattr(riid,FILL_ATTR))!=FAIL)
3346             { /* Found a fill value attribute */
3347                 if(GRgetattr(riid,at_index,fill_pixel)==FAIL)
3348                     HGOTO_ERROR(DFE_BADATTR,FAIL);
3349             } /* end if */
3350           else /* no fill value attribute */
3351               HDmemset(fill_pixel,0,pixel_mem_size);
3352 
3353           /* Fill the user's buffer with the fill value */
3354           HDmemfill(data,fill_pixel,pixel_mem_size,(uint32)(count[XDIM]*count[YDIM]));
3355           HDfree(fill_pixel);
3356       } /* end if */
3357     else
3358       { /* an image exists in the file */
3359           if(convert)
3360             {   /* convert image data to HDF disk format */
3361                 /* Allocate space for the conversion buffer */
3362                 if((img_data=HDmalloc(pixel_disk_size*(size_t)count[XDIM]*(size_t)count[YDIM]))==NULL)
3363                     HGOTO_ERROR(DFE_NOSPACE,FAIL);
3364             } /* end if */
3365           else /* no conversion necessary, just use the user's buffer */
3366               img_data=data;
3367 
3368           if(GRIgetaid(ri_ptr, DFACC_READ)==FAIL)
3369               HGOTO_ERROR(DFE_INTERNAL,FAIL);
3370 
3371           if(whole_image==TRUE)
3372             { /* read the whole image in */
3373 #ifdef OLD_WAY
3374                 if(Hgetelement(hdf_file_id,ri_ptr->img_tag,ri_ptr->img_ref,
3375                         (uint8 *)img_data)==FAIL)
3376                     HGOTO_ERROR(DFE_GETELEM,FAIL);
3377 #else /* OLD_WAY */
3378             /* Make certain we are at the beginning */
3379             if(Hseek(ri_ptr->img_aid,0,DF_START)==FAIL)
3380                 HGOTO_ERROR(DFE_SEEKERROR,FAIL);
3381 
3382             /* Read the entire image in */
3383 
3384       /* This offset is relative to the element not the file and this */
3385       /* is where it reads and decompresses the data -BMR 09/2010 */
3386             if(Hread(ri_ptr->img_aid,(int32)pixel_disk_size*count[XDIM]*count[YDIM],
3387                     (uint8 *)img_data)==FAIL)
3388                 HGOTO_ERROR(DFE_READERROR,FAIL);
3389 #endif /* OLD_WAY */
3390             } /* end if */
3391           else
3392             { /* read only part of the image in */
3393                 int32 img_offset; /* current offset in the image data */
3394                 void * tmp_data;   /* temp. pointer to the image data read in */
3395 
3396                 img_offset=((ri_ptr->img_dim.xdim*start[YDIM])+start[XDIM])*(int32)pixel_disk_size;
3397 
3398                 tmp_data=img_data;
3399                 if(solid_block==TRUE)
3400                   {   /* read in runs of data in the image */
3401                       int32 pix_len;    /* length of current row's pixel run */
3402                       intn i;           /* temporary loop variable */
3403 
3404                       pix_len=(int32)pixel_disk_size*count[XDIM];
3405 
3406                       /* read in the block */
3407                       for(i=0; i<count[YDIM]; i++)
3408                         {
3409                             if(Hseek(ri_ptr->img_aid,img_offset,DF_START)==FAIL)
3410                                 HGOTO_ERROR(DFE_SEEKERROR,FAIL);
3411                             if(Hread(ri_ptr->img_aid,pix_len,tmp_data)==FAIL)
3412                                 HGOTO_ERROR(DFE_READERROR,FAIL);
3413                             img_offset+=(int32)pixel_disk_size*ri_ptr->img_dim.xdim;
3414                             tmp_data=(void *)((char *)tmp_data+pix_len);
3415                         } /* end for */
3416                   } /* end if */
3417                 else
3418                   {   /* sub-sampling, seek to each data element and read it in */
3419                       intn i,j;         /* temporary loop variables */
3420                       int32 stride_add; /* amount to add for stride amount */
3421 
3422                       stride_add=(int32)pixel_disk_size*stride[XDIM];
3423 
3424                       for(i=0; i<count[YDIM]; i++)
3425                         {
3426                             int32 local_offset;
3427 
3428                             local_offset=img_offset;
3429                             for(j=0; j<count[XDIM]; j++)
3430                               {
3431                                 if(Hseek(ri_ptr->img_aid,local_offset,DF_START)==FAIL)
3432                                     HGOTO_ERROR(DFE_SEEKERROR,FAIL);
3433                                 if(Hread(ri_ptr->img_aid,(int32)pixel_disk_size,tmp_data)==FAIL)
3434                                     HGOTO_ERROR(DFE_READERROR,FAIL);
3435                                 local_offset+=stride_add;
3436                                 tmp_data=(void *)((char *)tmp_data+pixel_disk_size);
3437                               } /* end for */
3438 
3439                             img_offset+=ri_ptr->img_dim.xdim*stride[YDIM]*(int32)pixel_disk_size;
3440                         } /* end for */
3441                   } /* end else */
3442             } /* end else */
3443 
3444           if(convert)
3445             { /* convert the pixel data into the HDF disk format */
3446               DFKconvert(img_data,data,ri_ptr->img_dim.nt,
3447                   ri_ptr->img_dim.ncomps*count[XDIM]*count[YDIM],DFACC_READ,0,0);
3448               HDfree(img_data);
3449             } /* end if */
3450       } /* end else */
3451 
3452       /* Check whether we need to convert the buffer to the user's */
3453       /*    requested interlace scheme. */
3454       /* Note: This is implemented in a horribly ugly & slow manner, but I'm */
3455       /*        in a bit of a hurry right now - QAK */
3456       if(ri_ptr->im_il!=MFGR_INTERLACE_PIXEL)
3457         {
3458           void * pixel_buf;  /* buffer for the pixel interlaced data */
3459 
3460           /* Allocate space for the conversion buffer */
3461           if((pixel_buf=HDmalloc(pixel_mem_size*(size_t)count[XDIM]*(size_t)count[YDIM]))==NULL)
3462               HGOTO_ERROR(DFE_NOSPACE,FAIL);
3463 
3464           GRIil_convert(data,MFGR_INTERLACE_PIXEL,pixel_buf,ri_ptr->im_il,
3465               count,ri_ptr->img_dim.ncomps,ri_ptr->img_dim.nt);
3466 
3467           HDmemcpy(data,pixel_buf,pixel_mem_size*(size_t)count[XDIM]*(size_t)count[YDIM]);
3468 
3469           HDfree(pixel_buf);
3470         } /* end if */
3471 
3472 done:
3473   if(ret_value == FAIL)
3474     { /* Error condition cleanup */
3475 
3476     } /* end if */
3477 
3478   /* Normal function cleanup */
3479   return ret_value;
3480 } /* end GRreadimage() */
3481 
3482 /*--------------------------------------------------------------------------
3483  NAME
3484     GRendaccess
3485 
3486  PURPOSE
3487     End access to an RI.
3488 
3489  USAGE
3490     intn GRendaccess(riid)
3491         int32 riid;         IN: RI ID from GRselect/GRcreate
3492 
3493  RETURNS
3494     SUCCEED/FAIL
3495 
3496  DESCRIPTION
3497     End access to an RI.  Further attempts to access the RI ID will result in
3498     an error.
3499 
3500  GLOBAL VARIABLES
3501  COMMENTS, BUGS, ASSUMPTIONS
3502  EXAMPLES
3503  REVISION LOG
3504 --------------------------------------------------------------------------*/
GRendaccess(int32 riid)3505 intn GRendaccess(int32 riid)
3506 {
3507     CONSTR(FUNC, "GRendaccess");   /* for HERROR */
3508     ri_info_t *ri_ptr;          /* ptr to the image to work with */
3509     intn  ret_value = SUCCEED;
3510 
3511     /* clear error stack and check validity of args */
3512     HEclear();
3513 
3514     /* check the validity of the RI ID */
3515     if (HAatom_group(riid)!=RIIDGROUP)
3516         HGOTO_ERROR(DFE_ARGS, FAIL);
3517 
3518     /* locate RI's object in hash table */
3519     if (NULL == (ri_ptr = (ri_info_t *) HAatom_object(riid)))
3520         HGOTO_ERROR(DFE_RINOTFOUND, FAIL);
3521 
3522     if(!(ri_ptr->access>0))
3523         HGOTO_ERROR(DFE_CANTENDACCESS,FAIL);
3524 
3525     /* Check for writing a fill value attribute out */
3526     if(ri_ptr->store_fill==TRUE)
3527       { /* store the fill value attribute before letting go of the image */
3528           if(GRsetattr(riid,FILL_ATTR,ri_ptr->img_dim.nt,ri_ptr->img_dim.ncomps,ri_ptr->fill_value)==FAIL)
3529               HGOTO_ERROR(DFE_WRITEERROR,FAIL);
3530           ri_ptr->store_fill=FALSE;
3531       } /* end if */
3532 
3533     /* Reduce the number of accesses to the RI */
3534     ri_ptr->access--;
3535 
3536     /* Check if we should shut down the AID we've been holding open */
3537     if(!(ri_ptr->access>0) && ri_ptr->img_aid!=0)
3538       {
3539         Hendaccess(ri_ptr->img_aid);
3540         ri_ptr->img_aid=0;
3541       } /* end if */
3542 
3543     /* Double check on setting the GR modified flag */
3544     /* Maybe this should be flagged as as error? -QAK */
3545     if(ri_ptr->meta_modified==TRUE && ri_ptr->gr_ptr->gr_modified==FALSE)
3546         ri_ptr->gr_ptr->gr_modified=TRUE;
3547 
3548     /* Delete the atom for the RI ID */
3549     if(NULL==HAremove_atom(riid))
3550         HGOTO_ERROR(DFE_RINOTFOUND, FAIL);
3551 
3552 done:
3553   if(ret_value == FAIL)
3554     { /* Error condition cleanup */
3555 
3556     } /* end if */
3557 
3558   /* Normal function cleanup */
3559   return ret_value;
3560 } /* end GRendaccess() */
3561 
3562 /*--------------------------------------------------------------------------
3563  NAME
3564     GRidtoref
3565 
3566  PURPOSE
3567     Maps an RI ID to a reference # for annotating or including in a Vgroup.
3568 
3569  USAGE
3570     uint16 GRidtoref(riid)
3571         int32 riid;         IN: RI ID from GRselect/GRcreate
3572 
3573  RETURNS
3574     A valid reference # on success or 0
3575 
3576  DESCRIPTION
3577     Maps an riid to a reference # for annotating or including in a Vgroup.
3578 
3579  GLOBAL VARIABLES
3580  COMMENTS, BUGS, ASSUMPTIONS
3581  EXAMPLES
3582  REVISION LOG
3583 --------------------------------------------------------------------------*/
GRidtoref(int32 riid)3584 uint16 GRidtoref(int32 riid)
3585 {
3586     CONSTR(FUNC, "GRidtoref");   /* for HERROR */
3587     ri_info_t *ri_ptr;          /* ptr to the image to work with */
3588     uint16  ret_value = 0; /* FAIL? */
3589 
3590     /* clear error stack and check validity of args */
3591     HEclear();
3592 
3593     /* check the validity of the RI ID */
3594     if (HAatom_group(riid)!=RIIDGROUP)
3595         HGOTO_ERROR(DFE_ARGS, 0);
3596 
3597     /* locate RI's object in hash table */
3598     if (NULL == (ri_ptr = (ri_info_t *) HAatom_object(riid)))
3599         HGOTO_ERROR(DFE_RINOTFOUND, 0);
3600 
3601 #ifdef OLD_WAY
3602     ret_value = (ri_ptr->ri_ref!=DFREF_WILDCARD ? ri_ptr->ri_ref : ri_ptr->rig_ref);
3603 #else /* OLD_WAY */
3604 /* Changed to handle case when ri_ptr->rig_ref is DFREF_WILDCARD */
3605     if(ri_ptr->ri_ref!=DFREF_WILDCARD)
3606         ret_value=ri_ptr->ri_ref;
3607     else
3608       {
3609         if(ri_ptr->rig_ref==DFREF_WILDCARD) {
3610             if(ri_ptr->img_ref==DFREF_WILDCARD)
3611                 HGOTO_ERROR(DFE_INTERNAL,0);
3612             ret_value=ri_ptr->img_ref;
3613         }
3614         else
3615             ret_value=ri_ptr->rig_ref;
3616       } /* end else */
3617 #endif /* OLD_WAY */
3618 
3619 done:
3620   if(ret_value == 0)   /* 0 is invalid ref */
3621     { /* Error condition cleanup */
3622 
3623     } /* end if */
3624 
3625   /* Normal function cleanup */
3626   return ret_value;
3627 } /* end GRidtoref() */
3628 
3629 /*--------------------------------------------------------------------------
3630  NAME
3631     GRreftoindex
3632 
3633  PURPOSE
3634     Maps the reference # of an RI into an index which can be used with GRselect.
3635 
3636  USAGE
3637     int32 GRreftoindex(grid,ref)
3638         int32 grid;         IN: GR ID from GRstart
3639         uint16 ref;         IN: reference number of raster image to map to index
3640 
3641  RETURNS
3642     A valid index # on success or FAIL
3643 
3644  DESCRIPTION
3645     Maps the reference # of an RI into an index which can be used with GRselect.
3646 
3647  GLOBAL VARIABLES
3648  COMMENTS, BUGS, ASSUMPTIONS
3649  EXAMPLES
3650  REVISION LOG
3651 --------------------------------------------------------------------------*/
GRreftoindex(int32 grid,uint16 ref)3652 int32 GRreftoindex(int32 grid,uint16 ref)
3653 {
3654     CONSTR(FUNC, "GRreftoindex");   /* for HERROR */
3655     gr_info_t *gr_ptr;          /* ptr to the GR information for this grid */
3656     ri_info_t *ri_ptr;          /* ptr to the image to work with */
3657     void * *t;                   /* temp. ptr to the image found */
3658     int32   ret_value = SUCCEED;
3659 
3660     /* clear error stack and check validity of args */
3661     HEclear();
3662 
3663     /* check the validity of the RI ID */
3664     if (HAatom_group(grid)!=GRIDGROUP)
3665         HGOTO_ERROR(DFE_ARGS, FAIL);
3666 
3667     /* locate GR's object in hash table */
3668     if (NULL == (gr_ptr = (gr_info_t *) HAatom_object(grid)))
3669         HGOTO_ERROR(DFE_GRNOTFOUND, FAIL);
3670 
3671     if((t = (void **)tbbtfirst((TBBT_NODE *) *(gr_ptr->grtree)))==NULL)
3672         HGOTO_ERROR(DFE_RINOTFOUND,FAIL);
3673     do {
3674         ri_ptr=(ri_info_t *)*t;
3675         if(ri_ptr!=NULL && ((ri_ptr->ri_ref==ref) || (ri_ptr->ri_ref==DFREF_WILDCARD && ri_ptr->rig_ref==ref)))  /* the ref matches */
3676             HGOTO_DONE(ri_ptr->index);
3677     } while((t= (void **)tbbtnext((TBBT_NODE *)t))!=NULL);
3678 
3679     ret_value = (FAIL);
3680 
3681 done:
3682   if(ret_value == 0)
3683     { /* Error condition cleanup */
3684 
3685     } /* end if */
3686 
3687   /* Normal function cleanup */
3688   return ret_value;
3689 } /* end GRreftoindex() */
3690 
3691 /*--------------------------------------------------------------------------
3692  NAME
3693     GRreqlutil
3694 
3695  PURPOSE
3696     Request that the next LUT read from an RI have a particular interlace.
3697 
3698  USAGE
3699     intn GRreqlutil(riid,il)
3700         int32 riid;         IN: RI ID from GRselect/GRcreate
3701         intn il;            IN: interlace for next LUT.  From the following
3702                                 values (found in mfgr.h):
3703                       MFGR_INTERLACE_PIXEL      - pixel interlacing
3704                       MFGR_INTERLACE_LINE       - line interlacing
3705                       MFGR_INTERLACE_COMPONENT  - component/plane interlacing
3706 
3707  RETURNS
3708     SUCCEED/FAIL
3709 
3710  DESCRIPTION
3711     Request that the next LUT read from an RI have a particular interlace.
3712 
3713  GLOBAL VARIABLES
3714  COMMENTS, BUGS, ASSUMPTIONS
3715  EXAMPLES
3716  REVISION LOG
3717 --------------------------------------------------------------------------*/
GRreqlutil(int32 riid,intn il)3718 intn GRreqlutil(int32 riid,intn il)
3719 {
3720     CONSTR(FUNC, "GRreqlutil");   /* for HERROR */
3721     ri_info_t *ri_ptr;          /* ptr to the image to work with */
3722     intn  ret_value = SUCCEED;
3723 
3724     /* clear error stack and check validity of args */
3725     HEclear();
3726 
3727     /* check the validity of the RI ID */
3728     if (HAatom_group(riid)!=RIIDGROUP || il<(intn)MFGR_INTERLACE_PIXEL ||
3729             il>(intn)MFGR_INTERLACE_COMPONENT)
3730         HGOTO_ERROR(DFE_ARGS, FAIL);
3731 
3732     /* locate RI's object in hash table */
3733     if (NULL == (ri_ptr = (ri_info_t *) HAatom_object(riid)))
3734         HGOTO_ERROR(DFE_RINOTFOUND, FAIL);
3735 
3736     /* Assign interlacing scheme */
3737     ri_ptr->lut_il=(gr_interlace_t)il;
3738 
3739 done:
3740   if(ret_value == 0)
3741     { /* Error condition cleanup */
3742 
3743     } /* end if */
3744 
3745   /* Normal function cleanup */
3746   return ret_value;
3747 } /* end GRreqlutil() */
3748 
3749 /*--------------------------------------------------------------------------
3750  NAME
3751     GRreqimageil
3752 
3753  PURPOSE
3754     Request that the image read from an RI have a particular interlace.
3755 
3756  USAGE
3757     intn GRreqimageil(riid,il)
3758         int32 riid;         IN: RI ID from GRselect/GRcreate
3759         intn il;            IN: interlace for next RI.  From the following
3760                                 values (found in mfgr.h):
3761                       MFGR_INTERLACE_PIXEL      - pixel interlacing
3762                       MFGR_INTERLACE_LINE       - line interlacing
3763                       MFGR_INTERLACE_COMPONENT  - component/plane interlacing
3764 
3765  RETURNS
3766     SUCCEED/FAIL
3767 
3768  DESCRIPTION
3769     Request that the image read from an RI have a particular interlace.
3770 
3771  GLOBAL VARIABLES
3772  COMMENTS, BUGS, ASSUMPTIONS
3773  EXAMPLES
3774  REVISION LOG
3775 --------------------------------------------------------------------------*/
GRreqimageil(int32 riid,intn il)3776 intn GRreqimageil(int32 riid,intn il)
3777 {
3778     CONSTR(FUNC, "GRreqimageil");   /* for HERROR */
3779     ri_info_t *ri_ptr;          /* ptr to the image to work with */
3780     intn  ret_value = SUCCEED;
3781 
3782     /* clear error stack and check validity of args */
3783     HEclear();
3784 
3785     /* check the validity of the RI ID */
3786     if (HAatom_group(riid)!=RIIDGROUP || il<(intn)MFGR_INTERLACE_PIXEL ||
3787             il>(intn)MFGR_INTERLACE_COMPONENT)
3788         HGOTO_ERROR(DFE_ARGS, FAIL);
3789 
3790     /* locate RI's object in hash table */
3791     if (NULL == (ri_ptr = (ri_info_t *) HAatom_object(riid)))
3792         HGOTO_ERROR(DFE_RINOTFOUND, FAIL);
3793 
3794     /* Assign interlacing scheme */
3795     ri_ptr->im_il=(gr_interlace_t)il;
3796 
3797 done:
3798   if(ret_value == 0)
3799     { /* Error condition cleanup */
3800 
3801     } /* end if */
3802 
3803   /* Normal function cleanup */
3804   return ret_value;
3805 } /* end GRreqimageil() */
3806 
3807 /*--------------------------------------------------------------------------
3808  NAME
3809     GRgetlutid
3810 
3811  PURPOSE
3812     Get a LUT id ('lutid') for an RI.
3813 
3814  USAGE
3815     int32 GRgetlutid(riid,index)
3816         int32 riid;         IN: RI ID from GRselect/GRcreate
3817         int32 lut_index;    IN: Which LUT image to select (indexed from 0)
3818 
3819  RETURNS
3820     Valid LUT ID on success, FAIL on failure
3821 
3822  DESCRIPTION
3823     Get a LUT id ('lutid') for accessing LUTs in an RI.
3824 
3825  GLOBAL VARIABLES
3826  COMMENTS, BUGS, ASSUMPTIONS
3827     Currently only supports one LUT per image, at index 0 and LUTID==RIID.
3828 
3829  EXAMPLES
3830  REVISION LOG
3831 --------------------------------------------------------------------------*/
GRgetlutid(int32 riid,int32 lut_index)3832 int32 GRgetlutid(int32 riid,int32 lut_index)
3833 {
3834     CONSTR(FUNC, "GRgetlutid");   /* for HERROR */
3835     int32  ret_value = SUCCEED;
3836 
3837     /* clear error stack and check validity of args */
3838     HEclear();
3839 
3840     /* check the validity of the RI ID */
3841     if (HAatom_group(riid)!=RIIDGROUP || lut_index!=0)
3842         HGOTO_ERROR(DFE_ARGS, FAIL);
3843 
3844     ret_value =(riid);
3845 
3846 done:
3847   if(ret_value == 0)
3848     { /* Error condition cleanup */
3849 
3850     } /* end if */
3851 
3852   /* Normal function cleanup */
3853   return ret_value;
3854 } /* end GRgetlutid() */
3855 
3856 /*--------------------------------------------------------------------------
3857  NAME
3858     GRluttoref
3859 
3860  PURPOSE
3861     Returns the ref # for a LUT.
3862 
3863  USAGE
3864     uint16 GRluttoref(lutid)
3865         int32 lutid;        IN: LUT ID from GRgetlutid
3866 
3867  RETURNS
3868     Valid ref # if a palette exists, or 0 when:
3869   - palette doesn't exist, or
3870   - unable to get the image from the palette id. - BMR
3871 
3872  DESCRIPTION
3873     Gets the ref # used to store the LUT in the file.
3874 
3875  GLOBAL VARIABLES
3876  COMMENTS, BUGS, ASSUMPTIONS
3877  EXAMPLES
3878  REVISION LOG
3879 --------------------------------------------------------------------------*/
GRluttoref(int32 lutid)3880 uint16 GRluttoref(int32 lutid)
3881 {
3882     CONSTR(FUNC, "GRluttoref");   /* for HERROR */
3883     ri_info_t *ri_ptr;          /* ptr to the image to work with */
3884     uint16 ret_value = 0;
3885 
3886     /* clear error stack and check validity of args */
3887     HEclear();
3888 
3889     /* check the validity of the RI ID */
3890     if (HAatom_group(lutid)!=RIIDGROUP)
3891         HGOTO_ERROR(DFE_ARGS, 0);  /* return 0 for invalid ref # - BMR */
3892 
3893     /* locate LUT's object in hash table */
3894     if (NULL == (ri_ptr = (ri_info_t *) HAatom_object(lutid)))
3895         HGOTO_ERROR(DFE_LUTNOTFOUND, 0); /* return 0 for invalid ref # - BMR */
3896 
3897     ret_value=ri_ptr->lut_ref;
3898 
3899 done:
3900   if(ret_value == 0)
3901     { /* Error condition cleanup */
3902 
3903     } /* end if */
3904 
3905   /* Normal function cleanup */
3906   return ret_value;
3907 } /* end GRluttoref() */
3908 
3909 /*--------------------------------------------------------------------------
3910  NAME
3911     GRgetlutinfo
3912 
3913  PURPOSE
3914     Gets information about a LUT.
3915 
3916  USAGE
3917     intn GRgetlutinfo(lutid,ncomp,nt,il,nentries)
3918         int32 lutid;        IN: LUT ID from GRgetlutid
3919         int32 *ncomp;       OUT: number of components in LUT
3920         int32 *nt;          OUT: number type of components
3921         int32 *il;          OUT: interlace of the LUT
3922         int32 *nentries;    OUT: the number of entries for the LUT
3923 
3924  RETURNS
3925     SUCCEED/FAIL
3926 
3927  DESCRIPTION
3928     Gets information about a LUT.
3929 
3930  GLOBAL VARIABLES
3931  COMMENTS, BUGS, ASSUMPTIONS
3932  EXAMPLES
3933  REVISION LOG
3934 --------------------------------------------------------------------------*/
GRgetlutinfo(int32 lutid,int32 * ncomp,int32 * nt,int32 * il,int32 * nentries)3935 intn GRgetlutinfo(int32 lutid,int32 *ncomp,int32 *nt,int32 *il,int32 *nentries)
3936 {
3937     CONSTR(FUNC, "GRgetlutinfo");   /* for HERROR */
3938     ri_info_t *ri_ptr;          /* ptr to the image to work with */
3939     intn  ret_value = SUCCEED;
3940 
3941     /* clear error stack and check validity of args */
3942     HEclear();
3943 
3944     /* check the validity of the RI ID */
3945     if (HAatom_group(lutid)!=RIIDGROUP)
3946         HGOTO_ERROR(DFE_ARGS, FAIL);
3947 
3948     /* locate LUT's object in hash table */
3949     if (NULL == (ri_ptr = (ri_info_t *) HAatom_object(lutid)))
3950         HGOTO_ERROR(DFE_LUTNOTFOUND, FAIL);
3951 
3952     if(ri_ptr->lut_ref==DFREF_WILDCARD) { /* check for no palette defined currently */
3953         if(ncomp!=NULL)
3954             *ncomp=0;
3955         if(nt!=NULL)
3956             *nt=DFNT_NONE;
3957         if(il!=NULL)
3958             *il=-1;
3959         if(nentries!=NULL)
3960             *nentries=0;
3961     } /* end if */
3962     else        /* we've got a valid palette currently */
3963       {
3964           if(ncomp!=NULL)
3965               *ncomp=ri_ptr->lut_dim.ncomps;
3966           if(nt!=NULL)
3967               *nt=ri_ptr->lut_dim.nt;
3968           if(il!=NULL)
3969               *il=(int32)ri_ptr->lut_dim.il;
3970           if(nentries!=NULL)  /* xdim for LUTs is the number of entries */
3971               *nentries=ri_ptr->lut_dim.xdim;
3972       } /* end else */
3973 
3974 done:
3975   if(ret_value == 0)
3976     { /* Error condition cleanup */
3977 
3978     } /* end if */
3979 
3980   /* Normal function cleanup */
3981     return ret_value;
3982 } /* end GRgetlutinfo() */
3983 
3984 /*--------------------------------------------------------------------------
3985  NAME
3986     GRwritelut
3987 
3988  PURPOSE
3989     Writes out a LUT for an RI.
3990 
3991  USAGE
3992     intn GRwritelut(riid,ncomps,nt,il,nentries,data)
3993         int32 lutid;        IN: LUT ID from GRgetlutid
3994         int32 ncomp;        IN: number of components in LUT
3995         int32 nt;           IN: number type of components
3996         int32 il;           IN: interlace of the LUT
3997         int32 nentries;     IN: the number of entries for the LUT
3998         void * data;         IN: LUT data to write out
3999 
4000  RETURNS
4001     SUCCEED/FAIL
4002 
4003  DESCRIPTION
4004     Writes out a LUT for an RI.
4005 
4006  GLOBAL VARIABLES
4007  COMMENTS, BUGS, ASSUMPTIONS
4008  EXAMPLES
4009  REVISION LOG
4010 --------------------------------------------------------------------------*/
GRwritelut(int32 lutid,int32 ncomps,int32 nt,int32 il,int32 nentries,void * data)4011 intn GRwritelut(int32 lutid,int32 ncomps,int32 nt,int32 il,int32 nentries,void * data)
4012 {
4013     CONSTR(FUNC, "GRwritelut");   /* for HERROR */
4014     int32 hdf_file_id;          /* file ID from Hopen */
4015     ri_info_t *ri_ptr;          /* ptr to the image to work with */
4016     intn  ret_value = SUCCEED;
4017 
4018     /* clear error stack and check validity of args */
4019     HEclear();
4020 
4021     /* check the validity of the args (how to check il?) */
4022     if (HAatom_group(lutid)!=RIIDGROUP || ncomps<1 || (DFKNTsize(nt)==FAIL)
4023             || nentries<1 || data==NULL)
4024         HGOTO_ERROR(DFE_ARGS, FAIL);
4025 
4026     /* locate LUT's object in hash table */
4027     if (NULL == (ri_ptr = (ri_info_t *) HAatom_object(lutid)))
4028         HGOTO_ERROR(DFE_LUTNOTFOUND, FAIL);
4029     hdf_file_id=ri_ptr->gr_ptr->hdf_file_id;
4030 
4031     /* Check if this is compatible with older-style palettes */
4032     if(ncomps==3 && (nt==DFNT_UINT8 ||nt==DFNT_UCHAR8) &&
4033         il==MFGR_INTERLACE_PIXEL && nentries==256)
4034       {
4035           /* Check if LUT exists already */
4036           if(ri_ptr->lut_tag!=DFTAG_NULL && ri_ptr->lut_ref!=DFREF_WILDCARD)
4037             {   /* LUT already exists */
4038                 if(Hputelement(hdf_file_id,ri_ptr->lut_tag,ri_ptr->lut_ref,
4039                         data,ncomps*nentries*DFKNTsize(nt))==FAIL)
4040                     HGOTO_ERROR(DFE_PUTELEM,FAIL);
4041             } /* end if */
4042           else
4043             {   /* LUT does not exist */
4044                 ri_ptr->lut_tag=DFTAG_LUT;
4045                 ri_ptr->lut_ref=Htagnewref(hdf_file_id,ri_ptr->lut_tag);
4046                 ri_ptr->lut_dim.dim_ref=DFREF_WILDCARD;
4047                 ri_ptr->lut_dim.xdim=256;
4048                 ri_ptr->lut_dim.ydim=1;
4049                 ri_ptr->lut_dim.ncomps=3;
4050                 ri_ptr->lut_dim.nt=DFNT_UINT8;
4051                 ri_ptr->lut_dim.file_nt_subclass=DFNTF_HDFDEFAULT;
4052                 ri_ptr->lut_dim.il=MFGR_INTERLACE_PIXEL;
4053                 ri_ptr->lut_dim.nt_tag=DFTAG_NULL;
4054                 ri_ptr->lut_dim.nt_ref=DFREF_WILDCARD;
4055                 ri_ptr->lut_dim.comp_tag=DFTAG_NULL;
4056                 ri_ptr->lut_dim.comp_ref=DFREF_WILDCARD;
4057                 if(Hputelement(hdf_file_id,ri_ptr->lut_tag,ri_ptr->lut_ref,
4058                         data,ncomps*nentries*DFKNTsize(nt))==FAIL)
4059                     HGOTO_ERROR(DFE_PUTELEM,FAIL);
4060 
4061                 ri_ptr->meta_modified=TRUE;
4062                 ri_ptr->gr_ptr->gr_modified=TRUE;
4063             } /* end else */
4064       } /* end if */
4065     else
4066       {     /* currently, we are not going to support non-standard palettes */
4067           HGOTO_ERROR(DFE_UNSUPPORTED,FAIL);
4068       } /* end else */
4069 
4070 done:
4071   if(ret_value == 0)
4072     { /* Error condition cleanup */
4073 
4074     } /* end if */
4075 
4076   /* Normal function cleanup */
4077   return ret_value;
4078 } /* end GRwritelut() */
4079 
4080 /*--------------------------------------------------------------------------
4081  NAME
4082     GRreadlut
4083 
4084  PURPOSE
4085     Reads a LUT from an RI.
4086 
4087  USAGE
4088     intn GRreadlut(lutid,data)
4089         int32 lutid;        IN: LUT ID from GRgetlutid
4090         void * data;         IN: buffer for LUT data read in
4091 
4092  RETURNS
4093     SUCCEED/FAIL
4094 
4095  DESCRIPTION
4096     Reads a LUT from an RI.
4097 
4098  GLOBAL VARIABLES
4099  COMMENTS, BUGS, ASSUMPTIONS
4100  EXAMPLES
4101  REVISION LOG
4102 --------------------------------------------------------------------------*/
GRreadlut(int32 lutid,void * data)4103 intn GRreadlut(int32 lutid,void * data)
4104 {
4105     CONSTR(FUNC, "GRreadlut");   /* for HERROR */
4106     int32 hdf_file_id;          /* file ID from Hopen */
4107     ri_info_t *ri_ptr;          /* ptr to the image to work with */
4108     intn  ret_value = SUCCEED;
4109 
4110     /* clear error stack and check validity of args */
4111     HEclear();
4112 
4113     /* check the validity of the RI ID */
4114     if (HAatom_group(lutid)!=RIIDGROUP || data==NULL)
4115         HGOTO_ERROR(DFE_ARGS, FAIL);
4116 
4117     /* locate LUT's object in hash table */
4118     if (NULL == (ri_ptr = (ri_info_t *) HAatom_object(lutid)))
4119         HGOTO_ERROR(DFE_LUTNOTFOUND, FAIL);
4120     hdf_file_id=ri_ptr->gr_ptr->hdf_file_id;
4121 
4122     if(ri_ptr->lut_tag!=DFTAG_NULL && ri_ptr->lut_ref!=DFREF_WILDCARD)
4123       {
4124           if(Hgetelement(hdf_file_id,ri_ptr->lut_tag,ri_ptr->lut_ref,data)==FAIL)
4125               HGOTO_ERROR(DFE_GETELEM,FAIL);
4126       } /* end if */
4127 
4128     /* Re-format the palette into the user's requested interlacing */
4129     if(ri_ptr->lut_il!=MFGR_INTERLACE_PIXEL)
4130       {
4131           uintn pixel_mem_size;       /* size of a pixel in memory */
4132           void * pixel_buf;  /* buffer for the pixel interlaced data */
4133           int32 count[2];   /* "dimension" info */
4134 
4135           pixel_mem_size=(uintn)(ri_ptr->lut_dim.ncomps*DFKNTsize((ri_ptr->lut_dim.nt | DFNT_NATIVE) & (~DFNT_LITEND)));
4136 
4137           /* Allocate space for the conversion buffer */
4138           if((pixel_buf=HDmalloc(pixel_mem_size*(size_t)ri_ptr->lut_dim.xdim))==NULL)
4139               HGOTO_ERROR(DFE_NOSPACE,FAIL);
4140 
4141           count[XDIM]=1;
4142           count[YDIM]=ri_ptr->lut_dim.xdim;
4143           GRIil_convert(data,MFGR_INTERLACE_PIXEL,pixel_buf,ri_ptr->lut_il,
4144               count,ri_ptr->lut_dim.ncomps,ri_ptr->lut_dim.nt);
4145 
4146           HDmemcpy(data,pixel_buf,pixel_mem_size*(size_t)ri_ptr->lut_dim.xdim);
4147 
4148           HDfree(pixel_buf);
4149       } /* end if */
4150 
4151 done:
4152   if(ret_value == 0)
4153     { /* Error condition cleanup */
4154 
4155     } /* end if */
4156 
4157   /* Normal function cleanup */
4158   return ret_value;
4159 } /* end GRreadlut() */
4160 
4161 /*--------------------------------------------------------------------------
4162  NAME
4163     GRsetexternalfile
4164 
4165  PURPOSE
4166     Makes the image data of an RI into an external element special element.
4167 
4168  USAGE
4169     intn GRsetexternalfile(riid,filename,offset)
4170         int32 riid;         IN: RI ID from GRselect/GRcreate
4171         char *filename;     IN: name of the external file
4172         int32 offset;       IN: offset in the external file to store the image
4173 
4174  RETURNS
4175     SUCCEED/FAIL
4176 
4177  DESCRIPTION
4178     Makes the image data of an RI into an external element special element.
4179 
4180  GLOBAL VARIABLES
4181  COMMENTS, BUGS, ASSUMPTIONS
4182  EXAMPLES
4183  REVISION LOG
4184 --------------------------------------------------------------------------*/
GRsetexternalfile(int32 riid,const char * filename,int32 offset)4185 intn GRsetexternalfile(int32 riid,const char *filename,int32 offset)
4186 {
4187     CONSTR(FUNC, "GRsetexternalfile");   /* for HERROR */
4188     ri_info_t *ri_ptr;          /* ptr to the image to work with */
4189     int32 tmp_aid;  /* AID returned from HXcreate() */
4190     intn  ret_value = SUCCEED;
4191 
4192     /* clear error stack and check validity of args */
4193     HEclear();
4194 
4195     /* check the validity of the RI ID */
4196     if (HAatom_group(riid)!=RIIDGROUP)
4197         HGOTO_ERROR(DFE_ARGS, FAIL);
4198 
4199     /* locate RI's object in hash table */
4200     if (NULL == (ri_ptr = (ri_info_t *) HAatom_object(riid)))
4201         HGOTO_ERROR(DFE_RINOTFOUND, FAIL);
4202 
4203     if((ri_ptr->ext_name=(char *)HDmalloc(HDstrlen(filename)+1))==NULL)
4204         HGOTO_ERROR(DFE_NOSPACE,FAIL);
4205 
4206     /* Mark the image as external and cache parameters */
4207     ri_ptr->ext_img=TRUE;
4208     HDstrcpy(ri_ptr->ext_name,filename);
4209     ri_ptr->ext_offset=offset;
4210 
4211     /* Create the image tag/ref if it's a new image */
4212     if(ri_ptr->img_tag==DFTAG_NULL || ri_ptr->img_ref==DFREF_WILDCARD)
4213       {
4214         ri_ptr->img_tag=DFTAG_RI;
4215         ri_ptr->img_ref=Htagnewref(ri_ptr->gr_ptr->hdf_file_id,ri_ptr->img_tag);
4216         ri_ptr->meta_modified=TRUE;
4217       } /* end if */
4218 
4219     /* close any existing AID, to convert to external element AID */
4220     if(ri_ptr->img_aid!=0)
4221       {
4222         Hendaccess(ri_ptr->img_aid);
4223         ri_ptr->img_aid=0;
4224       } /* end if */
4225 
4226     /* Convert the image into an external element */
4227     if((tmp_aid=HXcreate(ri_ptr->gr_ptr->hdf_file_id,ri_ptr->img_tag,
4228             ri_ptr->img_ref,filename,offset,0))==FAIL)
4229         HGOTO_ERROR(DFE_BADAID, FAIL);
4230     if(Hendaccess(tmp_aid)==FAIL)
4231         HGOTO_ERROR(DFE_CANTENDACCESS, FAIL);
4232 
4233 done:
4234   if(ret_value == 0)
4235     { /* Error condition cleanup */
4236 
4237     } /* end if */
4238 
4239   /* Normal function cleanup */
4240   return ret_value;
4241 } /* end GRsetexternalfile() */
4242 
4243 /*--------------------------------------------------------------------------
4244  NAME
4245     GRsetaccesstype
4246 
4247  PURPOSE
4248     Sets the access for an RI to be either serial or parallel I/O.
4249 
4250  USAGE
4251     intn GRsetaccesstype(riid,accesstype)
4252         int32 riid;         IN: RI ID from GRselect/GRcreate
4253         uintn accesstype;   IN: access type for image data, from the following
4254            values:
4255         DFACC_SERIAL - for serial access
4256         DFACC_PARALLEL - for parallel access
4257 
4258  RETURNS
4259     SUCCEED/FAIL
4260 
4261  DESCRIPTION
4262     Sets the access for an RI to be either serial or parallel I/O.
4263 
4264  GLOBAL VARIABLES
4265  COMMENTS, BUGS, ASSUMPTIONS
4266  EXAMPLES
4267  REVISION LOG
4268 --------------------------------------------------------------------------*/
GRsetaccesstype(int32 riid,uintn accesstype)4269 intn GRsetaccesstype(int32 riid,uintn accesstype)
4270 {
4271     CONSTR(FUNC, "GRsetaccesstype");   /* for HERROR */
4272     ri_info_t *ri_ptr;          /* ptr to the image to work with */
4273     intn  ret_value = SUCCEED;
4274 
4275     /* clear error stack and check validity of args */
4276     HEclear();
4277 
4278     /* check the validity of the RI ID */
4279     if (HAatom_group(riid)!=RIIDGROUP || (accesstype!=DFACC_DEFAULT && accesstype!=DFACC_SERIAL
4280             && accesstype!=DFACC_PARALLEL))
4281         HGOTO_ERROR(DFE_ARGS, FAIL);
4282 
4283     /* locate RI's object in hash table */
4284     if (NULL == (ri_ptr = (ri_info_t *) HAatom_object(riid)))
4285         HGOTO_ERROR(DFE_RINOTFOUND, FAIL);
4286 
4287     /* Mark the image as having an access-mode and cache args */
4288     ri_ptr->acc_img=TRUE;
4289     ri_ptr->acc_type=accesstype;
4290 
4291 done:
4292   if(ret_value == 0)
4293     { /* Error condition cleanup */
4294 
4295     } /* end if */
4296 
4297   /* Normal function cleanup */
4298   return ret_value;
4299 } /* end GRsetaccesstype() */
4300 
4301 
4302 #ifdef H4_HAVE_LIBSZ          /* we have the library */
4303 /*--------------------------------------------------------------------------
4304  NAME
4305     GRsetup_szip_parms( ri_info_t *ri_ptr, comp_info *c_info, int32 *cdims)
4306 
4307  PURPOSE
4308     Set up the szip parameters
4309 
4310  USAGE
4311     intn GRsetaccesstype( ri_info_t *ri_ptr, comp_info *c_info, int32 *cdims)
4312     ri_info_t *ri_ptr;  IN: the RI object
4313     comp_info *c_info;  IN/OUT: the compression info (szip)
4314     int32 *cdims;       IN: chunk dims if chunked, else NULL
4315 
4316  RETURNS
4317     SUCCEED/FAIL
4318 
4319  DESCRIPTION
4320     Sets the computed szip parameters before calling HCcreate.
4321 
4322  GLOBAL VARIABLES
4323  COMMENTS, BUGS, ASSUMPTIONS
4324  EXAMPLES
4325  REVISION LOG
4326 --------------------------------------------------------------------------*/
4327 intn
GRsetup_szip_parms(ri_info_t * ri_ptr,comp_info * c_info,int32 * cdims)4328 GRsetup_szip_parms( ri_info_t *ri_ptr, comp_info *c_info, int32 *cdims)
4329 {
4330     int32 nt;
4331     int32 ndims;
4332     int32 ncomp;
4333     int32 xdims[H4_MAX_VAR_DIMS];
4334     intn  ret_value = SUCCEED;
4335 
4336 
4337     ndims = 2;
4338     xdims[0] = ri_ptr->img_dim.xdim;
4339     xdims[1] = ri_ptr->img_dim.ydim;
4340 
4341     nt = ri_ptr->img_dim.nt;
4342     ncomp = ri_ptr->img_dim.ncomps;
4343 
4344     ret_value = HCPsetup_szip_parms( c_info, nt, ncomp, ndims, xdims, cdims);
4345 
4346 done:
4347     return(ret_value);
4348 }
4349 #endif
4350 
4351 /*--------------------------------------------------------------------------
4352  NAME
4353     GRsetcompress
4354 
4355  PURPOSE
4356     Compressed the image data of an RI.
4357 
4358  USAGE
4359     intn GRsetcompress(riid,comp_type,cinfo)
4360         int32 riid;             IN: RI ID from GRselect/GRcreate
4361         comp_coder_t comp_type; IN: type of compression
4362         comp_info *cinfo;       IN: compression specific information
4363 
4364  RETURNS
4365     SUCCEED/FAIL
4366 
4367  DESCRIPTION
4368     Compressed the image data of an RI.
4369     (Makes the image data of an RI into a compressed special element)
4370 
4371  GLOBAL VARIABLES
4372  COMMENTS, BUGS, ASSUMPTIONS
4373  EXAMPLES
4374  REVISION LOG
4375 --------------------------------------------------------------------------*/
GRsetcompress(int32 riid,comp_coder_t comp_type,comp_info * cinfo)4376 intn GRsetcompress(int32 riid,comp_coder_t comp_type,comp_info *cinfo)
4377 {
4378     CONSTR(FUNC, "GRsetcompress");   /* for HERROR */
4379     ri_info_t *ri_ptr;          /* ptr to the image to work with */
4380     comp_info cinfo_x;
4381     uint32 comp_config;
4382     intn  ret_value = SUCCEED;
4383 
4384     /* clear error stack and check validity of args */
4385     HEclear();
4386 
4387     HDmemcpy(&cinfo_x,cinfo,sizeof(comp_info));
4388     /* check the validity of the RI ID */
4389     if (HAatom_group(riid)!=RIIDGROUP)
4390         HGOTO_ERROR(DFE_ARGS, FAIL);
4391 
4392     /* Check the validity of the compression type */
4393     if ((comp_type < COMP_CODE_NONE || comp_type >= COMP_CODE_INVALID)
4394   && comp_type!=COMP_CODE_JPEG)
4395         HGOTO_ERROR(DFE_ARGS, FAIL);
4396 
4397     /* locate RI's object in hash table */
4398     if (NULL == (ri_ptr = (ri_info_t *) HAatom_object(riid)))
4399         HGOTO_ERROR(DFE_RINOTFOUND, FAIL);
4400 
4401     /* Check if the image is already special (all special elements use the buffered driver) */
4402     if (ri_ptr->use_buf_drvr)
4403         HGOTO_ERROR(DFE_CANTMOD, FAIL);
4404 
4405     /* Check that the compression method is enabled */
4406     HCget_config_info(comp_type, &comp_config);
4407     if ((comp_config & (COMP_DECODER_ENABLED|COMP_ENCODER_ENABLED)) == 0) {
4408   /* coder not present?? */
4409       HGOTO_ERROR(DFE_BADCODER, FAIL);
4410     }
4411     if ((comp_config & COMP_ENCODER_ENABLED) != COMP_ENCODER_ENABLED) {
4412      /* if ((comp_config & COMP_ENCODER_ENABLED) == 0) {
4413  */
4414   /* encoder not present?? */
4415       HGOTO_ERROR(DFE_NOENCODER, FAIL);
4416     }
4417 
4418     if (comp_type==COMP_CODE_SZIP)
4419 #ifndef H4_HAVE_LIBSZ
4420         HGOTO_ERROR(DFE_NOSZLIB, FAIL);
4421 #else
4422     {
4423     /* szip is enabled, check and set up szip parms */
4424   if (GRsetup_szip_parms( ri_ptr, &cinfo_x, NULL) == FAIL) {
4425       HGOTO_ERROR(DFE_INTERNAL, FAIL);
4426   }
4427     }
4428 #endif
4429 
4430     /* Mark the image as being compressed and cache args */
4431     if(comp_type==COMP_CODE_JPEG)
4432       {
4433         if(ri_ptr->img_dim.ncomps==1)
4434             ri_ptr->img_dim.comp_tag=DFTAG_GREYJPEG5;
4435         else if(ri_ptr->img_dim.ncomps==3)
4436             ri_ptr->img_dim.comp_tag=DFTAG_JPEG5;
4437         else
4438             HGOTO_ERROR(DFE_CANTMOD, FAIL);
4439         ri_ptr->use_cr_drvr=TRUE;
4440       } /* end if */
4441     else
4442       {
4443         ri_ptr->comp_img=TRUE;
4444         ri_ptr->comp_type=comp_type;
4445       } /* end else */
4446 
4447     /* Todo: Application may send in COMP_CODE_NONE -BMR 9/2010 */
4448 
4449     /* Store compression parameters */
4450     HDmemcpy(&(ri_ptr->cinfo),&cinfo_x,sizeof(comp_info));
4451 
4452     /* Mark the image as needing to be a buffered special element */
4453     ri_ptr->use_buf_drvr=1;
4454 
4455     /* Make certain the image gets created */
4456     if(GRIgetaid(ri_ptr, DFACC_WRITE)==FAIL)
4457         HGOTO_ERROR(DFE_INTERNAL,FAIL);
4458 
4459 done:
4460   if(ret_value == 0)
4461     { /* Error condition cleanup */
4462 
4463     } /* end if */
4464 
4465   /* Normal function cleanup */
4466   return ret_value;
4467 } /* end GRsetcompress() */
4468 
4469 /*--------------------------------------------------------------------------
4470  NAME
4471     GRgetcompress
4472 
4473  PURPOSE
4474     Get the compression information of a raster image's data.
4475 
4476  USAGE
4477     intn GRgetcompress(riid,comp_type,cinfo)
4478         int32 riid;       IN: RI ID from GRselect/GRcreate
4479         comp_coder_t* comp_type;   OUT: type of compression
4480         comp_info* cinfo;     OUT: retrieved compression information
4481 
4482  RETURNS
4483     SUCCEED/FAIL
4484 
4485  DESCRIPTION
4486     This routine gets the compression type of the given RI's data, then
4487     retrieves the appropriate information into the provided compression
4488     info structure.
4489 
4490  GLOBAL VARIABLES
4491  COMMENTS, BUGS, ASSUMPTIONS
4492     JPEG information is currently not retrievable because the JPEG
4493     parameters, 'quality' and 'force_baseline', are irreversibly
4494     mapped to a quantization table.  Thus, only the correct compression
4495     type will be returned; cinfo will only contain 0s.
4496 
4497  EXAMPLES
4498  REVISION LOG
4499     July 2001: Added to fix bug #307 -BMR
4500     Apr 2005: Replaced by GRgetcompinfo due to deficiency in handling some
4501 		special elements. -BMR
4502 --------------------------------------------------------------------------*/
GRgetcompress(int32 riid,comp_coder_t * comp_type,comp_info * cinfo)4503 intn GRgetcompress(int32 riid, comp_coder_t* comp_type, comp_info* cinfo)
4504 {
4505     CONSTR(FUNC, "GRgetcompress");   /* for HGOTO_ERROR */
4506     ri_info_t *ri_ptr;          /* ptr to the image to work with */
4507     int32 file_id;
4508     uint16 scheme;  /* compression scheme used for JPEG images */
4509     intn  ret_value = SUCCEED;
4510 
4511     /* clear error stack and check validity of args */
4512     HEclear();
4513 
4514     /* check the validity of the RI ID */
4515     if (HAatom_group(riid) != RIIDGROUP)
4516         HGOTO_ERROR(DFE_ARGS, FAIL);
4517 
4518     /* and check the output arguments */
4519     if (comp_type == NULL || cinfo == NULL)
4520         HGOTO_ERROR(DFE_ARGS, FAIL);
4521 
4522     /* locate RI's object in hash table */
4523     if (NULL == (ri_ptr = (ri_info_t *) HAatom_object(riid)))
4524         HGOTO_ERROR(DFE_BADPTR, FAIL);
4525 
4526     file_id = ri_ptr->gr_ptr->hdf_file_id;  /* temporary use */
4527 
4528     /* If the compression scheme used was JPEG, return the compression type
4529        and 0 for the 'quality' and 'force_baseline' parameters, because
4530        these parameters are currently not possible to be retrieved. */
4531     scheme = ri_ptr->img_dim.comp_tag;
4532     if (scheme == DFTAG_JPEG5 || scheme == DFTAG_GREYJPEG5
4533             || scheme==DFTAG_JPEG || scheme==DFTAG_GREYJPEG)
4534     {
4535 	*comp_type = COMP_CODE_JPEG;
4536 	cinfo->jpeg.quality = 0;
4537 	cinfo->jpeg.force_baseline = 0;
4538     }
4539     else
4540     {
4541 	/* use lower-level routine to get the compression information */
4542 	ret_value = HCPgetcompress(file_id, ri_ptr->img_tag, ri_ptr->img_ref,
4543                                 comp_type, cinfo);
4544 	if (ret_value == FAIL)
4545 	    HGOTO_ERROR(DFE_INTERNAL, FAIL);
4546     }
4547 
4548 done:
4549   if(ret_value == 0)
4550     { /* Error condition cleanup */
4551 
4552     } /* end if */
4553 
4554   /* Normal function cleanup */
4555   return ret_value;
4556 } /* end GRgetcompress() */
4557 
4558 /*--------------------------------------------------------------------------
4559  NAME
4560     GRgetcomptype
4561 
4562  PURPOSE
4563     Get the compression type of a raster image's data.
4564 
4565  USAGE
4566     intn GRgetcomptype(riid, comp_type)
4567         int32 riid;     IN: RI ID from GRselect/GRcreate
4568         comp_coder_t* comp_type;  OUT: type of compression, including obsolete ones
4569 
4570  RETURNS
4571     SUCCEED/FAIL
4572 
4573  DESCRIPTION
4574     Historical note:
4575     This function (old name grgetcomptype) was implemented specifically
4576     for the hmap project.  It gets the compression type of the given
4577     RI's data.  The existing function GRgetcompinfo did not detect the
4578     obsolete compression scheme IMCOMP.  Because the hmap writer needs
4579     to report when an image with IMCOMP exists in the file, it needs a
4580     way to detect such images.  One option is to add COMP_CODE_IMCOMP
4581     to the enum type comp_coder_t.  However, with the consideration of
4582     backward/forward compatibility, it would be risky to change the
4583     existing public type comp_coder_t while running against deadlines.
4584     Instead, it was decided that a function would be made for the hmap
4585     project only, and would not be published in the HDF4 documentation.
4586     The function, grgetcomptype, will return comp_type as COMP_IMCOMP
4587     or one of the values included in the type comp_coder_t.  Mar 11, 2011 -BMR
4588 
4589     Update:
4590     Further investigation indicated that it is safe to add COMP_CODE_IMCOMP
4591     to comp_coder_t, with the value of 12 (as DFTAG_IMC/DFTAG_IMCOMP), which
4592     is after COMP_CODE_JPEG.  Extra care had been taken to ensure that GR
4593     interface cannot create or write images using IMCOMP compression.
4594     grgetcomptype is now changed to GRgetcomptype and published in
4595     release 4.2.8.  Jul 11, 2012 -BMR
4596 
4597  GLOBAL VARIABLES
4598  COMMENTS, BUGS, ASSUMPTIONS
4599     At this time, hdp and other tools still use GRgetcompinfo.  We need to
4600     discuss about how to handle its limitation.  In addition, GR2bmapped is
4601     using grgetcomptype until we have an official GRgetcomptype or will change
4602     to use GRgetcompinfo if we decide not to have GRgetcomptype.  The fact that
4603     grgetcomptype uses int32 for comp_type makes it not a good long term option
4604     due to inconsistency in the library.  Mar 11, 2011 -BMR
4605 
4606     Update:
4607     GRgetcomptype is now used in place of grgetcomptype and in hdp to detect
4608     and report IMCOMP compression, in release 4.2.8.  Jul 11, 2012 -BMR
4609 
4610  EXAMPLES
4611  REVISION LOG
4612 
4613 --------------------------------------------------------------------------*/
GRgetcomptype(int32 riid,comp_coder_t * comp_type)4614 intn GRgetcomptype(int32 riid, comp_coder_t* comp_type)
4615 {
4616     CONSTR(FUNC, "GRgetcomptype");  /* for HGOTO_ERROR */
4617     ri_info_t *ri_ptr;            /* ptr to the image to work with */
4618     int32 file_id;
4619     uint16 scheme;  /* compression scheme used for old images */
4620     intn  ret_value = SUCCEED;
4621 
4622     /* clear error */
4623     HEclear();
4624 
4625     /* Validate the RI ID */
4626     if (HAatom_group(riid) != RIIDGROUP)
4627         HGOTO_ERROR(DFE_ARGS, FAIL);
4628 
4629     /* Check the output argument */
4630     if (comp_type == NULL)
4631         HGOTO_ERROR(DFE_ARGS, FAIL);
4632 
4633     /* Locate RI's object in hash table */
4634     if (NULL == (ri_ptr = (ri_info_t *) HAatom_object(riid)))
4635         HGOTO_ERROR(DFE_BADPTR, FAIL);
4636 
4637     file_id = ri_ptr->gr_ptr->hdf_file_id;  /* temporary use */
4638 
4639     /* Handle old compression schemes separately */
4640     scheme = ri_ptr->img_dim.comp_tag;
4641     if (scheme == DFTAG_JPEG5 || scheme == DFTAG_GREYJPEG5
4642             || scheme==DFTAG_JPEG || scheme==DFTAG_GREYJPEG)
4643     {
4644         *comp_type = COMP_CODE_JPEG;
4645     }
4646     else if (scheme == DFTAG_RLE)
4647         *comp_type = COMP_CODE_RLE;
4648     else if (scheme == DFTAG_IMC || scheme == DFTAG_IMCOMP)
4649         *comp_type = COMP_CODE_IMCOMP;
4650 
4651     /* Use lower-level routine to get the new compression type */
4652     else
4653     {
4654         comp_coder_t temp_comp_type = COMP_CODE_INVALID;
4655         ret_value = HCPgetcomptype(file_id, ri_ptr->img_tag, ri_ptr->img_ref,
4656                                 &temp_comp_type);
4657         if (ret_value == FAIL)
4658             HGOTO_ERROR(DFE_INTERNAL, FAIL);
4659         *comp_type = temp_comp_type;
4660     }
4661 done:
4662   if(ret_value == 0)
4663     { /* Error condition cleanup */
4664     } /* end if */
4665   /* Normal function cleanup */
4666   return ret_value;
4667 } /* end GRgetcomptype() */
4668 
4669 /*--------------------------------------------------------------------------
4670  NAME
4671     GRgetcompinfo
4672 
4673  PURPOSE
4674     Get the compression information of a raster image's data.
4675 
4676  USAGE
4677     intn GRgetcompinfo(riid,comp_type,cinfo)
4678         int32 riid;       IN: RI ID from GRselect/GRcreate
4679         comp_coder_t* comp_type;   OUT: type of compression
4680         comp_info* cinfo;     OUT: retrieved compression information
4681 
4682  RETURNS
4683     SUCCEED/FAIL
4684 
4685  DESCRIPTION
4686     This routine gets the compression type of the given RI's data, then
4687     retrieves the appropriate information into the provided compression
4688     info structure.
4689 
4690  GLOBAL VARIABLES
4691  COMMENTS, BUGS, ASSUMPTIONS
4692     JPEG information is currently not retrievable because the JPEG
4693     parameters, 'quality' and 'force_baseline', are irreversibly
4694     mapped to a quantization table.  Thus, only the correct compression
4695     type will be returned; cinfo will only contain 0s.
4696 
4697  EXAMPLES
4698  REVISION LOG
4699     July 2001: Added to fix bug #307 - BMR (from GRgetcompress)
4700     Apr 2005:  This function was actually created at this time, but it is
4701                almost a duplicate of GRgetcompress, which is intended to be
4702                removed in the future, due to its incorrect behavior.  The
4703                only difference is the call to the low-level routine,
4704                HCPgetcompinfo, instead of HCPgetcompress.
4705 
4706 --------------------------------------------------------------------------*/
GRgetcompinfo(int32 riid,comp_coder_t * comp_type,comp_info * cinfo)4707 intn GRgetcompinfo(int32 riid, comp_coder_t* comp_type, comp_info* cinfo)
4708 {
4709     CONSTR(FUNC, "GRgetcompinfo");  /* for HGOTO_ERROR */
4710     ri_info_t *ri_ptr;            /* ptr to the image to work with */
4711     int32 file_id;
4712     uint16 scheme;  /* compression scheme used for JPEG images */
4713     intn  ret_value = SUCCEED;
4714 
4715     /* clear error stack and check validity of args */
4716     HEclear();
4717 
4718     /* check the validity of the RI ID */
4719     if (HAatom_group(riid) != RIIDGROUP)
4720         HGOTO_ERROR(DFE_ARGS, FAIL);
4721 
4722     /* and check the output arguments */
4723     if (comp_type == NULL || cinfo == NULL)
4724         HGOTO_ERROR(DFE_ARGS, FAIL);
4725 
4726     /* locate RI's object in hash table */
4727     if (NULL == (ri_ptr = (ri_info_t *) HAatom_object(riid)))
4728         HGOTO_ERROR(DFE_BADPTR, FAIL);
4729 
4730     file_id = ri_ptr->gr_ptr->hdf_file_id;  /* temporary use */
4731 
4732     /* If the compression scheme used was JPEG, return the compression type
4733        and 0 for the 'quality' and 'force_baseline' parameters, because
4734        these parameters are currently not possible to be retrieved. */
4735     scheme = ri_ptr->img_dim.comp_tag;
4736     if (scheme == DFTAG_JPEG5 || scheme == DFTAG_GREYJPEG5
4737             || scheme==DFTAG_JPEG || scheme==DFTAG_GREYJPEG)
4738     {
4739 	*comp_type = COMP_CODE_JPEG;
4740 	cinfo->jpeg.quality = 0;
4741 	cinfo->jpeg.force_baseline = 0;
4742     }
4743     /* Catch old images to avoid going into HCPgetcompinfo */
4744     else if (scheme == DFTAG_RLE) /* old image */
4745 	*comp_type = COMP_CODE_RLE;
4746     else if (scheme == DFTAG_IMC) /* old image */
4747         *comp_type = COMP_CODE_IMCOMP;
4748     else
4749     {
4750 	/* use lower-level routine to get the compression information */
4751 	ret_value = HCPgetcompinfo(file_id, ri_ptr->img_tag, ri_ptr->img_ref,
4752                                 comp_type, cinfo);
4753 	if (ret_value == FAIL)
4754 	    HGOTO_ERROR(DFE_INTERNAL, FAIL);
4755     }
4756 
4757 done:
4758   if(ret_value == 0)
4759     { /* Error condition cleanup */
4760 
4761     } /* end if */
4762 
4763   /* Normal function cleanup */
4764   return ret_value;
4765 } /* end GRgetcompinfo() */
4766 
4767 /*--------------------------------------------------------------------------
4768  NAME
4769     GRsetattr
4770 
4771  PURPOSE
4772     Write an attribute for an object.
4773 
4774  USAGE
4775     intn GRsetattr(dimid|riid|grid,name,attr_nt,count,data)
4776         int32 dimid|riid|grid;  IN: DIM|RI|GR ID
4777         char *name;             IN: name of attribute
4778         int32 attr_nt;          IN: number-type of attribute
4779         int32 count;            IN: number of entries of the attribute
4780         void * data;             IN: attribute data to write
4781 
4782  RETURNS
4783     SUCCEED/FAIL
4784 
4785  DESCRIPTION
4786     Write an attribute for an object (function will figure out ID type).
4787 
4788  GLOBAL VARIABLES
4789  COMMENTS, BUGS, ASSUMPTIONS
4790     Currently does not allow changing NT of an existing attribute.
4791 
4792  EXAMPLES
4793  REVISION LOG
4794 --------------------------------------------------------------------------*/
GRsetattr(int32 id,const char * name,int32 attr_nt,int32 count,const void * data)4795 intn GRsetattr(int32 id,const char *name,int32 attr_nt,int32 count,const void * data)
4796 {
4797     CONSTR(FUNC, "GRsetattr");   /* for HERROR */
4798     int32 hdf_file_id;          /* HDF file ID from Hopen */
4799     gr_info_t *gr_ptr;          /* ptr to the GR information for this grid */
4800     ri_info_t *ri_ptr=NULL;     /* ptr to the image to work with */
4801     void * *t;                   /* temp. ptr to the image found */
4802     TBBT_TREE *search_tree;     /* attribute tree to search through */
4803     at_info_t *at_ptr=NULL;     /* ptr to the attribute to work with */
4804     int32 at_size;              /* size in bytes of the attribute data */
4805     int32 *update_count;        /* pointer to the count of attributes in a tree */
4806     uintn *update_flag;         /* pointer to the flag to indicate an attribute tree is changed */
4807     uintn found=FALSE;          /* boolean for indicating the attribute exists already */
4808     intn is_riid=FALSE;         /* whether we had a RIID */
4809     intn ret_value = SUCCEED;
4810 
4811     /* clear error stack and check validity of args */
4812     HEclear();
4813 
4814     /* Make sure that count is less than MAX_ORDER(Vdata)
4815            and total size is less than MAX_FIELD_SIZE(Vdata) */
4816     if ((count > MAX_ORDER) ||
4817         ((count * DFKNTsize(attr_nt)) > MAX_FIELD_SIZE))
4818         HGOTO_ERROR(DFE_ARGS, FAIL);
4819 
4820     /* check the validity of the args */
4821     if ((HAatom_group(id)!=RIIDGROUP && HAatom_group(id)!=GRIDGROUP) || data==NULL || name==NULL
4822             || count<=0 || DFKNTsize(attr_nt)==FAIL)
4823         HGOTO_ERROR(DFE_ARGS, FAIL);
4824 
4825     if (HAatom_group(id)==GRIDGROUP)
4826       {
4827           /* locate GR's object in hash table */
4828           if (NULL == (gr_ptr = (gr_info_t *) HAatom_object(id)))
4829               HGOTO_ERROR(DFE_GRNOTFOUND, FAIL);
4830 
4831           hdf_file_id=gr_ptr->hdf_file_id;
4832           search_tree=gr_ptr->gattree;
4833           update_flag=&(gr_ptr->gattr_modified);
4834           update_count=&(gr_ptr->gattr_count);
4835       } /* end if */
4836     else if (HAatom_group(id)==RIIDGROUP)
4837       {
4838           /* Need this flag for later */
4839           is_riid=TRUE;
4840 
4841           /* locate RI's object in hash table */
4842           if (NULL == (ri_ptr = (ri_info_t *) HAatom_object(id)))
4843               HGOTO_ERROR(DFE_RINOTFOUND, FAIL);
4844           gr_ptr=ri_ptr->gr_ptr;
4845 
4846           hdf_file_id=gr_ptr->hdf_file_id;
4847           search_tree=ri_ptr->lattree;
4848           update_flag=&(ri_ptr->attr_modified);
4849           update_count=&(ri_ptr->lattr_count);
4850       } /* end if */
4851     else    /* shouldn't get here, but what the heck... */
4852         HGOTO_ERROR(DFE_ARGS, FAIL);
4853 
4854     /* Search for an attribute with the same name */
4855     if((t = (void **)tbbtfirst((TBBT_NODE *)*search_tree))!=NULL)
4856       {
4857           do {
4858               at_ptr=(at_info_t *)*t;
4859               if(at_ptr!=NULL && HDstrcmp(at_ptr->name,name)==0)  /* ie. the name matches */
4860                 {
4861                     found=TRUE;
4862                     break;
4863                 } /* end if */
4864           } while((t= (void **)tbbtnext((TBBT_NODE *)t))!=NULL);
4865       } /* end if */
4866 
4867     if(found==TRUE) /* attribute already exists, just update it */
4868       {
4869           int32 new_at_size;          /* size in bytes of the new attribute data */
4870 
4871           /* Catch the user if he tries to change the NT */
4872           if(attr_nt!=at_ptr->nt)
4873               HGOTO_ERROR(DFE_ARGS, FAIL);
4874 
4875           /* Calc. old & new attr. sizes */
4876           new_at_size=count*DFKNTsize((attr_nt | DFNT_NATIVE) & (~DFNT_LITEND));
4877           at_size=at_ptr->len*DFKNTsize((at_ptr->nt | DFNT_NATIVE) & (~DFNT_LITEND));
4878 
4879           if((uint32)new_at_size>gr_ptr->attr_cache)    /* check if data is cacheable */
4880             {   /* not cacheable, write directly out to disk and throw away old in-memory copy */
4881                 int32 AttrID;       /* attribute Vdata id */
4882 
4883                 /* Update data on disk */
4884                 if((AttrID=VSattach(hdf_file_id,(int32)at_ptr->ref,"w"))==FAIL)
4885                     HGOTO_ERROR(DFE_CANTATTACH,FAIL);
4886                 if(VSsetfields(AttrID,at_ptr->name)==FAIL)
4887                   {
4888                     VSdetach(AttrID);
4889                     HGOTO_ERROR(DFE_BADFIELDS,FAIL);
4890                   } /* end if */
4891                 if(VSwrite(AttrID,data,count,FULL_INTERLACE)==FAIL)
4892                   {
4893                     VSdetach(AttrID);
4894                     HGOTO_ERROR(DFE_VSWRITE,FAIL);
4895                   } /* end if */
4896                 if(VSdetach(AttrID)==FAIL)
4897                     HGOTO_ERROR(DFE_CANTDETACH,FAIL);
4898 
4899                 /* Update in-memory fields */
4900                 at_ptr->len=count;
4901                 at_ptr->data_modified=FALSE;
4902 
4903                 /* Toss the old data, it's not valid and it's un-cacheable now */
4904                 if(at_ptr->data!=NULL)
4905                     HDfreenclear(at_ptr->data);
4906             }  /* end if */
4907           else
4908             {
4909                 /* check if we need a bigger buffer */
4910                 if(new_at_size>at_size || at_ptr->data==NULL)
4911                   {
4912                       if(at_ptr->data!=NULL)
4913                           HDfree(at_ptr->data);
4914                       if((at_ptr->data=HDmalloc(new_at_size))==NULL)
4915                           HGOTO_ERROR(DFE_NOSPACE,FAIL);
4916                   } /* end if */
4917                 HDmemcpy(at_ptr->data,data,new_at_size);
4918 
4919                 /* Update in-memory fields */
4920                 at_ptr->len=count;
4921                 at_ptr->data_modified=TRUE;
4922                 *update_flag=TRUE;  /* flag the tree as changed */
4923             } /* end else */
4924       } /* end if */
4925     else    /* a new attribute */
4926       {
4927         if((at_ptr=(at_info_t *)HDmalloc(sizeof(at_info_t)))==NULL)
4928             HGOTO_ERROR(DFE_NOSPACE,FAIL);
4929 
4930         /* Fill in fields for the new attribute */
4931         at_ptr->index=*update_count;  /* get the index and update the tree's count */
4932         at_ptr->nt=attr_nt;
4933         at_ptr->len=count;
4934 
4935         /* allocate space for the attribute name & copy it */
4936         if((at_ptr->name=(char *)HDmalloc(HDstrlen(name)+1))==NULL)
4937             HGOTO_ERROR(DFE_NOSPACE,FAIL);
4938         HDstrcpy(at_ptr->name,name);
4939 
4940         /* calc. the attr size to see if it is worth caching */
4941         at_size=at_ptr->len*DFKNTsize((at_ptr->nt | DFNT_NATIVE) & (~DFNT_LITEND));
4942         if((uint32)at_size<gr_ptr->attr_cache)
4943           { /* cacheable */
4944               /* allocate space for the attribute name & copy it */
4945               if((at_ptr->data=(char *)HDmalloc(at_size))==NULL)
4946                   HGOTO_ERROR(DFE_NOSPACE,FAIL);
4947               HDmemcpy(at_ptr->data,data,at_size);
4948               at_ptr->data_modified=TRUE;
4949               at_ptr->ref=DFREF_WILDCARD;
4950           } /* end if */
4951         else
4952           { /* non-cacheable */
4953               if((at_ptr->ref=(uint16)VHstoredata(hdf_file_id,at_ptr->name,data,
4954                       at_ptr->len,at_ptr->nt,RIGATTRNAME,RIGATTRCLASS))==(uint16)FAIL)
4955                   HGOTO_ERROR(DFE_VSCANTCREATE,FAIL);
4956               at_ptr->data=NULL;
4957               at_ptr->data_modified=FALSE;
4958           } /* end else */
4959         at_ptr->new_at=TRUE;
4960 
4961         /* Add the attribute to the attribute tree */
4962         if(tbbtdins(search_tree, at_ptr, NULL)==NULL)
4963             HGOTO_ERROR(DFE_TBBTINS,FAIL);
4964 
4965         /* flag the attribute tree as being modified */
4966         *update_flag=TRUE;
4967         (*update_count)++;  /* get the index and update the tree's count */
4968       } /* end else */
4969 
4970     /* set this flag also, if we set local attributes */
4971     if(is_riid==TRUE)
4972       {
4973         if(found==FALSE)    /* when adding new attributes, make certain the RI gets updated */
4974             ri_ptr->meta_modified=TRUE;
4975         gr_ptr->gr_modified=TRUE;
4976       } /* end if */
4977 
4978 done:
4979   if(ret_value == 0)
4980     { /* Error condition cleanup */
4981 
4982     } /* end if */
4983 
4984   /* Normal function cleanup */
4985   return ret_value;
4986 } /* end GRsetattr() */
4987 
4988 /*--------------------------------------------------------------------------
4989  NAME
4990     GRattrinfo
4991 
4992  PURPOSE
4993     Get attribute information for an object.
4994 
4995  USAGE
4996     intn GRattrinfo(dimid|riid|grid,index,name,attr_nt,count)
4997         int32 dimid|riid|grid;  IN: DIM|RI|GR ID
4998         int32 index;            IN: index of the attribute for info
4999         char *name;             OUT: name of attribute
5000         int32 attr_nt;          OUT: number-type of attribute
5001         int32 count;            OUT: number of entries of the attribute
5002 
5003  RETURNS
5004     SUCCEED/FAIL
5005 
5006  DESCRIPTION
5007     Get attribute information for an object.
5008 
5009  GLOBAL VARIABLES
5010  COMMENTS, BUGS, ASSUMPTIONS
5011  EXAMPLES
5012  REVISION LOG
5013 --------------------------------------------------------------------------*/
GRattrinfo(int32 id,int32 index,char * name,int32 * attr_nt,int32 * count)5014 intn GRattrinfo(int32 id,int32 index,char *name,int32 *attr_nt,int32 *count)
5015 {
5016     CONSTR(FUNC, "GRattrinfo");   /* for HERROR */
5017     gr_info_t *gr_ptr;          /* ptr to the GR information for this grid */
5018     ri_info_t *ri_ptr;          /* ptr to the image to work with */
5019     void * *t;                   /* temp. ptr to the image found */
5020     TBBT_TREE *search_tree;     /* attribute tree to search through */
5021     at_info_t *at_ptr;          /* ptr to the attribute to work with */
5022     intn   ret_value = SUCCEED;
5023 
5024     /* clear error stack and check validity of args */
5025     HEclear();
5026 
5027     /* check the validity of the ID, the index is checked below */
5028     if (HAatom_group(id)!=RIIDGROUP && HAatom_group(id)!=GRIDGROUP)
5029         HGOTO_ERROR(DFE_ARGS, FAIL);
5030 
5031     if (HAatom_group(id)==GRIDGROUP)
5032       {
5033           /* locate GR's object in hash table */
5034           if (NULL == (gr_ptr = (gr_info_t *) HAatom_object(id)))
5035               HGOTO_ERROR(DFE_GRNOTFOUND, FAIL);
5036 
5037           if(index<0 || index>=gr_ptr->gattr_count)
5038               HGOTO_ERROR(DFE_ARGS, FAIL);
5039 
5040           search_tree=gr_ptr->gattree;
5041       } /* end if */
5042     else if (HAatom_group(id)==RIIDGROUP)
5043       {
5044           /* locate RI's object in hash table */
5045           if (NULL == (ri_ptr = (ri_info_t *) HAatom_object(id)))
5046               HGOTO_ERROR(DFE_RINOTFOUND, FAIL);
5047 
5048           if(index<0 || index>=ri_ptr->lattr_count)
5049               HGOTO_ERROR(DFE_ARGS, FAIL);
5050           search_tree=ri_ptr->lattree;
5051       } /* end if */
5052     else    /* shouldn't get here, but what the heck... */
5053         HGOTO_ERROR(DFE_ARGS, FAIL);
5054 
5055     if((t = (void **)tbbtdfind(search_tree, &index, NULL))==NULL)
5056         HGOTO_ERROR(DFE_RINOTFOUND,FAIL);
5057     at_ptr=(at_info_t *)*t;
5058 
5059     if(name!=NULL)
5060         HDstrcpy(name,at_ptr->name);
5061     if(attr_nt!=NULL)
5062         *attr_nt=at_ptr->nt;
5063     if(count!=NULL)
5064         *count=at_ptr->len;
5065 
5066 done:
5067   if(ret_value == 0)
5068     { /* Error condition cleanup */
5069 
5070     } /* end if */
5071 
5072   /* Normal function cleanup */
5073   return ret_value;
5074 } /* end GRattrinfo() */
5075 
5076 /*--------------------------------------------------------------------------
5077  NAME
5078     GRgetattr
5079 
5080  PURPOSE
5081     Read an attribute for an object.
5082 
5083  USAGE
5084     intn GRgetattr(dimid|riid|grid,index,data)
5085         int32 dimid|riid|grid;  IN: DIM|RI|GR ID
5086         int32 index;            IN: index of the attribute for info
5087         void * data;             OUT: data read for attribute
5088 
5089  RETURNS
5090     SUCCEED/FAIL
5091 
5092  DESCRIPTION
5093     Read an attribute for an object.
5094 
5095  GLOBAL VARIABLES
5096  COMMENTS, BUGS, ASSUMPTIONS
5097  EXAMPLES
5098  REVISION LOG
5099 --------------------------------------------------------------------------*/
GRgetattr(int32 id,int32 index,void * data)5100 intn GRgetattr(int32 id,int32 index,void * data)
5101 {
5102     CONSTR(FUNC, "GRgetattr");   /* for HERROR */
5103     int32 hdf_file_id;          /* HDF file ID from Hopen */
5104     gr_info_t *gr_ptr;          /* ptr to the GR information for this grid */
5105     ri_info_t *ri_ptr;          /* ptr to the image to work with */
5106     void * *t;                   /* temp. ptr to the image found */
5107     TBBT_TREE *search_tree;     /* attribute tree to search through */
5108     at_info_t *at_ptr;          /* ptr to the attribute to work with */
5109     int32 at_size;              /* size in bytes of the attribute data */
5110     intn  ret_value = SUCCEED;
5111 
5112     /* clear error stack and check validity of args */
5113     HEclear();
5114 
5115     /* check the validity of the ID & data ptr, the index is checked below */
5116     if ((HAatom_group(id)!=RIIDGROUP && HAatom_group(id)!=GRIDGROUP) || data==NULL)
5117         HGOTO_ERROR(DFE_ARGS, FAIL);
5118 
5119     if (HAatom_group(id)==GRIDGROUP)
5120       {
5121           /* locate GR's object in hash table */
5122           if (NULL == (gr_ptr = (gr_info_t *) HAatom_object(id)))
5123               HGOTO_ERROR(DFE_GRNOTFOUND, FAIL);
5124 
5125           if(index<0 || index>=gr_ptr->gattr_count)
5126               HGOTO_ERROR(DFE_ARGS, FAIL);
5127 
5128           search_tree=gr_ptr->gattree;
5129       } /* end if */
5130     else if (HAatom_group(id)==RIIDGROUP)
5131       {
5132           /* locate RI's object in hash table */
5133           if (NULL == (ri_ptr = (ri_info_t *) HAatom_object(id)))
5134               HGOTO_ERROR(DFE_RINOTFOUND, FAIL);
5135           gr_ptr=ri_ptr->gr_ptr;
5136 
5137           if(index<0 || index>=ri_ptr->lattr_count)
5138               HGOTO_ERROR(DFE_ARGS, FAIL);
5139 
5140           search_tree=ri_ptr->lattree;
5141       } /* end if */
5142     else    /* shouldn't get here, but what the heck... */
5143         HGOTO_ERROR(DFE_ARGS, FAIL);
5144 
5145     hdf_file_id=gr_ptr->hdf_file_id;
5146     if((t = (void **)tbbtdfind(search_tree, &index, NULL))==NULL)
5147         HGOTO_ERROR(DFE_RINOTFOUND,FAIL);
5148     at_ptr=(at_info_t *)*t;
5149 
5150     /* Calculate the size of the attribute data */
5151     at_size=at_ptr->len*DFKNTsize((at_ptr->nt | DFNT_NATIVE) & (~DFNT_LITEND));
5152 
5153     /* Check if the attribute has been read in yet, and get it if not */
5154     if(at_ptr->data==NULL)
5155       {
5156         int32 AttrID;       /* attribute Vdata id */
5157 
5158         /* Grab some memory for the attribute data */
5159         if((at_ptr->data=HDmalloc(at_size))==NULL)
5160             HGOTO_ERROR(DFE_NOSPACE,FAIL);
5161 
5162         if((AttrID=VSattach(hdf_file_id,(int32)at_ptr->ref,"r"))==FAIL)
5163             HGOTO_ERROR(DFE_CANTATTACH,FAIL);
5164         if(VSsetfields(AttrID,at_ptr->name)==FAIL)
5165           {
5166             VSdetach(AttrID);
5167             HGOTO_ERROR(DFE_BADFIELDS,FAIL);
5168           } /* end if */
5169         if(VSread(AttrID,at_ptr->data,at_ptr->len,FULL_INTERLACE)==FAIL)
5170           {
5171             VSdetach(AttrID);
5172             HGOTO_ERROR(DFE_VSWRITE,FAIL);
5173           } /* end if */
5174         if(VSdetach(AttrID)==FAIL)
5175             HGOTO_ERROR(DFE_CANTDETACH,FAIL);
5176       } /* end if */
5177 
5178     /* Copy the attribute into the user's buffer */
5179     HDmemcpy(data,at_ptr->data,at_size);
5180 
5181     /* If the attribute is too large to keep in memory, chuck it again */
5182     if((uint32)at_size>gr_ptr->attr_cache)
5183         HDfreenclear(at_ptr->data);
5184 
5185 done:
5186   if(ret_value == 0)
5187     { /* Error condition cleanup */
5188 
5189     } /* end if */
5190 
5191   /* Normal function cleanup */
5192   return ret_value;
5193 } /* end GRgetattr() */
5194 
5195 /*--------------------------------------------------------------------------
5196  NAME
5197     GRfindattr
5198 
5199  PURPOSE
5200     Get the index of an attribute with a given name for an object.
5201 
5202  USAGE
5203     int32 GRfindattr(int32 dimid|riid|grid,char *name)
5204         int32 dimid|riid|grid;  IN: DIM|RI|GR ID
5205         char *name;             IN: name of attribute to search for
5206 
5207  RETURNS
5208     Valid index for an attribute on success, FAIL on failure
5209 
5210  DESCRIPTION
5211     Get the index of an attribute with a given name for an object.
5212 
5213  GLOBAL VARIABLES
5214  COMMENTS, BUGS, ASSUMPTIONS
5215  EXAMPLES
5216  REVISION LOG
5217 --------------------------------------------------------------------------*/
GRfindattr(int32 id,const char * name)5218 int32 GRfindattr(int32 id,const char *name)
5219 {
5220     CONSTR(FUNC, "GRfindattr");   /* for HERROR */
5221     gr_info_t *gr_ptr;          /* ptr to the GR information for this grid */
5222     ri_info_t *ri_ptr;          /* ptr to the image to work with */
5223     void * *t;                   /* temp. ptr to the image found */
5224     TBBT_TREE *search_tree;     /* attribute tree to search through */
5225     at_info_t *at_ptr;          /* ptr to the attribute to work with */
5226     int32 ret_value = SUCCEED;
5227 
5228     /* clear error stack and check validity of args */
5229     HEclear();
5230 
5231     /* check the validity of the RI ID */
5232     if (HAatom_group(id)!=RIIDGROUP && HAatom_group(id)!=GRIDGROUP)
5233         HGOTO_ERROR(DFE_ARGS, FAIL);
5234 
5235     if (HAatom_group(id)==GRIDGROUP)
5236       {
5237           /* locate GR's object in hash table */
5238           if (NULL == (gr_ptr = (gr_info_t *) HAatom_object(id)))
5239               HGOTO_ERROR(DFE_GRNOTFOUND, FAIL);
5240 
5241           search_tree=gr_ptr->gattree;
5242       } /* end if */
5243     else if (HAatom_group(id)==RIIDGROUP)
5244       {
5245           /* locate RI's object in hash table */
5246           if (NULL == (ri_ptr = (ri_info_t *) HAatom_object(id)))
5247               HGOTO_ERROR(DFE_RINOTFOUND, FAIL);
5248 
5249           search_tree=ri_ptr->lattree;
5250       } /* end if */
5251     else    /* shouldn't get here, but what the heck... */
5252         HGOTO_ERROR(DFE_ARGS, FAIL);
5253 
5254     if((t = (void **)tbbtfirst((TBBT_NODE *)*search_tree))==NULL)
5255         HGOTO_ERROR(DFE_RINOTFOUND,FAIL);
5256     do {
5257         at_ptr=(at_info_t *)*t;
5258         if(at_ptr!=NULL && HDstrcmp(at_ptr->name,name)==0)  /* ie. the name matches */
5259             HGOTO_DONE(at_ptr->index);
5260     } while((t= (void **)tbbtnext((TBBT_NODE *)t))!=NULL);
5261 
5262     ret_value = (FAIL);
5263 
5264 done:
5265   if(ret_value == 0)
5266     { /* Error condition cleanup */
5267 
5268     } /* end if */
5269 
5270   /* Normal function cleanup */
5271   return ret_value;
5272 } /* end GRfindattr() */
5273 
5274 /*--------------------------------------------------------------------------
5275  NAME
5276     GRIstart
5277  PURPOSE
5278     GR-level initialization routine
5279  USAGE
5280     intn GRIstart()
5281  RETURNS
5282     Returns SUCCEED/FAIL
5283  DESCRIPTION
5284     Register the shut-down routine (GRPshutdown) for call with atexit
5285  GLOBAL VARIABLES
5286  COMMENTS, BUGS, ASSUMPTIONS
5287  EXAMPLES
5288  REVISION LOG
5289 --------------------------------------------------------------------------*/
GRIstart(void)5290 PRIVATE intn GRIstart(void)
5291 {
5292     CONSTR(FUNC, "GRIstart");    /* for HERROR */
5293     intn        ret_value = SUCCEED;
5294 
5295     /* Don't call this routine again... */
5296     library_terminate = TRUE;
5297 
5298     /* Install atexit() library cleanup routine */
5299     if (HPregister_term_func(&GRPshutdown) != 0)
5300       HGOTO_ERROR(DFE_CANTINIT, FAIL);
5301 
5302 done:
5303   if(ret_value == FAIL)
5304     { /* Error condition cleanup */
5305 
5306     } /* end if */
5307 
5308   /* Normal function cleanup */
5309 
5310     return(ret_value);
5311 } /* end GRIstart() */
5312 
5313 /*--------------------------------------------------------------------------
5314  NAME
5315     GRIgetaid
5316  PURPOSE
5317     Internal routine to make certain an image has an AID attached to it.
5318  USAGE
5319     intn GRIgetaid(img_ptr, acc_perm)
5320         ri_info_t *img_ptr;         IN: pointer to the image info for the
5321                                         image to access.
5322         intn acc_perm;              IN: method of access desired.
5323  RETURNS
5324     SUCCEED/FAIL
5325 
5326  DESCRIPTION
5327     Attach an AID to the image's in-memory structures, in order to better
5328     manage I/O.  If the prior method of access for the image's AID was read
5329     and write permission, then the previous AID is closed and reopened for
5330     both read & write permission.
5331 
5332  GLOBAL VARIABLES
5333  COMMENTS, BUGS, ASSUMPTIONS
5334  EXAMPLES
5335  REVISION LOG
5336 --------------------------------------------------------------------------*/
GRIgetaid(ri_info_t * ri_ptr,intn acc_perm)5337 PRIVATE intn GRIgetaid(ri_info_t *ri_ptr, intn acc_perm)
5338 {
5339     CONSTR(FUNC, "GRIgetaid");  /* for HERROR */
5340     int32 hdf_file_id;          /* HDF file ID */
5341     gr_info_t *gr_ptr;          /* ptr to the file GR information for this image */
5342     model_info minfo;           /* Dummy modeling information structure */
5343     intn  ret_value = SUCCEED;
5344 
5345     HEclear();
5346     if (ri_ptr==NULL)
5347         HGOTO_ERROR(DFE_ARGS, FAIL);
5348 
5349     /* initialize important values */
5350     gr_ptr=ri_ptr->gr_ptr;
5351     hdf_file_id=gr_ptr->hdf_file_id;
5352 
5353     /* everybody gets read permission */
5354     acc_perm|=DFACC_READ;
5355 
5356     /* Test if the tag/ref pair has been assigned yet */
5357     if(ri_ptr->img_tag==DFTAG_NULL || ri_ptr->img_ref==DFREF_WILDCARD)
5358       {
5359 
5360         if(ri_ptr->use_cr_drvr)
5361             ri_ptr->img_tag=DFTAG_CI;
5362         else
5363             ri_ptr->img_tag=DFTAG_RI;
5364         ri_ptr->img_ref=Htagnewref(hdf_file_id,ri_ptr->img_tag);
5365       } /* end if */
5366 
5367     /* Check if we need to increase the access permissions asked for */
5368     if(ri_ptr->comp_img || (ri_ptr->img_aid!=0 && (acc_perm&DFACC_WRITE)!=0 && (ri_ptr->acc_perm&DFACC_WRITE)==0))
5369       {
5370         /* Close the old AID (which only had read permission) */
5371         Hendaccess(ri_ptr->img_aid);
5372         ri_ptr->img_aid=0;
5373       } /* end if */
5374 
5375     /* Check if we are the first to open the AID */
5376     if(ri_ptr->img_aid==0)
5377       {
5378         /* Go get the AID */
5379         if(ri_ptr->comp_img)
5380           { /* Need to create the compressed data element */
5381             if((ri_ptr->img_aid=HCcreate(hdf_file_id,ri_ptr->img_tag,ri_ptr->img_ref,COMP_MODEL_STDIO,&minfo,ri_ptr->comp_type,&(ri_ptr->cinfo)))==FAIL)
5382                 HGOTO_ERROR(DFE_BADAID,FAIL);
5383             ri_ptr->comp_img=0;     /* reset the compression flag */
5384           } /* end if */
5385         else
5386           { /* Check for old-style compressed raster or just open normally */
5387             if(ri_ptr->use_cr_drvr)
5388               { /* Use compressed raster driver */
5389                 uintn pixel_size;        /* size of a pixel on disk */
5390 
5391 
5392                 pixel_size=(uintn)(ri_ptr->img_dim.ncomps*DFKNTsize(ri_ptr->img_dim.nt));
5393 
5394 /* BMR: HRPconvert made access_rec->special = SPECIAL_COMPRAS */
5395                 if((ri_ptr->img_aid=HRPconvert(hdf_file_id,ri_ptr->img_tag,
5396                     ri_ptr->img_ref,ri_ptr->img_dim.xdim,ri_ptr->img_dim.ydim,
5397                     ri_ptr->img_dim.comp_tag,&(ri_ptr->cinfo),pixel_size))==FAIL)
5398                     HGOTO_ERROR(DFE_BADAID,FAIL);
5399               } /* end if */
5400             else
5401               { /* Use regular startaccess to create element */
5402                 if((ri_ptr->img_aid=Hstartaccess(hdf_file_id,ri_ptr->img_tag,ri_ptr->img_ref,acc_perm))==FAIL)
5403                     HGOTO_ERROR(DFE_BADAID,FAIL);
5404               } /* end else */
5405           } /* end else */
5406         if(ri_ptr->use_buf_drvr)
5407           { /* Convert to buffered special element if needed */
5408             if(HBconvert(ri_ptr->img_aid)==FAIL)
5409                 HGOTO_ERROR(DFE_CANTINIT,FAIL);
5410           } /* end if */
5411         ri_ptr->acc_perm=acc_perm;
5412       } /* end if */
5413 
5414 done:
5415   if(ret_value == FAIL)
5416     { /* Error condition cleanup */
5417         ri_ptr->img_aid=0;
5418     } /* end if */
5419 
5420   /* Normal function cleanup */
5421 
5422   return ret_value;
5423 } /* end GRIgetaid() */
5424 
5425 /*--------------------------------------------------------------------------
5426  NAME
5427     GRPshutdown
5428  PURPOSE
5429     Terminate various static buffers.
5430  USAGE
5431     intn GRPshutdown()
5432  RETURNS
5433     Returns SUCCEED/FAIL
5434  DESCRIPTION
5435     Free various buffers allocated in the GR routines.
5436  GLOBAL VARIABLES
5437  COMMENTS, BUGS, ASSUMPTIONS
5438     Should only ever be called by the "atexit" function HDFend
5439  EXAMPLES
5440  REVISION LOG
5441 --------------------------------------------------------------------------*/
GRPshutdown(void)5442 intn GRPshutdown(void)
5443 {
5444     if(gr_tree!=NULL)
5445       {
5446           /* Free the vfile tree */
5447           tbbtdfree(gr_tree, GRIgrdestroynode, NULL);
5448 
5449           /* Destroy the atom groups for GRs and RIs */
5450           HAdestroy_group(GRIDGROUP);
5451           HAdestroy_group(RIIDGROUP);
5452 
5453           gr_tree=NULL;
5454       } /* end if */
5455     return(SUCCEED);
5456 } /* end GRPshutdown() */
5457 
5458 
5459 
5460 /*====================== Chunking Routines ================================*/
5461 
5462 /* Debugging */
5463 /* #define CHK_DEBUG */
5464 
5465 /* NOTE: the definition of the union HDF_CHUNK_DEF can be found in hproto.h */
5466 
5467 /******************************************************************************
5468  NAME
5469       GRsetchunk  -- make GR a chunked GR
5470 
5471  DESCRIPTION
5472       This routine makes the GR a chunked GR according to the chunk
5473       definiton passed in.
5474 
5475       The image currently cannot be special already.  i.e. NBIT,
5476       COMPRESSED, or EXTERNAL. This is an Error.
5477 
5478       The defintion of the HDF_CHUNK_DEF union with relvant fields is:
5479 
5480       typedef union hdf_chunk_def_u
5481       {
5482          int32   chunk_lengths[2];  Chunk lengths along each dimension
5483 
5484          struct
5485           {
5486             int32     chunk_lengths[2]; Chunk lengths along each dimension
5487             int32     comp_type;                   Compression type
5488             comp_info cinfo;                       Compression info struct
5489           }comp;
5490 
5491       } HDF_CHUNK_DEF
5492 
5493       The variable agruement 'flags' is a bit-or'd value which can currently be
5494       'HDF_CHUNK' or 'HDF_CHUNK | HDF_COMP'.
5495 
5496       The simplist is the 'chunk_lengths' array specifiying chunk
5497       lengths for each dimension where the 'flags' argument set to
5498       'HDF_CHUNK';
5499 
5500       COMPRESSION is set by using the 'HDF_CHUNK_DEF' union to set the
5501       appropriate compression information along with the required chunk lengths
5502       for each dimension. The compression information is the same as
5503       that set in 'GRsetcompress()'. The bit-or'd 'flags' argument' is set to
5504       'HDF_CHUNK | HDF_COMP'.
5505 
5506       See the example in pseudo-C below for further usage.
5507 
5508       The maximum number of Chunks in an HDF file is 65,535.
5509 
5510       The performance of the GRxxx interface with chunking is greatly
5511       affected by the users access pattern over the image and by
5512       the maximum number of chunks set in the chunk cache. The cache contains
5513       the Least Recently Used(LRU cache replacment policy) chunks. See the
5514       routine GRsetchunkcache() for further info on the chunk cache and how
5515       to set the maximum number of chunks in the chunk cache. A default chunk
5516       cache is always created.
5517 
5518       The following example shows the organization of chunks for a 2D array.
5519       e.g. 4x4 array with 2x2 chunks. The array shows the layout of
5520            chunks in the chunk array.
5521 
5522             4 ---------------------
5523               |         |         |
5524         Y     |  (0,1)  |  (1,1)  |
5525         ^     |         |         |
5526         |   2 ---------------------
5527         |     |         |         |
5528         |     |  (0,0)  |  (1,0)  |
5529         |     |         |         |
5530         |     ---------------------
5531         |     0         2         4
5532         ---------------> X
5533 
5534         --Without compression--:
5535         {
5536         HDF_CHUNK_DEF chunk_def;
5537 
5538         .......
5539         -- Set chunk lengths --
5540         chunk_def.chunk_lengths[0]= 2;
5541         chunk_def.chunk_lengths[1]= 2;
5542 
5543         -- Set Chunking --
5544         GRsetchunk(riid, chunk_def, HDF_CHUNK);
5545          ......
5546         }
5547 
5548         --With compression--:
5549         {
5550         HDF_CHUNK_DEF chunk_def;
5551 
5552         .......
5553         -- Set chunk lengths first --
5554         chunk_def.chunk_lengths[0]= 2;
5555         chunk_def.chunk_lengths[1]= 2;
5556 
5557         -- Set compression --
5558         chunk_def.comp.cinfo.deflate.level = 9;
5559         chunk_def.comp.comp_type = COMP_CODE_DEFLATE;
5560 
5561         -- Set Chunking with Compression --
5562         GRsetchunk(riid, chunk_def, HDF_CHUNK | HDF_COMP);
5563          ......
5564         }
5565 
5566         NOTE:
5567            This routine directly calls a Special Chunked Element fcn HMCxxx.
5568 
5569  RETURNS
5570         SUCCEED/FAIL
5571 
5572  AUTHOR
5573         -GeorgeV
5574 ******************************************************************************/
5575 intn
GRsetchunk(int32 riid,HDF_CHUNK_DEF chunk_def,int32 flags)5576 GRsetchunk(int32 riid,              /* IN: raster access id */
5577            HDF_CHUNK_DEF chunk_def, /* IN: chunk definition */
5578            int32 flags              /* IN: flags */)
5579 {
5580     CONSTR(FUNC, "GRsetchunk");
5581     ri_info_t     *ri_ptr = NULL;    /* ptr to the image to work with */
5582     HCHUNK_DEF     chunk[1];         /* H-level chunk defintion */
5583     HDF_CHUNK_DEF *cdef   = NULL;    /* GR Chunk definition */
5584     model_info minfo;                /* dummy model info struct */
5585     comp_info  cinfo;                /* compression info - NBIT */
5586     int32      *cdims    = NULL;     /* array of chunk lengths */
5587     uintn      pixel_mem_size;       /* size of a pixel in memory */
5588     uintn      pixel_disk_size;      /* size of a pixel on disk */
5589     void *      fill_pixel = NULL;    /* converted value for the filled pixel */
5590     int32      at_index;             /* attribute index for the fill value */
5591     uint32     comp_config;
5592     int32      ndims    = 0;         /* # dimensions i.e. rank */
5593     uint8      nlevels  = 1;         /* default # levels is 1 */
5594     intn       i;                    /* loop variable */
5595     int32      hdf_file_id;          /* HDF file ID */
5596     gr_info_t *gr_ptr;               /* ptr to the file GR information for this image */
5597     intn       ret_value = SUCCEED;  /* return value */
5598 
5599 
5600 #ifdef CHK_DEBUG
5601     fprintf(stderr,"GRsetchunk: called  \n");
5602 #endif
5603     /* clear error stack and check validity of args */
5604     HEclear();
5605 
5606     memset(chunk,0,sizeof(chunk[0]));
5607     /* Check some args */
5608 
5609     /* check the validity of the RI ID */
5610     if (HAatom_group(riid)!=RIIDGROUP)
5611         HGOTO_ERROR(DFE_ARGS, FAIL);
5612 
5613     /* locate RI's object in hash table */
5614     if (NULL == (ri_ptr = (ri_info_t *) HAatom_object(riid)))
5615         HGOTO_ERROR(DFE_RINOTFOUND, FAIL);
5616 
5617     /* initialize important values */
5618     gr_ptr = ri_ptr->gr_ptr;
5619     hdf_file_id = gr_ptr->hdf_file_id;
5620 
5621     /* Test if the tag/ref pair has been assigned yet
5622        Note that HMCcreate() needs to do the Hstartaccess on
5623        the special tag/ref pair that is created. If another
5624        GRxx routine does it then the special element cannot be
5625        created. Special elements require 'lazy' DD creation. */
5626     if(ri_ptr->img_tag == DFTAG_NULL || ri_ptr->img_ref == DFREF_WILDCARD)
5627       {
5628         ri_ptr->img_tag = DFTAG_RI;
5629         ri_ptr->img_ref = Htagnewref(hdf_file_id,ri_ptr->img_tag);
5630       } /* end if */
5631 
5632 #ifdef CHK_DEBUG
5633     fprintf(stderr,"GRsetchunk: ri_ptr->img_aid=%d  \n",ri_ptr->img_aid);
5634 #endif
5635 
5636     /* Decide type of defintion passed in  */
5637     switch (flags)
5638       {
5639       case HDF_CHUNK: /* case where chunk_def only has chunk lengths */
5640           cdef  = (HDF_CHUNK_DEF *)&chunk_def;
5641           cdims = cdef->chunk_lengths;
5642           chunk[0].chunk_flag = 0;  /* nothing set for this now */
5643           chunk[0].comp_type = COMP_CODE_NONE; /* nothing set */
5644           chunk[0].model_type = COMP_MODEL_STDIO; /* Default */
5645           chunk[0].cinfo = &cinfo; /* dummy */
5646           chunk[0].minfo = &minfo; /* dummy */
5647           break;
5648       case (HDF_CHUNK | HDF_COMP):
5649     /*  EIP 9/12/03
5650      *  We have to take special care if SZIP library is not available;
5651      *  Fow all other compression types do
5652      */
5653           cdef  = (HDF_CHUNK_DEF *)&chunk_def;
5654 
5655     /* Check that the compression encoder is available */
5656     HCget_config_info((comp_coder_t )(cdef->comp.comp_type), &comp_config);
5657     if ((comp_config & (COMP_DECODER_ENABLED|COMP_ENCODER_ENABLED)) == 0) {
5658     /* coder not present?? */
5659               HGOTO_ERROR(DFE_BADCODER,FAIL);
5660     }
5661     if ((comp_config & COMP_ENCODER_ENABLED) == 0) {
5662     /* encoder not present?? */
5663               HGOTO_ERROR(DFE_NOENCODER,FAIL);
5664     }
5665           cdims = cdef->comp.chunk_lengths;
5666           chunk[0].chunk_flag = SPECIAL_COMP;  /* Compression */
5667           chunk[0].comp_type  = (comp_coder_t)cdef->comp.comp_type;
5668           chunk[0].model_type = COMP_MODEL_STDIO; /* Default */
5669           chunk[0].minfo = &minfo; /* dummy */
5670 
5671     if ((comp_coder_t)cdef->comp.comp_type != COMP_CODE_SZIP) {
5672               chunk[0].cinfo = &cdef->comp.cinfo;
5673     }
5674     else
5675 #ifdef H4_HAVE_LIBSZ          /* we have the library */
5676           {
5677             HDmemcpy(&cinfo,&(cdef->comp.cinfo),sizeof(comp_info));
5678         if (GRsetup_szip_parms(ri_ptr, &cinfo, cdims) == FAIL)
5679                   HGOTO_ERROR(DFE_INTERNAL,FAIL);
5680               chunk[0].cinfo = &cinfo;
5681     }
5682 #else                         /* we do not have the SZIP library */
5683           {
5684         HGOTO_ERROR(DFE_NOSZLIB, FAIL);
5685           }
5686 #endif /* H4_HAVE_LIBSZ */
5687           break;
5688       case (HDF_CHUNK | HDF_NBIT): /* don't support NBIT for GRs */
5689     HGOTO_ERROR(DFE_UNSUPPORTED, FAIL);
5690       default:
5691     HGOTO_ERROR(DFE_BADSCHEME, FAIL);
5692       } /* end switch */
5693 
5694     /* Now start setting chunk info */
5695     ndims = 2; /* set number of dims i.e. rank
5696                   for Rasters it is 2 */
5697 
5698     /* allocate space for chunk dimensions */
5699     if ((chunk[0].pdims = (DIM_DEF *)HDmalloc(ndims*sizeof(DIM_DEF))) == NULL)
5700         HGOTO_ERROR(DFE_NOSPACE,FAIL);
5701 
5702     /* initialize image/chunk sizes using CHUNK defintion structure */
5703     chunk[0].chunk_size = 1;
5704     chunk[0].num_dims = ndims;
5705     for (i = 0; i < ndims; i++)
5706       {   /* get dimension length from shape arrays */
5707           if ( i == 0) /* X */
5708               chunk[0].pdims[i].dim_length = ri_ptr->img_dim.xdim;
5709           else /* Y */
5710               chunk[0].pdims[i].dim_length = ri_ptr->img_dim.ydim;
5711 
5712           /* set chunk lengths */
5713           if (cdims[i] >= 1)
5714               chunk[0].pdims[i].chunk_length = cdims[i];
5715           else
5716             { /* chunk length is less than 1 */
5717                 ret_value = FAIL;
5718                 goto done;
5719             }
5720 #ifdef CHK_DEBUG
5721     fprintf(stderr,"GRsetchunk: cdims[%d]=%d \n",i,cdims[i]);
5722     fflush(stderr);
5723 #endif
5724           /* Data distribution along dimensions
5725           *  Check dimension length agains chunk length */
5726           if (i == 0) /* X */
5727             {
5728                 if (cdims[i] == ri_ptr->img_dim.xdim)
5729                     chunk[0].pdims[i].distrib_type = 0;     /* NONE */
5730                 else
5731                     chunk[0].pdims[i].distrib_type = 1;     /* BLOCK */
5732             }
5733           else /* Y */
5734             {
5735                 if (cdims[i] == ri_ptr->img_dim.ydim)
5736                     chunk[0].pdims[i].distrib_type = 0;     /* NONE */
5737                 else
5738                     chunk[0].pdims[i].distrib_type = 1;     /* BLOCK */
5739             }
5740 
5741           /* compute chunk size */
5742           chunk[0].chunk_size *= cdims[i];
5743       } /* end for ndims */
5744 
5745     /* Get the size of the pixels in memory and on disk */
5746     pixel_mem_size  = (uintn)(ri_ptr->img_dim.ncomps*DFKNTsize((ri_ptr->img_dim.nt | DFNT_NATIVE) & (~DFNT_LITEND)));
5747     pixel_disk_size = (uintn)(ri_ptr->img_dim.ncomps*DFKNTsize(ri_ptr->img_dim.nt));
5748 
5749     /* Set number type size i.e. size of data type
5750        number of components times the number type */
5751     chunk[0].nt_size = ri_ptr->img_dim.ncomps*DFKNTsize(ri_ptr->img_dim.nt);
5752 
5753 #ifdef CHK_DEBUG
5754     fprintf(stderr,"GRsetchunk: datatype size =%d\n",
5755             ri_ptr->img_dim.ncomps*DFKNTsize(ri_ptr->img_dim.nt));
5756     fflush(stderr);
5757 #endif
5758 
5759     /* allocate space for fill pixel */
5760     if((fill_pixel = HDmalloc(pixel_disk_size)) == NULL)
5761         HGOTO_ERROR(DFE_NOSPACE,FAIL);
5762 
5763     /* create correct disk version of fill pixel */
5764     if(ri_ptr->fill_value != NULL)
5765       {
5766           if (FAIL == DFKconvert(ri_ptr->fill_value,fill_pixel,
5767                                  ri_ptr->img_dim.nt,ri_ptr->img_dim.ncomps,
5768                                  DFACC_WRITE,0,0))
5769               HGOTO_ERROR(DFE_INTERNAL,FAIL);
5770       } /* end if */
5771     else  /* create default pixel fill value of all zero components */
5772       {
5773           /* Try to find a fill value attribute */
5774           if((at_index = GRfindattr(riid,FILL_ATTR)) != FAIL)
5775             { /* Found a fill value attribute */
5776                 if((ri_ptr->fill_value = HDmalloc(pixel_mem_size)) == NULL)
5777                     HGOTO_ERROR(DFE_NOSPACE,FAIL);
5778                 if(GRgetattr(riid,at_index,ri_ptr->fill_value) == FAIL)
5779                     HGOTO_ERROR(DFE_BADATTR,FAIL);
5780                 if (FAIL == DFKconvert(ri_ptr->fill_value,fill_pixel,
5781                                        ri_ptr->img_dim.nt,ri_ptr->img_dim.ncomps,
5782                                        DFACC_WRITE,0,0))
5783                     HGOTO_ERROR(DFE_INTERNAL,FAIL);
5784             } /* end if */
5785           else
5786               HDmemset(fill_pixel,0,pixel_disk_size);
5787       } /* end else */
5788 
5789 #ifdef CHK_DEBUG
5790     fprintf(stderr,"GRsetchunk: get ready to create\n");
5791     fprintf(stderr,"GRsetchunk: img_tag=%d, img_ref=%d\n",
5792             ri_ptr->img_tag, ri_ptr->img_ref);
5793 #endif
5794 
5795     /* check to see already special.
5796        Error if already special since doubly special elements are
5797        not yet handled. HMCcreate should catch this....*/
5798     /* Create GR as chunked element  */
5799     ret_value = HMCcreate(hdf_file_id, /* HDF file handle */
5800                           (uint16)ri_ptr->img_tag,/* Data tag */
5801                           (uint16)ri_ptr->img_ref,/* Data ref */
5802                           nlevels,                /* nlevels */
5803                           pixel_disk_size,        /* fill value length */
5804                           (VOID *)fill_pixel,     /* fill value */
5805                           (HCHUNK_DEF *)chunk     /* chunk definition */);
5806 
5807 #ifdef CHK_DEBUG
5808     fprintf(stderr,"HMCcreate: ret_value =%d \n", ret_value);
5809 #endif
5810 
5811     /* check return */
5812     if(ret_value != FAIL)
5813       { /* close old aid and set new one
5814          ..hmm......this is for the doubly special hack */
5815           if((ri_ptr->img_aid != 0) && (ri_ptr->img_aid != FAIL))
5816             {
5817               if (FAIL == Hendaccess(ri_ptr->img_aid))
5818                   HGOTO_ERROR(DFE_INTERNAL,FAIL);
5819             }
5820 
5821           ri_ptr->img_aid = ret_value; /* set new access id */
5822           ret_value = SUCCEED; /* re-set to successful */
5823       } /* end if */
5824 
5825 #ifdef CHK_DEBUG
5826     fprintf(stderr,"GRsetchunk: ri_ptr->img_aid =%d \n", ri_ptr->img_aid);
5827 #endif
5828 
5829 done:
5830     if (ret_value == FAIL)
5831       { /* Failure cleanup */
5832 
5833       }
5834     /* Normal cleanup */
5835 
5836     /* free fill value */
5837     if (fill_pixel != NULL)
5838         HDfree(fill_pixel);
5839 
5840     /* free chunk dims */
5841     if (chunk[0].pdims != NULL)
5842         HDfree(chunk[0].pdims);
5843 
5844     return ret_value;
5845 } /* GRsetchunk */
5846 
5847 /******************************************************************************
5848  NAME
5849      GRgetchunkinfo -- get Info on GR
5850 
5851  DESCRIPTION
5852      This routine gets any special information on the GR. If its chunked,
5853      chunked and compressed or just a regular GR. Currently it will only
5854      fill the array of chunk lengths for each dimension as specified in
5855      the 'HDF_CHUNK_DEF' union. You can pass in a NULL for 'chunk_def'
5856      if don't want the chunk lengths for each dimension.
5857      If successfull it will return a bit-or'd value in 'flags' indicating
5858      if the GR is  chunked(HDF_CHUNK), chunked and compressed(HDF_CHUNK | HDF_COMP)
5859      or non-chunked(HDF_NONE).
5860 
5861      e.g. 4x4 array - Pseudo-C
5862      {
5863      HDF_CHUNK_DEF rchunk_def;
5864      int32   cflags;
5865      ...
5866      GRgetchunkinfo(riid, &rchunk_def, &cflags);
5867      ...
5868      }
5869 
5870  RETURNS
5871         SUCCEED/FAIL
5872 
5873  AUTHOR
5874         -GeorgeV
5875 ******************************************************************************/
5876 intn
GRgetchunkinfo(int32 riid,HDF_CHUNK_DEF * chunk_def,int32 * flags)5877 GRgetchunkinfo(int32 riid,               /* IN: sds access id */
5878                HDF_CHUNK_DEF *chunk_def, /* IN/OUT: chunk definition */
5879                int32 *flags              /* IN/OUT: flags */)
5880 {
5881     CONSTR(FUNC, "GRgetchunkinfo");
5882     ri_info_t      *ri_ptr = NULL;        /* ptr to the image to work with */
5883     sp_info_block_t info_block;           /* special info block */
5884     int16           special;              /* Special code */
5885     intn            i;                    /* loop variable */
5886     intn            ret_value = SUCCEED;  /* return value */
5887 
5888 
5889     /* clear error stack and check validity of args */
5890     HEclear();
5891 
5892     /* Check some args */
5893 
5894     /* check the validity of the RI ID */
5895     if (HAatom_group(riid)!=RIIDGROUP)
5896         HGOTO_ERROR(DFE_ARGS, FAIL);
5897 
5898     /* locate RI's object in hash table */
5899     if (NULL == (ri_ptr = (ri_info_t *) HAatom_object(riid)))
5900         HGOTO_ERROR(DFE_RINOTFOUND, FAIL);
5901 
5902     /* check if access id exists already */
5903     if(ri_ptr->img_aid == 0)
5904       {
5905           /* now get access id, use read access for now */
5906           if(GRIgetaid(ri_ptr,DFACC_READ)==FAIL)
5907               HGOTO_ERROR(DFE_INTERNAL,FAIL);
5908       }
5909     else if (ri_ptr->img_aid == FAIL)
5910         HGOTO_ERROR(DFE_INTERNAL,FAIL);
5911 
5912 #ifdef CHK_DEBUG
5913     fprintf(stderr,"%s: ri_ptr->img_aid =%d \n", FUNC, ri_ptr->img_aid);
5914 #endif
5915 
5916     /* inquire about element */
5917     ret_value = Hinquire(ri_ptr->img_aid, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &special);
5918     if (ret_value != FAIL)
5919       {   /* make sure it is chunked element */
5920           if (special == SPECIAL_CHUNKED)
5921             { /* get info about chunked element */
5922              if ((ret_value = HDget_special_info(ri_ptr->img_aid, &info_block)) != FAIL)
5923                {   /* Does user want chunk lengths back? */
5924                    if (chunk_def != NULL)
5925                      {
5926                          /* we assume user has allocat space for chunk lengths */
5927                          /* copy chunk lengths over */
5928                          for (i = 0; i < info_block.ndims; i++)
5929                            {
5930                                chunk_def->chunk_lengths[i] = info_block.cdims[i];
5931                            }
5932                      }
5933                    /* dont forget to free up info is special info block
5934                       This space was allocated by the library */
5935                    HDfree(info_block.cdims);
5936 
5937                    /* Check to see if compressed */
5938                    switch(info_block.comp_type)
5939                      {
5940                      case COMP_CODE_NONE:
5941                          *flags = HDF_CHUNK;
5942                          break;
5943                      case COMP_CODE_NBIT:
5944                          /* is this an error?
5945                             NBIT can't be set in GRsetchunk(). */
5946                          *flags = (HDF_CHUNK | HDF_NBIT);
5947                          break;
5948                      default:
5949                          *flags = (HDF_CHUNK | HDF_COMP);
5950                          break;
5951                      }
5952                }
5953             }
5954           else /* not special chunked element */
5955             {
5956               *flags = HDF_NONE; /* regular GR */
5957             }
5958       }
5959 
5960   done:
5961     if (ret_value == FAIL)
5962       { /* Failure cleanup */
5963 
5964       }
5965     /* Normal cleanup */
5966     return ret_value;
5967 } /* GRgetchunkinfo() */
5968 
5969 
5970 /******************************************************************************
5971  NAME
5972      GRwritechunk   -- write the specified chunk to the GR
5973 
5974  DESCRIPTION
5975      This routine writes a whole chunk of data to the chunked GR
5976      specified by chunk 'origin' for the given GR and can be used
5977      instead of GRwriteimage() when this information is known. This
5978      routine has less overhead and is much faster than using GRwriteimage().
5979 
5980      Origin specifies the co-ordinates of the chunk according to the chunk
5981      position in the overall chunk array.
5982 
5983      'datap' must point to a whole chunk of data.
5984 
5985      See GRsetchunk() for a description of the organization of chunks in an GR.
5986 
5987      NOTE:
5988            This routine directly calls a Special Chunked Element fcn HMCxxx.
5989 
5990  RETURNS
5991         SUCCEED/FAIL
5992 
5993  AUTHOR
5994        -GeorgeV
5995 ******************************************************************************/
5996 intn
GRwritechunk(int32 riid,int32 * origin,const VOID * datap)5997 GRwritechunk(int32 riid,       /* IN: access aid to GR */
5998              int32 *origin,    /* IN: origin of chunk to write */
5999              const VOID *datap /* IN: buffer for data */)
6000 {
6001     CONSTR(FUNC, "GRwritechunk");
6002     ri_info_t *ri_ptr = NULL;   /* ptr to the image to work with */
6003     uintn      pixel_mem_size,  /* size of a pixel in memory */
6004                pixel_disk_size; /* size of a pixel on disk */
6005     VOID      *img_data = NULL; /* buffer used for conversion */
6006     int16      special;         /* Special code */
6007     int32      csize;           /* phsical chunk size */
6008     sp_info_block_t info_block; /* special info block */
6009     uint32     byte_count;      /* bytes to write */
6010     int8       platnumsubclass; /* the machine type of the current platform */
6011     uintn      convert;         /* whether to convert or not */
6012     intn       i;
6013     uint16 scheme;  /* compression scheme used for JPEG images */
6014     uint32     comp_config;
6015     comp_coder_t comp_type;
6016     comp_info cinfo;
6017     intn       status=FAIL;
6018     intn       switch_interlace = FALSE;/* whether the memory interlace needs to be switched around */
6019     intn       ret_value = SUCCEED;
6020 
6021 
6022     /* clear error stack and check validity of args */
6023     HEclear();
6024 
6025     info_block.cdims = NULL;
6026 
6027     /* Check args */
6028     if (origin == NULL || datap == NULL)
6029       {
6030         ret_value = FAIL;
6031         goto done;
6032       }
6033 
6034     /* check the validity of the RI ID */
6035     if (HAatom_group(riid)!=RIIDGROUP)
6036         HGOTO_ERROR(DFE_ARGS, FAIL);
6037 
6038     /* locate RI's object in hash table */
6039     if (NULL == (ri_ptr = (ri_info_t *) HAatom_object(riid)))
6040         HGOTO_ERROR(DFE_RINOTFOUND, FAIL);
6041 
6042     /* check if access id exists already */
6043     if(ri_ptr->img_aid == 0)
6044       {
6045           /* now get access id, use write access */
6046           if(GRIgetaid(ri_ptr,DFACC_WRITE)==FAIL)
6047               HGOTO_ERROR(DFE_INTERNAL,FAIL);
6048       }
6049     else if (ri_ptr->img_aid == FAIL)
6050         HGOTO_ERROR(DFE_INTERNAL,FAIL);
6051 
6052 #ifdef CHK_DEBUG
6053     fprintf(stderr,"%s: ri_ptr->img_aid =%d \n", FUNC, ri_ptr->img_aid);
6054 #endif
6055     comp_type = COMP_CODE_NONE;
6056     scheme = ri_ptr->img_dim.comp_tag;
6057     if (scheme == DFTAG_JPEG5 || scheme == DFTAG_GREYJPEG5
6058             || scheme==DFTAG_JPEG || scheme==DFTAG_GREYJPEG)
6059     {
6060 	comp_type = COMP_CODE_JPEG;
6061 	cinfo.jpeg.quality = 0;
6062 	cinfo.jpeg.force_baseline = 0;
6063     }
6064     else if (scheme == DFTAG_IMC)
6065     { /* coder no longer supported */
6066         HGOTO_ERROR(DFE_BADCODER,FAIL);
6067     }
6068     else
6069     {
6070 	/* use lower-level routine to get the compression information */
6071 	status = HCPgetcompinfo(ri_ptr->gr_ptr->hdf_file_id,
6072                         ri_ptr->img_tag, ri_ptr->img_ref,
6073                         &comp_type, &cinfo);
6074 	if (status == FAIL)
6075             HGOTO_ERROR(DFE_INTERNAL,FAIL);
6076     }
6077     if (comp_type != COMP_CODE_NONE)
6078     {
6079         /* Check that the compression encoder is available */
6080         HCget_config_info(comp_type, &comp_config);
6081         if ((comp_config & (COMP_DECODER_ENABLED|COMP_ENCODER_ENABLED)) == 0) {
6082             /* coder not present?? */
6083              HGOTO_ERROR(DFE_BADCODER,FAIL);
6084         }
6085         if ((comp_config & COMP_ENCODER_ENABLED) == 0) {
6086             /* encoder not present?? */
6087              HGOTO_ERROR(DFE_NOENCODER,FAIL);
6088         }
6089     }
6090 
6091    /* inquire about element */
6092     ret_value = Hinquire(ri_ptr->img_aid, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &special);
6093     if (ret_value != FAIL)
6094       {
6095           if (special == SPECIAL_CHUNKED)
6096             {  /* yes */
6097 
6098                 /* get info about chunked element */
6099                 if ((ret_value = HDget_special_info(ri_ptr->img_aid, &info_block)) != FAIL)
6100                   {
6101                       /* calculate chunk size  */
6102                       csize = 1;
6103                       for (i = 0; i < info_block.ndims; i++)
6104                           csize *= info_block.cdims[i];
6105 
6106                       /* Get the size of the pixels in memory and on disk */
6107                       pixel_mem_size  =(uintn)(ri_ptr->img_dim.ncomps*DFKNTsize((ri_ptr->img_dim.nt | DFNT_NATIVE) & (~DFNT_LITEND)));
6108                       pixel_disk_size =(uintn)(ri_ptr->img_dim.ncomps*DFKNTsize(ri_ptr->img_dim.nt));
6109 
6110                       /* adjust for data type size */
6111                       /* csize *= pixel_mem_size; */
6112                       byte_count = csize * pixel_mem_size;
6113 
6114                       /* figure out if data needs to be converted */
6115                       /* Get number-type and conversion information */
6116                       if (FAIL == (platnumsubclass = DFKgetPNSC(ri_ptr->img_dim.nt & (~DFNT_LITEND), DF_MT)))
6117                           HGOTO_ERROR(DFE_INTERNAL,FAIL);
6118                      convert = (ri_ptr->img_dim.file_nt_subclass != platnumsubclass) ||
6119                               (pixel_mem_size != pixel_disk_size);  /* is conversion necessary? */
6120 
6121                       /* check interlace */
6122                       if(ri_ptr->img_dim.il != MFGR_INTERLACE_PIXEL)
6123                           switch_interlace=TRUE;
6124 
6125                       /* convert if necessary */
6126                       if(convert || switch_interlace == TRUE)
6127                         {
6128                             /* Allocate space for the conversion buffer */
6129                             if((img_data = HDmalloc(pixel_disk_size*csize)) == NULL)
6130                                 HGOTO_ERROR(DFE_NOSPACE,FAIL);
6131 
6132                             if(switch_interlace == TRUE)
6133                               {
6134                                   void * pixel_buf;  /* buffer for the pixel interlaced data */
6135 
6136                                   /* Allocate space for the conversion buffer */
6137                                   if((pixel_buf = HDmalloc(pixel_mem_size*csize)) == NULL)
6138                                       HGOTO_ERROR(DFE_NOSPACE,FAIL);
6139 
6140                                   if (FAIL == GRIil_convert((VOID *)datap,ri_ptr->img_dim.il,pixel_buf,MFGR_INTERLACE_PIXEL,
6141                                                             info_block.cdims,ri_ptr->img_dim.ncomps,ri_ptr->img_dim.nt))
6142                                       HGOTO_ERROR(DFE_INTERNAL,FAIL);
6143 
6144                                   /* convert the pixel data into the HDF disk format */
6145                                   if (FAIL == DFKconvert(pixel_buf,img_data,ri_ptr->img_dim.nt,
6146                                                          ri_ptr->img_dim.ncomps*csize,DFACC_WRITE,0,0))
6147                                       HGOTO_ERROR(DFE_INTERNAL,FAIL);
6148 
6149                                   HDfree(pixel_buf);
6150                               } /* end if */
6151                             else /* convert the pixel data into the HDF disk format */
6152                               {
6153                                   if (FAIL == DFKconvert((VOID *)datap,img_data,ri_ptr->img_dim.nt,
6154                                                          ri_ptr->img_dim.ncomps*csize,DFACC_WRITE,0,0))
6155                                       HGOTO_ERROR(DFE_INTERNAL,FAIL);
6156                               }
6157                           /* Write chunk out, */
6158                           if ((ret_value = HMCwriteChunk(ri_ptr->img_aid, origin, img_data)) != FAIL)
6159                               ret_value = SUCCEED;
6160                         }
6161                       else { /* no conversion necessary, just use the user's buffer */
6162                           /* Write chunk out, */
6163                           if ((ret_value = HMCwriteChunk(ri_ptr->img_aid, origin, datap)) != FAIL)
6164                               ret_value = SUCCEED;
6165                       } /* end else */
6166                   } /* end if get special info block */
6167             }
6168           else /* not special CHUNKED */
6169               ret_value = FAIL;
6170       } /* end if Hinquire */
6171 
6172   done:
6173     if (ret_value == FAIL)
6174       { /* Failure cleanup */
6175 
6176       }
6177     /* Normal cleanup */
6178     /* dont forget to free up info is special info block
6179        This space was allocated by the library */
6180     if (info_block.cdims != NULL)
6181         HDfree(info_block.cdims);
6182 
6183     /* free conversion buffers if we created them */
6184     if (img_data != NULL)
6185         HDfree(img_data);
6186 
6187     return ret_value;
6188 } /* GRwritechunk() */
6189 
6190 /******************************************************************************
6191  NAME
6192      GRreadchunk   -- read the specified chunk to the GR
6193 
6194  DESCRIPTION
6195      This routine reads a whole chunk of data from the chunked GR
6196      specified by chunk 'origin' for the given GR and can be used
6197      instead of GRreaddata() when this information is known. This
6198      routine has less overhead and is much faster than using GRreaddata().
6199 
6200      Origin specifies the co-ordinates of the chunk according to the chunk
6201      position in the overall chunk array.
6202 
6203      'datap' must point to a whole chunk of data.
6204 
6205      See GRsetchunk() for a description of the organization of chunks in an GR.
6206 
6207      NOTE:
6208          This routine directly calls a Special Chunked Element fcn HMCxxx.
6209 
6210  RETURNS
6211         SUCCEED/FAIL
6212 
6213  AUTHOR
6214        -GeorgeV
6215 ******************************************************************************/
6216 intn
GRreadchunk(int32 riid,int32 * origin,VOID * datap)6217 GRreadchunk(int32 riid,    /* IN: access aid to GR */
6218             int32 *origin, /* IN: origin of chunk to write */
6219             VOID *datap    /* IN/OUT: buffer for data */)
6220 {
6221     CONSTR(FUNC, "GRreadchunk");
6222     ri_info_t *ri_ptr = NULL;   /* ptr to the image to work with */
6223     uintn      pixel_mem_size;  /* size of a pixel in memory */
6224     uintn      pixel_disk_size; /* size of a pixel on disk */
6225     VOID      *img_data = NULL; /* buffer used for conversion */
6226     int16      special;         /* Special code */
6227     int32      csize;           /* phsical chunk size */
6228     sp_info_block_t info_block; /* special info block */
6229     uint32     byte_count;      /* bytes to read */
6230     int8       platnumsubclass; /* the machine type of the current platform */
6231     uintn      convert;         /* whether to convert or not */
6232     intn       i;
6233     uint16 scheme;  /* compression scheme used for JPEG images */
6234     uint32     comp_config;
6235     comp_coder_t comp_type;
6236     comp_info cinfo;
6237     intn       status=FAIL;
6238     intn       switch_interlace = FALSE;/* whether the memory interlace needs to be switched around */
6239     intn       ret_value = SUCCEED;
6240 
6241 
6242     /* clear error stack and check validity of args */
6243     HEclear();
6244 
6245     info_block.cdims = NULL;
6246 
6247     /* Check args */
6248     if (origin == NULL || datap == NULL)
6249       {
6250         ret_value = FAIL;
6251         goto done;
6252       }
6253 
6254     /* check the validity of the RI ID */
6255     if (HAatom_group(riid)!=RIIDGROUP)
6256         HGOTO_ERROR(DFE_ARGS, FAIL);
6257 
6258     /* locate RI's object in hash table */
6259     if (NULL == (ri_ptr = (ri_info_t *) HAatom_object(riid)))
6260         HGOTO_ERROR(DFE_RINOTFOUND, FAIL);
6261 
6262     /* check if access id exists already */
6263     if(ri_ptr->img_aid == 0)
6264       {
6265           /* now get access id, use write access */
6266           if(GRIgetaid(ri_ptr,DFACC_WRITE)==FAIL)
6267               HGOTO_ERROR(DFE_INTERNAL,FAIL);
6268       }
6269     else if (ri_ptr->img_aid == FAIL)
6270         HGOTO_ERROR(DFE_INTERNAL,FAIL);
6271 
6272 #ifdef CHK_DEBUG
6273     fprintf(stderr,"%s: ri_ptr->img_aid =%d \n", FUNC, ri_ptr->img_aid);
6274 #endif
6275 
6276     comp_type = COMP_CODE_NONE;
6277     scheme = ri_ptr->img_dim.comp_tag;
6278     if (scheme == DFTAG_JPEG5 || scheme == DFTAG_GREYJPEG5
6279             || scheme==DFTAG_JPEG || scheme==DFTAG_GREYJPEG)
6280     {
6281 	comp_type = COMP_CODE_JPEG;
6282 	cinfo.jpeg.quality = 0;
6283 	cinfo.jpeg.force_baseline = 0;
6284     }
6285     /* Catch old images to avoid going into HCPgetcompinfo.  Note: I don't
6286        think old images have chunking, but just in case I'm wrong.  Should
6287        verify these later. -BMR, Jul 2012 */
6288     else if (scheme == DFTAG_RLE) /* old image */
6289 	comp_type = COMP_CODE_RLE;
6290     else if (scheme == DFTAG_IMC) /* old image */
6291         comp_type = COMP_CODE_IMCOMP;
6292     else
6293     {
6294 	/* use lower-level routine to get the compression information */
6295 	status = HCPgetcompinfo(ri_ptr->gr_ptr->hdf_file_id,
6296                         ri_ptr->img_tag, ri_ptr->img_ref,
6297                         &comp_type, &cinfo);
6298 	if (status == FAIL)
6299             HGOTO_ERROR(DFE_INTERNAL,FAIL);
6300     }
6301     if (comp_type != COMP_CODE_NONE &&
6302 	comp_type != COMP_CODE_RLE &&
6303 	comp_type != COMP_CODE_IMCOMP)
6304     {   /* BMR: this is reading, why do we need encoder? */
6305 	/* Check that the compression encoder is available */
6306 	HCget_config_info(comp_type, &comp_config);
6307 	if ((comp_config & (COMP_DECODER_ENABLED|COMP_ENCODER_ENABLED)) == 0) {
6308     /* coder not present?? */
6309          HGOTO_ERROR(DFE_BADCODER,FAIL);
6310       }
6311       if ((comp_config & COMP_DECODER_ENABLED) == 0) {
6312     /* decoder not present?? */
6313          HGOTO_ERROR(DFE_NOENCODER,FAIL);
6314       }
6315     }
6316     /* inquire about element */
6317     ret_value = Hinquire(ri_ptr->img_aid, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &special);
6318     if (ret_value != FAIL)
6319       {
6320           if (special == SPECIAL_CHUNKED)
6321             {  /* yes */
6322 
6323                 /* get info about chunked element */
6324                 if ((ret_value = HDget_special_info(ri_ptr->img_aid, &info_block)) != FAIL)
6325                   {
6326                       /* calcualte chunk size  */
6327                       csize = 1;
6328                       for (i = 0; i < info_block.ndims; i++)
6329                           csize *= info_block.cdims[i];
6330 
6331                       /* Get the size of the pixels in memory and on disk */
6332                       pixel_mem_size  =(uintn)(ri_ptr->img_dim.ncomps*DFKNTsize((ri_ptr->img_dim.nt | DFNT_NATIVE) & (~DFNT_LITEND)));
6333                       pixel_disk_size =(uintn)(ri_ptr->img_dim.ncomps*DFKNTsize(ri_ptr->img_dim.nt));
6334 
6335                       /* adjust for number type size */
6336                       /* csize *= pixel_mem_size; */
6337                       byte_count = csize * pixel_mem_size;
6338 
6339                       /* figure out if data needs to be converted */
6340                       /* Get number-type and conversion information */
6341                       if (FAIL ==(platnumsubclass = DFKgetPNSC(ri_ptr->img_dim.nt & (~DFNT_LITEND), DF_MT)))
6342                           HGOTO_ERROR(DFE_INTERNAL,FAIL);
6343                        convert = (ri_ptr->img_dim.file_nt_subclass != platnumsubclass)
6344                                  ||  (pixel_mem_size != pixel_disk_size);  /* is conversion necessary? */
6345 
6346                       /* check interlace */
6347                       if(ri_ptr->img_dim.il != MFGR_INTERLACE_PIXEL)
6348                           switch_interlace=TRUE;
6349 
6350                       /* read chunk in */
6351                       if(convert)
6352                         {
6353                             /* Allocate space for the conversion buffer */
6354                             if((img_data = HDmalloc(pixel_disk_size*csize)) == NULL)
6355                                 HGOTO_ERROR(DFE_NOSPACE,FAIL);
6356 
6357                             /* read it in */
6358                             if ((ret_value = HMCreadChunk(ri_ptr->img_aid, origin, img_data))
6359                                 != FAIL)
6360                                 {
6361                                     if (FAIL == DFKconvert(img_data,datap,ri_ptr->img_dim.nt,
6362                                                            ri_ptr->img_dim.ncomps*csize,DFACC_READ,0,0))
6363                                         HGOTO_ERROR(DFE_INTERNAL,FAIL);
6364 
6365                                     ret_value = SUCCEED;
6366                                 }
6367                         } /* end if */
6368                       else
6369                         {
6370                           if ((ret_value = HMCreadChunk(ri_ptr->img_aid, origin, datap))
6371                               != FAIL)
6372                               ret_value = SUCCEED;
6373                         }
6374 
6375                       /* Check whether we need to convert the buffer to the user's */
6376                       /*    requested interlace scheme. */
6377                       /* Note: This is implemented in a horribly ugly & slow manner, but I'm */
6378                       /*        in a bit of a hurry right now - QAK */
6379                       /* I took this code from GRwrite() and put it here - GV */
6380                       if(ri_ptr->im_il != MFGR_INTERLACE_PIXEL)
6381                         {
6382                             void * pixel_buf;  /* buffer for the pixel interlaced data */
6383 
6384                             /* Allocate space for the conversion buffer */
6385                             if((pixel_buf = HDmalloc(pixel_mem_size*csize)) == NULL)
6386                                 HGOTO_ERROR(DFE_NOSPACE,FAIL);
6387 
6388                             if (FAIL == GRIil_convert(datap,MFGR_INTERLACE_PIXEL,pixel_buf,ri_ptr->im_il,
6389                                                       info_block.cdims,ri_ptr->img_dim.ncomps,ri_ptr->img_dim.nt))
6390                                 HGOTO_ERROR(DFE_INTERNAL,FAIL);
6391 
6392                             HDmemcpy(datap,pixel_buf,pixel_mem_size*csize);
6393 
6394                             HDfree(pixel_buf);
6395                         } /* end if */
6396 
6397                   } /* end if get special info block */
6398             }
6399           else /* not special CHUNKED */
6400               ret_value = FAIL;
6401       } /* end if Hinquire */
6402 
6403   done:
6404     if (ret_value == FAIL)
6405       { /* Failure cleanup */
6406 
6407       }
6408     /* Normal cleanup */
6409     /* dont forget to free up info is special info block
6410        This space was allocated by the library */
6411     if (info_block.cdims != NULL)
6412         HDfree(info_block.cdims);
6413 
6414     /* free conversion buffers if any */
6415     if (img_data != NULL)
6416         HDfree(img_data);
6417 
6418     return ret_value;
6419 } /* GRreadchunk() */
6420 
6421 
6422 /******************************************************************************
6423 NAME
6424      GRsetchunkcache - maximum number of chunks to cache
6425 
6426 DESCRIPTION
6427      Set the maximum number of chunks to cache.
6428 
6429      The cache contains the Least Recently Used(LRU cache replacment policy)
6430      chunks. This routine allows the setting of maximum number of chunks that
6431      can be cached, 'maxcache'.
6432 
6433      The performance of the GRxxx interface with chunking is greatly
6434      affected by the users access pattern over the image and by
6435      the maximum number of chunks set in the chunk cache. The number chunks
6436      that can be set in the cache is process memory limited. It is a good
6437      idea to always set the maximum number of chunks in the cache as the
6438      default heuristic does not take into account the memory available for
6439      the application.
6440 
6441      By default when the GR is promoted to a chunked element the
6442      maximum number of chunks in the cache 'maxcache' is set to the number of
6443      chunks along the last dimension.
6444 
6445      The values set here affects the current GR object's caching behaviour.
6446 
6447      If the chunk cache is full and 'maxcache' is greater then the
6448      current 'maxcache' value, then the chunk cache is reset to the new
6449      'maxcache' value, else the chunk cache remains at the current
6450      'maxcache' value.
6451 
6452      If the chunk cache is not full, then the chunk cache is set to the
6453      new 'maxcache' value only if the new 'maxcache' value is greater than the
6454      current number of chunks in the cache.
6455 
6456      Use flags argument of 'HDF_CACHEALL' if the whole object is to be cached
6457      in memory, otherwise pass in zero(0). Currently you can only
6458      pass in zero.
6459 
6460      See GRsetchunk() for a description of the organization of chunks in an GR.
6461 
6462      NOTE:
6463           This routine directly calls a Special Chunked Element fcn HMCxxx.
6464 
6465 RETURNS
6466      Returns the 'maxcache' value for the chunk cache if successful
6467      and FAIL otherwise
6468 
6469 AUTHOR
6470       -GeorgeV
6471 ******************************************************************************/
6472 intn
GRsetchunkcache(int32 riid,int32 maxcache,int32 flags)6473 GRsetchunkcache(int32 riid,     /* IN: access aid to mess with */
6474                 int32 maxcache, /* IN: max number of chunks to cache */
6475                 int32 flags     /* IN: flags = 0, HDF_CACHEALL */)
6476 {
6477     CONSTR(FUNC, "GRsetchunkcache");
6478     ri_info_t *ri_ptr = NULL;        /* ptr to the image to work with */
6479     int16      special;              /* Special code */
6480     intn       ret_value = SUCCEED;
6481 
6482 
6483     /* clear error stack and check validity of args */
6484     HEclear();
6485 
6486     /* Check args */
6487     if (maxcache < 1 )
6488       {
6489         ret_value = FAIL;
6490         goto done;
6491       }
6492 
6493     if (flags != 0 && flags != HDF_CACHEALL)
6494       {
6495         ret_value = FAIL;
6496         goto done;
6497       }
6498 
6499     /* check the validity of the RI ID */
6500     if (HAatom_group(riid)!=RIIDGROUP)
6501         HGOTO_ERROR(DFE_ARGS, FAIL);
6502 
6503     /* locate RI's object in hash table */
6504     if (NULL == (ri_ptr = (ri_info_t *) HAatom_object(riid)))
6505         HGOTO_ERROR(DFE_RINOTFOUND, FAIL);
6506 
6507     /* check if access id exists already */
6508     if(ri_ptr->img_aid == 0)
6509       {
6510           /* now get access id, use write access */
6511           if(GRIgetaid(ri_ptr,DFACC_WRITE)==FAIL)
6512               HGOTO_ERROR(DFE_INTERNAL,FAIL);
6513       }
6514     else if (ri_ptr->img_aid == FAIL)
6515         HGOTO_ERROR(DFE_INTERNAL,FAIL);
6516 
6517 #ifdef CHK_DEBUG
6518     fprintf(stderr,"%s: ri_ptr->img_aid =%d \n", FUNC, ri_ptr->img_aid);
6519 #endif
6520 
6521     /* inquire about element */
6522     ret_value = Hinquire(ri_ptr->img_aid, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &special);
6523     if (ret_value != FAIL)
6524       {
6525           if (special == SPECIAL_CHUNKED) /* set cache*/
6526               ret_value = HMCsetMaxcache(ri_ptr->img_aid, maxcache, flags);
6527           else
6528               ret_value = FAIL;
6529       }
6530 
6531   done:
6532     if (ret_value == FAIL)
6533       { /* Failure cleanup */
6534 
6535       }
6536     /* Normal cleanup */
6537     return ret_value;
6538 } /* GRsetchunkcache() */
6539 
6540 
6541 /*---------------------------------------------------------------
6542 NAME
6543    GRmapped - Checks whether an RI is to be mapped (hmap project)
6544 
6545 USAGE
6546     intn GRmapped(riid, *tobe_mapped, *created_byGR)
6547         int32 riid;     IN: raster image ID
6548         intn *tobe_mapped;  IN: TRUE if the image should be mapped
6549   intn *created_byGR;  IN: TRUE if the image was created by GR API
6550 DESCRIPTION
6551    GRmapped checks if the given RI satisfies the following conditions:
6552    + being an 8-bit RI
6553    + having one component
6554    + being non-special or RLE compressed only, i.e., no other
6555         compressions, no chunking,...
6556 
6557    The function will set tobe_mapped to TRUE if the image satisfies the
6558    above conditions, and FALSE, otherwise.
6559 
6560    In addition, the function will set the flag name_generated to indicate
6561    whether the image has name that was generated by the library.  Old images
6562    (or images created with non-GR API) didn't have a name so the library
6563    would generate a name for it while reading in the file.
6564 
6565 RETURNS
6566    SUCCEED/FAIL
6567    Feb 24, 2011 -BMR
6568 
6569 MODIFICATION
6570    Mar 17, 2011: Changed the function from
6571   intn GR2bmapped(int32 riid), returning TRUE/FALSE/FAIL, to
6572   intn GR2bmapped(int32 riid, intn *tobe_mapped, intn *name_generated),
6573   returning SUCCEED/FAIL
6574 ----------------------------------------------------------------*/
6575 intn
GR2bmapped(int32 riid,intn * tobe_mapped,intn * name_generated)6576 GR2bmapped(int32 riid, intn *tobe_mapped, intn *name_generated)
6577 {
6578     CONSTR(FUNC, "GR2bmapped");
6579     ri_info_t *ri_ptr;          /* ptr to the image to work with */
6580     intn   should_map = FALSE;  /* TRUE if the image should be mapped */
6581     uint16 img_tag, img_ref;  /* shortcuts image's tag/ref */
6582     int32  ritype;    /* image's type */
6583     intn   special_type=0;  /* specialness of the image data */
6584     int32  file_id;    /* shortcut file id */
6585     intn   status;
6586     intn   ret_value = SUCCEED;
6587 
6588     /* Clear error stack */
6589     HEclear();
6590 
6591     /* Check the validity of the ID */
6592     if (HAatom_group(riid) != RIIDGROUP)
6593         HGOTO_ERROR(DFE_ARGS, FAIL);
6594 
6595     /* Locate RI's object in hash table */
6596     ri_ptr = (ri_info_t *) HAatom_object(riid);
6597     if (NULL == ri_ptr)
6598         HGOTO_ERROR(DFE_RINOTFOUND, FAIL);
6599 
6600     /* shortcuts */
6601     img_tag = ri_ptr->img_tag;
6602     img_ref = ri_ptr->img_ref;
6603     file_id = ri_ptr->gr_ptr->hdf_file_id;
6604 
6605     /* If the image has old image tag, then make sure it is either non-special
6606        or compressed with RLE only */
6607     if (img_tag == DFTAG_RI8 || img_tag == DFTAG_CI8)
6608     {
6609 	if (ri_ptr->img_dim.comp_tag == DFTAG_RLE ||
6610 	    ri_ptr->img_dim.comp_tag == DFTAG_NULL)
6611 	    should_map = TRUE;
6612     }
6613     /* If the image has new image tag, then make sure that it has 8-bit data
6614        and has no special storage except RLE compression before determining
6615        that it is mapped-able */
6616     else if (img_tag == DFTAG_RI || img_tag == DFTAG_CI)
6617     {
6618 	/* Get the image data's type */
6619 	status = GRgetiminfo(riid, NULL, NULL, &ritype, NULL, NULL, NULL);
6620 
6621 	/* If it is 8-bit, set flag to check further for special storage */
6622 	if (ritype == DFNT_UCHAR8 || ritype == DFNT_CHAR8 ||
6623 	    ritype == DFNT_UINT8 || ritype == DFNT_INT8)
6624 	{
6625 	    /* Also make sure it only has one component */
6626 	    if (ri_ptr->img_dim.ncomps ==1)
6627 	    {
6628 		/* Make sure no specialness or only with RLE compression */
6629 		comp_coder_t comp_type=COMP_CODE_NONE;
6630 		status = GRgetcomptype(riid, &comp_type);
6631 		if (comp_type == COMP_CODE_RLE || comp_type == COMP_CODE_NONE)
6632 		{
6633 		    special_type = GRIisspecial_type(file_id, img_tag, img_ref);
6634 		    /* In some cases, special_type = 0 for old image with RLE,
6635 		    although the image has newer image tag.  Added the check
6636 		    for 0 here, but this should be investigated more. -BMR*/
6637 		    if (special_type == SPECIAL_COMP || special_type == 0)
6638 			should_map = TRUE;
6639 		}
6640 	    }
6641 	}
6642     }
6643     /* Set flag to return */
6644     *tobe_mapped = should_map;
6645 
6646     /* Copy flag that indicates whether this image has name that was
6647        generated by library, and not given by application */
6648     *name_generated = ri_ptr->name_generated;
6649 
6650 done:
6651   if(ret_value == 0)
6652     { /* Error condition cleanup */
6653     } /* end if */
6654   /* Normal function cleanup */
6655   return ret_value;
6656 }   /* GR2bmapped */
6657 /*
6658 
6659 API functions to finish:
6660 
6661 Misc. stuff left to do:
6662     Deal with special elements for images.
6663     GRrename for images.
6664     GRsetflags to suppress writing fill data and to suppress fillvalue attr.
6665     Read/Write Interlaced data (of line & plane types, pixel is working).
6666 
6667 Features not supported:
6668     Add in full support for multiple palettes with each RI.
6669     Add in support for named palettes with each RI.
6670     Add in support for palettes with non-standard formats.
6671     Deletion of attributes or images (would require changing the way index
6672         numbers are handled)
6673 
6674 */
6675