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 HDF5.  The full HDF5 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/HDF5/releases.  *
10  * If you do not have access to either file, you may request a copy from     *
11  * help@hdfgroup.org.                                                        *
12  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
13 
14 #include "H5IMcc.h"
15 
16 #include <string.h>
17 #include <stdlib.h>
18 
19 
20 /*-------------------------------------------------------------------------
21  * private functions
22  *-------------------------------------------------------------------------
23  */
24 herr_t H5IM_get_palette(hid_t loc_id,
25                          const char *image_name,
26                          int pal_number,
27                          hid_t tid,
28                          void *pal_data);
29 
30 /*-------------------------------------------------------------------------
31  * Function: H5IMmake_image_8bitf
32  *
33  * Purpose: Creates and writes an image an 8 bit image
34  *
35  * Return: Success: 0, Failure: -1
36  *
37  * Programmer: Pedro Vicente Nunes, pvn@ncsa.uiuc.edu
38  *
39  * Date: May 10, 2005
40  *
41  * Comments:
42  *  This function allows the creation and writing of an 8bit image on disk.
43  *  The memory datatype is H5T_NATIVE_INT. It is supposed to be called from
44  *  the FORTRAN interface where the image buffer is defined as type "integer"
45  *
46  * Modifications:
47  *
48  *-------------------------------------------------------------------------
49  */
50 
H5IMmake_image_8bitf(hid_t loc_id,const char * dset_name,hsize_t width,hsize_t height,int_f * buf)51 herr_t H5IMmake_image_8bitf(hid_t loc_id,
52                              const char *dset_name,
53                              hsize_t width,
54                              hsize_t height,
55                              int_f *buf)
56 {
57  hid_t    did;                  /* dataset ID */
58  hid_t    sid;                  /* space ID */
59  hsize_t  dims[IMAGE8_RANK];  /* dimensions */
60 
61  /* initialize the image dimensions */
62  dims[0] = height;
63  dims[1] = width;
64 
65 /*-------------------------------------------------------------------------
66  * create and write the dataset
67  *-------------------------------------------------------------------------
68  */
69 
70  /* create the data space for the dataset. */
71  if((sid = H5Screate_simple(IMAGE8_RANK, dims, NULL)) < 0)
72   return -1;
73 
74  /* create the dataset as H5T_NATIVE_UCHAR */
75  if((did = H5Dcreate2(loc_id, dset_name, H5T_NATIVE_UINT8, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0)
76   return -1;
77 
78  /* write with memory type H5T_NATIVE_INT */
79  /* Use long type if Fortran integer is 8 bytes and C long long is also 8 bytes*/
80  /* Fail if otherwise */
81  if(buf) {
82   if(sizeof(int_f) == sizeof(int)) {
83       if(H5Dwrite(did, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf) < 0)
84        return -1;
85   } else if(sizeof(int_f) == sizeof(long)) {
86       if(H5Dwrite(did, H5T_NATIVE_LONG, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf) < 0)
87        return -1;
88   } else if(sizeof(int_f) == sizeof(long long)) {
89       if(H5Dwrite(did, H5T_NATIVE_LLONG, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf) < 0)
90        return -1;
91   } else
92        return -1;
93  }
94 
95  /* close */
96  if(H5Dclose(did) < 0)
97   return -1;
98  if(H5Sclose(sid) < 0)
99   return -1;
100 
101 /*-------------------------------------------------------------------------
102  * attach the specification attributes
103  *-------------------------------------------------------------------------
104  */
105 
106  /* attach the CLASS attribute */
107  if(H5LTset_attribute_string(loc_id, dset_name, "CLASS", IMAGE_CLASS) < 0)
108   return -1;
109 
110  /* attach the VERSION attribute */
111  if(H5LTset_attribute_string(loc_id, dset_name, "IMAGE_VERSION", IMAGE_VERSION) < 0)
112   return -1;
113 
114  /* attach the IMAGE_SUBCLASS attribute */
115  if(H5LTset_attribute_string(loc_id, dset_name, "IMAGE_SUBCLASS", "IMAGE_INDEXED") < 0)
116   return -1;
117 
118  return 0;
119 }
120 
121 
122 
123 /*-------------------------------------------------------------------------
124  * Function: H5IMmake_image_24bitf
125  *
126  * Purpose:
127  *
128  * Return: Success: 0, Failure: -1
129  *
130  * Programmer: Pedro Vicente Nunes, pvn@ncsa.uiuc.edu
131  *
132  * Date: May 10, 2005
133  *
134  * Comments:
135  *  This function allows the creation and writing of an 8bit image on disk.
136  *  The memory datatype is H5T_NATIVE_INT. It is supposed to be called from
137  *  the FORTRAN interface where the image buffer is defined as type "integer"
138  *
139  * Interlace Mode Dimensions in the Dataspace
140  * INTERLACE_PIXEL [height][width][pixel components]
141  * INTERLACE_PLANE [pixel components][height][width]
142  *
143  *
144  * Modifications:
145  *
146  *-------------------------------------------------------------------------
147  */
148 
H5IMmake_image_24bitf(hid_t loc_id,const char * dset_name,hsize_t width,hsize_t height,const char * interlace,int_f * buf)149 herr_t H5IMmake_image_24bitf(hid_t loc_id,
150                               const char *dset_name,
151                               hsize_t width,
152                               hsize_t height,
153                               const char *interlace,
154                               int_f *buf)
155 {
156  hid_t    did;                /* dataset ID */
157  hid_t    sid;                /* space ID */
158  hsize_t  dims[IMAGE24_RANK]; /* dimensions */
159 
160 /*-------------------------------------------------------------------------
161  * attach the image dimensions according to the interlace mode
162  *-------------------------------------------------------------------------
163  */
164  if(strcmp(interlace, "INTERLACE_PIXEL") == 0) {
165   /* Number of color planes is defined as the third dimension */
166   dims[0] = height;
167   dims[1] = width;
168   dims[2] = IMAGE24_RANK;
169  }
170  else
171  if(strcmp(interlace, "INTERLACE_PLANE") == 0) {
172   /* Number of color planes is defined as the first dimension */
173   dims[0] = IMAGE24_RANK;
174   dims[1] = height;
175   dims[2] = width;
176  }
177  else
178   return -1;
179 
180 /*-------------------------------------------------------------------------
181  * create and write the dataset
182  *-------------------------------------------------------------------------
183  */
184 
185  /* create the data space for the dataset. */
186  if((sid = H5Screate_simple(IMAGE24_RANK, dims, NULL)) < 0)
187   return -1;
188 
189  /* create the dataset as H5T_NATIVE_UCHAR */
190  if((did = H5Dcreate2(loc_id, dset_name, H5T_NATIVE_UCHAR, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0)
191   return -1;
192 
193  /* write with memory type H5T_NATIVE_INT */
194  if(buf) {
195   if(sizeof(int_f) == sizeof(int)) {
196       if(H5Dwrite(did, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf) < 0)
197        return -1;
198   } else if(sizeof(int_f) == sizeof(long)) {
199       if(H5Dwrite(did, H5T_NATIVE_LONG, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf) < 0)
200        return -1;
201   } else if(sizeof(int_f) == sizeof(long long)) {
202       if(H5Dwrite(did, H5T_NATIVE_LLONG, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf) < 0)
203        return -1;
204   } else
205    return -1;
206  }
207 
208  /* close */
209  if(H5Dclose(did) < 0)
210   return -1;
211  if(H5Sclose(sid) < 0)
212   return -1;
213 
214 /*-------------------------------------------------------------------------
215  * attach the specification attributes
216  *-------------------------------------------------------------------------
217  */
218 
219  /* Attach the CLASS attribute */
220  if(H5LTset_attribute_string(loc_id, dset_name, "CLASS", IMAGE_CLASS) < 0)
221   return -1;
222 
223  /* Attach the VERSION attribute */
224  if(H5LTset_attribute_string(loc_id, dset_name, "IMAGE_VERSION", IMAGE_VERSION) < 0)
225   return -1;
226 
227  /* Attach the IMAGE_SUBCLASS attribute */
228  if(H5LTset_attribute_string(loc_id, dset_name, "IMAGE_SUBCLASS", "IMAGE_TRUECOLOR") < 0)
229   return -1;
230 
231  /* Attach the INTERLACE_MODE attribute. This attributes is only for true color images */
232  if(H5LTset_attribute_string(loc_id, dset_name, "INTERLACE_MODE", interlace) < 0)
233   return -1;
234 
235  return 0;
236 
237 }
238 
239 
240 /*-------------------------------------------------------------------------
241  * Function: H5IMread_imagef
242  *
243  * Purpose: Reads image data from disk.
244  *
245  * Return: Success: 0, Failure: -1
246  *
247  * Programmer: Pedro Vicente Nunes, pvn@ncsa.uiuc.edu
248  *
249  * Date: May 10, 2005
250  *
251  * Comments:
252  *  This function allows reading of an 8bit image on disk.
253  *  The memory datatype is H5T_NATIVE_INT. It is supposed to be called from
254  *  the FORTRAN interface where the image buffer is defined as type "integer"
255  *
256  * Modifications:
257  *
258  *-------------------------------------------------------------------------
259  */
260 
H5IMread_imagef(hid_t loc_id,const char * dset_name,int_f * buf)261 herr_t H5IMread_imagef(hid_t loc_id,
262                         const char *dset_name,
263                         int_f *buf)
264 {
265     hid_t   did;
266     hid_t   tid;
267 
268     /* open the dataset */
269     if((did = H5Dopen2(loc_id, dset_name, H5P_DEFAULT)) < 0)
270         return -1;
271 
272     /* determine appropriate datatype to use */
273     if(sizeof(int_f) == sizeof(int))
274         tid = H5T_NATIVE_INT;
275     else if(sizeof(int_f) == sizeof(long))
276         tid = H5T_NATIVE_LONG;
277     else if(sizeof(int_f) == sizeof(long long))
278         tid = H5T_NATIVE_LLONG;
279     else
280         goto out;
281 
282     /* read to memory */
283     if(H5Dread(did, tid, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf) < 0)
284         goto out;
285 
286     /* close */
287     if(H5Dclose(did))
288         return -1;
289 
290     return 0;
291 
292 out:
293     H5Dclose(did);
294     return -1;
295 }
296 
297 
298 /*-------------------------------------------------------------------------
299  * Function: H5IMmake_palettef
300  *
301  * Purpose: Creates and writes a palette.
302  *
303  * Return: Success: 0, Failure: -1
304  *
305  * Programmer: Pedro Vicente Nunes, pvn@ncsa.uiuc.edu
306  *
307  * Date: May 10, 2005
308  *
309  * Comments:
310  *  This function allows writing of an 8bit palette to disk.
311  *  The memory datatype is H5T_NATIVE_INT. It is supposed to be called from
312  *  the FORTRAN interface where the image buffer is defined as type "integer"
313  *
314  *  based on HDF5 Image and Palette Specification
315  *
316  * Modifications:
317  *
318  *-------------------------------------------------------------------------
319  */
320 
H5IMmake_palettef(hid_t loc_id,const char * pal_name,const hsize_t * pal_dims,int_f * pal_data)321 herr_t H5IMmake_palettef(hid_t loc_id,
322                           const char *pal_name,
323                           const hsize_t *pal_dims,
324                           int_f *pal_data)
325 
326 {
327 
328  hid_t did;                /* dataset ID */
329  hid_t sid;                /* space ID */
330  int   has_pal;
331 
332  /* Check if the dataset already exists */
333  has_pal = H5LTfind_dataset(loc_id, pal_name);
334 
335  /* It exists. Return */
336  if(has_pal == 1)
337   return 0;
338 
339 /*-------------------------------------------------------------------------
340  * create and write the dataset
341  *-------------------------------------------------------------------------
342  */
343 
344  /* create the data space for the dataset. */
345  if((sid = H5Screate_simple(2, pal_dims, NULL)) < 0)
346   return -1;
347 
348  /* create the dataset as H5T_NATIVE_UCHAR */
349  if((did = H5Dcreate2(loc_id, pal_name, H5T_NATIVE_UCHAR, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0)
350   return -1;
351 
352  /* write with memory type H5T_NATIVE_INT */
353  if(pal_data) {
354   if(sizeof(int_f) == sizeof(int)) {
355       if(H5Dwrite(did, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, pal_data) < 0)
356        return -1;
357   } else if(sizeof(int_f) == sizeof(long)) {
358       if(H5Dwrite(did, H5T_NATIVE_LONG, H5S_ALL, H5S_ALL, H5P_DEFAULT, pal_data) < 0)
359        return -1;
360   } else if(sizeof(int_f) == sizeof(long long)) {
361       if(H5Dwrite(did, H5T_NATIVE_LLONG, H5S_ALL, H5S_ALL, H5P_DEFAULT, pal_data) < 0)
362        return -1;
363   } else
364       return -1;
365  }
366 
367  /* close */
368  if(H5Dclose(did) < 0)
369   return -1;
370  if(H5Sclose(sid) < 0)
371   return -1;
372 
373 /*-------------------------------------------------------------------------
374  * attach the specification attributes
375  *-------------------------------------------------------------------------
376  */
377 
378  /* Attach the attribute "CLASS" to the >>palette<< dataset*/
379  if(H5LTset_attribute_string(loc_id, pal_name, "CLASS", PALETTE_CLASS) < 0)
380   return -1;
381 
382  /* Attach the attribute "PAL_VERSION" to the >>palette<< dataset*/
383  if(H5LTset_attribute_string(loc_id, pal_name, "PAL_VERSION", "1.2") < 0)
384   return -1;
385 
386  return 0;
387 
388 }
389 
390 
391 /*-------------------------------------------------------------------------
392  * Function: H5IMget_palettef
393  *
394  * Purpose: Read palette
395  *
396  * Return: Success: 0, Failure: -1
397  *
398  * Programmer: Pedro Vicente Nunes, pvn@ncsa.uiuc.edu
399  *
400  * Date: May 10, 2005
401  *
402  * Comments:
403  *  This function allows reading of an 8bit palette from disk.
404  *  The memory datatype is H5T_NATIVE_INT. It is supposed to be called from
405  *  the FORTRAN interface where the image buffer is defined as type "integer"
406  *
407  *  based on HDF5 Image and Palette Specification
408  *
409  * Modifications:
410  *
411  *-------------------------------------------------------------------------
412  */
413 
H5IMget_palettef(hid_t loc_id,const char * image_name,int pal_number,int_f * pal_data)414 herr_t H5IMget_palettef(hid_t loc_id,
415                          const char *image_name,
416                          int pal_number,
417                          int_f *pal_data)
418 {
419  if(sizeof(int_f) == sizeof(int))
420   return H5IM_get_palette(loc_id,image_name,pal_number,H5T_NATIVE_INT,pal_data);
421  else if(sizeof(int_f) == sizeof(long))
422   return H5IM_get_palette(loc_id,image_name,pal_number,H5T_NATIVE_LONG,pal_data);
423  else if(sizeof(int_f) == sizeof(long long))
424   return H5IM_get_palette(loc_id,image_name,pal_number,H5T_NATIVE_LLONG,pal_data);
425  else
426   return -1;
427 
428 }
429 
430 /*-------------------------------------------------------------------------
431  * Function: H5IM_get_palette
432  *
433  * Purpose: private function that reads a palette to memory type TID
434  *
435  * Return: Success: 0, Failure: -1
436  *
437  * Programmer: Pedro Vicente Nunes, pvn@ncsa.uiuc.edu
438  *
439  * Date: May 10, 2005
440  *
441  * Comments:
442  *  This function allows reading of an 8bit palette from disk disk
443  *   to memory type TID
444  *  The memory datatype can be H5T_NATIVE_INT or H5T_NATIVE_UCHAR currently.
445  *   the H5T_NATIVE_INT is supposed to be called from
446  *   the FORTRAN interface where the image buffer is defined as type "integer"
447  *
448  * Comments:
449  *  based on HDF5 Image and Palette Specification
450  *
451  * Modifications:
452  *
453  *-------------------------------------------------------------------------
454  */
H5IM_get_palette(hid_t loc_id,const char * image_name,int pal_number,hid_t tid,void * pal_data)455 herr_t H5IM_get_palette(hid_t loc_id,
456                          const char *image_name,
457                          int pal_number,
458                          hid_t tid,
459                          void *pal_data)
460 {
461  hid_t      image_id;
462  int        has_pal;
463  hid_t      attr_type;
464  hid_t      attr_id;
465  hid_t      attr_space_id;
466  hid_t      attr_class;
467  hssize_t   n_refs;
468  size_t    dim_ref;
469  hobj_ref_t *refbuf;     /* buffer to read references */
470  hid_t      pal_id;
471 
472  /* Open the dataset. */
473  if((image_id = H5Dopen2(loc_id, image_name, H5P_DEFAULT)) < 0)
474   return -1;
475 
476  /* Try to find the attribute "PALETTE" on the >>image<< dataset */
477  has_pal = H5IM_find_palette(image_id);
478 
479  if(has_pal ==  1)
480  {
481 
482   if((attr_id = H5Aopen(image_id, "PALETTE", H5P_DEFAULT)) < 0)
483    goto out;
484 
485   if((attr_type = H5Aget_type(attr_id)) < 0)
486    goto out;
487 
488   if((attr_class = H5Tget_class(attr_type)) < 0)
489    goto out;
490 
491   /* Check if it is really a reference */
492   if(attr_class == H5T_REFERENCE)
493   {
494 
495    /* Get the reference(s) */
496    if((attr_space_id = H5Aget_space(attr_id)) < 0)
497     goto out;
498 
499    n_refs = H5Sget_simple_extent_npoints(attr_space_id);
500 
501    dim_ref = (size_t)n_refs;
502 
503    refbuf = (hobj_ref_t *)HDmalloc(sizeof(hobj_ref_t) * dim_ref);
504 
505    if(H5Aread(attr_id, attr_type, refbuf) < 0)
506     goto out;
507 
508    /* Get the palette id */
509    if((pal_id = H5Rdereference(image_id, H5R_OBJECT, &refbuf[pal_number])) < 0)
510     goto out;
511 
512    /* Read the palette dataset using the memory type TID */
513    if(H5Dread(pal_id, tid, H5S_ALL, H5S_ALL, H5P_DEFAULT, pal_data) < 0)
514     goto out;
515 
516    if(H5Sclose(attr_space_id) < 0)
517     goto out;
518 
519    /* close the dereferenced dataset */
520    if(H5Dclose(pal_id) < 0)
521     goto out;
522 
523    free(refbuf);
524 
525   } /* H5T_REFERENCE */
526 
527   if(H5Tclose(attr_type) < 0)
528    goto out;
529 
530   /* Close the attribute. */
531   if(H5Aclose(attr_id) < 0)
532    goto out;
533 
534  }
535 
536  /* Close the image dataset. */
537  if(H5Dclose(image_id) < 0)
538   return -1;
539 
540  return 0;
541 
542 out:
543  H5Dclose(image_id);
544  return -1;
545 
546 
547 }
548