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