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