home *** CD-ROM | disk | FTP | other *** search
- /*
- gifbmap.h
-
- gifheader.c, gifbmap.c, and gif.h are based on "giftoppm"
- of David Koblas.
- They are modified by T. Ogihara. (1995)
- */
-
- /* +-------------------------------------------------------------------+ */
- /* | Copyright 1990, David Koblas. | */
- /* | Permission to use, copy, modify, and distribute this software | */
- /* | and its documentation for any purpose and without fee is hereby | */
- /* | granted, provided that the above copyright notice appear in all | */
- /* | copies and that both that copyright notice and this permission | */
- /* | notice appear in supporting documentation. This software is | */
- /* | provided "as is" without express or implied warranty. | */
- /* +-------------------------------------------------------------------+ */
-
- #include <signal.h>
- #include <setjmp.h>
- #include "gif.h"
- #include "strfunc.h"
-
- static int ReadColorMap(FILE *, gifHeader *);
- static int DoExtension(FILE *, gifHeader *);
- static int ReadImage(FILE *, const gifHeader *, unsigned char **);
-
- static void (*sav_violation)() = NULL;
- static void (*sav_buserror)() = NULL;
- static jmp_buf sav_env;
-
- static void
- catch_violation(int sig)
- {
- longjmp(sav_env, sig);
- }
-
- int gifGetImage(FILE *fp, gifHeader *gh, unsigned char **planes)
- {
- int c, rtn = 0;
-
- if (gh->colormap) { /* Global Colormap */
- if (ReadColorMap(fp, gh) == 0)
- return Err_FORMAT;
- }
-
- while ((c = getc(fp)) != ',' ) { /* start character */
- if (c == EOF || c == ';') /* GIF terminator */
- return Err_SHORT;
- if (c == '!') { /* Extension */
- if (DoExtension(fp, gh) < 0)
- return Err_ILLG;
- }
- /* other chars are illegal... ignore */
- }
-
- (void)get_long(fp); /* skip 4 bytes */
- gh->width = get_short(fp);
- gh->height = get_short(fp);
- c = getc(fp);
- gh->interlace = BitSet(c, INTERLACE);
- if (BitSet(c, LOCALCOLORMAP)) { /* Use Local Color Map */
- gh->colors = 2 << (c & 0x07);
- if (ReadColorMap(fp, gh) == 0)
- return Err_FORMAT;
- }
- if (gh->transp >= 0) {
- unsigned char *p = (unsigned char *)gh->palette[gh->transp];
- p[RED] = p[GREEN] = p[BLUE] = 255;
- if (gh->colors - 1 == gh->transp)
- --gh->colors; /* if last of palette is transp. */
- }
- gh->bits = howManyBits(gh->palette, gh->colors);
- gh->isgray = isGray(gh->palette, gh->colors);
- /* Initialize the Compression routines */
- if (initGifLZW(fp) == EOF)
- return Err_SHORT;
-
- sav_violation = signal(SIGSEGV, catch_violation);
- sav_buserror = signal(SIGBUS, catch_violation);
- if (setjmp(sav_env) == 0)
- rtn = ReadImage(fp, gh, planes);
- else /* return from Segmentation Error */
- rtn = Err_FORMAT;
- (void) signal(SIGSEGV, sav_violation);
- (void) signal(SIGBUS, sav_buserror);
- return rtn;
- }
-
- static int
- ReadColorMap(FILE *fd, gifHeader *gh)
- {
- int i, j, number;
- unsigned char *p, *q;
-
- number = gh->colors;
- for (i = 0; i < number; ++i) {
- p = (unsigned char *)gh->palette[i];
- p[RED] = getc(fd);
- p[GREEN] = getc(fd);
- p[BLUE] = getc(fd);
- if (feof(fd))
- return 0;
- }
- for (i = number - 1; i > 0; --i) { /* skip stab */
- p = (unsigned char *)gh->palette[i];
- q = (unsigned char *)gh->palette[i - 1];
- for (j = 0; j < 3; j++)
- if (p[j] != q[j]) goto EXIT;
- }
- EXIT:
- gh->colors = i + 1;
- return 1;
- }
-
- static int
- DoExtension(FILE *fd, gifHeader *gh)
- {
- int cc;
- unsigned char buf[256];
-
- switch (cc = getc(fd)) {
- case 0x01: /* Plain Text Extension */
- case 0x2c: /* Image Descriptor */
- case 0x3b: /* Trailer */
- case 0xff: /* Application Extension */
- break;
- case 0xf9: /* Graphic Control Extension */
- while (GetDataBlock(fd, buf) != 0) {
- if (BitSet(buf[0], TRANSPARENCY))
- gh->transp = buf[3]; /* Transparent Index */
- }
- return cc;
- case 0xfe: /* Comment Extension */
- while (GetDataBlock(fd, buf) != 0) {
- if (gh->memo == NULL)
- gh->memo = (unsigned char *)str_dup(buf);
- }
- return cc;
- default:
- return -1; /* ERROR */
- }
- while (GetDataBlock(fd, buf) != 0)
- ;
- return cc;
- }
-
- static int
- ReadImage(FILE *fd, const gifHeader *gh, unsigned char **planes)
- {
- int i, xpos, ypos, xbyte, pass, pn, err;
- long wd;
- unsigned char *map[MAXPLANE];
- unsigned char buffer[MAXWidth];
-
- pn = (gh->isgray ? 1:3) + ((gh->transp >= 0) ? 1 : 0);
- err = allocImage(planes, gh->width, gh->height, gh->bits, pn);
- if (err)
- return err;
- pass = 0;
- xbyte = byte_length(gh->bits, gh->width);
-
- for (ypos = 0; ; ) {
- for (xpos = 0; xpos < gh->width; xpos++)
- buffer[xpos] = LWZReadByte(fd);
- map[0] = planes[0] + (wd = xbyte * ypos);
- for (i = 1; i < pn; i++)
- map[i] = planes[i] + wd;
- expandImage(map, buffer, (const paltype *)gh->palette,
- gh->bits, gh->width, gh->isgray, gh->transp);
- if (gh->interlace) {
- ypos += pass ? (0x10 >> pass) : 0x08;
- if (ypos >= gh->height) {
- if (++pass > 3)
- break;
- ypos = 8 >> pass;
- }
- }else {
- if (++ypos >= gh->height)
- break;
- }
- }
- return 0;
- }
-