Blame src/gd_gif_in.c

Packit Service df60bb
/**
Packit Service df60bb
 * File: GIF Input
Packit Service df60bb
 *
Packit Service df60bb
 * Read GIF images.
Packit Service df60bb
 */
Packit Service df60bb
Packit Service df60bb
#ifdef HAVE_CONFIG_H
Packit Service df60bb
#include "config.h"
Packit Service df60bb
#endif
Packit Service df60bb
Packit Service df60bb
#include <stdio.h>
Packit Service df60bb
#include <math.h>
Packit Service df60bb
#include <string.h>
Packit Service df60bb
#include <stdlib.h>
Packit Service df60bb
#include "gd.h"
Packit Service df60bb
Packit Service df60bb
/* Used only when debugging GIF compression code */
Packit Service df60bb
/* #define DEBUGGING_ENVARS */
Packit Service df60bb
Packit Service df60bb
#ifdef DEBUGGING_ENVARS
Packit Service df60bb
Packit Service df60bb
static int verbose_set = 0;
Packit Service df60bb
static int verbose;
Packit Service df60bb
Packit Service df60bb
#define VERBOSE (verbose_set ? verbose : set_verbose())
Packit Service df60bb
Packit Service df60bb
static int set_verbose(void)
Packit Service df60bb
{
Packit Service df60bb
	verbose = !!getenv("GIF_VERBOSE");
Packit Service df60bb
	verbose_set = 1;
Packit Service df60bb
	return(verbose);
Packit Service df60bb
}
Packit Service df60bb
Packit Service df60bb
#else
Packit Service df60bb
Packit Service df60bb
#define VERBOSE	0
Packit Service df60bb
Packit Service df60bb
#endif
Packit Service df60bb
Packit Service df60bb
#define MAXCOLORMAPSIZE	256
Packit Service df60bb
Packit Service df60bb
#define TRUE	1
Packit Service df60bb
#define FALSE	0
Packit Service df60bb
Packit Service df60bb
#define CM_RED		0
Packit Service df60bb
#define CM_GREEN	1
Packit Service df60bb
#define CM_BLUE		2
Packit Service df60bb
Packit Service df60bb
#define MAX_LWZ_BITS	12
Packit Service df60bb
Packit Service df60bb
#define INTERLACE		0x40
Packit Service df60bb
#define LOCALCOLORMAP	0x80
Packit Service df60bb
Packit Service df60bb
#define BitSet(byte, bit)	(((byte) & (bit)) == (bit))
Packit Service df60bb
Packit Service df60bb
#define ReadOK(file, buffer, len) (gdGetBuf(buffer, len, file) > 0)
Packit Service df60bb
Packit Service df60bb
#define LM_to_uint(a, b)	(((b)<<8)|(a))
Packit Service df60bb
Packit Service df60bb
/* We may eventually want to use this information, but def it out for now */
Packit Service df60bb
#if 0
Packit Service df60bb
static struct {
Packit Service df60bb
	unsigned int    Width;
Packit Service df60bb
	unsigned int    Height;
Packit Service df60bb
	unsigned char   ColorMap[3][MAXCOLORMAPSIZE];
Packit Service df60bb
	unsigned int    BitPixel;
Packit Service df60bb
	unsigned int    ColorResolution;
Packit Service df60bb
	unsigned int    Background;
Packit Service df60bb
	unsigned int    AspectRatio;
Packit Service df60bb
} GifScreen;
Packit Service df60bb
#endif
Packit Service df60bb
Packit Service df60bb
#if 0
Packit Service df60bb
static struct {
Packit Service df60bb
	int     transparent;
Packit Service df60bb
	int     delayTime;
Packit Service df60bb
	int     inputFlag;
Packit Service df60bb
	int     disposal;
Packit Service df60bb
} Gif89 = { -1, -1, -1, 0 };
Packit Service df60bb
#endif
Packit Service df60bb
Packit Service df60bb
#define STACK_SIZE ((1<<(MAX_LWZ_BITS))*2)
Packit Service df60bb
Packit Service df60bb
#define CSD_BUF_SIZE 280
Packit Service df60bb
Packit Service df60bb
typedef struct {
Packit Service df60bb
	unsigned char buf[CSD_BUF_SIZE];
Packit Service df60bb
	int curbit;
Packit Service df60bb
	int lastbit;
Packit Service df60bb
	int done;
Packit Service df60bb
	int last_byte;
Packit Service df60bb
} CODE_STATIC_DATA;
Packit Service df60bb
Packit Service df60bb
typedef struct {
Packit Service df60bb
	int fresh;
Packit Service df60bb
	int code_size, set_code_size;
Packit Service df60bb
	int max_code, max_code_size;
Packit Service df60bb
	int firstcode, oldcode;
Packit Service df60bb
	int clear_code, end_code;
Packit Service df60bb
	int table[2][(1<< MAX_LWZ_BITS)];
Packit Service df60bb
	int stack[STACK_SIZE], *sp;
Packit Service df60bb
	CODE_STATIC_DATA scd;
Packit Service df60bb
} LZW_STATIC_DATA;
Packit Service df60bb
Packit Service df60bb
static int ReadColorMap (gdIOCtx *fd, int number, unsigned char (*buffer)[256]);
Packit Service df60bb
static int DoExtension (gdIOCtx *fd, int label, int *Transparent, int *ZeroDataBlockP);
Packit Service df60bb
static int GetDataBlock (gdIOCtx *fd, unsigned char *buf, int *ZeroDataBlockP);
Packit Service df60bb
static int GetCode (gdIOCtx *fd, CODE_STATIC_DATA *scd, int code_size, int flag, int *ZeroDataBlockP);
Packit Service df60bb
static int LWZReadByte (gdIOCtx *fd, LZW_STATIC_DATA *sd, char flag, int input_code_size, int *ZeroDataBlockP);
Packit Service df60bb
Packit Service df60bb
static void ReadImage (gdImagePtr im, gdIOCtx *fd, int len, int height, unsigned char (*cmap)[256], int interlace, int *ZeroDataBlockP); /*1.4//, int ignore); */
Packit Service df60bb
Packit Service df60bb
/*
Packit Service df60bb
  Function: gdImageCreateFromGif
Packit Service df60bb
Packit Service df60bb
    <gdImageCreateFromGif> is called to load images from GIF format
Packit Service df60bb
    files. Invoke <gdImageCreateFromGif> with an already opened
Packit Service df60bb
    pointer to a file containing the desired
Packit Service df60bb
    image.
Packit Service df60bb
Packit Service df60bb
    <gdImageCreateFromGif> returns a <gdImagePtr> to the new image, or
Packit Service df60bb
    NULL if unable to load the image (most often because the file is
Packit Service df60bb
    corrupt or does not contain a GIF image). <gdImageCreateFromGif>
Packit Service df60bb
    does not close the file. You can inspect the sx and sy members of
Packit Service df60bb
    the image to determine its size. The image must eventually be
Packit Service df60bb
    destroyed using <gdImageDestroy>.
Packit Service df60bb
Packit Service df60bb
  Variants:
Packit Service df60bb
Packit Service df60bb
    <gdImageCreateFromGifPtr> creates an image from GIF data (i.e. the
Packit Service df60bb
    contents of a GIF file) already in memory.
Packit Service df60bb
Packit Service df60bb
    <gdImageCreateFromGifCtx> reads in an image using the functions in
Packit Service df60bb
    a <gdIOCtx> struct.
Packit Service df60bb
Packit Service df60bb
  Parameters:
Packit Service df60bb
Packit Service df60bb
    infile - The input FILE pointer
Packit Service df60bb
Packit Service df60bb
  Returns:
Packit Service df60bb
Packit Service df60bb
    A pointer to the new image or NULL if an error occurred.
Packit Service df60bb
Packit Service df60bb
  Example:
Packit Service df60bb
Packit Service df60bb
    > gdImagePtr im;
Packit Service df60bb
    > ... inside a function ...
Packit Service df60bb
    > FILE *in;
Packit Service df60bb
    > in = fopen("mygif.gif", "rb");
Packit Service df60bb
    > im = gdImageCreateFromGif(in);
Packit Service df60bb
    > fclose(in);
Packit Service df60bb
    > // ... Use the image ... 
Packit Service df60bb
    > gdImageDestroy(im);
Packit Service df60bb
Packit Service df60bb
*/
Packit Service df60bb
BGD_DECLARE(gdImagePtr) gdImageCreateFromGif(FILE *fdFile)
Packit Service df60bb
{
Packit Service df60bb
	gdIOCtx *fd = gdNewFileCtx(fdFile);
Packit Service df60bb
	gdImagePtr im;
Packit Service df60bb
Packit Service df60bb
	if (fd == NULL) return NULL;
Packit Service df60bb
	im = gdImageCreateFromGifCtx(fd);
Packit Service df60bb
Packit Service df60bb
	fd->gd_free(fd);
Packit Service df60bb
Packit Service df60bb
	return im;
Packit Service df60bb
}
Packit Service df60bb
Packit Service df60bb
/*
Packit Service df60bb
  Function: gdImageCreateFromGifPtr
Packit Service df60bb
Packit Service df60bb
  Parameters:
Packit Service df60bb
Packit Service df60bb
    size - size of GIF data in bytes.
Packit Service df60bb
    data - GIF data (i.e. contents of a GIF file).
Packit Service df60bb
Packit Service df60bb
  See <gdImageCreateFromGif>.
Packit Service df60bb
*/
Packit Service df60bb
BGD_DECLARE(gdImagePtr) gdImageCreateFromGifPtr (int size, void *data)
Packit Service df60bb
{
Packit Service df60bb
	gdImagePtr im;
Packit Service df60bb
	gdIOCtx *in = gdNewDynamicCtxEx(size, data, 0);
Packit Service df60bb
	if(!in) {
Packit Service df60bb
		return 0;
Packit Service df60bb
	}
Packit Service df60bb
	im = gdImageCreateFromGifCtx(in);
Packit Service df60bb
	in->gd_free(in);
Packit Service df60bb
	return im;
Packit Service df60bb
}
Packit Service df60bb
Packit Service df60bb
/*
Packit Service df60bb
  Function: gdImageCreateFromGifCtx
Packit Service df60bb
Packit Service df60bb
  See <gdImageCreateFromGif>.
Packit Service df60bb
*/
Packit Service df60bb
BGD_DECLARE(gdImagePtr) gdImageCreateFromGifCtx(gdIOCtxPtr fd)
Packit Service df60bb
{
Packit Service df60bb
	int BitPixel;
Packit Service df60bb
#if 0
Packit Service df60bb
	int ColorResolution;
Packit Service df60bb
	int Background;
Packit Service df60bb
	int AspectRatio;
Packit Service df60bb
#endif
Packit Service df60bb
	int Transparent = (-1);
Packit Service df60bb
	unsigned char buf[16];
Packit Service df60bb
	unsigned char c;
Packit Service df60bb
	unsigned char ColorMap[3][MAXCOLORMAPSIZE];
Packit Service df60bb
	unsigned char localColorMap[3][MAXCOLORMAPSIZE];
Packit Service df60bb
	int imw, imh, screen_width, screen_height;
Packit Service df60bb
	int useGlobalColormap;
Packit Service df60bb
	int bitPixel, i;
Packit Service df60bb
	/*1.4//int             imageCount = 0; */
Packit Service df60bb
	/* 2.0.28: threadsafe storage */
Packit Service df60bb
	int ZeroDataBlock = FALSE;
Packit Service df60bb
	int haveGlobalColormap;
Packit Service df60bb
Packit Service df60bb
	gdImagePtr im = 0;
Packit Service df60bb
Packit Service df60bb
	memset(ColorMap, 0, 3 * MAXCOLORMAPSIZE);
Packit Service df60bb
	memset(localColorMap, 0, 3 * MAXCOLORMAPSIZE);
Packit Service df60bb
Packit Service df60bb
	if(!ReadOK(fd, buf, 6)) {
Packit Service df60bb
		return 0;
Packit Service df60bb
	}
Packit Service df60bb
Packit Service df60bb
	if(strncmp((char *)buf, "GIF", 3) != 0) {
Packit Service df60bb
		return 0;
Packit Service df60bb
	}
Packit Service df60bb
Packit Service df60bb
	if(memcmp((char *)buf + 3, "87a", 3) == 0) {
Packit Service df60bb
		/* GIF87a */
Packit Service df60bb
	} else if(memcmp((char *)buf + 3, "89a", 3) == 0) {
Packit Service df60bb
		/* GIF89a */
Packit Service df60bb
	} else {
Packit Service df60bb
		return 0;
Packit Service df60bb
	}
Packit Service df60bb
Packit Service df60bb
	if(!ReadOK(fd, buf, 7)) {
Packit Service df60bb
		return 0;
Packit Service df60bb
	}
Packit Service df60bb
Packit Service df60bb
	BitPixel = 2 << (buf[4] & 0x07);
Packit Service df60bb
#if 0
Packit Service df60bb
	ColorResolution = (int) (((buf[4]&0x70)>>3)+1);
Packit Service df60bb
	Background = buf[5];
Packit Service df60bb
	AspectRatio = buf[6];
Packit Service df60bb
#endif
Packit Service df60bb
	screen_width = imw = LM_to_uint(buf[0], buf[1]);
Packit Service df60bb
	screen_height = imh = LM_to_uint(buf[2], buf[3]);
Packit Service df60bb
Packit Service df60bb
	haveGlobalColormap = BitSet(buf[4], LOCALCOLORMAP); /* Global Colormap */
Packit Service df60bb
	if(haveGlobalColormap) {
Packit Service df60bb
		if(ReadColorMap(fd, BitPixel, ColorMap)) {
Packit Service df60bb
			return 0;
Packit Service df60bb
		}
Packit Service df60bb
	}
Packit Service df60bb
Packit Service df60bb
	for (;;) {
Packit Service df60bb
		int top, left;
Packit Service df60bb
		int width, height;
Packit Service df60bb
Packit Service df60bb
		if(!ReadOK(fd, &c, 1)) {
Packit Service df60bb
			return 0;
Packit Service df60bb
		}
Packit Service df60bb
Packit Service df60bb
		if (c == ';') { /* GIF terminator */
Packit Service df60bb
			goto terminated;
Packit Service df60bb
		}
Packit Service df60bb
Packit Service df60bb
		if(c == '!') { /* Extension */
Packit Service df60bb
			if(!ReadOK(fd, &c, 1)) {
Packit Service df60bb
				return 0;
Packit Service df60bb
			}
Packit Service df60bb
Packit Service df60bb
			DoExtension(fd, c, &Transparent, &ZeroDataBlock);
Packit Service df60bb
			continue;
Packit Service df60bb
		}
Packit Service df60bb
Packit Service df60bb
		if(c != ',') { /* Not a valid start character */
Packit Service df60bb
			continue;
Packit Service df60bb
		}
Packit Service df60bb
Packit Service df60bb
		/*1.4//++imageCount; */
Packit Service df60bb
Packit Service df60bb
		if(!ReadOK(fd, buf, 9)) {
Packit Service df60bb
			return 0;
Packit Service df60bb
		}
Packit Service df60bb
Packit Service df60bb
		useGlobalColormap = !BitSet(buf[8], LOCALCOLORMAP);
Packit Service df60bb
Packit Service df60bb
		bitPixel = 1 << ((buf[8] & 0x07) + 1);
Packit Service df60bb
		left = LM_to_uint(buf[0], buf[1]);
Packit Service df60bb
		top = LM_to_uint(buf[2], buf[3]);
Packit Service df60bb
		width = LM_to_uint(buf[4], buf[5]);
Packit Service df60bb
		height = LM_to_uint(buf[6], buf[7]);
Packit Service df60bb
Packit Service df60bb
		if(((left + width) > screen_width) || ((top + height) > screen_height)) {
Packit Service df60bb
			if(VERBOSE) {
Packit Service df60bb
				printf("Frame is not confined to screen dimension.\n");
Packit Service df60bb
			}
Packit Service df60bb
			return 0;
Packit Service df60bb
		}
Packit Service df60bb
Packit Service df60bb
		if(!(im = gdImageCreate(width, height))) {
Packit Service df60bb
			return 0;
Packit Service df60bb
		}
Packit Service df60bb
Packit Service df60bb
		im->interlace = BitSet(buf[8], INTERLACE);
Packit Service df60bb
		if(!useGlobalColormap) {
Packit Service df60bb
			if(ReadColorMap(fd, bitPixel, localColorMap)) {
Packit Service df60bb
				gdImageDestroy(im);
Packit Service df60bb
				return 0;
Packit Service df60bb
			}
Packit Service df60bb
Packit Service df60bb
			ReadImage(im, fd, width, height, localColorMap, BitSet(buf[8], INTERLACE), &ZeroDataBlock);
Packit Service df60bb
		} else {
Packit Service df60bb
			if(!haveGlobalColormap) {
Packit Service df60bb
				gdImageDestroy(im);
Packit Service df60bb
				return 0;
Packit Service df60bb
			}
Packit Service df60bb
Packit Service df60bb
			ReadImage(im, fd, width, height, ColorMap, BitSet(buf[8], INTERLACE), &ZeroDataBlock);
Packit Service df60bb
		}
Packit Service df60bb
Packit Service df60bb
		if(Transparent != (-1)) {
Packit Service df60bb
			gdImageColorTransparent(im, Transparent);
Packit Service df60bb
		}
Packit Service df60bb
Packit Service df60bb
		goto terminated;
Packit Service df60bb
	}
Packit Service df60bb
Packit Service df60bb
terminated:
Packit Service df60bb
	/* Terminator before any image was declared! */
Packit Service df60bb
	if(!im) {
Packit Service df60bb
		return 0;
Packit Service df60bb
	}
Packit Service df60bb
Packit Service df60bb
	/* Check for open colors at the end, so
Packit Service df60bb
	 * we can reduce colorsTotal and ultimately
Packit Service df60bb
	 * BitsPerPixel */
Packit Service df60bb
	for(i = im->colorsTotal - 1; i >= 0; i--) {
Packit Service df60bb
		if(im->open[i]) {
Packit Service df60bb
			im->colorsTotal--;
Packit Service df60bb
		} else {
Packit Service df60bb
			break;
Packit Service df60bb
		}
Packit Service df60bb
	}
Packit Service df60bb
Packit Service f38d28
	if(!im->colorsTotal) {
Packit Service f38d28
		gdImageDestroy(im);
Packit Service f38d28
		return 0;
Packit Service f38d28
	}
Packit Service f38d28
Packit Service df60bb
	return im;
Packit Service df60bb
}
Packit Service df60bb
Packit Service df60bb
static int
Packit Service df60bb
ReadColorMap(gdIOCtx *fd, int number, unsigned char (*buffer)[256])
Packit Service df60bb
{
Packit Service df60bb
	int i;
Packit Service df60bb
	unsigned char rgb[3];
Packit Service df60bb
Packit Service df60bb
	for(i = 0; i < number; ++i) {
Packit Service df60bb
		if(!ReadOK(fd, rgb, sizeof(rgb))) {
Packit Service df60bb
			return TRUE;
Packit Service df60bb
		}
Packit Service df60bb
Packit Service df60bb
		buffer[CM_RED][i] = rgb[0];
Packit Service df60bb
		buffer[CM_GREEN][i] = rgb[1];
Packit Service df60bb
		buffer[CM_BLUE][i] = rgb[2];
Packit Service df60bb
	}
Packit Service df60bb
Packit Service df60bb
	return FALSE;
Packit Service df60bb
}
Packit Service df60bb
Packit Service df60bb
static int
Packit Service df60bb
DoExtension(gdIOCtx *fd, int label, int *Transparent, int *ZeroDataBlockP)
Packit Service df60bb
{
Packit Service df60bb
	unsigned char buf[256];
Packit Service df60bb
Packit Service df60bb
	switch(label) {
Packit Service df60bb
	case 0xf9: /* Graphic Control Extension */
Packit Service df60bb
		memset(buf, 0, 4); /* initialize a few bytes in the case the next function fails */
Packit Service df60bb
		(void) GetDataBlock(fd, (unsigned char*) buf, ZeroDataBlockP);
Packit Service df60bb
#if 0
Packit Service df60bb
		Gif89.disposal  = (buf[0] >> 2) & 0x7;
Packit Service df60bb
		Gif89.inputFlag = (buf[0] >> 1) & 0x1;
Packit Service df60bb
		Gif89.delayTime = LM_to_uint(buf[1], buf[2]);
Packit Service df60bb
#endif
Packit Service df60bb
		if((buf[0] & 0x1) != 0) {
Packit Service df60bb
			*Transparent = buf[3];
Packit Service df60bb
		}
Packit Service df60bb
Packit Service df60bb
		while(GetDataBlock(fd, (unsigned char*) buf, ZeroDataBlockP) > 0);
Packit Service df60bb
Packit Service df60bb
		return FALSE;
Packit Service df60bb
Packit Service df60bb
	default:
Packit Service df60bb
		break;
Packit Service df60bb
	}
Packit Service df60bb
Packit Service df60bb
	while(GetDataBlock(fd, (unsigned char*) buf, ZeroDataBlockP) > 0);
Packit Service df60bb
Packit Service df60bb
	return FALSE;
Packit Service df60bb
}
Packit Service df60bb
Packit Service df60bb
static int
Packit Service df60bb
GetDataBlock_(gdIOCtx *fd, unsigned char *buf, int *ZeroDataBlockP)
Packit Service df60bb
{
Packit Service df60bb
	unsigned char count;
Packit Service df60bb
Packit Service df60bb
	if(!ReadOK(fd, &count, 1)) {
Packit Service df60bb
		return -1;
Packit Service df60bb
	}
Packit Service df60bb
Packit Service df60bb
	*ZeroDataBlockP = count == 0;
Packit Service df60bb
Packit Service df60bb
	if((count != 0) && (!ReadOK(fd, buf, count))) {
Packit Service df60bb
		return -1;
Packit Service df60bb
	}
Packit Service df60bb
Packit Service df60bb
	return count;
Packit Service df60bb
}
Packit Service df60bb
Packit Service df60bb
static int
Packit Service df60bb
GetDataBlock(gdIOCtx *fd, unsigned char *buf, int *ZeroDataBlockP)
Packit Service df60bb
{
Packit Service df60bb
	int rv, i;
Packit Service df60bb
Packit Service df60bb
	rv = GetDataBlock_(fd,buf, ZeroDataBlockP);
Packit Service df60bb
Packit Service df60bb
	if(VERBOSE) {
Packit Service df60bb
		printf("[GetDataBlock returning %d",rv);
Packit Service df60bb
		if(rv > 0) {
Packit Service df60bb
			printf(":");
Packit Service df60bb
			for(i = 0; i < rv; i++) {
Packit Service df60bb
				printf(" %02x",buf[i]);
Packit Service df60bb
			}
Packit Service df60bb
		}
Packit Service df60bb
		printf("]\n");
Packit Service df60bb
	}
Packit Service df60bb
Packit Service df60bb
	return rv;
Packit Service df60bb
}
Packit Service df60bb
Packit Service df60bb
static int
Packit Service df60bb
GetCode_(gdIOCtx *fd, CODE_STATIC_DATA *scd, int code_size, int flag, int *ZeroDataBlockP)
Packit Service df60bb
{
Packit Service df60bb
	int i, j, ret;
Packit Service f38d28
	int count;
Packit Service df60bb
Packit Service df60bb
	if(flag) {
Packit Service df60bb
		scd->curbit = 0;
Packit Service df60bb
		scd->lastbit = 0;
Packit Service df60bb
		scd->last_byte = 2;
Packit Service df60bb
		scd->done = FALSE;
Packit Service df60bb
		return 0;
Packit Service df60bb
	}
Packit Service df60bb
Packit Service df60bb
	if((scd->curbit + code_size) >= scd->lastbit) {
Packit Service df60bb
		if(scd->done) {
Packit Service df60bb
			if(scd->curbit >= scd->lastbit) {
Packit Service df60bb
				/* Oh well */
Packit Service df60bb
			}
Packit Service df60bb
			return -1;
Packit Service df60bb
		}
Packit Service df60bb
Packit Service df60bb
		scd->buf[0] = scd->buf[scd->last_byte - 2];
Packit Service df60bb
		scd->buf[1] = scd->buf[scd->last_byte - 1];
Packit Service df60bb
Packit Service df60bb
		if((count = GetDataBlock(fd, &scd->buf[2], ZeroDataBlockP)) <= 0) {
Packit Service df60bb
			scd->done = TRUE;
Packit Service df60bb
		}
Packit Service df60bb
Packit Service df60bb
		scd->last_byte = 2 + count;
Packit Service df60bb
		scd->curbit = (scd->curbit - scd->lastbit) + 16;
Packit Service df60bb
		scd->lastbit = (2 + count) * 8;
Packit Service df60bb
	}
Packit Service df60bb
Packit Service df60bb
	if ((scd->curbit + code_size - 1) >= (CSD_BUF_SIZE * 8)) {
Packit Service df60bb
		ret = -1;
Packit Service df60bb
	} else {
Packit Service df60bb
		ret = 0;
Packit Service df60bb
		for (i = scd->curbit, j = 0; j < code_size; ++i, ++j) {
Packit Service df60bb
			ret |= ((scd->buf[i / 8] & (1 << (i % 8))) != 0) << j;
Packit Service df60bb
		}
Packit Service df60bb
	}
Packit Service df60bb
Packit Service df60bb
	scd->curbit += code_size;
Packit Service df60bb
Packit Service df60bb
	return ret;
Packit Service df60bb
}
Packit Service df60bb
Packit Service df60bb
static int
Packit Service df60bb
GetCode(gdIOCtx *fd, CODE_STATIC_DATA *scd, int code_size, int flag, int *ZeroDataBlockP)
Packit Service df60bb
{
Packit Service df60bb
	int rv;
Packit Service df60bb
Packit Service df60bb
	rv = GetCode_(fd, scd, code_size,flag, ZeroDataBlockP);
Packit Service df60bb
Packit Service df60bb
	if(VERBOSE) {
Packit Service df60bb
		printf("[GetCode(,%d,%d) returning %d]\n",code_size,flag,rv);
Packit Service df60bb
	}
Packit Service df60bb
Packit Service df60bb
	return rv;
Packit Service df60bb
}
Packit Service df60bb
Packit Service df60bb
static int
Packit Service df60bb
LWZReadByte_(gdIOCtx *fd, LZW_STATIC_DATA *sd, char flag, int input_code_size, int *ZeroDataBlockP)
Packit Service df60bb
{
Packit Service df60bb
	int code, incode, i;
Packit Service df60bb
Packit Service df60bb
	if(flag) {
Packit Service df60bb
		sd->set_code_size = input_code_size;
Packit Service df60bb
		sd->code_size = sd->set_code_size + 1;
Packit Service df60bb
		sd->clear_code = 1 << sd->set_code_size;
Packit Service df60bb
		sd->end_code = sd->clear_code + 1;
Packit Service df60bb
		sd->max_code_size = 2 * sd->clear_code;
Packit Service df60bb
		sd->max_code = sd->clear_code + 2;
Packit Service df60bb
Packit Service df60bb
		GetCode(fd, &sd->scd, 0, TRUE, ZeroDataBlockP);
Packit Service df60bb
Packit Service df60bb
		sd->fresh = TRUE;
Packit Service df60bb
Packit Service df60bb
		for(i = 0; i < sd->clear_code; ++i) {
Packit Service df60bb
			sd->table[0][i] = 0;
Packit Service df60bb
			sd->table[1][i] = i;
Packit Service df60bb
		}
Packit Service df60bb
Packit Service df60bb
		for(; i < (1 << MAX_LWZ_BITS); ++i) {
Packit Service df60bb
			sd->table[0][i] = sd->table[1][0] = 0;
Packit Service df60bb
		}
Packit Service df60bb
Packit Service df60bb
		sd->sp = sd->stack;
Packit Service df60bb
Packit Service df60bb
		return 0;
Packit Service df60bb
Packit Service df60bb
	} else if(sd->fresh) {
Packit Service df60bb
		sd->fresh = FALSE;
Packit Service df60bb
Packit Service df60bb
		do {
Packit Service df60bb
			sd->firstcode = sd->oldcode =
Packit Service df60bb
			                    GetCode(fd, &sd->scd, sd->code_size, FALSE, ZeroDataBlockP);
Packit Service df60bb
		} while(sd->firstcode == sd->clear_code);
Packit Service df60bb
Packit Service df60bb
		return sd->firstcode;
Packit Service df60bb
	}
Packit Service df60bb
Packit Service df60bb
	if(sd->sp > sd->stack) {
Packit Service df60bb
		return *--sd->sp;
Packit Service df60bb
	}
Packit Service df60bb
Packit Service df60bb
	while((code = GetCode(fd, &sd->scd, sd->code_size, FALSE, ZeroDataBlockP)) >= 0) {
Packit Service df60bb
		if(code == sd->clear_code) {
Packit Service df60bb
			for(i = 0; i < sd->clear_code; ++i) {
Packit Service df60bb
				sd->table[0][i] = 0;
Packit Service df60bb
				sd->table[1][i] = i;
Packit Service df60bb
			}
Packit Service df60bb
Packit Service df60bb
			for (; i < (1 << MAX_LWZ_BITS); ++i) {
Packit Service df60bb
				sd->table[0][i] = sd->table[1][i] = 0;
Packit Service df60bb
			}
Packit Service df60bb
Packit Service df60bb
			sd->code_size = sd->set_code_size + 1;
Packit Service df60bb
			sd->max_code_size = 2 * sd->clear_code;
Packit Service df60bb
			sd->max_code = sd->clear_code + 2;
Packit Service df60bb
			sd->sp = sd->stack;
Packit Service df60bb
			sd->firstcode = sd->oldcode =
Packit Service df60bb
			                    GetCode(fd, &sd->scd, sd->code_size, FALSE, ZeroDataBlockP);
Packit Service df60bb
Packit Service df60bb
			return sd->firstcode;
Packit Service df60bb
		} else if(code == sd->end_code) {
Packit Service df60bb
			int count;
Packit Service df60bb
			unsigned char buf[260];
Packit Service df60bb
Packit Service df60bb
			if(*ZeroDataBlockP) {
Packit Service df60bb
				return -2;
Packit Service df60bb
			}
Packit Service df60bb
Packit Service df60bb
			while((count = GetDataBlock(fd, buf, ZeroDataBlockP)) > 0);
Packit Service df60bb
Packit Service df60bb
			if(count != 0) {
Packit Service df60bb
				return -2;
Packit Service df60bb
			}
Packit Service df60bb
		}
Packit Service df60bb
Packit Service df60bb
		incode = code;
Packit Service df60bb
Packit Service df60bb
		if(sd->sp == (sd->stack + STACK_SIZE)) {
Packit Service df60bb
			/* Bad compressed data stream */
Packit Service df60bb
			return -1;
Packit Service df60bb
		}
Packit Service df60bb
Packit Service df60bb
		if(code >= sd->max_code) {
Packit Service df60bb
			*sd->sp++ = sd->firstcode;
Packit Service df60bb
			code = sd->oldcode;
Packit Service df60bb
		}
Packit Service df60bb
Packit Service df60bb
		while(code >= sd->clear_code) {
Packit Service df60bb
			if(sd->sp == (sd->stack + STACK_SIZE)) {
Packit Service df60bb
				/* Bad compressed data stream */
Packit Service df60bb
				return -1;
Packit Service df60bb
			}
Packit Service df60bb
Packit Service df60bb
			*sd->sp++ = sd->table[1][code];
Packit Service df60bb
Packit Service df60bb
			if(code == sd->table[0][code]) {
Packit Service df60bb
				/* Oh well */
Packit Service df60bb
			}
Packit Service df60bb
Packit Service df60bb
			code = sd->table[0][code];
Packit Service df60bb
		}
Packit Service df60bb
Packit Service df60bb
		*sd->sp++ = sd->firstcode = sd->table[1][code];
Packit Service df60bb
Packit Service df60bb
		if((code = sd->max_code) < (1 << MAX_LWZ_BITS)) {
Packit Service df60bb
			sd->table[0][code] = sd->oldcode;
Packit Service df60bb
			sd->table[1][code] = sd->firstcode;
Packit Service df60bb
			++sd->max_code;
Packit Service df60bb
Packit Service df60bb
			if((sd->max_code >= sd->max_code_size) && (sd->max_code_size < (1<
Packit Service df60bb
				sd->max_code_size *= 2;
Packit Service df60bb
				++sd->code_size;
Packit Service df60bb
			}
Packit Service df60bb
		}
Packit Service df60bb
Packit Service df60bb
		sd->oldcode = incode;
Packit Service df60bb
Packit Service df60bb
		if(sd->sp > sd->stack) {
Packit Service df60bb
			return *--sd->sp;
Packit Service df60bb
		}
Packit Service df60bb
	}
Packit Service df60bb
Packit Service df60bb
	return code;
Packit Service df60bb
}
Packit Service df60bb
Packit Service df60bb
static int
Packit Service df60bb
LWZReadByte(gdIOCtx *fd, LZW_STATIC_DATA *sd, char flag, int input_code_size, int *ZeroDataBlockP)
Packit Service df60bb
{
Packit Service df60bb
	int rv;
Packit Service df60bb
Packit Service df60bb
	rv = LWZReadByte_(fd, sd, flag, input_code_size, ZeroDataBlockP);
Packit Service df60bb
Packit Service df60bb
	if(VERBOSE) {
Packit Service df60bb
		printf("[LWZReadByte(,%d,%d) returning %d]\n",flag,input_code_size,rv);
Packit Service df60bb
	}
Packit Service df60bb
Packit Service df60bb
	return rv;
Packit Service df60bb
}
Packit Service df60bb
Packit Service df60bb
static void
Packit Service df60bb
ReadImage(gdImagePtr im, gdIOCtx *fd, int len, int height, unsigned char (*cmap)[256], int interlace, int *ZeroDataBlockP) /*1.4//, int ignore) */
Packit Service df60bb
{
Packit Service df60bb
	unsigned char c;
Packit Service df60bb
	int xpos = 0, ypos = 0, pass = 0;
Packit Service df60bb
	int v, i;
Packit Service df60bb
	LZW_STATIC_DATA sd;
Packit Service df60bb
Packit Service df60bb
	/* Initialize the Compression routines */
Packit Service df60bb
	if(!ReadOK(fd, &c, 1)) {
Packit Service df60bb
		return;
Packit Service df60bb
	}
Packit Service df60bb
Packit Service df60bb
	if(c > MAX_LWZ_BITS) {
Packit Service df60bb
		return;
Packit Service df60bb
	}
Packit Service df60bb
Packit Service df60bb
	/* Stash the color map into the image */
Packit Service df60bb
	for(i=0; (i < gdMaxColors); i++) {
Packit Service df60bb
		im->red[i] = cmap[CM_RED][i];
Packit Service df60bb
		im->green[i] = cmap[CM_GREEN][i];
Packit Service df60bb
		im->blue[i] = cmap[CM_BLUE][i];
Packit Service df60bb
		im->open[i] = 1;
Packit Service df60bb
	}
Packit Service df60bb
Packit Service df60bb
	/* Many (perhaps most) of these colors will remain marked open. */
Packit Service df60bb
	im->colorsTotal = gdMaxColors;
Packit Service df60bb
	if(LWZReadByte(fd, &sd, TRUE, c, ZeroDataBlockP) < 0) {
Packit Service df60bb
		return;
Packit Service df60bb
	}
Packit Service df60bb
Packit Service df60bb
	/*
Packit Service df60bb
	**  If this is an "uninteresting picture" ignore it.
Packit Service df60bb
	**  REMOVED For 1.4
Packit Service df60bb
	*/
Packit Service df60bb
	/*if (ignore) { */
Packit Service df60bb
	/*        while (LWZReadByte(fd, &sd, FALSE, c) >= 0) */
Packit Service df60bb
	/*                ; */
Packit Service df60bb
	/*        return; */
Packit Service df60bb
	/*} */
Packit Service df60bb
Packit Service df60bb
	while((v = LWZReadByte(fd, &sd, FALSE, c, ZeroDataBlockP)) >= 0 ) {
Packit Service df60bb
		if(v >= gdMaxColors) {
Packit Service df60bb
			v = 0;
Packit Service df60bb
		}
Packit Service df60bb
Packit Service df60bb
		/* This how we recognize which colors are actually used. */
Packit Service df60bb
		if(im->open[v]) {
Packit Service df60bb
			im->open[v] = 0;
Packit Service df60bb
		}
Packit Service df60bb
Packit Service df60bb
		gdImageSetPixel(im, xpos, ypos, v);
Packit Service df60bb
Packit Service df60bb
		++xpos;
Packit Service df60bb
		if(xpos == len) {
Packit Service df60bb
			xpos = 0;
Packit Service df60bb
			if(interlace) {
Packit Service df60bb
				switch (pass) {
Packit Service df60bb
				case 0:
Packit Service df60bb
				case 1:
Packit Service df60bb
					ypos += 8;
Packit Service df60bb
					break;
Packit Service df60bb
				case 2:
Packit Service df60bb
					ypos += 4;
Packit Service df60bb
					break;
Packit Service df60bb
				case 3:
Packit Service df60bb
					ypos += 2;
Packit Service df60bb
					break;
Packit Service df60bb
				}
Packit Service df60bb
Packit Service df60bb
				if(ypos >= height) {
Packit Service df60bb
					++pass;
Packit Service df60bb
					switch (pass) {
Packit Service df60bb
					case 1:
Packit Service df60bb
						ypos = 4;
Packit Service df60bb
						break;
Packit Service df60bb
					case 2:
Packit Service df60bb
						ypos = 2;
Packit Service df60bb
						break;
Packit Service df60bb
					case 3:
Packit Service df60bb
						ypos = 1;
Packit Service df60bb
						break;
Packit Service df60bb
					default:
Packit Service df60bb
						goto fini;
Packit Service df60bb
					}
Packit Service df60bb
				}
Packit Service df60bb
			} else {
Packit Service df60bb
				++ypos;
Packit Service df60bb
			}
Packit Service df60bb
		}
Packit Service df60bb
Packit Service df60bb
		if(ypos >= height) {
Packit Service df60bb
			break;
Packit Service df60bb
		}
Packit Service df60bb
	}
Packit Service df60bb
Packit Service df60bb
fini:
Packit Service df60bb
	if(LWZReadByte(fd, &sd, FALSE, c, ZeroDataBlockP) >=0) {
Packit Service df60bb
		/* Ignore extra */
Packit Service df60bb
	}
Packit Service df60bb
}