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 /*LINTLIBRARY */
16 /* ------------------------------ hcompri.c -------------------------------
17
18 Routines for reading & writing old-style (i.e. non-special compressed)
19 compressed raster images, such as JPEG, (raster specific) RLE and IMCOMP.
20 These routines are designed to be layered underneath the buffered special
21 element code and only provide access to reading/writing the entire image
22 at once through the DFgetcomp/DFputcomp code.
23
24 File Organization
25 ******************
26 These special elements are invoked at run-time only, information about
27 whether an element was written/read through this interface is not stored in
28 the file. Unless specificly asked for by an API routine or required for a
29 particular kind of access by the library, these routines aren't called.
30
31 LOCAL ROUTINES
32
33 EXPORTED BUT LIBRARY PRIVATE ROUTINES
34 HRPcloseAID -- close object but keep AID active
35 HRPendacess -- close object, free AID
36 HRPinfo -- return info about a compressed raster element
37 HRPinquire -- retrieve information about a compressed raster element
38 HRPread -- read some data out of a compressed raster element
39 HRPreset -- replace the current comp. raster info with new info (NOP)
40 HRPseek -- set the seek position
41 HRPsetaccesstype -- set the I/O access type of the compressed raster element
42 HRPstread -- open an access record for reading
43 HRPstwrite -- open an access record for reading
44 HRPwrite -- write some data out to a compressed raster element
45 HRPconvert -- wrap access to a compress raster object
46
47 ------------------------------------------------------------------------- */
48
49 #include "hdf.h"
50 #include "hfile.h"
51 #include <assert.h>
52
53 /* crinfo_t -- compressed raster information structure */
54
55 typedef struct
56 {
57 intn attached; /* number of access records attached
58 to this information structure */
59 int32 fid; /* File ID of image */
60 uint16 tag, ref; /* Tag & ref of compressed raster image */
61 int32 xdim, ydim; /* Image dimensions */
62 int16 scheme; /* Compression scheme */
63 comp_info cinfo; /* Compression information */
64 uintn image_size; /* Size of the uncompressed image in memory */
65 }
66 crinfo_t;
67
68 /* forward declaration of the functions provided in this module */
69
70 /* cr_funcs -- table of the accessing functions of the compressed raster
71 data element function modules. The position of each function in
72 the table is standard */
73 funclist_t cr_funcs =
74 {
75 HRPstread,
76 HRPstwrite,
77 HRPseek,
78 HRPinquire,
79 HRPread,
80 HRPwrite,
81 HRPendaccess,
82 HRPinfo,
83 NULL /* no routine registered */
84 };
85
86 /*------------------------------------------------------------------------
87 NAME
88 HRPconvert -- wrap an existing raster image with the special element routines.
89 USAGE
90 intn HRPconvert(fid, tag, ref, xdim, ydim, scheme, cinfo, pixel_size)
91 int32 fid; IN: File ID for raster image
92 uint16 tag, ref; IN: Tag & Ref of raster image to wrap
93 int32 xdim, ydim; IN: Dimensions of raster image
94 int16 scheme; IN: Compression scheme used
95 comp_info *cinfo; IN: Additional compression parameters
96 uintn pixel_size; IN: Size of the pixels in the image
97 RETURNS
98 AID on SUCCEED/FAIL on failure
99 DESCRIPTION
100 Wraps an existing compressed raster image with the special element API.
101 This is designed only for use under a buffered special element.
102
103 FORTRAN
104 None
105
106 --------------------------------------------------------------------------*/
107 int32
HRPconvert(int32 fid,uint16 tag,uint16 ref,int32 xdim,int32 ydim,int16 scheme,comp_info * cinfo,uintn pixel_size)108 HRPconvert(int32 fid, uint16 tag, uint16 ref, int32 xdim, int32 ydim,int16 scheme, comp_info *cinfo, uintn pixel_size)
109 {
110 CONSTR(FUNC, "HRPconvert"); /* for HERROR */
111 filerec_t *file_rec; /* file record */
112 accrec_t *access_rec=NULL; /* access element record */
113 crinfo_t *info; /* information for the compressed raster element */
114 int32 ret_value = SUCCEED;
115
116 HEclear();
117
118 file_rec = HAatom_object(fid);
119 if (BADFREC(file_rec) || SPECIALTAG(tag))
120 HGOTO_ERROR(DFE_ARGS, FAIL);
121
122 /* allocate special info struct for buffered element */
123 if ((info = HDmalloc((uint32) sizeof(crinfo_t)))==NULL)
124 HGOTO_ERROR(DFE_NOSPACE, FAIL);
125
126 /* fill in special info struct */
127 info->attached= 1;
128 info->fid = fid;
129 info->tag = tag;
130 info->ref = ref;
131 info->xdim = xdim;
132 info->ydim = ydim;
133 info->image_size = xdim*ydim*pixel_size;
134 info->scheme = scheme;
135 HDmemcpy(&(info->cinfo),cinfo,sizeof(comp_info));
136
137 /* get empty access record */
138 access_rec = HIget_access_rec();
139 if (access_rec == NULL)
140 HGOTO_ERROR(DFE_TOOMANY, FAIL);
141
142 /* set up the information in the access record */
143 access_rec->special_info = info;
144
145 /* Check if the tag/ref pair exists */
146 if(Hexist(fid,tag,ref)<0) {
147 access_rec->new_elem=TRUE;
148 if((access_rec->ddid=HTPcreate(file_rec,tag,ref))==FAIL)
149 HGOTO_ERROR(DFE_INTERNAL, FAIL);
150 } /* end if */
151 else {
152 if((access_rec->ddid=HTPselect(file_rec,tag,ref))==FAIL)
153 HGOTO_ERROR(DFE_INTERNAL, FAIL);
154 } /* end else */
155 access_rec->special_func = &cr_funcs;
156 access_rec->special = SPECIAL_COMPRAS;
157 access_rec->posn = 0;
158 access_rec->access = DFACC_RDWR;
159 access_rec->file_id = fid;
160 access_rec->appendable = FALSE; /* data is non-appendable */
161 file_rec->attach++;
162
163 ret_value = HAregister_atom(AIDGROUP,access_rec); /* return access id */
164
165 done:
166 if(ret_value == FAIL)
167 { /* Error condition cleanup */
168 } /* end if */
169
170 return ret_value;
171 } /* HRPconvert */
172
173 /* ------------------------------ HRPstread ------------------------------- */
174 /*
175 NAME
176 HRPstread -- open an access record for reading
177 USAGE
178 int32 HRPstread(access_rec)
179 access_t * access_rec; IN: access record to fill in
180 RETURNS
181 The AID of the access record on success FAIL on error.
182 DESCRIPTION
183 This is a stub routine and should never be called
184
185 ---------------------------------------------------------------------------*/
186 int32
HRPstread(accrec_t * rec)187 HRPstread(accrec_t * rec)
188 {
189 /* shut compilers up*/
190 rec=rec;
191
192 assert(0 && "Should never be called");
193 return (FAIL);
194 } /* HRPstread */
195
196 /* ------------------------------ HRPstwrite ------------------------------- */
197 /*
198 NAME
199 HRPstwrite -- open an access record for reading
200 USAGE
201 int32 HRPstwrite(access_rec)
202 access_t * access_rec; IN: access record to fill in
203 RETURNS
204 The AID of the access record on success FAIL on error.
205 DESCRIPTION
206 This is a stub routine and should never be called.
207
208 ---------------------------------------------------------------------------*/
209 int32
HRPstwrite(accrec_t * rec)210 HRPstwrite(accrec_t * rec)
211 {
212 /* shut compilers up*/
213 rec=rec;
214
215 assert(0 && "Should never be called");
216 return (FAIL);
217 } /* HRPstwrite */
218
219 /* ------------------------------ HRPseek ------------------------------- */
220 /*
221 NAME
222 HRPseek -- set the seek posn
223 USAGE
224 int32 HRPseek(access_rec, offset, origin)
225 access_t * access_rec; IN: access record to mess with
226 int32 offset; IN: seek offset
227 int32 origin; IN: where we should calc the offset from
228 RETURNS
229 SUCCEED / FAIL
230 DESCRIPTION
231 Set the seek posn in the given compressed raster element. The only valid
232 position is 0 bytes from the beginning.
233
234 ---------------------------------------------------------------------------*/
235 int32
HRPseek(accrec_t * access_rec,int32 offset,int origin)236 HRPseek(accrec_t * access_rec, int32 offset, int origin)
237 {
238 int32 ret_value = SUCCEED;
239 CONSTR(FUNC, "HRPseek"); /* for HERROR */
240
241 /* Adjust offset according to origin. There is no upper bound to posn */
242 if (origin != DF_START || offset !=0)
243 HGOTO_ERROR(DFE_RANGE, FAIL);
244
245 /* set the offset */
246 access_rec->posn = offset;
247
248 done:
249 if(ret_value == FAIL)
250 { /* Error condition cleanup */
251
252 } /* end if */
253
254 /* Normal function cleanup */
255
256 return ret_value;
257 } /* HRPseek */
258
259 /* ------------------------------ HRPread ------------------------------- */
260 /*
261 NAME
262 HRPread -- read some data out of compressed raster element
263 USAGE
264 int32 HRPread(access_rec, length, data)
265 access_t * access_rec; IN: access record to mess with
266 int32 length; IN: number of bytes to read
267 void * data; IN: buffer for data
268 RETURNS
269 The number of bytes read or FAIL on error
270 DESCRIPTION
271 Uncompress a compressed raster image into the buffer provided. Support is
272 only provided for reading the entire image in.
273
274 ---------------------------------------------------------------------------*/
275 int32
HRPread(accrec_t * access_rec,int32 length,void * data)276 HRPread(accrec_t * access_rec, int32 length, void * data)
277 {
278 CONSTR(FUNC, "HRPread"); /* for HERROR */
279 crinfo_t *info = /* information on the special element */
280 (crinfo_t *) access_rec->special_info;
281 int32 ret_value = SUCCEED;
282
283 /* validate length */
284 if (length!=0 && length!=(int32)info->image_size)
285 HGOTO_ERROR(DFE_RANGE, FAIL);
286
287 /* adjust length */
288 if (length == 0)
289 length = info->image_size;
290
291 /* Copy data from buffer */
292 DFgetcomp(info->fid,info->tag,info->ref,data,info->xdim,info->ydim,info->scheme);
293
294 ret_value = length;
295
296 done:
297 if(ret_value == FAIL)
298 { /* Error condition cleanup */
299
300 } /* end if */
301
302 /* Normal function cleanup */
303
304 return(ret_value);
305 } /* HRPread */
306
307 /* ------------------------------ HRPwrite ------------------------------- */
308 /*
309 NAME
310 HRPwrite -- write data out to a compressed raster image
311 USAGE
312 int32 HRPwrite(access_rec, length, data)
313 access_t * access_rec; IN: access record to mess with
314 int32 length; IN: number of bytes to read
315 void * data; IN: buffer of data
316 RETURNS
317 The number of bytes written or FAIL on error
318 DESCRIPTION
319 Write out data to a compressed raster image. The entire image must be
320 written.
321
322 ---------------------------------------------------------------------------*/
323 int32
HRPwrite(accrec_t * access_rec,int32 length,const void * data)324 HRPwrite(accrec_t * access_rec, int32 length, const void * data)
325 {
326 CONSTR(FUNC, "HRPwrite"); /* for HERROR */
327 crinfo_t *info = /* information on the special element */
328 (crinfo_t *) (access_rec->special_info);
329 int32 ret_value = SUCCEED;
330
331 /* validate length */
332 if (length!=0 && length!=(int32)info->image_size)
333 HGOTO_ERROR(DFE_RANGE, FAIL);
334
335 /* adjust length */
336 if (length == 0)
337 length = info->image_size;
338
339 /* Copy data to buffer */
340 DFputcomp(info->fid,info->tag,info->ref,data,info->xdim,info->ydim,NULL,NULL,info->scheme,&(info->cinfo));
341
342 ret_value = length; /* return length of bytes written */
343
344 done:
345 if(ret_value == FAIL)
346 { /* Error condition cleanup */
347
348 } /* end if */
349
350 /* Normal function cleanup */
351
352 return(ret_value);
353 } /* HRPwrite */
354
355 /* ------------------------------ HRPinquire ------------------------------ */
356 /*
357 NAME
358 HRPinquire -- retreive information about a compressed raster element
359 USAGE
360 int32 HBPinquire(access_rec, file, tag, ref, len, off, pos, acc, sp)
361 access_t * access_rec; IN: access record to return info about
362 uint16 * file; OUT: file ID;
363 uint16 * tag; OUT: tag of info record;
364 uint16 * ref; OUT: ref of info record;
365 int32 * len; OUT: length of element;
366 int32 * off; OUT: offset of element (NOT correct);
367 int32 * pos; OUT: current position in element;
368 int16 * acc; OUT: access mode;
369 int16 * sp; OUT: special code;
370 RETURNS
371 SUCCEED
372 DESCRIPTION
373 Return interesting information about a compressed raster element.
374 NULL can be passed for any of the OUT parameters if their
375 value is not needed.
376
377 ---------------------------------------------------------------------------*/
378 int32
HRPinquire(accrec_t * access_rec,int32 * pfile_id,uint16 * ptag,uint16 * pref,int32 * plength,int32 * poffset,int32 * pposn,int16 * paccess,int16 * pspecial)379 HRPinquire(accrec_t * access_rec, int32 *pfile_id, uint16 *ptag,
380 uint16 *pref, int32 *plength, int32 *poffset,
381 int32 *pposn, int16 *paccess, int16 *pspecial)
382 {
383 CONSTR(FUNC, "HRPinquire"); /* for HERROR */
384 crinfo_t *info = /* special information record */
385 (crinfo_t *) access_rec->special_info;
386 uint16 data_tag,data_ref; /* tag/ref of the data we are checking */
387 int32 data_off; /* offset of the data we are checking */
388 int32 ret_value = SUCCEED;
389
390 /* Get the data's offset & length */
391 if(HTPinquire(access_rec->ddid,&data_tag,&data_ref,&data_off,NULL)==FAIL)
392 HGOTO_ERROR(DFE_INTERNAL, FAIL);
393
394 /* fill in the variables if they are present */
395 if (pfile_id)
396 *pfile_id = access_rec->file_id;
397 if (ptag)
398 *ptag = data_tag;
399 if (pref)
400 *pref = data_ref;
401 if (plength)
402 *plength = (access_rec->new_elem ? -1 : info->image_size);
403 if (poffset)
404 *poffset = data_off;
405 if (pposn)
406 *pposn = access_rec->posn;
407 if (paccess)
408 *paccess = (int16)access_rec->access;
409 if (pspecial)
410 *pspecial = (int16)access_rec->special;
411
412 done:
413 if(ret_value == FAIL)
414 { /* Error condition cleanup */
415
416 } /* end if */
417
418 /* Normal function cleanup */
419
420 return ret_value;
421 } /* HRPinquire */
422
423 /* ----------------------------- HRPendaccess ----------------------------- */
424 /*
425 NAME
426 HRPendacess -- free AID
427 USAGE
428 intn HRPendaccess(access_rec)
429 access_t * access_rec; IN: access record to close
430 RETURNS
431 SUCCEED / FAIL
432 DESCRIPTION
433 Free the AID
434
435 ---------------------------------------------------------------------------*/
436 intn
HRPendaccess(accrec_t * access_rec)437 HRPendaccess(accrec_t * access_rec)
438 {
439 CONSTR(FUNC, "HRPendaccess"); /* for HERROR */
440 filerec_t *file_rec; /* file record */
441 intn ret_value = SUCCEED;
442
443 /* validate argument */
444 if (access_rec == NULL)
445 HGOTO_ERROR(DFE_ARGS, FAIL);
446
447 /* convert file id to file record */
448 file_rec = HAatom_object(access_rec->file_id);
449 if (BADFREC(file_rec))
450 HGOTO_ERROR(DFE_ARGS, FAIL);
451
452 /* shut down dependant access record */
453 if (HRPcloseAID(access_rec) == FAIL)
454 HGOTO_ERROR(DFE_CANTCLOSE, FAIL);
455
456 /* end access to the tag/ref pair this ddid represents */
457 if (HTPendaccess(access_rec->ddid) == FAIL)
458 HGOTO_ERROR(DFE_CANTENDACCESS, FAIL);
459
460 /* free the access record */
461 HIrelease_accrec_node(access_rec);
462
463 /* detach from the file */
464 file_rec->attach--;
465
466
467 done:
468 if(ret_value == FAIL)
469 { /* Error condition cleanup */
470 if(access_rec!=NULL)
471 HIrelease_accrec_node(access_rec);
472 } /* end if */
473
474 /* Normal function cleanup */
475
476 return ret_value;
477 } /* HRPendaccess */
478
479 /* ----------------------------- HRPcloseAID ------------------------------ */
480 /*
481 NAME
482 HRPcloseAID -- free memory but keep AID active
483 USAGE
484 int32 HRPcloseAID(access_rec)
485 access_t * access_rec; IN: access record of file to close
486 RETURNS
487 SUCCEED / FAIL
488 DESCRIPTION
489 Free special element information, but do *NOT* free the AID.
490
491 ---------------------------------------------------------------------------*/
492 int32
HRPcloseAID(accrec_t * access_rec)493 HRPcloseAID(accrec_t * access_rec)
494 {
495 #ifdef LATER
496 CONSTR(FUNC, "HRPcloseAID"); /* for HERROR */
497 #endif /* LATER */
498 crinfo_t *info = /* special information record */
499 (crinfo_t *) access_rec->special_info;
500 int32 ret_value = SUCCEED;
501
502 /* detach the special information record.
503 If no more references to that, free the record */
504
505 if (--(info->attached) == 0)
506 {
507 HDfree(info);
508 access_rec->special_info = NULL;
509 }
510
511 #ifdef LATER
512 done:
513 #endif /* LATER */
514 if(ret_value == FAIL)
515 { /* Error condition cleanup */
516
517 } /* end if */
518
519 /* Normal function cleanup */
520
521 return(ret_value);
522 } /* HRPcloseAID */
523
524 /* ------------------------------- HRPinfo -------------------------------- */
525 /*
526 NAME
527 HRPinfo -- return info about a compressed raster element
528 USAGE
529 int32 HRPinfo(access_rec, info_block)
530 accrec_t * access_rec; IN: access record of element
531 sp_info_block_t * info_block; OUT: information about the special element
532 RETURNS
533 SUCCEED / FAIL
534 DESCRIPTION
535 Return information about the given external element. Info_block is
536 assumed to be non-NULL.
537
538 --------------------------------------------------------------------------- */
539 int32
HRPinfo(accrec_t * access_rec,sp_info_block_t * info_block)540 HRPinfo(accrec_t * access_rec, sp_info_block_t * info_block)
541 {
542 CONSTR(FUNC, "HRPinfo"); /* for HERROR */
543 int32 ret_value = SUCCEED;
544
545 /* validate access record */
546 if (access_rec->special != SPECIAL_COMPRAS)
547 HGOTO_ERROR(DFE_INTERNAL, FAIL);
548
549 /* fill in the info_block */
550 info_block->key = SPECIAL_COMPRAS;
551
552 done:
553 if(ret_value == FAIL)
554 { /* Error condition cleanup */
555
556 } /* end if */
557
558 /* Normal function cleanup */
559
560 return(ret_value);
561 } /* HRPinfo */
562
563