diff options
author | William Joye <wjoye@cfa.harvard.edu> | 2017-01-03 21:51:01 (GMT) |
---|---|---|
committer | William Joye <wjoye@cfa.harvard.edu> | 2017-01-03 21:51:01 (GMT) |
commit | a780057cc1b51dd3a557549c3cf2431f09136c0d (patch) | |
tree | 717f78052c55596449b27743171d7e170c4d39a0 /tkimg/gif/gif.c | |
parent | 7749430b9352c1eaf5dca7d8a89a6d35f565ef24 (diff) | |
download | blt-a780057cc1b51dd3a557549c3cf2431f09136c0d.zip blt-a780057cc1b51dd3a557549c3cf2431f09136c0d.tar.gz blt-a780057cc1b51dd3a557549c3cf2431f09136c0d.tar.bz2 |
upgrade tkimg to 1.4.6
Diffstat (limited to 'tkimg/gif/gif.c')
-rw-r--r-- | tkimg/gif/gif.c | 1760 |
1 files changed, 0 insertions, 1760 deletions
diff --git a/tkimg/gif/gif.c b/tkimg/gif/gif.c deleted file mode 100644 index 522e044..0000000 --- a/tkimg/gif/gif.c +++ /dev/null @@ -1,1760 +0,0 @@ -/* - * gif.c -- - * - * GIF photo image type, Tcl/Tk package - * - * A photo image file handler for GIF files. Reads 87a and 89a GIF - * files. At present, there only is a file write function. GIF images may be - * read using the -data option of the photo image. The data may be - * given as a binary string in a Tcl_Obj or by representing - * the data as BASE64 encoded ascii. Derived from the giftoppm code - * found in the pbmplus package and tkImgFmtPPM.c in the tk4.0b2 - * distribution. - * - * Copyright (c) 2002 Andreas Kupries <andreas_kupries@users.sourceforge.net> - * Copyright (c) 1997-2003 Jan Nijtmans <nijtmans@users.sourceforge.net> - * - * Copyright (c) Reed Wade (wade@cs.utk.edu), University of Tennessee - * Copyright (c) 1995-1997 Sun Microsystems, Inc. - * Copyright (c) 1997 Australian National University - * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. - * - * This file also contains code from the giftoppm program, which is - * copyrighted as follows: - * - * +-------------------------------------------------------------------+ - * | 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. | - * +-------------------------------------------------------------------+ - * - * $Id: gif.c,v 1.1.1.1 2016/01/25 21:20:46 joye Exp $ - * - */ - -/* - * Generic initialization code, parameterized via CPACKAGE and PACKAGE. - */ - -#include "init.c" - -/* - * Non-ASCII encoding support: - * Most data in a GIF image is binary and is treated as such. However, - * a few key bits are stashed in ASCII. If we try to compare those pieces - * to the char they represent, it will fail on any non-ASCII (eg, EBCDIC) - * system. To accomodate these systems, we test against the numeric value - * of the ASCII characters instead of the characters themselves. This is - * encoding independant. - */ - -# define GIF87a "\x47\x49\x46\x38\x37\x61" /* ASCII GIF87a */ -# define GIF89a "\x47\x49\x46\x38\x39\x61" /* ASCII GIF89a */ -# define GIF_TERMINATOR 0x3b /* ASCII ; */ -# define GIF_EXTENSION 0x21 /* ASCII ! */ -# define GIF_START 0x2c /* ASCII , */ - -typedef struct { - unsigned char buf[280]; - int bytes; - int done; - unsigned int window; - int bitsInWindow; - unsigned char *c; - tkimg_MFile handle; -} GIFImageConfig; - -/* - * The format record for the GIF file format: - */ - -static int CommonRead(Tcl_Interp *interp, - GIFImageConfig *gifConfPtr, const char *fileName, Tcl_Obj *format, - Tk_PhotoHandle imageHandle, int destX, int destY, - int width, int height, int srcX, int srcY); - -static int CommonWrite(Tcl_Interp *interp, - tkimg_MFile *handle, Tcl_Obj *format, - Tk_PhotoImageBlock *blockPtr); - -#define INTERLACE 0x40 -#define LOCALCOLORMAP 0x80 -#define BitSet(byte, bit) (((byte) & (bit)) == (bit)) -#define MAXCOLORMAPSIZE 256 -#define CM_RED 0 -#define CM_GREEN 1 -#define CM_BLUE 2 -#define CM_ALPHA 3 -#define MAX_LWZ_BITS 12 -#define LM_to_uint(a,b) (((b)<<8)|(a)) -#define ReadOK(handle,buf,len) (tkimg_Read(handle, (char *)(buf), len) == len) - -/* - * Prototypes for local procedures defined in this file: - */ - -static int DoExtension(GIFImageConfig *gifConfPtr, int label, - int *transparent); - -static int GetCode(GIFImageConfig *gifConfPtr, int code_size, - int flag); - -static int GetDataBlock(GIFImageConfig *gifConfPtr, - unsigned char *buf); - -static int ReadColorMap(GIFImageConfig *gifConfPtr, int number, - unsigned char buffer[MAXCOLORMAPSIZE][4]); - -static int ReadGIFHeader(GIFImageConfig *gifConfPtr, - int *widthPtr, int *heightPtr); - -static int ReadImage(Tcl_Interp *interp, - char *imagePtr, GIFImageConfig *gifConfPtr, int len, int rows, - unsigned char cmap[MAXCOLORMAPSIZE][4], - int width, int height, int srcX, int srcY, - int interlace, int transparent); - -/* - *---------------------------------------------------------------------- - * - * ChnMatch -- - * - * This procedure is invoked by the photo image type to see if - * a channel contains image data in GIF format. - * - * Results: - * The return value is 1 if the first characters in channel chan - * look like GIF data, and 0 otherwise. - * - * Side effects: - * The access position in f may change. - * - *---------------------------------------------------------------------- - */ - -static int -ChnMatch( - Tcl_Channel chan, /* The image channel, open for reading. */ - const char *fileName, /* The name of the image file. */ - Tcl_Obj *format, /* User-specified format object, or NULL. */ - int *widthPtr, /* The dimensions of the image are */ - int *heightPtr, /* returned here if the file is a valid - * raw GIF file. */ - Tcl_Interp *interp /* interpreter */ -) { - GIFImageConfig gifConf; - - memset(&gifConf, 0, sizeof(GIFImageConfig)); - - gifConf.handle.data = (char *) chan; - gifConf.handle.state = IMG_CHAN; - - return ReadGIFHeader(&gifConf, widthPtr, heightPtr); -} - -/* - *---------------------------------------------------------------------- - * - * ChnRead -- - * - * This procedure is called by the photo image type to read - * GIF format data from a channel and write it into a given - * photo image. - * - * Results: - * A standard TCL completion code. If TCL_ERROR is returned - * then an error message is left in the interp's result. - * - * Side effects: - * The access position in channel chan is changed, and new data is - * added to the image given by imageHandle. - * - *---------------------------------------------------------------------- - */ - -static int -ChnRead(interp, chan, fileName, format, imageHandle, destX, destY, - width, height, srcX, srcY) - Tcl_Interp *interp; /* Interpreter to use for reporting errors. */ - Tcl_Channel chan; /* The image channel, open for reading. */ - const char *fileName; /* The name of the image file. */ - Tcl_Obj *format; /* User-specified format object, or NULL. */ - Tk_PhotoHandle imageHandle; /* The photo image to write into. */ - int destX, destY; /* Coordinates of top-left pixel in - * photo image to be written to. */ - int width, height; /* Dimensions of block of photo image to - * be written to. */ - int srcX, srcY; /* Coordinates of top-left pixel to be used - * in image being read. */ -{ - GIFImageConfig gifConf; - - memset(&gifConf, 0, sizeof(GIFImageConfig)); - - gifConf.handle.data = (char *) chan; - gifConf.handle.state = IMG_CHAN; - - return CommonRead(interp, &gifConf, fileName, format, - imageHandle, destX, destY, width, height, srcX, srcY); -} - -/* - *---------------------------------------------------------------------- - * - * CommonRead -- - * - * This procedure is called by the photo image type to read - * GIF format data from a file and write it into a given - * photo image. - * - * Results: - * A standard TCL completion code. If TCL_ERROR is returned - * then an error message is left in the interp's result. - * - * Side effects: - * The access position in file f is changed, and new data is - * added to the image given by imageHandle. - * - *---------------------------------------------------------------------- - */ - -static int -CommonRead(interp, gifConfPtr, fileName, format, imageHandle, destX, destY, - width, height, srcX, srcY) - Tcl_Interp *interp; /* Interpreter to use for reporting errors. */ - GIFImageConfig *gifConfPtr; /* The image file, open for reading. */ - const char *fileName; /* The name of the image file. */ - Tcl_Obj *format; /* User-specified format object, or NULL. */ - Tk_PhotoHandle imageHandle; /* The photo image to write into. */ - int destX, destY; /* Coordinates of top-left pixel in - * photo image to be written to. */ - int width, height; /* Dimensions of block of photo image to - * be written to. */ - int srcX, srcY; /* Coordinates of top-left pixel to be used - * in image being read. */ -{ - int fileWidth, fileHeight, imageWidth, imageHeight; - int nBytes, index = 0, objc = 0; - Tcl_Obj **objv = NULL; - Tk_PhotoImageBlock block; - unsigned char buf[100]; - char *trashBuffer = NULL; - unsigned char *pixBuf = NULL; - int bitPixel; - unsigned char colorMap[MAXCOLORMAPSIZE][4]; - int transparent = -1; - - if (tkimg_ListObjGetElements(interp, format, &objc, &objv) != TCL_OK) { - return TCL_ERROR; - } - if (objc > 1) { - char *c = Tcl_GetStringFromObj(objv[1], &nBytes); - if ((objc > 3) || ((objc == 3) && ((c[0] != '-') || - (c[1] != 'i') || strncmp(c, "-index", strlen(c))))) { - Tcl_AppendResult(interp, "invalid format: \"", - tkimg_GetStringFromObj(format, NULL), "\"", (char *) NULL); - return TCL_ERROR; - } - if (Tcl_GetIntFromObj(interp, objv[objc-1], &index) != TCL_OK) { - return TCL_ERROR; - } - } - - if (!ReadGIFHeader(gifConfPtr, &fileWidth, &fileHeight)) { - Tcl_AppendResult(interp, "couldn't read GIF header from file \"", - fileName, "\"", NULL); - return TCL_ERROR; - } - if ((fileWidth <= 0) || (fileHeight <= 0)) { - Tcl_AppendResult(interp, "GIF image file \"", fileName, - "\" has dimension(s) <= 0", (char *) NULL); - return TCL_ERROR; - } - - if (tkimg_Read(&gifConfPtr->handle, (char *)buf, 3) != 3) { - return TCL_OK; - } - - bitPixel = 2<<(buf[0]&0x07); - - if (BitSet(buf[0], LOCALCOLORMAP)) { /* Global Colormap */ - if (!ReadColorMap(gifConfPtr, bitPixel, colorMap)) { - Tcl_AppendResult(interp, "error reading color map", - (char *) NULL); - return TCL_ERROR; - } - } - - if ((srcX + width) > fileWidth) { - width = fileWidth - srcX; - } - if ((srcY + height) > fileHeight) { - height = fileHeight - srcY; - } - if ((width <= 0) || (height <= 0) - || (srcX >= fileWidth) || (srcY >= fileHeight)) { - return TCL_OK; - } - - if (tkimg_PhotoExpand(interp, imageHandle, destX + width, destY + height) == TCL_ERROR) { - return TCL_ERROR;; - } - - block.pixelSize = 4; - block.offset[0] = 0; - block.offset[1] = 1; - block.offset[2] = 2; - block.offset[3] = 3; - block.pixelPtr = NULL; - - while (1) { - if (tkimg_Read(&gifConfPtr->handle, (char *)buf, 1) != 1) { - /* - * Premature end of image. We should really notify - * the user, but for now just show garbage. - */ - - break; - } - - if (buf[0] == GIF_TERMINATOR) { - /* - * GIF terminator. - */ - - Tcl_AppendResult(interp,"no image data for this index", - (char *) NULL); - goto error; - } - - if (buf[0] == GIF_EXTENSION) { - /* - * This is a GIF extension. - */ - - if (tkimg_Read(&gifConfPtr->handle, (char *)buf, 1) != 1) { - Tcl_AppendResult(interp, - "error reading extension function code in GIF image", - (char *) NULL); - goto error; - } - if (DoExtension(gifConfPtr, buf[0], &transparent) < 0) { - Tcl_AppendResult(interp, "error reading extension in GIF image", - (char *) NULL); - goto error; - } - continue; - } - - if (buf[0] != GIF_START) { - /* - * Not a valid start character; ignore it. - */ - continue; - } - - if (tkimg_Read(&gifConfPtr->handle, (char *)buf, 9) != 9) { - Tcl_AppendResult(interp, - "couldn't read left/top/width/height in GIF image", - (char *) NULL); - goto error; - } - - imageWidth = LM_to_uint(buf[4],buf[5]); - imageHeight = LM_to_uint(buf[6],buf[7]); - - bitPixel = 2<<(buf[8]&0x07); - - if (index--) { - /* this is not the image we want to read: skip it. */ - if (BitSet(buf[8], LOCALCOLORMAP)) { - if (!ReadColorMap(gifConfPtr, bitPixel, colorMap)) { - Tcl_AppendResult(interp, - "error reading color map", (char *) NULL); - goto error; - } - } - - /* If we've not yet allocated a trash buffer, do so now */ - if (trashBuffer == NULL) { - nBytes = fileWidth * fileHeight * 3; - trashBuffer = (char *) ckalloc((unsigned int) nBytes); - } - - /* - * Slurp! Process the data for this image and stuff it in a - * trash buffer. - * - * Yes, it might be more efficient here to *not* store the data - * (we're just going to throw it away later). However, I elected - * to implement it this way for good reasons. First, I wanted to - * avoid duplicating the (fairly complex) LWZ decoder in ReadImage. - * Fine, you say, why didn't you just modify it to allow the use of - * a NULL specifier for the output buffer? I tried that, but it - * negatively impacted the performance of what I think will be the - * common case: reading the first image in the file. Rather than - * marginally improve the speed of the less frequent case, I chose - * to maintain high performance for the common case. - */ - if (ReadImage(interp, trashBuffer, gifConfPtr, imageWidth, - imageHeight, colorMap, 0, 0, 0, 0, 0, -1) != TCL_OK) { - goto error; - } - continue; - } - - /* If a trash buffer has been allocated, free it now */ - if (trashBuffer != NULL) { - ckfree((char *)trashBuffer); - trashBuffer = NULL; - } - if (BitSet(buf[8], LOCALCOLORMAP)) { - if (!ReadColorMap(gifConfPtr, bitPixel, colorMap)) { - Tcl_AppendResult(interp, "error reading color map", - (char *) NULL); - goto error; - } - } - - index = LM_to_uint(buf[0],buf[1]); - srcX -= index; - if (srcX<0) { - destX -= srcX; width += srcX; - srcX = 0; - } - - if (width > imageWidth) { - width = imageWidth; - } - - index = LM_to_uint(buf[2],buf[3]); - srcY -= index; - if (index > srcY) { - destY -= srcY; height += srcY; - srcY = 0; - } - if (height > imageHeight) { - height = imageHeight; - } - - if ((width <= 0) || (height <= 0)) { - block.pixelPtr = 0; - goto noerror; - } - - block.width = width; - block.height = height; - block.pixelSize = (transparent>=0)?4:3; - block.pitch = block.pixelSize * imageWidth; - nBytes = block.pitch * imageHeight; - pixBuf = (unsigned char *) ckalloc((unsigned) nBytes); - block.pixelPtr = pixBuf; - - if (ReadImage(interp, (char *) block.pixelPtr, gifConfPtr, imageWidth, imageHeight, - colorMap, fileWidth, fileHeight, srcX, srcY, - BitSet(buf[8], INTERLACE), transparent) != TCL_OK) { - goto error; - } - break; - } - - block.pixelPtr = pixBuf + srcY * block.pitch + srcX * block.pixelSize; - if (tkimg_PhotoPutBlock(interp, imageHandle, &block, destX, destY, width, height, - (transparent == -1)? TK_PHOTO_COMPOSITE_SET: TK_PHOTO_COMPOSITE_OVERLAY) == TCL_ERROR) { - goto error; - } - - noerror: - if (pixBuf) { - ckfree((char *) pixBuf); - } - return TCL_OK; - - error: - if (pixBuf) { - ckfree((char *) pixBuf); - } - return TCL_ERROR; - -} - -/* - *---------------------------------------------------------------------- - * - * ObjMatch -- - * - * This procedure is invoked by the photo image type to see if - * an object contains image data in GIF format. - * - * Results: - * The return value is 1 if the first characters in the object are - * like GIF data, and 0 otherwise. - * - * Side effects: - * the size of the image is placed in widthPtr and heightPtr. - * - *---------------------------------------------------------------------- - */ - -static int -ObjMatch( - Tcl_Obj *data, /* the object containing the image data */ - Tcl_Obj *format, /* the image format object */ - int *widthPtr, /* where to put the image width */ - int *heightPtr, /* where to put the image height */ - Tcl_Interp *interp /* interpreter */ -) { - GIFImageConfig gifConf; - - memset(&gifConf, 0, sizeof(GIFImageConfig)); - - if (!tkimg_ReadInit(data, 'G', &gifConf.handle)) { - return 0; - } - return ReadGIFHeader(&gifConf, widthPtr, heightPtr); -} - -/* - *---------------------------------------------------------------------- - * - * ObjRead -- - * - * This procedure is called by the photo image type to read - * GIF format data from a base64 encoded string, and give it to - * the photo image. - * - * Results: - * A standard TCL completion code. If TCL_ERROR is returned - * then an error message is left in the interp's result. - * - * Side effects: - * new data is added to the image given by imageHandle. This - * procedure calls FileReadGif by redefining the operation of - * fprintf temporarily. - * - *---------------------------------------------------------------------- - */ - -static int -ObjRead(interp, data, format, imageHandle, - destX, destY, width, height, srcX, srcY) - Tcl_Interp *interp; /* interpreter for reporting errors in */ - Tcl_Obj *data; /* object containing the image */ - Tcl_Obj *format; /* format object if any */ - Tk_PhotoHandle imageHandle; /* the image to write this data into */ - int destX, destY; /* The rectangular region of the */ - int width, height; /* image to copy */ - int srcX, srcY; -{ - GIFImageConfig gifConf; - - memset(&gifConf, 0, sizeof(GIFImageConfig)); - - tkimg_ReadInit(data, 'G', &gifConf.handle); - return CommonRead(interp, &gifConf, "inline data", format, - imageHandle, destX, destY, width, height, srcX, srcY); -} - -/* - *---------------------------------------------------------------------- - * - * ReadGIFHeader -- - * - * This procedure reads the GIF header from the beginning of a - * GIF file and returns the dimensions of the image. - * - * Results: - * The return value is 1 if file "f" appears to start with - * a valid GIF header, 0 otherwise. If the header is valid, - * then *widthPtr and *heightPtr are modified to hold the - * dimensions of the image. - * - * Side effects: - * The access position in f advances. - * - *---------------------------------------------------------------------- - */ - -static int -ReadGIFHeader(gifConfPtr, widthPtr, heightPtr) - GIFImageConfig *gifConfPtr; /* Image file to read the header from */ - int *widthPtr, *heightPtr; /* The dimensions of the image are - * returned here. */ -{ - unsigned char buf[7]; - - if ((tkimg_Read(&gifConfPtr->handle, (char *)buf, 6) != 6) - || ((strncmp(GIF87a, (char *) buf, 6) != 0) - && (strncmp(GIF89a, (char *) buf, 6) != 0))) { - return 0; - } - - if (tkimg_Read(&gifConfPtr->handle, (char *)buf, 4) != 4) { - return 0; - } - - *widthPtr = LM_to_uint(buf[0],buf[1]); - *heightPtr = LM_to_uint(buf[2],buf[3]); - return 1; -} - -/* - *----------------------------------------------------------------- - * The code below is copied from the giftoppm program and modified - * just slightly. - *----------------------------------------------------------------- - */ - -static int -ReadColorMap(gifConfPtr, number, buffer) - GIFImageConfig *gifConfPtr; - int number; - unsigned char buffer[MAXCOLORMAPSIZE][4]; -{ - int i; - unsigned char rgb[3]; - - for (i = 0; i < number; ++i) { - if (! ReadOK(&gifConfPtr->handle, rgb, sizeof(rgb))) { - return 0; - } - - if (buffer) { - buffer[i][CM_RED] = rgb[0] ; - buffer[i][CM_GREEN] = rgb[1] ; - buffer[i][CM_BLUE] = rgb[2] ; - buffer[i][CM_ALPHA] = 255 ; - } - } - return 1; -} - -static int -DoExtension(gifConfPtr, label, transparent) - GIFImageConfig *gifConfPtr; - int label; - int *transparent; -{ - int count; - - switch (label) { - case 0x01: /* Plain Text Extension */ - break; - - case 0xff: /* Application Extension */ - break; - - case 0xfe: /* Comment Extension */ - do { - count = GetDataBlock(gifConfPtr, (unsigned char*) gifConfPtr->buf); - } while (count > 0); - return count; - - case 0xf9: /* Graphic Control Extension */ - count = GetDataBlock(gifConfPtr, (unsigned char*) gifConfPtr->buf); - if (count < 0) { - return 1; - } - if ((gifConfPtr->buf[0] & 0x1) != 0) { - *transparent = gifConfPtr->buf[3]; - } - - do { - count = GetDataBlock(gifConfPtr, (unsigned char*) gifConfPtr->buf); - } while (count > 0); - return count; - } - - do { - count = GetDataBlock(gifConfPtr, (unsigned char*) gifConfPtr->buf); - } while (count > 0); - return count; -} - -static int -GetDataBlock(gifConfPtr, buf) - GIFImageConfig *gifConfPtr; - unsigned char *buf; -{ - unsigned char count; - - if (! ReadOK(&gifConfPtr->handle,&count,1)) { - return -1; - } - - if ((count != 0) && (! ReadOK(&gifConfPtr->handle, buf, count))) { - return -1; - } - - return count; -} - - - -/* - *---------------------------------------------------------------------- - * - * ReadImage -- - * - * Process a GIF image from a given source, with a given height, - * width, transparency, etc. - * - * This code is based on the code found in the ImageMagick GIF decoder, - * which is (c) 2000 ImageMagick Studio. - * - * Some thoughts on our implementation: - * It sure would be nice if ReadImage didn't take 11 parameters! I think - * that if we were smarter, we could avoid doing that. - * - * Possible further optimizations: we could pull the GetCode function - * directly into ReadImage, which would improve our speed. - * - * Results: - * Processes a GIF image and loads the pixel data into a memory array. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -static int -ReadImage(interp, imagePtr, gifConfPtr, len, rows, cmap, - width, height, srcX, srcY, interlace, transparent) - Tcl_Interp *interp; - char *imagePtr; - GIFImageConfig *gifConfPtr; - int len, rows; - unsigned char cmap[MAXCOLORMAPSIZE][4]; - int width, height; - int srcX, srcY; - int interlace; - int transparent; -{ - unsigned char initialCodeSize; - int v; - int xpos = 0, ypos = 0, pass = 0, i; - register char *pixelPtr; - const static int interlaceStep[] = { 8, 8, 4, 2 }; - const static int interlaceStart[] = { 0, 4, 2, 1 }; - unsigned short prefix[(1 << MAX_LWZ_BITS)]; - unsigned char append[(1 << MAX_LWZ_BITS)]; - unsigned char stack[(1 << MAX_LWZ_BITS)*2]; - register unsigned char *top; - int codeSize, clearCode, inCode, endCode, oldCode, maxCode, - code, firstCode; - - /* - * Initialize the decoder - */ - if (! ReadOK(&gifConfPtr->handle,&initialCodeSize,1)) { - Tcl_AppendResult(interp, "error reading GIF image: ", - Tcl_PosixError(interp), (char *) NULL); - return TCL_ERROR; - } - if (initialCodeSize > MAX_LWZ_BITS) { - Tcl_AppendResult(interp, "error reading GIF image: malformed image", (char *) NULL); - return TCL_ERROR; - } - if (transparent!=-1) { - cmap[transparent][CM_RED] = 0; - cmap[transparent][CM_GREEN] = 0; - cmap[transparent][CM_BLUE] = 0; - cmap[transparent][CM_ALPHA] = 0; - } - - pixelPtr = imagePtr; - - /* Initialize the decoder */ - /* Set values for "special" numbers: - * clear code reset the decoder - * end code stop decoding - * code size size of the next code to retrieve - * max code next available table position - */ - clearCode = 1 << (int) initialCodeSize; - endCode = clearCode + 1; - codeSize = (int) initialCodeSize + 1; - maxCode = clearCode + 2; - oldCode = -1; - firstCode = -1; - - memset((void *)prefix, 0, (1 << MAX_LWZ_BITS) * sizeof(short)); - memset((void *)append, 0, (1 << MAX_LWZ_BITS) * sizeof(char)); - for (i = 0; i < clearCode; i++) { - append[i] = i; - } - top = stack; - - GetCode(gifConfPtr, 0, 1); - - /* Read until we finish the image */ - for (i = 0, ypos = 0; i < rows; i++) { - for (xpos = 0; xpos < len; ) { - - if (top == stack) { - /* Bummer -- our stack is empty. Now we have to work! */ - code = GetCode(gifConfPtr, codeSize, 0); - if (code < 0) { - return TCL_OK; - } - - if (code > maxCode || code == endCode) { - /* - * If we're doing things right, we should never - * receive a code that is greater than our current - * maximum code. If we do, bail, because our decoder - * does not yet have that code set up. - * - * If the code is the magic endCode value, quit. - */ - return TCL_OK; - } - - if (code == clearCode) { - /* Reset the decoder */ - codeSize = initialCodeSize + 1; - maxCode = clearCode + 2; - oldCode = -1; - continue; - } - - if (oldCode == -1) { - /* - * Last pass reset the decoder, so the first code we - * see must be a singleton. Seed the stack with it, - * and set up the old/first code pointers for - * insertion into the string table. We can't just - * roll this into the clearCode test above, because - * at that point we have not yet read the next code. - */ - *top++=append[code]; - oldCode = code; - firstCode = code; - continue; - } - - inCode = code; - - if (code == maxCode) { - /* - * maxCode is always one bigger than our highest assigned - * code. If the code we see is equal to maxCode, then - * we are about to add a new string to the table. ??? - */ - *top++ = firstCode; - code = oldCode; - } - - while (code > clearCode) { - /* - * Populate the stack by tracing the string in the - * string table from its tail to its head - */ - *top++ = append[code]; - code = prefix[code]; - } - firstCode = append[code]; - - /* - * If there's no more room in our string table, quit. - * Otherwise, add a new string to the table - */ - if (maxCode >= (1 << MAX_LWZ_BITS)) { - return TCL_OK; - } - - /* Push the head of the string onto the stack */ - *top++ = firstCode; - - /* Add a new string to the string table */ - prefix[maxCode] = oldCode; - append[maxCode] = firstCode; - maxCode++; - - /* maxCode tells us the maximum code value we can accept. - * If we see that we need more bits to represent it than - * we are requesting from the unpacker, we need to increase - * the number we ask for. - */ - if ((maxCode >= (1 << codeSize)) - && (maxCode < (1<<MAX_LWZ_BITS))) { - codeSize++; - } - oldCode = inCode; - } - - /* Pop the next color index off the stack */ - v = *(--top); - if (v < 0) { - return TCL_OK; - } - - /* - * If pixelPtr is null, we're skipping this image (presumably - * there are more in the file and we will be called to read - * one of them later) - */ - *pixelPtr++ = cmap[v][CM_RED]; - *pixelPtr++ = cmap[v][CM_GREEN]; - *pixelPtr++ = cmap[v][CM_BLUE]; - if (transparent >= 0) { - *pixelPtr++ = cmap[v][CM_ALPHA]; - } - xpos++; - - } - - /* If interlacing, the next ypos is not just +1 */ - if (interlace) { - ypos += interlaceStep[pass]; - while (ypos >= rows) { - pass++; - if (pass > 3) { - return TCL_OK; - } - ypos = interlaceStart[pass]; - } - } else { - ypos++; - } - pixelPtr = imagePtr + (ypos) * len * ((transparent>=0)?4:3); - } - return TCL_OK; -} - -/* - *---------------------------------------------------------------------- - * - * GetCode -- - * - * Extract the next compression code from the file. In GIF's, the - * compression codes are between 3 and 12 bits long and are then - * packed into 8 bit bytes, left to right, for example: - * bbbaaaaa - * dcccccbb - * eeeedddd - * ... - * We use a byte buffer read from the file and a sliding window - * to unpack the bytes. Thanks to ImageMagick for the sliding window - * idea. - * args: handle the handle to read from - * code_size size of the code to extract - * flag boolean indicating whether the extractor - * should be reset or not - * - * Results: - * code the next compression code - * - * Side effects: - * May consume more input from chan. - * - *---------------------------------------------------------------------- - */ - -static int -GetCode(gifConfPtr, code_size, flag) - GIFImageConfig *gifConfPtr; - int code_size; - int flag; -{ - int ret; - - if (flag) { - /* Initialize the decoder */ - gifConfPtr->bitsInWindow = 0; - gifConfPtr->bytes = 0; - gifConfPtr->window = 0; - gifConfPtr->done = 0; - gifConfPtr->c = NULL; - return 0; - } - - while (gifConfPtr->bitsInWindow < code_size) { - /* Not enough bits in our window to cover the request */ - if (gifConfPtr->done) { - return -1; - } - if (gifConfPtr->bytes == 0) { - /* Not enough bytes in our buffer to add to the window */ - gifConfPtr->bytes = GetDataBlock(gifConfPtr, gifConfPtr->buf); - gifConfPtr->c = gifConfPtr->buf; - if (gifConfPtr->bytes <= 0) { - gifConfPtr->done = 1; - break; - } - } - /* Tack another byte onto the window, see if that's enough */ - gifConfPtr->window += (*gifConfPtr->c) << gifConfPtr->bitsInWindow; - gifConfPtr->c++; - gifConfPtr->bitsInWindow += 8; - gifConfPtr->bytes--; - } - - - /* The next code will always be the last code_size bits of the window */ - ret = gifConfPtr->window & ((1 << code_size) - 1); - - /* Shift data in the window to put the next code at the end */ - gifConfPtr->window >>= code_size; - gifConfPtr->bitsInWindow -= code_size; - return ret; -} - -/* - * This software is copyrighted as noted below. It may be freely copied, - * modified, and redistributed, provided that the copyright notice is - * preserved on all copies. - * - * There is no warranty or other guarantee of fitness for this software, - * it is provided solely "as is". Bug reports or fixes may be sent - * to the author, who may or may not act on them as he desires. - * - * You may not include this software in a program or other software product - * without supplying the source, or without informing the end-user that the - * source is available for no extra charge. - * - * If you modify this software, you should include a notice giving the - * name of the person performing the modification, the date of modification, - * and the reason for such modification. - */ - - -/* - * ChnWrite - writes a image in GIF format. - *------------------------------------------------------------------------- - * Author: Lolo - * Engeneering Projects Area - * Department of Mining - * University of Oviedo - * e-mail zz11425958@zeus.etsimo.uniovi.es - * lolo@pcsig22.etsimo.uniovi.es - * Date: Fri September 20 1996 - * - * Modified for transparency handling (gif89a) and miGIF compression - * by Jan Nijtmans <nijtmans@users.sourceforge.net> - * - *---------------------------------------------------------------------- - * FileWriteGIF- - * - * This procedure is called by the photo image type to write - * GIF format data from a photo image into a given file - * - * Results: - * A standard TCL completion code. If TCL_ERROR is returned - * then an error message is left in the interp's result. - * - *---------------------------------------------------------------------- - */ - - /* - * Types, defines and variables needed to write and compress a GIF. - */ - -#define LSB(a) ((unsigned char) (((short)(a)) & 0x00FF)) -#define MSB(a) ((unsigned char) (((short)(a)) >> 8)) - -#define GIFBITS 12 -#define HSIZE 5003 /* 80% occupancy */ - -typedef struct { - int ssize; - int csize; - int rsize; - unsigned char *pixelo; - int pixelSize; - int pixelPitch; - int greenOffset; - int blueOffset; - int alphaOffset; - int num; - unsigned char mapa[MAXCOLORMAPSIZE][3]; -} GifWriterState; - -typedef int (* ifunptr) (GifWriterState *statePtr); - -/* - * Definition of new functions to write GIFs - */ - -static int color(GifWriterState *statePtr, int red, int green, int blue); - -static void compress(GifWriterState *statePtr, int init_bits, tkimg_MFile *handle, - ifunptr readValue); - -static int nuevo(GifWriterState *statePtr, int red, int green ,int blue); - -static int savemap(GifWriterState *statePtr, Tk_PhotoImageBlock *blockPtr); - -static int ReadValue(GifWriterState *statePtr); - -static int no_bits(int colors); - -static int -ChnWrite (interp, filename, format, blockPtr) - Tcl_Interp *interp; /* Interpreter to use for reporting errors. */ - const char *filename; - Tcl_Obj *format; - Tk_PhotoImageBlock *blockPtr; -{ - Tcl_Channel chan = NULL; - tkimg_MFile handle; - int result; - - chan = tkimg_OpenFileChannel(interp, filename, 0644); - if (!chan) { - return TCL_ERROR; - } - - handle.data = (char *) chan; - handle.state = IMG_CHAN; - - result = CommonWrite(interp, &handle, format, blockPtr); - if (Tcl_Close(interp, chan) == TCL_ERROR) { - return TCL_ERROR; - } - return result; -} - -static int StringWrite( - Tcl_Interp *interp, - Tcl_Obj *format, - Tk_PhotoImageBlock *blockPtr -) { - int result; - tkimg_MFile handle; - Tcl_DString data; - - Tcl_DStringInit(&data); - Tcl_DStringSetLength(&data, 1024); - tkimg_WriteInit(&data, &handle); - - result = CommonWrite(interp, &handle, format, blockPtr); - tkimg_Putc(IMG_DONE, &handle); - - if (result == TCL_OK) { - Tcl_DStringResult(interp, &data); - } else { - Tcl_DStringFree(&data); - } - return result; -} - -static int -CommonWrite(interp, handle, format, blockPtr) - Tcl_Interp *interp; - tkimg_MFile *handle; - Tcl_Obj *format; - Tk_PhotoImageBlock *blockPtr; -{ - GifWriterState state; - int resolution; - long numcolormap; - - long width,height,x; - unsigned char c; - unsigned int top,left; - int num; - - top = 0; - left = 0; - - state.pixelSize=blockPtr->pixelSize; - state.greenOffset=blockPtr->offset[1]-blockPtr->offset[0]; - state.blueOffset=blockPtr->offset[2]-blockPtr->offset[0]; - state.alphaOffset = blockPtr->offset[0]; - if (state.alphaOffset < blockPtr->offset[2]) { - state.alphaOffset = blockPtr->offset[2]; - } - if (++state.alphaOffset < state.pixelSize) { - state.alphaOffset -= blockPtr->offset[0]; - } else { - state.alphaOffset = 0; - } - - tkimg_Write(handle, (const char *) (state.alphaOffset ? GIF89a:GIF87a), 6); - - for (x=0;x<MAXCOLORMAPSIZE;x++) { - state.mapa[x][CM_RED] = 255; - state.mapa[x][CM_GREEN] = 255; - state.mapa[x][CM_BLUE] = 255; - } - - - width=blockPtr->width; - height=blockPtr->height; - state.pixelo=blockPtr->pixelPtr + blockPtr->offset[0]; - state.pixelPitch=blockPtr->pitch; - if ((num=savemap(&state,blockPtr))<0) { - Tcl_AppendResult(interp, "too many colors", (char *) NULL); - return TCL_ERROR; - } - if (state.num<3) state.num=3; - c=LSB(width); - tkimg_Putc(c,handle); - c=MSB(width); - tkimg_Putc(c,handle); - c=LSB(height); - tkimg_Putc(c,handle); - c=MSB(height); - tkimg_Putc(c,handle); - - c= (1 << 7) | (no_bits(num) << 4) | (no_bits(num)); - tkimg_Putc(c,handle); - resolution = no_bits(num)+1; - - numcolormap=1 << resolution; - - /* background color */ - - tkimg_Putc(0,handle); - - /* zero for future expansion */ - - tkimg_Putc(0,handle); - - for (x=0; x<numcolormap ;x++) { - tkimg_Putc(state.mapa[x][CM_RED],handle); - tkimg_Putc(state.mapa[x][CM_GREEN],handle); - tkimg_Putc(state.mapa[x][CM_BLUE],handle); - } - - /* - * Write out extension for transparent colour index, if necessary. - */ - - if (state.alphaOffset) { - tkimg_Write(handle, "!\371\4\1\0\0\0", 8); - } - - c = GIF_START; - tkimg_Putc(c,handle); - c=LSB(top); - tkimg_Putc(c,handle); - c=MSB(top); - tkimg_Putc(c,handle); - c=LSB(left); - tkimg_Putc(c,handle); - c=MSB(left); - tkimg_Putc(c,handle); - - c=LSB(width); - tkimg_Putc(c,handle); - c=MSB(width); - tkimg_Putc(c,handle); - - c=LSB(height); - tkimg_Putc(c,handle); - c=MSB(height); - tkimg_Putc(c,handle); - - c=0; - tkimg_Putc(c,handle); - c=resolution; - tkimg_Putc(c,handle); - - state.ssize = state.rsize = blockPtr->width; - state.csize = blockPtr->height; - compress(&state, resolution+1, handle, ReadValue); - - tkimg_Putc(0,handle); - c = GIF_TERMINATOR; - tkimg_Putc(c,handle); - - return TCL_OK; -} - -static int -color(statePtr, red, green, blue) - GifWriterState *statePtr; - int red; - int green; - int blue; -{ - int x; - for (x=(statePtr->alphaOffset != 0);x<=MAXCOLORMAPSIZE;x++) { - if ((statePtr->mapa[x][CM_RED]==red) && (statePtr->mapa[x][CM_GREEN]==green) && - (statePtr->mapa[x][CM_BLUE]==blue)) { - return x; - } - } - return -1; -} - - -static int -nuevo(statePtr, red, green, blue) - GifWriterState *statePtr; - int red,green,blue; -{ - int x; - for (x=(statePtr->alphaOffset != 0);x<statePtr->num;x++) { - if ((statePtr->mapa[x][CM_RED]==red) && (statePtr->mapa[x][CM_GREEN]==green) && - (statePtr->mapa[x][CM_BLUE]==blue)) { - return 0; - } - } - return 1; -} - -static int -savemap(statePtr, blockPtr) - GifWriterState *statePtr; - Tk_PhotoImageBlock *blockPtr; -{ - unsigned char *colores; - int x,y; - unsigned char red,green,blue; - - if (statePtr->alphaOffset) { - statePtr->num = 1; - statePtr->mapa[0][CM_RED] = 0xd9; - statePtr->mapa[0][CM_GREEN] = 0xd9; - statePtr->mapa[0][CM_BLUE] = 0xd9; - } else { - statePtr->num = 0; - } - - for(y=0;y<blockPtr->height;y++) { - colores=blockPtr->pixelPtr + blockPtr->offset[0] - + y * blockPtr->pitch; - for(x=0;x<blockPtr->width;x++) { - if (!statePtr->alphaOffset || (colores[statePtr->alphaOffset] != 0)) { - red = colores[0]; - green = colores[statePtr->greenOffset]; - blue = colores[statePtr->blueOffset]; - if (nuevo(statePtr, red, green, blue)) { - if (statePtr->num>255) - return -1; - - statePtr->mapa[statePtr->num][CM_RED]=red; - statePtr->mapa[statePtr->num][CM_GREEN]=green; - statePtr->mapa[statePtr->num][CM_BLUE]=blue; - statePtr->num++; - } - } - colores += statePtr->pixelSize; - } - } - return statePtr->num; -} - -static int -ReadValue(statePtr) - GifWriterState *statePtr; -{ - unsigned int col; - - if (statePtr->csize == 0) { - return EOF; - } - if (statePtr->alphaOffset && (statePtr->pixelo[statePtr->alphaOffset]==0)) { - col = 0; - } else { - col = color(statePtr, statePtr->pixelo[0],statePtr->pixelo[statePtr->greenOffset],statePtr->pixelo[statePtr->blueOffset]); - } - statePtr->pixelo += statePtr->pixelSize; - if (--statePtr->ssize <= 0) { - statePtr->ssize = statePtr->rsize; - statePtr->csize--; - statePtr->pixelo += statePtr->pixelPitch - (statePtr->rsize * statePtr->pixelSize); - } - - return col; -} - -/* - * Return the number of bits ( -1 ) to represent a given - * number of colors ( ex: 256 colors => 7 ). - */ -static int -no_bits( colors ) -int colors; -{ - register int bits = 0; - - colors--; - while ( colors >> bits ) { - bits++; - } - - return (bits-1); -} - - -/* - * - * GIF Image compression - modified 'compress' - * - * Based on: compress.c - File compression ala IEEE Computer, June 1984. - * - * By Authors: Spencer W. Thomas (decvax!harpo!utah-cs!utah-gr!thomas) - * Jim McKie (decvax!mcvax!jim) - * Steve Davies (decvax!vax135!petsd!peora!srd) - * Ken Turkowski (decvax!decwrl!turtlevax!ken) - * James A. Woods (decvax!ihnp4!ames!jaw) - * Joe Orost (decvax!vax135!petsd!joe) - * - */ - -#define MAXCODE(n_bits) (((long) 1 << (n_bits)) - 1) - -typedef struct { - int n_bits; /* number of bits/code */ - long maxcode; /* maximum code, given n_bits */ - int htab[HSIZE]; - unsigned int codetab[HSIZE]; - - long hsize; /* for dynamic table sizing */ - -/* - * To save much memory, we overlay the table used by compress() with those - * used by decompress(). The tab_prefix table is the same size and type - * as the codetab. The tab_suffix table needs 2**GIFBITS characters. We - * get this from the beginning of htab. The output stack uses the rest - * of htab, and contains characters. There is plenty of room for any - * possible stack (stack used to be 8000 characters). - */ - - int free_ent; /* first unused entry */ - -/* - * block compression parameters -- after all codes are used up, - * and compression rate changes, start over. - */ - int clear_flg; - - int offset; - unsigned int in_count; /* length of input */ - unsigned int out_count; /* # of codes output (for debugging) */ - -/* - * compress stdin to stdout - * - * Algorithm: use open addressing double hashing (no chaining) on the - * prefix code / next character combination. We do a variant of Knuth's - * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime - * secondary probe. Here, the modular division first probe is gives way - * to a faster exclusive-or manipulation. Also do block compression with - * an adaptive reset, whereby the code table is cleared when the compression - * ratio decreases, but after the table fills. The variable-length output - * codes are re-sized at this point, and a special CLEAR code is generated - * for the decompressor. Late addition: construct the table according to - * file size for noticeable speed improvement on small files. Please direct - * questions about this implementation to ames!jaw. - */ - - int g_init_bits; - tkimg_MFile *g_outfile; - - int ClearCode; - int EOFCode; - - unsigned long cur_accum; - int cur_bits; - -/* - * Number of characters so far in this 'packet' - */ - int a_count; - -/* - * Define the storage for the packet accumulator - */ - unsigned char accum[256]; -} GIFState_t; - -static void output(GIFState_t *statePtr, long code); -static void cl_block(GIFState_t *statePtr); -static void cl_hash(GIFState_t *statePtr, int hsize); -static void char_init(GIFState_t *statePtr); -static void char_out(GIFState_t *statePtr, int c); -static void flush_char(GIFState_t *statePtr); - -static void compress(statePtr, init_bits, handle, readValue) - GifWriterState *statePtr; - int init_bits; - tkimg_MFile *handle; - ifunptr readValue; -{ - register long fcode; - register long i = 0; - register int c; - register long ent; - register long disp; - register long hsize_reg; - register int hshift; - GIFState_t state; - - memset(&state, 0, sizeof(state)); - /* - * Set up the globals: g_init_bits - initial number of bits - * g_outfile - pointer to output file - */ - state.g_init_bits = init_bits; - state.g_outfile = handle; - - /* - * Set up the necessary values - */ - state.offset = 0; - state.hsize = HSIZE; - state.out_count = 0; - state.clear_flg = 0; - state.in_count = 1; - state.maxcode = MAXCODE(state.n_bits = state.g_init_bits); - - state.ClearCode = (1 << (init_bits - 1)); - state.EOFCode = state.ClearCode + 1; - state.free_ent = state.ClearCode + 2; - - char_init(&state); - - ent = readValue(statePtr); - - hshift = 0; - for ( fcode = (long) state.hsize; fcode < 65536L; fcode *= 2L ) - hshift++; - hshift = 8 - hshift; /* set hash code range bound */ - - hsize_reg = state.hsize; - cl_hash(&state, (int) hsize_reg); /* clear hash table */ - - output(&state, (long)state.ClearCode); - -#ifdef SIGNED_COMPARE_SLOW - while ( (c = readValue(statePtr) ) != (unsigned) EOF ) { -#else - while ( (c = readValue(statePtr)) != EOF ) { -#endif - - state.in_count++; - - fcode = (long) (((long) c << GIFBITS) + ent); - i = (((long)c << hshift) ^ ent); /* xor hashing */ - - if (state.htab[i] == fcode) { - ent = state.codetab[i]; - continue; - } else if ( (long) state.htab[i] < 0 ) /* empty slot */ - goto nomatch; - disp = hsize_reg - i; /* secondary hash (after G. Knott) */ - if ( i == 0 ) - disp = 1; -probe: - if ( (i -= disp) < 0 ) - i += hsize_reg; - - if (state.htab[i] == fcode) { - ent = state.codetab[i]; - continue; - } - if ( (long) state.htab[i] > 0 ) - goto probe; -nomatch: - output (&state, (long) ent); - state.out_count++; - ent = c; -#ifdef SIGNED_COMPARE_SLOW - if ( (unsigned) free_ent < (unsigned) ((long)1 << GIFBITS)) { -#else - if (state.free_ent < ((long)1 << GIFBITS)) { -#endif - state.codetab[i] = state.free_ent++; /* code -> hashtable */ - state.htab[i] = fcode; - } else - cl_block(&state); - } - /* - * Put out the final code. - */ - output(&state, (long)ent); - state.out_count++; - output(&state, (long) state.EOFCode); - - return; -} - -/***************************************************************** - * TAG( output ) - * - * Output the given code. - * Inputs: - * code: A n_bits-bit integer. If == -1, then EOF. This assumes - * that n_bits =< (long) wordsize - 1. - * Outputs: - * Outputs code to the file. - * Assumptions: - * Chars are 8 bits long. - * Algorithm: - * Maintain a GIFBITS character long buffer (so that 8 codes will - * fit in it exactly). Use the VAX insv instruction to insert each - * code in turn. When the buffer fills up empty it and start over. - */ - -static const -unsigned long masks[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, - 0x001F, 0x003F, 0x007F, 0x00FF, - 0x01FF, 0x03FF, 0x07FF, 0x0FFF, - 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF }; - -static void -output(statePtr, code) - GIFState_t *statePtr; - long code; -{ - statePtr->cur_accum &= masks[statePtr->cur_bits]; - - if (statePtr->cur_bits > 0) { - statePtr->cur_accum |= ((long) code << statePtr->cur_bits); - } else { - statePtr->cur_accum = code; - } - - statePtr->cur_bits += statePtr->n_bits; - - while (statePtr->cur_bits >= 8 ) { - char_out(statePtr, (unsigned int)(statePtr->cur_accum & 0xff)); - statePtr->cur_accum >>= 8; - statePtr->cur_bits -= 8; - } - - /* - * If the next entry is going to be too big for the code size, - * then increase it, if possible. - */ - - if ((statePtr->free_ent > statePtr->maxcode)|| statePtr->clear_flg ) { - if (statePtr->clear_flg) { - statePtr->maxcode = MAXCODE(statePtr->n_bits = statePtr->g_init_bits); - statePtr->clear_flg = 0; - } else { - statePtr->n_bits++; - if (statePtr->n_bits == GIFBITS) { - statePtr->maxcode = (long)1 << GIFBITS; - } else { - statePtr->maxcode = MAXCODE(statePtr->n_bits); - } - } - } - - if (code == statePtr->EOFCode) { - /* - * At EOF, write the rest of the buffer. - */ - while (statePtr->cur_bits > 0) { - char_out(statePtr, (unsigned int)(statePtr->cur_accum & 0xff)); - statePtr->cur_accum >>= 8; - statePtr->cur_bits -= 8; - } - flush_char(statePtr); - } -} - -/* - * Clear out the hash table - */ -static void -cl_block(statePtr) /* table clear for block compress */ - GIFState_t *statePtr; -{ - - cl_hash (statePtr, (int) statePtr->hsize); - statePtr->free_ent = statePtr->ClearCode + 2; - statePtr->clear_flg = 1; - - output(statePtr, (long) statePtr->ClearCode); -} - -static void -cl_hash(statePtr, hsize) /* reset code table */ - GIFState_t *statePtr; - int hsize; -{ - register int *htab_p = statePtr->htab+hsize; - register long i; - register long m1 = -1; - - i = hsize - 16; - do { /* might use Sys V memset(3) here */ - *(htab_p-16) = m1; - *(htab_p-15) = m1; - *(htab_p-14) = m1; - *(htab_p-13) = m1; - *(htab_p-12) = m1; - *(htab_p-11) = m1; - *(htab_p-10) = m1; - *(htab_p-9) = m1; - *(htab_p-8) = m1; - *(htab_p-7) = m1; - *(htab_p-6) = m1; - *(htab_p-5) = m1; - *(htab_p-4) = m1; - *(htab_p-3) = m1; - *(htab_p-2) = m1; - *(htab_p-1) = m1; - htab_p -= 16; - } while ((i -= 16) >= 0); - - for (i += 16; i > 0; i--) { - *--htab_p = m1; - } -} - - -/****************************************************************************** - * - * GIF Specific routines - * - ******************************************************************************/ - -/* - * Set up the 'byte output' routine - */ -static void -char_init(statePtr) - GIFState_t *statePtr; -{ - statePtr->a_count = 0; - statePtr->cur_accum = 0; - statePtr->cur_bits = 0; -} - -/* - * Add a character to the end of the current packet, and if it is 254 - * characters, flush the packet to disk. - */ -static void -char_out(statePtr, c) - GIFState_t *statePtr; - int c; -{ - statePtr->accum[statePtr->a_count++] = c; - if (statePtr->a_count >= 254) { - flush_char(statePtr); - } -} - -/* - * Flush the packet to disk, and reset the accumulator - */ -static void -flush_char(statePtr) - GIFState_t *statePtr; -{ - unsigned char c; - if (statePtr->a_count > 0) { - c = statePtr->a_count; - tkimg_Write(statePtr->g_outfile, (const char *) &c, 1); - tkimg_Write(statePtr->g_outfile, (const char *) statePtr->accum, statePtr->a_count); - statePtr->a_count = 0; - } -} - -/* The End */ |