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 <stdio.h>
15 #include <assert.h>
16 #include "gif.h"
17 #include "H5IMpublic.h"
18 #include "h5tools.h"
19 #include "h5tools_utils.h"
20 
21 #define IMAGE_WIDTH_MAX		65535	/* unsigned 16bits integer */
22 #define IMAGE_HEIGHT_MAX	65535	/* unsigned 16bits integer */
23 
24 
25 int EndianOrder;
26 
27 static void
putword(int w,FILE * fp)28 putword(int w, FILE *fp)
29 {
30     /* writes a 16-bit integer in GIF order (LSB first) */
31     fputc(w &0xff, fp);
32     fputc((w>>8)&0xff,fp);
33 }
34 
35 static void
usage(void)36 usage(void)
37 {
38     printf("Usage: h52gif <h5_file> <gif_file> -i <h5_image>\n");
39     fprintf(stdout, "       h52gif -V \n");
40     fprintf(stdout, "        Print HDF5 library version and exit\n");
41     printf("h52gif expects *at least* one h5_image.\n");
42 
43 }
44 
45 FILE *fpGif = NULL;
main(int argc,char ** argv)46 int main(int argc , char **argv)
47 {
48     BYTE *Image;
49     void *edata;
50     H5E_auto2_t func;
51 
52     /* compression structs */
53     CHAR *HDFName = NULL;
54     CHAR *GIFName = NULL;
55 
56     BYTE* b;
57 
58     BYTE  GlobalPalette[256][3];
59     BYTE  Red[256];
60     BYTE  Green[256];
61     BYTE  Blue[256];
62 
63     int   RWidth, RHeight;
64     int   ColorMapSize, InitCodeSize, Background, BitsPerPixel;
65     int   j,nc;
66     int   i;
67     int   numcols = 0;
68 
69     BYTE pc2nc[256] , r1[256] , g1[256] , b1[256];
70 
71     int arg_index = 2;
72     int bool_is_image = 0; /* 0 = false , 1 = true */
73     char *image_name = NULL;
74     int idx;
75 
76     /* Disable error reporting */
77     H5Eget_auto2(H5E_DEFAULT, &func, &edata);
78     H5Eset_auto2(H5E_DEFAULT, NULL, NULL);
79 
80     /* Initialize h5tools lib */
81     h5tools_init();
82 
83     if ( argv[1] && (strcmp("-V",argv[1])==0) )
84     {
85         print_version("gif2h5");
86         exit(EXIT_SUCCESS);
87 
88     }
89 
90 
91     if (argc < 4)
92     {
93         /* they didn't supply at least one image -- bail */
94         usage();
95         return EXIT_FAILURE;
96     }
97 
98     HDFName = argv[1];
99     GIFName = argv[2];
100 
101     /* get the options */
102     while (arg_index++ < argc - 1)
103     {
104         if (!strcmp(argv[arg_index] , "-i")) {
105             bool_is_image = 1;
106             continue;
107         }
108 
109         if (bool_is_image)
110         {
111             /* allocate space to store the image name */
112             size_t len = strlen(argv[arg_index]);
113             image_name = (CHAR*) malloc( len + 1);
114             strcpy(image_name , argv[arg_index]);
115 
116             bool_is_image = 0;
117             continue;
118         }
119 
120         /* oops. This was not meant to happen */
121         usage();
122 
123         goto out;
124     }
125 
126    /* Do Endian Order testing and set Endian Order */
127     idx = 0x0001;
128     b = (BYTE *) &idx;
129     EndianOrder = (b[0] ? 1:0);
130 
131     if (!(fpGif = fopen(GIFName , "wb")))
132     {
133         printf("Error opening gif file for output. Aborting.\n");
134         goto out;
135     }
136 
137     Background = 0;
138     {
139         hsize_t       width, height, planes;
140         hid_t         fid;
141         char          interlace[20];
142         hssize_t      npals;
143         hsize_t       pal_dims[2];
144         unsigned char *pal;
145 
146         if ((fid = H5Fopen(HDFName , H5F_ACC_RDONLY , H5P_DEFAULT)) < 0)
147         {
148             fprintf(stderr , "Unable to open HDF file for input. Aborting.\n");
149             goto out;
150         }
151 
152         /* read image */
153         if ( H5IMget_image_info( fid, image_name, &width, &height, &planes, interlace, &npals ) < 0 )
154             goto out;
155 
156 	if (width > IMAGE_WIDTH_MAX || height > IMAGE_HEIGHT_MAX){
157 	    fprintf(stderr, "HDF5 image is too large. Limit is %d by %d.\n", IMAGE_WIDTH_MAX, IMAGE_HEIGHT_MAX);
158 	    goto out;
159 	}
160 
161 	/* tool can handle single plane images only. */
162 	if (planes > 1){
163 	    fprintf(stderr, "Cannot handle multiple planes image\n");
164 	    goto out;
165 	}
166 
167         Image = (BYTE*) malloc( (size_t) width * (size_t) height );
168 
169         if ( H5IMread_image( fid, image_name, Image ) < 0 )
170             goto out;
171 
172         if (npals)
173         {
174             if ( H5IMget_palette_info( fid, image_name, 0, pal_dims ) < 0 )
175                 goto out;
176 
177             pal = (BYTE*) malloc( (size_t) pal_dims[0] * (size_t) pal_dims[1] );
178 
179             if ( H5IMget_palette( fid, image_name, 0, pal ) < 0 )
180                 goto out;
181 
182             numcols = (int) pal_dims[0];
183 
184             for (i = 0, j = 0 ; i < numcols ; j+=3, i++)
185             {
186                 GlobalPalette[i][0] = pal[j];
187                 GlobalPalette[i][1] = pal[j+1];
188                 GlobalPalette[i][2] = pal[j+2];
189             }
190 
191             free(pal);
192         }
193 
194         H5Fclose(fid);
195 
196         RWidth  = (int)width;
197         RHeight = (int)height;
198 
199 
200         /*
201          * If the first image does not have a palette, I make my own global
202          * color table Obviously this is not the best thing to do, better
203          * steps would be:
204          *
205          *   1. Check for either a global palette or a global attribute called
206          *      palette
207          *   2. Check for palettes in any of the other images.
208          */
209         if (!npals)
210         {
211             numcols = 256;
212             for (i = 0 ; i < numcols ; i++)
213             {
214 	      Red[i] = (BYTE)(255 - i);
215 	      Green[i] = (BYTE)(255 - i);
216 	      Blue[i] = (BYTE)(255 - i);
217             }
218         }
219         else
220         {
221             for (i = 0 ; i < numcols ; i++)
222             {
223                 Red[i] = GlobalPalette[i][0];
224                 Green[i] = GlobalPalette[i][1];
225                 Blue[i] = GlobalPalette[i][2];
226             }
227         }
228 
229         for (i = 0; i < numcols; i++)
230         {
231             pc2nc[i] = r1[i] = g1[i] = b1[i] = 0;
232         }
233 
234         /* compute number of unique colors */
235         nc = 0;
236 
237         for (i = 0; i < numcols; i++)
238         {
239             /* see if color #i is already used */
240             for (j = 0; j < i; j++)
241             {
242                 if (Red[i] == Red[j] && Green[i] == Green[j] && Blue[i] == Blue[j])
243                     break;
244             }
245 
246             if (j==i)
247             {
248                 /* wasn't found */
249 	      pc2nc[i] = (BYTE)nc;
250                 r1[nc] = Red[i];
251                 g1[nc] = Green[i];
252                 b1[nc] = Blue[i];
253                 nc++;
254             }
255             else
256             {
257                 pc2nc[i] = pc2nc[j];
258             }
259         }
260 
261         /* figure out 'BitsPerPixel' */
262         for (i = 1; i < 8; i++)
263         {
264             if ((1<<i) >= nc)
265                 break;
266         }
267 
268         BitsPerPixel = i;
269         ColorMapSize = 1 << BitsPerPixel;
270 
271         if (BitsPerPixel <= 1)
272             InitCodeSize = 2;
273         else
274             InitCodeSize = BitsPerPixel;
275 
276         if (!fpGif)
277         {
278             fprintf(stderr,  "WriteGIF: file not open for writing\n" );
279             goto out;
280         }
281 
282 
283         fwrite("GIF87a", sizeof( char ), 6, fpGif);  /* the GIF magic number */
284 
285         putword(RWidth, fpGif);             /* screen descriptor */
286         putword(RHeight, fpGif);
287 
288         i = 0x00;                   /* No, there is no color map */
289         i |= (8-1)<<4;              /* OR in the color resolution (hardwired 8) */
290         i |= (BitsPerPixel - 1);    /* OR in the # of bits per pixel */
291         fputc(i,fpGif);
292 
293         fputc(Background,fpGif);    /* background color */
294         fputc(0, fpGif);            /* future expansion byte */
295 
296 
297         /*
298          * Put Image Descriptor
299          * Hardwiring Left Offset and Top Offset to 0x00
300          */
301         fputc(0x2c , fpGif);
302         putword(0x00 , fpGif);
303         putword(0x00  , fpGif);
304         putword(RWidth   , fpGif);
305         putword(RHeight  , fpGif);
306 
307         /* since we always have a local color palette ... */
308         fputc((0x80 | (BitsPerPixel - 1)) , fpGif);
309 
310         for (i = 0; i < ColorMapSize; i++)
311         {
312             /* write out Global colormap */
313             fputc(r1[i], fpGif);
314             fputc(g1[i], fpGif);
315             fputc(b1[i], fpGif);
316         }
317 
318         fputc(InitCodeSize , fpGif);
319 
320         i = hdfWriteGIF(fpGif , Image , 0 , RHeight , RWidth , r1, g1 , b1 , pc2nc , 256 , 8 , BitsPerPixel);
321         fputc(0x00, fpGif);
322         free(Image);
323     }
324 
325     if (fputc(';',fpGif) == EOF)
326     {
327         /* Write GIF file terminator */
328         fprintf(stderr , "Error!");
329         goto out;
330     }
331 
332     if (fpGif != NULL)
333         fclose(fpGif);
334     if (image_name != NULL)
335         free(image_name);
336 
337     H5Eset_auto2(H5E_DEFAULT, func, edata);
338 
339     return EXIT_SUCCESS;
340 
341 
342 out:
343 
344     if (fpGif != NULL)
345         fclose(fpGif);
346     if (image_name != NULL)
347         free(image_name);
348 
349     H5Eset_auto2(H5E_DEFAULT, func, edata);
350 
351     return EXIT_FAILURE;
352 }
353