9 #define PUSH_PIXEL(p) \
11 if (pstk_idx == PSTK_SIZE) \
12 return GIFIN_ERR_PSO; \
14 pstk[pstk_idx++] = (p); \
18 * push a string (denoted by a code) onto the pixel stack
19 * (returns the code of the first pixel in the string in ps_rslt)
22 int ps_rslt; /* return result */
24 #define GIFIN_PUSH_STRING(code) \
29 while (((unsigned int)ps_code) < STAB_SIZE && prefix[ps_code] != NULL_CODE) \
31 PUSH_PIXEL(extnsn[ps_code]); \
32 ps_code = prefix[ps_code]; \
35 if (((unsigned int)ps_code) >= STAB_SIZE) \
36 return GIFIN_ERR_TAO; \
37 PUSH_PIXEL(extnsn[ps_code]); \
38 ps_rslt = extnsn[ps_code]; \
39 if (((unsigned int)ps_rslt) >= STAB_SIZE) \
40 return GIFIN_ERR_TAO; \
44 * Look up the ascii message coresponding to
47 static char *get_err_string(int errno)
50 for (i=0;gif_err_strings[i].err_no != 0;i++)
52 if (gif_err_strings[i].err_no == errno)
53 return gif_err_strings[i].name;
59 static int interlace_start[4] = /* start line for interlacing */
64 static int interlace_rate[4] = /* rate at which we accelerate vertically */
69 static BYTE file_open = 0; /* status flags */
70 static BYTE image_open = 0;
72 static FILE *ins; /* input stream */
74 static int root_size; /* root code size */
75 static int clr_code; /* clear code */
76 static int eoi_code; /* end of information code */
77 static int code_size; /* current code size */
78 static int code_mask; /* current code mask */
79 static int prev_code; /* previous code */
81 static long work_data; /* working bit buffer */
82 static int work_bits; /* working bit count */
84 static BYTE buf[256]; /* byte buffer */
85 static int buf_cnt; /* byte count */
86 static int buf_idx; /* buffer index */
88 static int table_size; /* string table size */
89 static int prefix[STAB_SIZE]; /* string table : prefixes */
90 static int extnsn[STAB_SIZE]; /* string table : extensions */
92 static BYTE pstk[PSTK_SIZE]; /* pixel stack */
93 static int pstk_idx; /* pixel stack pointer */
96 static int gifin_rast_width; /* raster width */
97 static int gifin_rast_height; /* raster height */
98 static BYTE gifin_g_cmap_flag; /* global colormap flag */
99 static int gifin_g_pixel_bits; /* bits per pixel, global colormap */
100 static int gifin_g_ncolors; /* number of colors, global colormap */
101 static BYTE gifin_g_cmap[3][256]; /* global colormap */
102 static BYTE gifin_g_cmap_sorted; /* global colormap sorted (GIF89a only) */
103 static int gifin_bg_color; /* background color index */
104 static int gifin_color_bits; /* bits of color resolution */
105 static double gifin_aspect; /* pixel aspect ratio (width/height) */
106 static int gifin_version; /* gif file version */
108 static int gifin_img_left; /* image position on raster */
109 static int gifin_img_top; /* image position on raster */
110 static int gifin_img_width; /* image width */
111 static int gifin_img_height; /* image height */
112 static BYTE gifin_l_cmap_flag; /* local colormap flag */
113 static int gifin_l_pixel_bits; /* bits per pixel, local colormap */
114 static int gifin_l_ncolors; /* number of colors, local colormap */
115 static BYTE gifin_l_cmap[3][256]; /* local colormap */
116 static BYTE gifin_interlace_flag; /* interlace image format flag */
119 * open a GIF file, using s as the input stream
122 static int gifin_open_file(FILE *s)
125 /* make sure there isn't already a file open */
127 return GIFIN_ERR_FAO;
129 /* remember that we've got this file open */
133 /* check GIF signature */
134 if (fread(buf, 1, GIF_SIG_LEN, ins) != GIF_SIG_LEN)
135 return GIFIN_ERR_EOF;
137 buf[GIF_SIG_LEN] = '\0';
138 if (strcmp((char *) buf, GIF_SIG) == 0)
139 gifin_version = GIF87a;
140 else if (strcmp((char *) buf, GIF_SIG_89) == 0)
141 gifin_version = GIF89a;
143 return GIFIN_ERR_BAD_SIG;
145 /* read screen descriptor */
146 if (fread(buf, 1, GIF_SD_SIZE, ins) != GIF_SD_SIZE)
147 return GIFIN_ERR_EOF;
149 /* decode screen descriptor */
150 gifin_rast_width = (buf[1] << 8) + buf[0];
151 gifin_rast_height = (buf[3] << 8) + buf[2];
152 gifin_g_cmap_flag = (buf[4] & 0x80) ? 1 : 0;
153 gifin_color_bits = (((int)(buf[4] & 0x70)) >> 4) + 1;
154 gifin_g_pixel_bits = (buf[4] & 0x07) + 1;
155 gifin_bg_color = buf[5];
158 if (gifin_version == GIF87a)
160 if (buf[4] & 0x08 || buf[6] != 0)
161 return GIFIN_ERR_BAD_SD;
165 gifin_g_cmap_sorted = ((buf[4] & 0x08) != 0);
167 gifin_aspect = ((double)buf[6] + 15.0) / 64.0;
170 /* load global colormap */
171 if (gifin_g_cmap_flag)
173 gifin_g_ncolors = (1 << gifin_g_pixel_bits);
175 if ((errno = gifin_load_cmap(gifin_g_cmap, gifin_g_ncolors)) != GIFIN_SUCCESS)
184 return GIFIN_SUCCESS;
189 * open next GIF image in the input stream; returns GIFIN_SUCCESS if
190 * successful. if there are no more images, returns GIFIN_DONE. (might
191 * also return various GIFIN_ERR codes.)
194 static int gifin_open_image()
200 /* make sure there's a file open */
202 return GIFIN_ERR_NFO;
204 /* make sure there isn't already an image open */
206 return GIFIN_ERR_IAO;
208 /* remember that we've got this image open */
211 /* skip over any extension blocks */
214 separator = fgetc(ins);
215 if (separator == GIF_EXTENSION)
217 if ((errno = gifin_skip_extension()) != GIFIN_SUCCESS)
221 while (separator == GIF_EXTENSION);
223 /* check for end of file marker */
224 if (separator == GIF_TERMINATOR)
227 /* make sure we've got an image separator */
228 if (separator != GIF_SEPARATOR)
229 return GIFIN_ERR_BAD_SEP;
231 /* read image descriptor */
232 if (fread(buf, 1, GIF_ID_SIZE, ins) != GIF_ID_SIZE)
233 return GIFIN_ERR_EOF;
235 /* decode image descriptor */
236 gifin_img_left = (buf[1] << 8) + buf[0];
237 gifin_img_top = (buf[3] << 8) + buf[2];
238 gifin_img_width = (buf[5] << 8) + buf[4];
239 gifin_img_height = (buf[7] << 8) + buf[6];
240 gifin_l_cmap_flag = (buf[8] & 0x80) ? 1 : 0;
241 gifin_interlace_flag = (buf[8] & 0x40) ? 1 : 0;
242 gifin_l_pixel_bits = (buf[8] & 0x07) + 1;
244 /* load local colormap */
245 if (gifin_l_cmap_flag)
247 gifin_l_ncolors = (1 << gifin_l_pixel_bits);
249 if ((errno = gifin_load_cmap(gifin_l_cmap, gifin_l_ncolors)) != GIFIN_SUCCESS)
257 /* initialize raster data stream decoder */
258 root_size = fgetc(ins);
259 clr_code = 1 << root_size;
260 eoi_code = clr_code + 1;
261 code_size = root_size + 1;
262 code_mask = (1 << code_size) - 1;
268 /* initialize string table */
269 for (i=0; i<STAB_SIZE; i++)
271 prefix[i] = NULL_CODE;
275 /* initialize pixel stack */
279 return GIFIN_SUCCESS;
283 * try to read next pixel from the raster, return result in *pel
286 static int gifin_get_pixel(pel)
294 /* decode until there are some pixels on the pixel stack */
295 while (pstk_idx == 0)
297 /* load bytes until we have enough bits for another code */
298 while (work_bits < code_size)
300 if (buf_idx == buf_cnt)
302 /* read a new data block */
303 if ((errno = gifin_read_data_block()) != GIFIN_SUCCESS)
307 return GIFIN_ERR_EOD;
310 work_data |= ((long) buf[buf_idx++]) << work_bits;
314 /* get the next code */
315 code = work_data & code_mask;
316 work_data >>= code_size;
317 work_bits -= code_size;
319 /* interpret the code */
320 if (code == clr_code)
322 /* reset decoder stream */
323 code_size = root_size + 1;
324 code_mask = (1 << code_size) - 1;
325 prev_code = NULL_CODE;
326 table_size = eoi_code + 1;
328 else if (code == eoi_code)
330 /* Ooops! no more pixels */
331 return GIFIN_ERR_EOF;
333 else if (prev_code == NULL_CODE)
335 GIFIN_PUSH_STRING(code);
340 if (code < table_size)
342 GIFIN_PUSH_STRING(code);
348 PUSH_PIXEL(NULL_CODE);
349 GIFIN_PUSH_STRING(prev_code);
354 if ((errno = gifin_add_string(prev_code, first)) != GIFIN_SUCCESS)
360 /* pop a pixel off the pixel stack */
361 *pel = (int) pstk[--pstk_idx];
364 return GIFIN_SUCCESS;
368 * close an open GIF file
371 static int gifin_close_file()
373 /* make sure there's a file open */
375 return GIFIN_ERR_NFO;
377 /* mark file (and image) as closed */
382 return GIFIN_SUCCESS;
386 * load a colormap from the input stream
389 static int gifin_load_cmap(BYTE cmap[3][256], int ncolors)
393 for (i=0; i<ncolors; i++)
395 if (fread(buf, 1, 3, ins) != 3)
396 return GIFIN_ERR_EOF;
398 cmap[GIF_RED][i] = buf[GIF_RED];
399 cmap[GIF_GRN][i] = buf[GIF_GRN];
400 cmap[GIF_BLU][i] = buf[GIF_BLU];
404 return GIFIN_SUCCESS;
408 * skip an extension block in the input stream
411 static int gifin_skip_extension()
415 /* get the extension function byte */
418 /* skip any remaining raster data */
421 if ((errno = gifin_read_data_block()) != GIFIN_SUCCESS)
427 return GIFIN_SUCCESS;
431 * read a new data block from the input stream
434 static int gifin_read_data_block()
436 /* read the data block header */
437 buf_cnt = fgetc(ins);
439 /* read the data block body */
440 if (fread(buf, 1, buf_cnt, ins) != buf_cnt)
441 return GIFIN_ERR_EOF;
446 return GIFIN_SUCCESS;
451 * add a new string to the string table
454 static int gifin_add_string(int p, int e)
456 prefix[table_size] = p;
457 extnsn[table_size] = e;
459 if ((table_size == code_mask) && (code_size < 12))
462 code_mask = (1 << code_size) - 1;
466 if (table_size > STAB_SIZE)
467 return GIFIN_ERR_TAO;
468 return GIFIN_SUCCESS;
471 Image *gifLoad(char *fullname)
475 int x, y, pixel, pass, scanlen;
476 byte *pixptr, *pixline;
479 if (!(f = fopen(fullname,"r")))
485 if ((gifin_open_file(f) != GIFIN_SUCCESS) || /* read GIF header */
486 (gifin_open_image() != GIFIN_SUCCESS)) /* read image header */
488 printf("gifin_open_file or gifin_open_image failed!\n");
498 printf("%s:\n %dx%d %s%s image with %d colors at depth %d\n",
499 fullname, gifin_img_width, gifin_img_height,
500 (gifin_interlace_flag ? "interlaced " : ""),
501 gif_version_name[gifin_version],
502 (gifin_l_cmap_flag ? gifin_l_ncolors : gifin_g_ncolors),
503 (gifin_l_cmap_flag ? gifin_l_pixel_bits : gifin_g_pixel_bits));
508 image = newRGBImage(gifin_img_width, gifin_img_height, (gifin_l_cmap_flag ?
510 gifin_g_pixel_bits));
511 image->title = dupString(fullname);
513 /* if image has a local colormap, override global colormap
516 if (gifin_l_cmap_flag)
518 for (x=0; x<gifin_l_ncolors; x++)
520 image->rgb.red[x] = gifin_l_cmap[GIF_RED][x] << 8;
521 image->rgb.green[x] = gifin_l_cmap[GIF_GRN][x] << 8;
522 image->rgb.blue[x] = gifin_l_cmap[GIF_BLU][x] << 8;
524 image->rgb.used = gifin_l_ncolors;
528 for (x=0; x<gifin_g_ncolors; x++)
530 image->rgb.red[x] = gifin_g_cmap[GIF_RED][x] << 8;
531 image->rgb.green[x] = gifin_g_cmap[GIF_GRN][x] << 8;
532 image->rgb.blue[x] = gifin_g_cmap[GIF_BLU][x] << 8;
534 image->rgb.used = gifin_g_ncolors;
537 /* interlaced image -- futz with the vertical trace. i wish i knew what
538 * kind of drugs the GIF people were on when they decided that they
539 * needed to support interlacing.
542 if (gifin_interlace_flag)
544 scanlen = image->height * image->pixlen;
546 /* interlacing takes four passes to read, each starting at a different
550 for (pass=0; pass<4; pass++)
552 y = interlace_start[pass];
553 scanlen = image->width * image->pixlen * interlace_rate[pass];
554 pixline = image->data + (y * image->width * image->pixlen);
555 while (y < gifin_img_height)
558 for (x=0; x<gifin_img_width; x++)
560 if ((errno = gifin_get_pixel(&pixel)) != GIFIN_SUCCESS)
562 fprintf(stderr, "gifLoad: %s - Short read within image data, '%s'\n", fullname, get_err_string(errno));
563 y = gifin_img_height;
566 valToMem(pixel, pixptr, image->pixlen);
567 pixptr += image->pixlen;
569 y += interlace_rate[pass];
576 /* not an interlaced image, just read in sequentially
579 if (image->pixlen == 1) /* the usual case */
581 pixptr = image->data;
582 for (y=0; y<gifin_img_height; y++)
583 for (x=0; x<gifin_img_width; x++)
585 if ((errno = gifin_get_pixel(&pixel)) != GIFIN_SUCCESS)
587 fprintf(stderr, "gifLoad: %s - Short read within image data, '%s'\n", fullname, get_err_string(errno));
588 y = gifin_img_height;
591 valToMem(pixel, pixptr, 1);
595 else /* less ususal case */
597 pixptr = image->data;
598 for (y=0; y<gifin_img_height; y++)
599 for (x=0; x<gifin_img_width; x++)
601 if ((errno = gifin_get_pixel(&pixel)) != GIFIN_SUCCESS)
603 fprintf(stderr, "gifLoad: %s - Short read within image data, '%s'\n", fullname, get_err_string(errno));
604 y = gifin_img_height;
607 valToMem(pixel, pixptr, image->pixlen);
608 pixptr += image->pixlen;