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 HDF. The full HDF 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/HDF/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 "gif.h"
15 #include <stdio.h>
16
17 #define HDFNAME "laser.hdf"
18 #define VGROUPCLASS "RIG0.0"
19 #define GIFNAME "temp.gif"
20
21 extern int hdfWriteGIF(FILE *fp, BYTE *pic, int ptype, int w, int h, BYTE *rmap,
22 BYTE *gmap, BYTE *bmap, BYTE *pc2ncmap, int numcols, int colorstyle, int BitsPerPixel);
23
24 int EndianOrder;
25
26 VOID
PutByte(b,fpGif)27 PutByte(b , fpGif)
28 BYTE b;
29 FILE *fpGif;
30 {
31 if (fputc(b , fpGif) == EOF) {
32 printf("File Writing Error, cannot continue");
33 exit(-1);
34 }
35 }
36
37 VOID
WordToByte(w,b)38 WordToByte(w , b)
39 WORD w;
40 BYTE *b;
41 {
42 if (EndianOrder == 0) /* Big Endian */
43 {
44 b[0] = w & 0xFF00;
45 b[1] = w & 0xFF;
46 }
47 else /* Little Endian */
48 {
49 b[0] = w & 0xFF;
50 b[1] = w & 0xFF00;
51 }
52 }
53
54 VOID
putword(w,fp)55 putword(w, fp)
56 int w;
57 FILE *fp;
58 {
59 /* writes a 16-bit integer in GIF order (LSB first) */
60
61 fputc(w &0xff, fp);
62
63 fputc((w>>8)&0xff,fp);
64 }
65
main(int argc,char ** argv)66 int main(int argc , char **argv) {
67
68 intn status; /* status for functions returning an intn */
69 int32 file_id, /* HDF file identifier */
70 gr_id, /* GR interface identifier */
71 ri_id,
72 pal_id,
73 start[2], /* start position to write for each dimension */
74 stride[2],
75 dim_sizes[2], /* dimension sizes of the image array */
76 interlace_mode, /* interlace mode of the image */
77 data_type, /* data type of the image data */
78 i,
79 index;
80
81 char gr_name[256];
82
83 FILE *fpGif;
84
85 int32 ncomp;
86 int32 num_attrs;
87 int32 num_entries;
88 int32 n_images;
89 int32 n_fileattributes;
90
91 BYTE *Image;
92 /* compression structs */
93
94 char *HDFName;
95 char *GIFName;
96 /* reference variables */
97
98 int has_local_palette; /* treated as a flag */
99 int loop_times; /* number of times to loop, i'm going to treat it as a yes or no */
100
101 BYTE* b;
102 BYTE x;
103
104 BYTE GlobalPalette[256][3];
105 BYTE Red[256];
106 BYTE Green[256];
107 BYTE Blue[256];
108
109 int RWidth, RHeight;
110 int LeftOfs, TopOfs;
111 int ColorMapSize, InitCodeSize, Background, BitsPerPixel;
112 int j,nc;
113 int w,h;
114 int numcols = 256;
115 int CountDown;
116 int curx , cury;
117 int time_out;
118
119 BYTE pc2nc[256] , r1[256] , g1[256] , b1[256];
120 if (argc < 3) {
121 printf("Wrong number of arguments.\nUsage:\nhdf2gif <hdf file> <gif file>\n");
122 exit (-1);
123 }
124
125 HDFName = argv[1];
126 GIFName = argv[2];
127 /* Set a default 10 ms time between two consequetive images in case of multiple image file */
128 if (argc > 3)
129 time_out = atoi(argv[3]);
130 else
131 time_out = 10;
132
133 /* Do Endian Order testing and set Endian Order */
134 x = 0x0001;
135 b = (BYTE *) &w;
136 EndianOrder = (b[0] ? 1:0);
137
138 start[0] = start[1] = 0;
139 stride[0] = stride[1] = 1;
140
141 /*Start HDF file*/
142 file_id = Hopen(HDFName, DFACC_READ, 0);
143 if(file_id == -1) {
144 printf("Unable to open HDF file");
145 status = HEvalue(1);
146 printf("%s\n", HEstring(status));
147 exit(0);
148 }
149
150 if (!(fpGif = fopen(GIFName , "wb"))) {
151 printf("Error opening gif file for output. Aborting.\n");
152 exit (-1);
153 }
154
155 /* Open the hdf file using the GR interface and retrieve the images from it
156 ** Note that for now the images have to be 8 bit. If they are 24 bit this
157 ** program cannot handle it. I shall try to include it, if not please
158 ** refer to the file hdf2gif.c in the source code for the remormat utility.
159 ** There you should find the code to convert 24 bit images to 8 bit (GIF)
160 */
161 gr_id = GRstart(file_id);
162
163 if ((status = GRfileinfo(gr_id , &n_images , &n_fileattributes)) == -1) {
164 status = HEvalue(1);
165 printf("%s\n", HEstring(status));
166 exit(0);
167 }
168
169 if (n_images < 1) {
170 printf("Error: No GRimages found in hdf file. Aborting.\n");
171 exit (-1);
172 }
173
174
175 Background = 0;
176 for (index = 0 ; index < n_images ; index++) {
177
178 has_local_palette = true;
179 ri_id = GRselect(gr_id , index);
180 if ((pal_id = GRgetlutid(ri_id , 0)) == -1)
181 has_local_palette = false;
182
183 if (has_local_palette) {
184 status = GRgetlutinfo(pal_id , &ncomp , &data_type , &interlace_mode , &num_entries);
185 status = GRreadlut(pal_id , (VOIDP)&GlobalPalette);
186 }
187
188 status = GRgetiminfo(ri_id , gr_name , &ncomp , &data_type , &interlace_mode , dim_sizes , &num_attrs);
189 if (!(data_type == DFNT_CHAR || data_type == DFNT_UCHAR || data_type == DFNT_INT8 || data_type == DFNT_UINT8 || data_type == DFNT_NINT8 || data_type == DFNT_NUINT8)) {
190 printf("The GR data type of image %s in the hdf file appears not to be 8-bit. Trying next image...\n", gr_name);
191 continue;
192 }
193
194 /* BUG FIX 601 - pkamat */
195 if (1 != ncomp) { /* not an 8-bit image */
196 if (3 == ncomp) { /* 24-bit image */
197 printf("The GR data type of image %s in the hdf file appears to be a 24-bit image. ", gr_name);
198 printf("Use hdf2jpeg to convert this image. Trying next image... \n");
199 continue;
200 }
201 printf("The GR data type of image %s in the hdf file does not appear to be a 8-bit image. ", gr_name);
202 printf("Trying next image... \n");
203 continue;
204 }
205 /* End BUG FIX 601 */
206
207 Image = (BYTE *)malloc(dim_sizes[0] * dim_sizes[1]);
208 status = GRreadimage(ri_id , start , stride , dim_sizes , Image);
209 w = dim_sizes[0];
210 h = dim_sizes[1];
211
212 /* If the first image does not have a palette, I make my own global color table
213 ** Obviously this is not the best thing to do, better steps would be:
214 ** 1. Check for either a global palette or a global attribute called palette
215 ** 2. Check for palettes in any of the other images.
216 */
217 if (!has_local_palette) {
218 for (i = 0 ; i < 256 ; i++) {
219 Red[i] = 255 - i;
220 Green[i] = 255 - i;
221 Blue[i] = 255 - i;
222 }
223 }
224 else {
225 for (i = 0 ; i < 256 ; i++){
226 Red[i] = GlobalPalette[i][0];
227 Green[i] = GlobalPalette[i][1];
228 Blue[i] = GlobalPalette[i][2];
229 }
230 }
231
232 for (i=0; i<256; i++) { pc2nc[i] = r1[i] = g1[i] = b1[i] = 0; }
233 /* compute number of unique colors */
234 nc = 0;
235 for (i=0; i<numcols; i++) {
236 /* see if color #i is already used */
237 for (j=0; j<i; j++) {
238 if (Red[i] == Red[j] && Green[i] == Green[j] &&
239 Blue[i] == Blue[j]) break;
240 }
241 if (j==i) { /* wasn't found */
242 pc2nc[i] = nc;
243 r1[nc] = Red[i];
244 g1[nc] = Green[i];
245 b1[nc] = Blue[i];
246 nc++;
247 }
248 else pc2nc[i] = pc2nc[j];
249 }
250 /* figure out 'BitsPerPixel' */
251 for (i=1; i<8; i++) {
252 if ( (1<<i) >= nc) break;
253 }
254 BitsPerPixel = i;
255 ColorMapSize = 1 << BitsPerPixel;
256
257 RWidth = dim_sizes[0];
258 RHeight = dim_sizes[1];
259 LeftOfs = TopOfs = 0;
260
261 CountDown = w * h; /* # of pixels we'll be doing */
262
263 if (BitsPerPixel <= 1) InitCodeSize = 2;
264 else InitCodeSize = BitsPerPixel;
265
266 curx = cury = 0;
267
268 if (!fpGif) {
269 fprintf(stderr, "WriteGIF: file not open for writing\n" );
270 return (1);
271 }
272
273 /* If it is the first image we do all the header stuff that isn't required for the
274 ** rest of the images.
275 */
276 if (index == 0) {
277 /* Write out the GIF header and logical screen descriptor */
278 if (n_images > 0) {
279 fwrite("GIF89a", 1, 6, fpGif); /* the GIF magic number */
280 loop_times = 0;
281 }
282 else {
283 fwrite("GIF87a", 1, 6, fpGif); /* the GIF magic number */
284 loop_times = 1;
285 }
286
287 putword(RWidth, fpGif); /* screen descriptor */
288 putword(RHeight, fpGif);
289
290 i = 0x00; /* No, there is no color map */
291 i |= (8-1)<<4; /* OR in the color resolution (hardwired 8) */
292 i |= (BitsPerPixel - 1); /* OR in the # of bits per pixel */
293 fputc(i,fpGif);
294
295 fputc(Background,fpGif); /* background color */
296
297 fputc(0, fpGif); /* future expansion byte */
298
299
300 /* If loop_times is 0 , put in the application extension to make the gif anime loop
301 ** indefinitely
302 */
303 if (!loop_times) {
304 fputc(0x21 , fpGif);
305 fputc(0xFF , fpGif);
306 fputc(11 , fpGif);
307 fwrite("NETSCAPE2.0" , 1 , 11 , fpGif);
308 fputc(3 , fpGif);
309 fputc(1 , fpGif);
310 fputc(0 , fpGif);
311 fputc(0 , fpGif);
312 fputc(0 , fpGif);
313
314 }
315
316
317 }
318
319 if (n_images > 1) {
320 /* write a graphic control block */
321 fputc(0x21 , fpGif);
322 fputc(0xF9 , fpGif);
323 fputc(4 , fpGif);
324 fputc(4 , fpGif);
325 putword(time_out , fpGif);
326 fputc(255, fpGif);
327 fputc(0 , fpGif);
328 }
329
330 /* Put Image Descriptor
331 ** Hardwiring Left Offset and Top Offset to 0x00
332 */
333
334 fputc (0x2c , fpGif);
335 putword (0x00 , fpGif);
336 putword (0x00 , fpGif);
337 putword (RWidth , fpGif);
338 putword (RHeight , fpGif);
339 if (has_local_palette) {
340 fputc ((0x80 | (BitsPerPixel - 1)) , fpGif);
341 for (i=0; i<ColorMapSize; i++) { /* write out Global colormap */
342 fputc(r1[i], fpGif);
343 fputc(g1[i], fpGif);
344 fputc(b1[i], fpGif);
345 }
346 }
347 else
348 fputc (0x00 , fpGif);
349
350 fputc (InitCodeSize , fpGif);
351
352 i = hdfWriteGIF(fpGif , Image , 0 , dim_sizes[0] , dim_sizes[1] , r1, g1 , b1 , pc2nc , 256 , 8 , BitsPerPixel);
353 fputc(0x00 , fpGif);
354 free (Image);
355 status = GRendaccess (ri_id);
356 }
357
358 fputc(';',fpGif); /* Write GIF file terminator */
359 status = GRend (gr_id);
360
361 /* Close the HDF file */
362 status = Hclose (file_id);
363 fclose (fpGif);
364 return(0);
365 }
366