summaryrefslogtreecommitdiffstats
path: root/tools/gifconv/writehdf.c
blob: 4d69d015651e434601e115606f1d81e52ae4be2c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
/*
 * Copyright (C) 2001 National Center for Supercomputing Applications
 *                    All rights reserved.
 */
#include <string.h>
#include <stdlib.h>
#include <string.h>

#include "gif.h"

/*******************************************************************
 * Function:	write_text_attribute
 * Use:         Just a small wrapper to write text attributes easily
 *******************************************************************/
static int write_text_attribute(hid_t dataset_id , const char *attr_name,
                                const char *attr_value)
{
    /* variables for the attributes */
    hsize_t attr_dims_size;     /* dimensions for the attribute */
    hid_t attr_dataspace_id;    /* dataspaces needed for the various attributes */
    hid_t attr_attr_id;	        /* attribute id */
    herr_t status;              /* check return status */
    hid_t attr_type_id;

    /* check strings */
    if (!attr_name || !attr_value)
        return -1;

    /* figure out size of the data */
    attr_dims_size = strlen(attr_value) + 1;

    /* set the type to string */
    attr_type_id = H5Tcopy(H5T_C_S1);
    H5Tset_size(attr_type_id , (size_t)attr_dims_size);

    /* create the dataspace for the attribute */
    attr_dataspace_id = H5Screate_simple(1 , &attr_dims_size , NULL);

    /* create the attribute */
    attr_attr_id = H5Acreate(dataset_id , attr_name , attr_type_id ,
                             attr_dataspace_id , H5P_DEFAULT);

    /* write out the attribute data */
    if ((status = H5Awrite(attr_attr_id , attr_type_id , attr_value)) < 0) 
        return -1;

    /* close the attribute */
    if ((status = H5Aclose(attr_attr_id)) < 0) 
        return -1;

    /* close the dataspace */
    if ((status = H5Sclose(attr_dataspace_id)) < 0) {
        fprintf(stderr , "Unable to close attribute dataspace. Aborting \n");
        return -1;
    }

    return 0;
}

