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