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 "gif.h"
- #include "strfunc.h"
-
- char *Comment;
-
- static int ReadColorMap(FILE *, gifHeader *gh);
- static int DoExtension(FILE *);
- static int ReadImage(FILE *, const gifHeader *, int, BOOL, unsigned char **);
-
- int gifGetImage(FILE *fp, gifHeader *gh, int *bits, unsigned char **planes)
- {
- int c, rt, bitp = 8;
- BOOL isgray = NO;
-
- Comment = NULL;
- if (gh->colormap) { /* Global Colormap */
- if ((bitp = ReadColorMap(fp, gh)) == 0)
- return Err_FORMAT;
- isgray = isGray(gh->palette, gh->colors);
- }
-
- while ((c = getc(fp)) != ',' ) { /* start character */
- if (c == EOF || c == ';') /* GIF terminator */
- return Err_SHORT;
- if (c == '!') { /* Extension */
- if (DoExtension(fp) < 0)
- return Err_ILLG;
- }
- /* other chars are illegal... ignore */
- }
- if (Comment)
- gh->memo = Comment, Comment = NULL;
-
- (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 ((bitp = ReadColorMap(fp, gh)) == 0)
- return Err_FORMAT;
- isgray = isGray(gh->palette, gh->colors);
- }
- /* Initialize the Compression routines */
- if (initGifLZW(fp) == EOF)
- return Err_SHORT;
- *bits = bitp;
- rt = ReadImage(fp, gh, bitp, isgray, planes);
- if (isgray || bitp == 1) planes[1] = NULL;
- return rt;
- }
-
- static int
- ReadColorMap(FILE *fd, gifHeader *gh)
- {
- int i, number;
- paltype *pal;
- unsigned char *p;
-
- number = gh->colors;
- if (gh->palette) {
- free((void *)gh->palette);
- gh->palette = NULL;
- }
- if ((pal = (paltype *)malloc(sizeof(paltype) * number)) == NULL)
- return 0;
- for (i = 0; i < number; ++i) {
- p = pal[i];
- p[RED] = getc(fd);
- p[GREEN] = getc(fd);
- p[BLUE] = getc(fd);
- if (feof(fd)) {
- free((void *)pal);
- return 0;
- }
- }
- gh->palette = pal;
- return howManyBits(gh->palette, number);
- }
-
- static int
- DoExtension(FILE *fd)
- {
- int cc;
- unsigned char buf[256];
-
- switch (cc = getc(fd)) {
- case 0x01: /* Plain Text Extension */
- case 0xff: /* Application Extension */
- case 0xf9: /* Graphic Control Extension */
- break;
- case 0xfe: /* Comment Extension */
- while (GetDataBlock(fd, buf) != 0) {
- if (Comment == NULL)
- Comment = (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, int bitp, BOOL isgray,
- unsigned char **planes)
- {
- int xpos, ypos, xbyte, pass, err;
- long wd;
- unsigned char *map[5];
- unsigned char buffer[MAXWidth];
-
- err = allocImage(planes, gh->width, gh->height, bitp, isgray);
- if (err)
- return err;
- pass = 0;
- xbyte = byte_length(bitp, gh->width);
-
- for (ypos = 0; ; ) {
- for (xpos = 0; xpos < gh->width; xpos++)
- buffer[xpos] = LWZReadByte(fd);
- map[0] = planes[0] + (wd = xbyte * ypos);
- if (!isgray) {
- map[1] = planes[1] + wd;
- map[2] = planes[2] + wd;
- }
- expandImage(map,
- buffer, gh->palette, bitp, gh->width, isgray);
- 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;
- }
-