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