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