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