int
WriteHDF(GIFTOMEM GifMemoryStruct, char *HDFName , char *GIFFileName)
{
    GIFHEAD          gifHead;           /* GIF Header structure            */
    GIFIMAGEDESC    *gifImageDesc;      /* Logical Image Descriptor struct */

    long ImageCount,                    /* number of images */
         CommentCount,                  /* number of comments */
         ApplicationCount,              /* number of application extensions */
         PlainTextCount;                /* number of plain text extensions */

    char ImageName[256];                /* Image name for the GR Image */
    char GroupName[VSNAMELENMAX];       /* so that we can name the subgroups appropriately */

    /* H5 variables */
    hid_t file_id;      /* H5 file id */
    hid_t image_id;     /* H5 id for the whole image */
    hid_t pal_id;       /* H5 id for the palette */
    herr_t status;      /* status variable */
    hobj_ref_t pal_ref; /* Create a reference for the palette */

    /* temp counter */
    int i;

    /* get the GIFMem stuff */
    gifHead = *(GifMemoryStruct.GifHeader);

    /* get some data from gifHead */
    ImageCount = (WORD)gifHead.ImageCount;
    CommentCount = (WORD)gifHead.CommentCount;
    ApplicationCount = (WORD)gifHead.ApplicationCount;
    PlainTextCount = (WORD)gifHead.PlainTextCount;

    /* get the main group name from GIFFileName */
    GroupName[0]= '/';

    if (strncpy(GroupName , GIFFileName , VSNAMELENMAX-2) == NULL) {
        fprintf(stderr , "strncpy failed\n");
        exit(1);
    }

    GroupName[VSNAMELENMAX - 1] = '\0';

    if ((file_id = H5Fcreate(HDFName , H5F_ACC_TRUNC , H5P_DEFAULT , H5P_DEFAULT)) < 0) {
        /* error occured opening the HDF File for write */
        fprintf(stderr , "HDF file could not be opened for writing\n");
        fprintf(stderr , "NOTE: GIF file must be present in the same directory as the binary on UNIX systems.\n");
        exit(1);
    }

    /* create a group within the root group to hold the gif image */
    /* might want to make a different naming style out here */
    image_id = H5Gcreate(file_id, GroupName , 0);

    /* first create the global palette if there is one */
    if (gifHead.PackedField & 0x80) { /* global palette exists */
        hid_t dataspace_id;	/* identifier for dataspace */
        hsize_t dims[2];	/* specify the dimensions of the palette */

        hsize_t dimsr[1] = {1};	/* needed to store reference */
        hid_t ref_dataspace_id;	/* dataspace id for references */
        hid_t ref_dataset_id;	/* dataset id for references */

        /* size of the palette is tablesize (rows) X 3 (columns) */
        dims[0] = gifHead.TableSize;
        dims[1] = 3;

        /* create the dataspace */
        if ((dataspace_id = H5Screate_simple(2 , dims , NULL)) < 0) {
            fprintf(stderr , "Could not create dataspace for palette. Aborting...\n");
            return -1;
        }

        /* create the palette dataset */
        if ((pal_id = H5Dcreate(image_id , "Global Palette" , H5T_NATIVE_UINT8 , dataspace_id , H5P_DEFAULT )) < 0) {
            fprintf(stderr , "Could not create palette dataset. Aborting...\n");
            return -1;
        }

        /* write the palette data out */
        /****** Ask Elena about VOIDP ******/
        if ((status = H5Dwrite(pal_id , H5T_NATIVE_UINT8 , H5S_ALL , H5S_ALL , H5P_DEFAULT , (void *)gifHead.HDFPalette)) < 0) {
            fprintf(stderr , "Error writing dataset. Aborting...\n");
            return -1;
        }

        /* set palette attributes */

        /* attribute CLASS = PALETTE */
        if ((write_text_attribute(pal_id , "CLASS" , "PALETTE")) < 0) {
            fprintf(stderr , "Unable to write palette attributes. Aborting\n");
            return -1;
        }

        /* attribute PAL_COLORMODEL = RGB */
        if ((write_text_attribute(pal_id , "PAL_COLORMODEL" , "RGB")) < 0) {
            fprintf(stderr , "Unable to write palette attributes. Aborting\n");
            return -1;
        }

        /* attribute PAL_TYPE = STANDARD8 */
        if ((write_text_attribute(pal_id , "PAL_TYPE" , "STANDARD8")) < 0) {
            fprintf(stderr , "Unable to write palette attributes. Aborting\n");
            return -1;
        }

        /* attribute PAL_VERSION = 1.0 */
        if ((write_text_attribute(pal_id , "PAL_VERSION" , "1.0")) < 0) {
            fprintf(stderr , "Unable to write palette attributes. Aborting\n");
            return -1;
        }

        /* create dataspace for the dataset to store references */
        ref_dataspace_id = H5Screate_simple(1 , dimsr , NULL);

        /* create a dataset to store the references */
        ref_dataset_id = H5Dcreate(image_id , "Palette Reference" , H5T_STD_REF_OBJ , ref_dataspace_id , H5P_DEFAULT);

        /* create a reference to the palette */
        if ((status = H5Rcreate(&pal_ref , image_id , "Global Palette" , H5R_OBJECT , -1)) < 0) {
            fprintf(stderr , "Unable to create palette reference\n");
            return -1;
        }

        /* write the reference out */	
        if ((status = H5Dwrite(ref_dataset_id , H5T_STD_REF_OBJ, H5S_ALL, H5S_ALL , H5P_DEFAULT, &pal_ref)) < 0) {
            fprintf(stderr , "Unable to write Palette Reference");
            return -1;
        }
        
        /* close dataset */
        if ((status = H5Dclose(ref_dataset_id)) < 0) {
            fprintf(stderr , "Unable to close palette dataset.\n");
            return -1;
        }

        /* close dataspace */
        if ((status = H5Sclose(ref_dataspace_id)) < 0) {
            fprintf(stderr , "Unable to close palette dataspace.\n");
            return -1;
        }

        /* close everything */
        if ((status = H5Dclose(pal_id)) < 0) {
            fprintf(stderr , "Unable to close palette dataset. Aborting.\n");
            return -1;
        }

        if ((status = H5Sclose(dataspace_id)) < 0) {
            fprintf(stderr , "Unable to close palette dataspace. Aborting.\n");
            return -1;
        }
    }

    for(i = 0; i < ImageCount; i++) {
        /* variables for the images */
        hsize_t dims[2];        /* dimensions for the dataset */
        hid_t dataspace_id;     /* identifier for the dataspace */
        hid_t sub_image_id;     /* wierd name to distinguish from the group_id */

        /* variables for the attributes */
        hsize_t attr_dims[2];   /* dimensions for the attribute */
        hid_t attr_dataspace_id;/* dataspaces needed for the various attributes */
        hid_t attr_attr_id;     /* attribute id */
        BYTE minmax[2];         /* lower and upper minmax values */

        /* initialise minmax */
        minmax[0] = 0 ;
        minmax[1] = 255;

        /* get the gifImageDesc */
        gifImageDesc = GifMemoryStruct.GifImageDesc[i];

        /* set the dimensions */
        dims[0] = gifImageDesc->ImageHeight;
        dims[1] = gifImageDesc->ImageWidth;

        /* create the empty dataspace */
        if ((dataspace_id = H5Screate_simple(2 , dims , NULL)) < 0) {
            fprintf(stderr , "Could not create image dataspace. Aborting\n");
            return -1;
        }

        /* create the image name */
        sprintf(ImageName , "Image%d" , i);

        /* create the image data set */
        if ((sub_image_id = H5Dcreate(image_id , ImageName , H5T_NATIVE_UINT8 , dataspace_id , H5P_DEFAULT)) < 0) {
            fprintf(stderr , "Could not create dataset for image. Aborting... \n");
            return -1;
        }

        /* write out the image */
        /****** Ask Elena about VOIDP ******/
        if ((status = H5Dwrite(sub_image_id , H5T_NATIVE_UINT8 , H5S_ALL , H5S_ALL , H5P_DEFAULT , (void *)(gifImageDesc->Image))) < 0) {
            fprintf(stderr , "Error writing image. Aborting... \n");
            return -1;
        }

        /* set the attributes */
        /* This info is available at http://hdf.ncsa.uiuc.edu/HDF5/doc/ImageSpec.html */
        /* The following attributes must be set for each image:
        ** ---------------------------------------
        ** Attribute Name			Value 
        **		CLASS				IMAGE
        **		IMAGE_VERSION		1.0
        **		IMAGE_SUBCLASS		IMAGE_BITMAP
        **		PALETTE				ref. to palette datasets
        **		IMAGE_MINMAXRANGE	[0,255]
        ** ---------------------------------------
        */

        /****************************************
        ** Attribute: CLASS
        ** Value	: IMAGE
        *****************************************/

        if (write_text_attribute(sub_image_id , "CLASS" , "IMAGE") < 0) {
            fprintf(stderr , "Unable to write CLASS = IMAGE attribute\n");
            return -1;
        }

        /****************************************
        ** Attribute: IMAGE_VERSION
        ** Value	: 1.0
        *****************************************/

        if (write_text_attribute(sub_image_id , "IMAGE_VERSION" , "1.0") < 0) {
            fprintf(stderr , "Unable to write IMAGE_VERSION attribute\n");
            return -1;
        }

        /****************************************
        ** Attribute: IMAGE_SUBCLASS
        ** Value	: IMAGE_BITMAP
        *****************************************/

        if (write_text_attribute(sub_image_id , "IMAGE_SUBCLASS" , "IMAGE_BITMAP") < 0) {
            fprintf(stderr , "Unable to write IMAGE_SUBCLASS attribute\n");
            return -1;
        }

        /****************************************
        ** Attribute: IMAGE_COLORMODEL
        ** Value	: RGB
        *****************************************/

        if (write_text_attribute(sub_image_id , "IMAGE_COLORMODEL" , "RGB") < 0) {
            fprintf(stderr , "Unable to write IMAGE_SUBCLASS attribute\n");
            return -1;
        }

        /****************************************
        ** Attribute: PALETTE
        ** Value	: Reference to Palette
        *****************************************/
        
        /**** MAKE SURE PALETTE EXISTS!!! ****/
        if (gifHead.PackedField & 0x80) {
            /* global palette exists */
            attr_dims[0] = 1;

            /* create the dataspace for the attribute */
            attr_dataspace_id = H5Screate_simple(1 , attr_dims , NULL);

            /* create the attribute */
            attr_attr_id = H5Acreate(sub_image_id , "PALETTE" , H5T_STD_REF_OBJ , attr_dataspace_id , H5P_DEFAULT);

            if ((status = H5Awrite(attr_attr_id , H5T_STD_REF_OBJ , &pal_ref)) < 0) {
                fprintf(stderr , "Unable to write attribute. Aborting \n");
                return -1;
            }

            /* close the attribute */
            if ((status = H5Aclose(attr_attr_id)) < 0) {
                fprintf(stderr , "Unable to close CLASS IMAGE attribute. Aborting.\n");
                return -1;
            }

            /* close the dataspace */
            if ((status = H5Sclose(attr_dataspace_id)) < 0) {
                fprintf(stderr , "Unable to close attribute dataspace. Aborting \n");
                return -1;
            }
        }

        /****************************************
        ** Attribute: IMAGE_MINMAXRANGE
        ** Value	: minmax
        *****************************************/

        attr_dims[0] = 2;

        /* create the dataspace for the attribute */
        attr_dataspace_id = H5Screate_simple(1 , attr_dims , NULL);

        /* create the attribute */
        attr_attr_id = H5Acreate(sub_image_id , "IMAGE_MINMAXRANGE" , H5T_NATIVE_UINT8 , attr_dataspace_id , H5P_DEFAULT);

        if ((status = H5Awrite(attr_attr_id , H5T_NATIVE_UINT8 , minmax)) < 0) {
            fprintf(stderr , "Unable to write attribute. Aborting \n");
            return -1;
        }

        /* close the attribute */
        if ((status = H5Aclose(attr_attr_id)) < 0) {
            fprintf(stderr , "Unable to close CLASS IMAGE attribute. Aborting.\n");
            return -1;
        }

        /* close the dataspace */
        if ((status = H5Sclose(attr_dataspace_id)) < 0) {
            fprintf(stderr , "Unable to close attribute dataspace. Aborting \n");
            return -1;
        }

        /* close everything */
        if ((status = H5Dclose(sub_image_id)) < 0) {
            fprintf(stderr , "Unable to close image dataset. Aborting \n");
            return -1;
        }

        if ((status = H5Sclose(dataspace_id)) < 0) {
            fprintf(stderr , "Unable to close image dataspace. Aborting \n");
            return -1;
        }
    }

    /* close the main image group */
    if ((status = H5Gclose(image_id)) < 0) {
        fprintf(stderr , "Could not close the image group. Aborting...\n");
        return -1;
    }

    /* close the H5 file */
    if ((status = H5Fclose(file_id)) < 0) {
        fprintf(stderr , "Could not close HDF5 file. Aborting...\n");
        return -1;
    }

    return 0;
}