ftp.nice.ch/pub/next/graphics/viewer/ToyViewer.2.6a.s.tar.gz#/ToyViewer2.6a/src/gifbmap.c

This is gifbmap.c in view mode; [Download] [Up]

/*
	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;
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.