summaryrefslogtreecommitdiffstats
path: root/generic/tkImgGIF.c
diff options
context:
space:
mode:
Diffstat (limited to 'generic/tkImgGIF.c')
-rw-r--r--generic/tkImgGIF.c1954
1 files changed, 1033 insertions, 921 deletions
diff --git a/generic/tkImgGIF.c b/generic/tkImgGIF.c
index 9c2004a..e576559 100644
--- a/generic/tkImgGIF.c
+++ b/generic/tkImgGIF.c
@@ -1,20 +1,20 @@
/*
* tkImgGIF.c --
*
- * 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.
+ * 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) Reed Wade (wade@cs.utk.edu), University of Tennessee
* Copyright (c) 1995-1997 Sun Microsystems, Inc.
* Copyright (c) 1997 Australian National University
+ * Copyright (c) 2005 Donal K. Fellows
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * 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:
@@ -25,18 +25,22 @@
* | 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 |
+ * | notice appear in supporting documentation. This software is |
* | provided "as is" without express or implied warranty. |
- * +-------------------------------------------------------------------+
+ * +--------------------------------------------------------------------+
+ *
+ * This file also contains code from miGIF. See lower down in file for the
+ * applicable copyright notice for that portion.
*/
+#include "tkInt.h"
+
/*
- * GIF's are represented as data in base64 format.
- * base64 strings consist of 4 6-bit characters -> 3 8 bit bytes.
- * A-Z, a-z, 0-9, + and / represent the 64 values (in order).
- * '=' is a trailing padding char when the un-encoded data is not a
- * multiple of 3 bytes. We'll ignore white space when encountered.
- * Any other invalid character is treated as an EOF
+ * GIF's are represented as data in either binary or base64 format. base64
+ * strings consist of 4 6-bit characters -> 3 8 bit bytes. A-Z, a-z, 0-9, +
+ * and / represent the 64 values (in order). '=' is a trailing padding char
+ * when the un-encoded data is not a multiple of 3 bytes. We'll ignore white
+ * space when encountered. Any other invalid character is treated as an EOF
*/
#define GIF_SPECIAL (256)
@@ -46,77 +50,86 @@
#define GIF_DONE (GIF_SPECIAL+4)
/*
- * structure to "mimic" FILE for Mread, so we can look like fread.
- * The decoder state keeps track of which byte we are about to read,
- * or EOF.
+ * structure to "mimic" FILE for Mread, so we can look like fread. The decoder
+ * state keeps track of which byte we are about to read, or EOF.
*/
typedef struct mFile {
unsigned char *data; /* mmencoded source string */
- int length; /* Length of string in bytes */
int c; /* bits left over from previous character */
int state; /* decoder state (0-4 or GIF_DONE) */
+ int length; /* Total amount of bytes in data */
} MFile;
-#include "tkInt.h"
-#include "tkPort.h"
-
/*
* 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.
+ * 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.
*/
-static CONST char GIF87a[] = { /* ASCII GIF87a */
+static const char GIF87a[] = { /* ASCII GIF87a */
0x47, 0x49, 0x46, 0x38, 0x37, 0x61, 0x00
};
-static CONST char GIF89a[] = { /* ASCII GIF89a */
+static const char GIF89a[] = { /* ASCII GIF89a */
0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 0x00
};
-# define GIF_TERMINATOR 0x3b /* ASCII ; */
-# define GIF_EXTENSION 0x21 /* ASCII ! */
-# define GIF_START 0x2c /* ASCII , */
+#define GIF_TERMINATOR 0x3b /* ASCII ; */
+#define GIF_EXTENSION 0x21 /* ASCII ! */
+#define GIF_START 0x2c /* ASCII , */
/*
- * HACK ALERT!! HACK ALERT!! HACK ALERT!!
- * This code is hard-wired for reading from files. In order to read
- * from a data stream, we'll trick fread so we can reuse the same code.
- * 0==from file; 1==from base64 encoded data; 2==from binary data
+ * Flags used to notify that we've got inline data instead of a file to read
+ * from. Note that we need to figure out which type of inline data we've got
+ * before handing off to the GIF reading code; this is done in StringReadGIF.
*/
-typedef struct ThreadSpecificData {
- int fromData;
-} ThreadSpecificData;
-static Tcl_ThreadDataKey dataKey;
+#define INLINE_DATA_BINARY ((const char *) 0x01)
+#define INLINE_DATA_BASE64 ((const char *) 0x02)
+
+/*
+ * HACK ALERT!! HACK ALERT!! HACK ALERT!!
+ * This code is hard-wired for reading from files. In order to read from a
+ * data stream, we'll trick fread so we can reuse the same code. 0==from file;
+ * 1==from base64 encoded data; 2==from binary data
+ */
+
+typedef struct {
+ const char *fromData;
+ unsigned char workingBuffer[280];
+ struct {
+ int bytes;
+ int done;
+ unsigned int window;
+ int bitsInWindow;
+ unsigned char *c;
+ } reader;
+} GIFImageConfig;
/*
* The format record for the GIF file format:
*/
-static int FileMatchGIF _ANSI_ARGS_((Tcl_Channel chan, CONST char *fileName,
- Tcl_Obj *format, int *widthPtr, int *heightPtr,
- Tcl_Interp *interp));
-static int FileReadGIF _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Channel chan, CONST char *fileName, Tcl_Obj *format,
- Tk_PhotoHandle imageHandle, int destX, int destY,
- int width, int height, int srcX, int srcY));
-static int StringMatchGIF _ANSI_ARGS_(( Tcl_Obj *dataObj,
- Tcl_Obj *format, int *widthPtr, int *heightPtr,
- Tcl_Interp *interp));
-static int StringReadGIF _ANSI_ARGS_((Tcl_Interp *interp, Tcl_Obj *dataObj,
- Tcl_Obj *format, Tk_PhotoHandle imageHandle,
- int destX, int destY, int width, int height,
- int srcX, int srcY));
-static int FileWriteGIF _ANSI_ARGS_((Tcl_Interp *interp,
- CONST char *filename, Tcl_Obj *format,
- Tk_PhotoImageBlock *blockPtr));
-static int CommonWriteGIF _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Channel handle, Tcl_Obj *format,
- Tk_PhotoImageBlock *blockPtr));
+static int FileMatchGIF(Tcl_Channel chan, const char *fileName,
+ Tcl_Obj *format, int *widthPtr, int *heightPtr,
+ Tcl_Interp *interp);
+static int FileReadGIF(Tcl_Interp *interp, Tcl_Channel chan,
+ const char *fileName, Tcl_Obj *format,
+ Tk_PhotoHandle imageHandle, int destX, int destY,
+ int width, int height, int srcX, int srcY);
+static int StringMatchGIF(Tcl_Obj *dataObj, Tcl_Obj *format,
+ int *widthPtr, int *heightPtr, Tcl_Interp *interp);
+static int StringReadGIF(Tcl_Interp *interp, Tcl_Obj *dataObj,
+ Tcl_Obj *format, Tk_PhotoHandle imageHandle,
+ int destX, int destY, int width, int height,
+ int srcX, int srcY);
+static int FileWriteGIF(Tcl_Interp *interp, const char *filename,
+ Tcl_Obj *format, Tk_PhotoImageBlock *blockPtr);
+static int CommonWriteGIF(Tcl_Interp *interp, Tcl_Channel handle,
+ Tcl_Obj *format, Tk_PhotoImageBlock *blockPtr);
Tk_PhotoImageFormat tkImgFmtGIF = {
"gif", /* name */
@@ -138,54 +151,53 @@ Tk_PhotoImageFormat tkImgFmtGIF = {
#define CM_ALPHA 3
#define MAX_LWZ_BITS 12
#define LM_to_uint(a,b) (((b)<<8)|(a))
-#define ReadOK(file,buffer,len) (Fread(buffer, len, 1, file) != 0)
/*
- * Prototypes for local procedures defined in this file:
+ * Prototypes for local functions defined in this file:
*/
-static int DoExtension _ANSI_ARGS_((Tcl_Channel chan, int label,
- int *transparent));
-static int GetCode _ANSI_ARGS_((Tcl_Channel chan, int code_size,
- int flag));
-static int GetDataBlock _ANSI_ARGS_((Tcl_Channel chan,
- unsigned char *buf));
-static int ReadColorMap _ANSI_ARGS_((Tcl_Channel chan, int number,
- unsigned char buffer[MAXCOLORMAPSIZE][4]));
-static int ReadGIFHeader _ANSI_ARGS_((Tcl_Channel chan,
- int *widthPtr, int *heightPtr));
-static int ReadImage _ANSI_ARGS_((Tcl_Interp *interp,
- char *imagePtr, Tcl_Channel chan,
- int len, int rows,
- unsigned char cmap[MAXCOLORMAPSIZE][4],
- int width, int height, int srcX, int srcY,
- int interlace, int transparent));
+static int DoExtension(GIFImageConfig *gifConfPtr,
+ Tcl_Channel chan, int label, unsigned char *buffer,
+ int *transparent);
+static int GetCode(Tcl_Channel chan, int code_size, int flag,
+ GIFImageConfig *gifConfPtr);
+static int GetDataBlock(GIFImageConfig *gifConfPtr,
+ Tcl_Channel chan, unsigned char *buf);
+static int ReadColorMap(GIFImageConfig *gifConfPtr,
+ Tcl_Channel chan, int number,
+ unsigned char buffer[MAXCOLORMAPSIZE][4]);
+static int ReadGIFHeader(GIFImageConfig *gifConfPtr,
+ Tcl_Channel chan, int *widthPtr, int *heightPtr);
+static int ReadImage(GIFImageConfig *gifConfPtr,
+ Tcl_Interp *interp, unsigned char *imagePtr,
+ Tcl_Channel chan, int len, int rows,
+ unsigned char cmap[MAXCOLORMAPSIZE][4], int srcX,
+ int srcY, int interlace, int transparent);
/*
* these are for the BASE64 image reader code only
*/
-static int Fread _ANSI_ARGS_((unsigned char *dst, size_t size,
- size_t count, Tcl_Channel chan));
-static int Mread _ANSI_ARGS_((unsigned char *dst, size_t size,
- size_t count, MFile *handle));
-static int Mgetc _ANSI_ARGS_((MFile *handle));
-static int char64 _ANSI_ARGS_((int c));
-static void mInit _ANSI_ARGS_((unsigned char *string,
- int length, MFile *handle));
-
+static int Fread(GIFImageConfig *gifConfPtr, unsigned char *dst,
+ size_t size, size_t count, Tcl_Channel chan);
+static int Mread(unsigned char *dst, size_t size, size_t count,
+ MFile *handle);
+static int Mgetc(MFile *handle);
+static int char64(int c);
+static void mInit(unsigned char *string, MFile *handle,
+ int length);
/*
*----------------------------------------------------------------------
*
* FileMatchGIF --
*
- * This procedure is invoked by the photo image type to see if
- * a file contains image data in GIF format.
+ * This function is invoked by the photo image type to see if a file
+ * contains image data in GIF format.
*
* Results:
- * The return value is 1 if the first characters in file f look
- * like GIF data, and 0 otherwise.
+ * The return value is 1 if the first characters in file f look like GIF
+ * data, and 0 otherwise.
*
* Side effects:
* The access position in f may change.
@@ -194,16 +206,19 @@ static void mInit _ANSI_ARGS_((unsigned char *string,
*/
static int
-FileMatchGIF(chan, fileName, format, widthPtr, heightPtr, interp)
- Tcl_Channel chan; /* The image file, open for reading. */
- CONST char *fileName; /* The name of the image file. */
- Tcl_Obj *format; /* User-specified format object, or NULL. */
- int *widthPtr, *heightPtr; /* The dimensions of the image are
- * returned here if the file is a valid
- * raw GIF file. */
- Tcl_Interp *interp; /* not used */
+FileMatchGIF(
+ Tcl_Channel chan, /* The image file, open for reading. */
+ const char *fileName, /* The name of the image file. */
+ Tcl_Obj *format, /* User-specified format object, or NULL. */
+ int *widthPtr, int *heightPtr,
+ /* The dimensions of the image are returned
+ * here if the file is a valid raw GIF file. */
+ Tcl_Interp *interp) /* not used */
{
- return ReadGIFHeader(chan, widthPtr, heightPtr);
+ GIFImageConfig gifConf;
+
+ memset(&gifConf, 0, sizeof(GIFImageConfig));
+ return ReadGIFHeader(&gifConf, chan, widthPtr, heightPtr);
}
/*
@@ -211,88 +226,108 @@ FileMatchGIF(chan, fileName, format, widthPtr, heightPtr, interp)
*
* FileReadGIF --
*
- * 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.
+ * This function 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.
+ * 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.
+ * The access position in file f is changed, and new data is added to the
+ * image given by imageHandle.
*
*----------------------------------------------------------------------
*/
static int
-FileReadGIF(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 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. */
+FileReadGIF(
+ Tcl_Interp *interp, /* Interpreter to use for reporting errors. */
+ Tcl_Channel chan, /* 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, int destY, /* Coordinates of top-left pixel in photo
+ * image to be written to. */
+ int width, int height, /* Dimensions of block of photo image to be
+ * written to. */
+ int srcX, int srcY) /* Coordinates of top-left pixel to be used in
+ * image being read. */
{
int fileWidth, fileHeight, imageWidth, imageHeight;
- int nBytes, index = 0, argc = 0, i;
+ int nBytes, index = 0, argc = 0, i, result = TCL_ERROR;
Tcl_Obj **objv;
- Tk_PhotoImageBlock block;
unsigned char buf[100];
unsigned char *trashBuffer = NULL;
int bitPixel;
unsigned char colorMap[MAXCOLORMAPSIZE][4];
int transparent = -1;
- static CONST char *optionStrings[] = {
- "-index", NULL
+ static const char *optionStrings[] = {
+ "-index", NULL
};
+ GIFImageConfig gifConf, *gifConfPtr = &gifConf;
+
+ /*
+ * Decode the magic used to convey when we're sourcing data from a string
+ * source and not a file.
+ */
+
+ memset(gifConfPtr, 0, sizeof(GIFImageConfig));
+ if (fileName == INLINE_DATA_BINARY || fileName == INLINE_DATA_BASE64) {
+ gifConfPtr->fromData = fileName;
+ fileName = "inline data";
+ }
+
+ /*
+ * Parse the format string to get options.
+ */
if (format && Tcl_ListObjGetElements(interp, format,
&argc, &objv) != TCL_OK) {
return TCL_ERROR;
}
for (i = 1; i < argc; i++) {
- if (Tcl_GetIndexFromObj(interp, objv[i], optionStrings, "option name", 0,
- &nBytes) != TCL_OK) {
+ if (Tcl_GetIndexFromObj(interp, objv[i], optionStrings, "option name",
+ 0, &nBytes) != TCL_OK) {
return TCL_ERROR;
}
if (i == (argc-1)) {
Tcl_AppendResult(interp, "no value given for \"",
- Tcl_GetStringFromObj(objv[i], NULL),
- "\" option", (char *) NULL);
+ Tcl_GetString(objv[i]), "\" option", NULL);
return TCL_ERROR;
}
if (Tcl_GetIntFromObj(interp, objv[++i], &index) != TCL_OK) {
return TCL_ERROR;
}
}
- if (!ReadGIFHeader(chan, &fileWidth, &fileHeight)) {
- Tcl_AppendResult(interp, "couldn't read GIF header from file \"",
+
+ /*
+ * Read the GIF file header and check for some sanity.
+ */
+
+ if (!ReadGIFHeader(gifConfPtr, chan, &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);
+ "\" has dimension(s) <= 0", NULL);
return TCL_ERROR;
}
- if (Fread(buf, 1, 3, chan) != 3) {
+ /*
+ * Get the general colormap information.
+ */
+
+ if (Fread(gifConfPtr, buf, 1, 3, chan) != 3) {
return TCL_OK;
}
- bitPixel = 2<<(buf[0]&0x07);
+ bitPixel = 2 << (buf[0] & 0x07);
if (BitSet(buf[0], LOCALCOLORMAP)) { /* Global Colormap */
- if (!ReadColorMap(chan, bitPixel, colorMap)) {
- Tcl_AppendResult(interp, "error reading color map",
- (char *) NULL);
+ if (!ReadColorMap(gifConfPtr, chan, bitPixel, colorMap)) {
+ Tcl_AppendResult(interp, "error reading color map", NULL);
return TCL_ERROR;
}
}
@@ -308,85 +343,87 @@ FileReadGIF(interp, chan, fileName, format, imageHandle, destX, destY,
return TCL_OK;
}
- Tk_PhotoExpand(imageHandle, destX + width, destY + height);
+ /*
+ * Make sure we have enough space in the photo image to hold the data from
+ * the GIF.
+ */
+
+ if (Tk_PhotoExpand(interp, imageHandle,
+ destX + width, destY + height) != TCL_OK) {
+ return TCL_ERROR;
+ }
- block.width = width;
- block.height = height;
- block.pixelSize = 4;
- block.pitch = block.pixelSize * block.width;
- block.offset[0] = 0;
- block.offset[1] = 1;
- block.offset[2] = 2;
- block.offset[3] = 3;
- block.pixelPtr = NULL;
+ /*
+ * Search for the frame from the GIF to display.
+ */
while (1) {
- if (Fread(buf, 1, 1, chan) != 1) {
+ if (Fread(gifConfPtr, buf, 1, 1, chan) != 1) {
/*
* Premature end of image.
*/
- Tcl_AppendResult(interp,"premature end of image data for this index",
- (char *) NULL);
+ Tcl_AppendResult(interp,
+ "premature end of image data for this index", NULL);
goto error;
}
- if (buf[0] == GIF_TERMINATOR) {
- /*
- * GIF terminator.
- */
-
- Tcl_AppendResult(interp,"no image data for this index",
- (char *) NULL);
+ switch (buf[0]) {
+ case GIF_TERMINATOR:
+ Tcl_AppendResult(interp, "no image data for this index", NULL);
goto error;
- }
- if (buf[0] == GIF_EXTENSION) {
+ case GIF_EXTENSION:
/*
* This is a GIF extension.
*/
- if (Fread(buf, 1, 1, chan) != 1) {
+ if (Fread(gifConfPtr, buf, 1, 1, chan) != 1) {
Tcl_SetResult(interp,
"error reading extension function code in GIF image",
TCL_STATIC);
goto error;
}
- if (DoExtension(chan, buf[0], &transparent) < 0) {
+ if (DoExtension(gifConfPtr, chan, buf[0],
+ gifConfPtr->workingBuffer, &transparent) < 0) {
Tcl_SetResult(interp, "error reading extension in GIF image",
TCL_STATIC);
goto error;
}
continue;
- }
-
- if (buf[0] != GIF_START) {
+ case GIF_START:
+ if (Fread(gifConfPtr, buf, 1, 9, chan) != 9) {
+ Tcl_SetResult(interp,
+ "couldn't read left/top/width/height in GIF image",
+ TCL_STATIC);
+ goto error;
+ }
+ break;
+ default:
/*
* Not a valid start character; ignore it.
*/
- continue;
- }
- if (Fread(buf, 1, 9, chan) != 9) {
- Tcl_SetResult(interp,
- "couldn't read left/top/width/height in GIF image",
- TCL_STATIC);
- goto error;
+ continue;
}
- imageWidth = LM_to_uint(buf[4],buf[5]);
- imageHeight = LM_to_uint(buf[6],buf[7]);
+ /*
+ * We've read the header for a GIF frame. Work out what we are going
+ * to do about it.
+ */
- bitPixel = 1<<((buf[8]&0x07)+1);
+ imageWidth = LM_to_uint(buf[4], buf[5]);
+ imageHeight = LM_to_uint(buf[6], buf[7]);
+ bitPixel = 1 << ((buf[8] & 0x07) + 1);
if (index--) {
/*
- * This is not the image we want to read: skip it.
+ * This is not the GIF frame we want to read: skip it.
*/
+
if (BitSet(buf[8], LOCALCOLORMAP)) {
- if (!ReadColorMap(chan, bitPixel, colorMap)) {
- Tcl_AppendResult(interp,
- "error reading color map", (char *) NULL);
+ if (!ReadColorMap(gifConfPtr, chan, bitPixel, colorMap)) {
+ Tcl_AppendResult(interp, "error reading color map", NULL);
goto error;
}
}
@@ -394,113 +431,126 @@ FileReadGIF(interp, chan, fileName, format, imageHandle, destX, destY,
/*
* If we've not yet allocated a trash buffer, do so now.
*/
+
if (trashBuffer == NULL) {
nBytes = fileWidth * fileHeight * 3;
- trashBuffer =
- (unsigned char *) ckalloc((unsigned int) nBytes);
+ trashBuffer = (unsigned char *) ckalloc((unsigned) nBytes);
}
/*
- * Slurp! Process the data for this image and stuff it in
- * a trash buffer.
+ * 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.
+ * 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, (char *) trashBuffer, chan, imageWidth,
- imageHeight, colorMap, 0, 0, 0, 0, 0, -1) != TCL_OK) {
+
+ if (ReadImage(gifConfPtr, interp, trashBuffer, chan, imageWidth,
+ imageHeight, colorMap, 0, 0, 0, -1) != TCL_OK) {
goto error;
}
continue;
}
+ break;
+ }
- if (BitSet(buf[8], LOCALCOLORMAP)) {
- if (!ReadColorMap(chan, bitPixel, colorMap)) {
- Tcl_AppendResult(interp, "error reading color map",
- (char *) NULL);
- goto error;
- }
- }
+ /*
+ * Found the frame we want to read. Next, check for a local color map for
+ * this frame.
+ */
- index = LM_to_uint(buf[0],buf[1]);
- srcX -= index;
- if (srcX<0) {
- destX -= srcX; width += srcX;
- srcX = 0;
+ if (BitSet(buf[8], LOCALCOLORMAP)) {
+ if (!ReadColorMap(gifConfPtr, chan, bitPixel, colorMap)) {
+ Tcl_AppendResult(interp, "error reading color map", NULL);
+ goto error;
}
+ }
- if (width > imageWidth) {
- width = imageWidth;
- }
+ /*
+ * Extract the location within the overall visible image to put the data
+ * in this frame, together with the size of this frame.
+ */
- index = LM_to_uint(buf[2],buf[3]);
- srcY -= index;
- if (index > srcY) {
- destY -= srcY; height += srcY;
- srcY = 0;
- }
- if (height > imageHeight) {
- height = imageHeight;
- }
+ index = LM_to_uint(buf[0], buf[1]);
+ srcX -= index;
+ if (srcX<0) {
+ destX -= srcX; width += srcX;
+ srcX = 0;
+ }
- if ((width <= 0) || (height <= 0)) {
- block.pixelPtr = 0;
- goto noerror;
- }
+ 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)) {
+ Tk_PhotoImageBlock block;
+
+ /*
+ * Read the data and put it into the photo buffer for display by the
+ * general image machinery.
+ */
block.width = width;
block.height = height;
block.pixelSize = (transparent>=0) ? 4 : 3;
+ block.offset[0] = 0;
+ block.offset[1] = 1;
+ block.offset[2] = 2;
block.offset[3] = (transparent>=0) ? 3 : 0;
block.pitch = block.pixelSize * imageWidth;
nBytes = block.pitch * imageHeight;
block.pixelPtr = (unsigned char *) ckalloc((unsigned) nBytes);
- if (ReadImage(interp, (char *) block.pixelPtr, chan, imageWidth,
- imageHeight, colorMap, fileWidth, fileHeight, srcX, srcY,
- BitSet(buf[8], INTERLACE), transparent) != TCL_OK) {
+ if (ReadImage(gifConfPtr, interp, block.pixelPtr, chan, imageWidth,
+ imageHeight, colorMap, srcX, srcY, BitSet(buf[8],INTERLACE),
+ transparent) != TCL_OK) {
+ ckfree((char *) block.pixelPtr);
goto error;
}
- break;
+ if (Tk_PhotoPutBlock(interp, imageHandle, &block, destX, destY,
+ width, height, TK_PHOTO_COMPOSITE_SET) != TCL_OK) {
+ ckfree((char *) block.pixelPtr);
+ goto error;
+ }
+ ckfree((char *) block.pixelPtr);
}
- Tk_PhotoPutBlock(imageHandle, &block, destX, destY, width, height,
- TK_PHOTO_COMPOSITE_SET);
-
- noerror:
/*
- * If a trash buffer has been allocated, free it now.
+ * We've successfully read the GIF frame (or there was nothing to read,
+ * which suits as well). We're done.
*/
- if (trashBuffer != NULL) {
- ckfree((char *)trashBuffer);
- }
- if (block.pixelPtr) {
- ckfree((char *) block.pixelPtr);
- }
- Tcl_AppendResult(interp, tkImgFmtGIF.name, (char *) NULL);
- return TCL_OK;
- error:
+ Tcl_AppendResult(interp, tkImgFmtGIF.name, NULL);
+ result = TCL_OK;
+
+ error:
/*
* If a trash buffer has been allocated, free it now.
*/
+
if (trashBuffer != NULL) {
- ckfree((char *)trashBuffer);
- }
- if (block.pixelPtr) {
- ckfree((char *) block.pixelPtr);
+ ckfree((char *) trashBuffer);
}
- return TCL_ERROR;
+ return result;
}
/*
@@ -508,26 +558,26 @@ FileReadGIF(interp, chan, fileName, format, imageHandle, destX, destY,
*
* StringMatchGIF --
*
- * This procedure is invoked by the photo image type to see if
- * an object contains image data in GIF format.
+ * This function 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 data are
- * like GIF data, and 0 otherwise.
+ * The return value is 1 if the first characters in the data are like GIF
+ * data, and 0 otherwise.
*
* Side effects:
- * the size of the image is placed in widthPre and heightPtr.
+ * The size of the image is placed in widthPtr and heightPtr.
*
*----------------------------------------------------------------------
*/
static int
-StringMatchGIF(dataObj, format, widthPtr, heightPtr, interp)
- Tcl_Obj *dataObj; /* the object containing the image data */
- Tcl_Obj *format; /* the image format object, or NULL */
- int *widthPtr; /* where to put the string width */
- int *heightPtr; /* where to put the string height */
- Tcl_Interp *interp; /* not used */
+StringMatchGIF(
+ Tcl_Obj *dataObj, /* the object containing the image data */
+ Tcl_Obj *format, /* the image format object, or NULL */
+ int *widthPtr, /* where to put the string width */
+ int *heightPtr, /* where to put the string height */
+ Tcl_Interp *interp) /* not used */
{
unsigned char *data, header[10];
int got, length;
@@ -538,6 +588,7 @@ StringMatchGIF(dataObj, format, widthPtr, heightPtr, interp)
/*
* Header is a minimum of 10 bytes.
*/
+
if (length < 10) {
return 0;
}
@@ -546,97 +597,99 @@ StringMatchGIF(dataObj, format, widthPtr, heightPtr, interp)
* Check whether the data is Base64 encoded.
*/
- if ((strncmp(GIF87a, (char *) data, 6) != 0) &&
+ if ((strncmp(GIF87a, (char *) data, 6) != 0) &&
(strncmp(GIF89a, (char *) data, 6) != 0)) {
/*
* Try interpreting the data as Base64 encoded
*/
- mInit((unsigned char *) data, length, &handle);
+
+ mInit((unsigned char *) data, &handle, length);
got = Mread(header, 10, 1, &handle);
- if (got != 10
- || ((strncmp(GIF87a, (char *) header, 6) != 0)
+ if (got != 10 ||
+ ((strncmp(GIF87a, (char *) header, 6) != 0)
&& (strncmp(GIF89a, (char *) header, 6) != 0))) {
return 0;
}
} else {
- memcpy((VOID *) header, (VOID *) data, 10);
+ memcpy(header, data, 10);
}
- *widthPtr = LM_to_uint(header[6],header[7]);
- *heightPtr = LM_to_uint(header[8],header[9]);
+ *widthPtr = LM_to_uint(header[6], header[7]);
+ *heightPtr = LM_to_uint(header[8], header[9]);
return 1;
}
/*
*----------------------------------------------------------------------
*
- * StringReadGif -- --
+ * StringReadGIF --
*
- * This procedure is called by the photo image type to read
- * GIF format data from an object, optionally base64 encoded,
- * and give it to the photo image.
+ * This function is called by the photo image type to read GIF format
+ * data from an object, optionally base64 encoded, 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.
+ * 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.
+ * New data is added to the image given by imageHandle. This function
+ * calls FileReadGIF by redefining the operation of fprintf temporarily.
*
*----------------------------------------------------------------------
*/
static int
-StringReadGIF(interp, dataObj, format, imageHandle,
- destX, destY, width, height, srcX, srcY)
- Tcl_Interp *interp; /* interpreter for reporting errors in */
- Tcl_Obj *dataObj; /* object containing the image */
- Tcl_Obj *format; /* format object, or NULL */
- 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;
+StringReadGIF(
+ Tcl_Interp *interp, /* interpreter for reporting errors in */
+ Tcl_Obj *dataObj, /* object containing the image */
+ Tcl_Obj *format, /* format object, or NULL */
+ Tk_PhotoHandle imageHandle, /* the image to write this data into */
+ int destX, int destY, /* The rectangular region of the */
+ int width, int height, /* image to copy */
+ int srcX, int srcY)
{
- int result, length;
- MFile handle;
- ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
- Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
- Tcl_Channel dataSrc;
- char *data;
+ MFile handle, *hdlPtr = &handle;
+ int length;
+ const char *xferFormat;
+ unsigned char *data = Tcl_GetByteArrayFromObj(dataObj, &length);
+
+ mInit(data, hdlPtr, length);
/*
- * Check whether the data is Base64 encoded
+ * Check whether the data is Base64 encoded by doing a character-by-
+ * charcter comparison with the binary-format headers; BASE64-encoded
+ * never matches (matching the other way is harder because of potential
+ * padding of the BASE64 data).
*/
- data = (char *) Tcl_GetByteArrayFromObj(dataObj, &length);
- if ((strncmp(GIF87a, data, 6) != 0) && (strncmp(GIF89a, data, 6) != 0)) {
- mInit((unsigned char *)data, length, &handle);
- tsdPtr->fromData = 1;
- dataSrc = (Tcl_Channel) &handle;
+
+ if (strncmp(GIF87a, (char *) data, 6)
+ && strncmp(GIF89a, (char *) data, 6)) {
+ xferFormat = INLINE_DATA_BASE64;
} else {
- tsdPtr->fromData = 2;
- mInit((unsigned char *)data, length, &handle);
- dataSrc = (Tcl_Channel) &handle;
+ xferFormat = INLINE_DATA_BINARY;
}
- result = FileReadGIF(interp, dataSrc, "inline data",
- format, imageHandle, destX, destY, width, height, srcX, srcY);
- tsdPtr->fromData = 0;
- return result;
-}
+ /*
+ * Fall through to the file reader now that we have a correctly-configured
+ * pseudo-channel to pull the data from.
+ */
+
+ return FileReadGIF(interp, (Tcl_Channel) hdlPtr, xferFormat, 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.
+ * This function 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.
+ * 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.
@@ -645,68 +698,70 @@ StringReadGIF(interp, dataObj, format, imageHandle,
*/
static int
-ReadGIFHeader(chan, widthPtr, heightPtr)
- Tcl_Channel chan; /* Image file to read the header from */
- int *widthPtr, *heightPtr; /* The dimensions of the image are
- * returned here. */
+ReadGIFHeader(
+ GIFImageConfig *gifConfPtr,
+ Tcl_Channel chan, /* Image file to read the header from */
+ int *widthPtr, int *heightPtr)
+ /* The dimensions of the image are returned
+ * here. */
{
unsigned char buf[7];
- if ((Fread(buf, 1, 6, chan) != 6)
+ if ((Fread(gifConfPtr, buf, 1, 6, chan) != 6)
|| ((strncmp(GIF87a, (char *) buf, 6) != 0)
&& (strncmp(GIF89a, (char *) buf, 6) != 0))) {
return 0;
}
- if (Fread(buf, 1, 4, chan) != 4) {
+ if (Fread(gifConfPtr, buf, 1, 4, chan) != 4) {
return 0;
}
- *widthPtr = LM_to_uint(buf[0],buf[1]);
- *heightPtr = LM_to_uint(buf[2],buf[3]);
+ *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.
+ * The code below is copied from the giftoppm program and modified just
+ * slightly.
*-----------------------------------------------------------------
*/
static int
-ReadColorMap(chan, number, buffer)
- Tcl_Channel chan;
- int number;
- unsigned char buffer[MAXCOLORMAPSIZE][4];
+ReadColorMap(
+ GIFImageConfig *gifConfPtr,
+ Tcl_Channel chan,
+ int number,
+ unsigned char buffer[MAXCOLORMAPSIZE][4])
{
int i;
unsigned char rgb[3];
for (i = 0; i < number; ++i) {
- if (! ReadOK(chan, rgb, sizeof(rgb))) {
+ if (Fread(gifConfPtr, rgb, sizeof(rgb), 1, chan) <= 0) {
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 ;
+ 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(chan, label, transparent)
- Tcl_Channel chan;
- int label;
- int *transparent;
+DoExtension(
+ GIFImageConfig *gifConfPtr,
+ Tcl_Channel chan,
+ int label,
+ unsigned char *buf,
+ int *transparent)
{
- static unsigned char buf[256];
int count;
switch (label) {
@@ -718,12 +773,12 @@ DoExtension(chan, label, transparent)
case 0xfe: /* Comment Extension */
do {
- count = GetDataBlock(chan, (unsigned char*) buf);
+ count = GetDataBlock(gifConfPtr, chan, buf);
} while (count > 0);
return count;
case 0xf9: /* Graphic Control Extension */
- count = GetDataBlock(chan, (unsigned char*) buf);
+ count = GetDataBlock(gifConfPtr, chan, buf);
if (count < 0) {
return 1;
}
@@ -732,53 +787,52 @@ DoExtension(chan, label, transparent)
}
do {
- count = GetDataBlock(chan, (unsigned char*) buf);
+ count = GetDataBlock(gifConfPtr, chan, buf);
} while (count > 0);
return count;
}
do {
- count = GetDataBlock(chan, (unsigned char*) buf);
+ count = GetDataBlock(gifConfPtr, chan, buf);
} while (count > 0);
return count;
}
-
+
static int
-GetDataBlock(chan, buf)
- Tcl_Channel chan;
- unsigned char *buf;
+GetDataBlock(
+ GIFImageConfig *gifConfPtr,
+ Tcl_Channel chan,
+ unsigned char *buf)
{
unsigned char count;
- if (! ReadOK(chan, &count,1)) {
+ if (Fread(gifConfPtr, &count, 1, 1, chan) <= 0) {
return -1;
}
- if ((count != 0) && (! ReadOK(chan, buf, count))) {
+ if ((count != 0) && (Fread(gifConfPtr, buf, count, 1, chan) <= 0)) {
return -1;
}
return count;
}
-
-
/*
*----------------------------------------------------------------------
*
* ReadImage --
*
- * Process a GIF image from a given source, with a given height,
- * width, transparency, etc.
+ * 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
+ * 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
+ * Possible further optimizations: we could pull the GetCode function
* directly into ReadImage, which would improve our speed.
*
* Results:
@@ -791,37 +845,36 @@ GetDataBlock(chan, buf)
*/
static int
-ReadImage(interp, imagePtr, chan, len, rows, cmap,
- width, height, srcX, srcY, interlace, transparent)
- Tcl_Interp *interp;
- char *imagePtr;
- Tcl_Channel chan;
- int len, rows;
- unsigned char cmap[MAXCOLORMAPSIZE][4];
- int width, height;
- int srcX, srcY;
- int interlace;
- int transparent;
+ReadImage(
+ GIFImageConfig *gifConfPtr,
+ Tcl_Interp *interp,
+ unsigned char *imagePtr,
+ Tcl_Channel chan,
+ int len, int rows,
+ unsigned char cmap[MAXCOLORMAPSIZE][4],
+ int srcX, int 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 };
+ register unsigned char *pixelPtr;
+ static const int interlaceStep[] = { 8, 8, 4, 2 };
+ static const 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];
+ 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;
- int code, firstCode;
+ int code, firstCode, v;
/*
- * Initialize the decoder
+ * Initialize the decoder
*/
- if (! ReadOK(chan, &initialCodeSize, 1)) {
+
+ if (Fread(gifConfPtr, &initialCodeSize, 1, 1, chan) <= 0) {
Tcl_AppendResult(interp, "error reading GIF image: ",
- Tcl_PosixError(interp), (char *) NULL);
+ Tcl_PosixError(interp), NULL);
return TCL_ERROR;
}
@@ -848,46 +901,49 @@ ReadImage(interp, imagePtr, chan, len, rows, cmap,
* 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));
+
+ memset(prefix, 0, (1 << MAX_LWZ_BITS) * sizeof(short));
+ memset(append, 0, (1 << MAX_LWZ_BITS) * sizeof(char));
for (i = 0; i < clearCode; i++) {
append[i] = i;
}
top = stack;
- GetCode(chan, 0, 1);
+ GetCode(chan, 0, 1, gifConfPtr);
/*
* 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!
+ * Bummer - our stack is empty. Now we have to work!
*/
- code = GetCode(chan, codeSize, 0);
+
+ code = GetCode(chan, codeSize, 0, gifConfPtr);
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 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;
}
@@ -895,44 +951,48 @@ ReadImage(interp, imagePtr, chan, len, rows, cmap,
/*
* 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.
+ * 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. ???
+ * 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
+ * Populate the stack by tracing the string in the string
+ * table from its tail to its head
*/
+
*top++ = append[code];
code = prefix[code];
}
@@ -942,6 +1002,7 @@ ReadImage(interp, imagePtr, chan, len, rows, cmap,
* 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;
}
@@ -949,21 +1010,24 @@ ReadImage(interp, imagePtr, chan, len, rows, cmap,
/*
* 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.
+ * 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++;
@@ -974,16 +1038,18 @@ ReadImage(interp, imagePtr, chan, len, rows, cmap,
/*
* 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)
+ * 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];
@@ -995,8 +1061,9 @@ ReadImage(interp, imagePtr, chan, len, rows, cmap,
}
/*
- * If interlacing, the next ypos is not just +1
+ * If interlacing, the next ypos is not just +1.
*/
+
if (interlace) {
ypos += interlaceStep[pass];
while (ypos >= rows) {
@@ -1013,27 +1080,25 @@ ReadImage(interp, imagePtr, chan, len, rows, cmap,
}
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:
+ * 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.
+ * 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: chan the channel to read from
* code_size size of the code to extract
- * flag boolean indicating whether the extractor
- * should be reset or not
+ * flag boolean indicating whether the extractor should be
+ * reset or not
*
* Results:
* code the next compression code
@@ -1045,69 +1110,72 @@ ReadImage(interp, imagePtr, chan, len, rows, cmap,
*/
static int
-GetCode(chan, code_size, flag)
- Tcl_Channel chan;
- int code_size;
- int flag;
+GetCode(
+ Tcl_Channel chan,
+ int code_size,
+ int flag,
+ GIFImageConfig *gifConfPtr)
{
- static unsigned char buf[280];
- static int bytes = 0, done;
- static unsigned char *c;
-
- static unsigned int window;
- static int bitsInWindow = 0;
int ret;
-
+
if (flag) {
/*
* Initialize the decoder.
*/
- bitsInWindow = 0;
- bytes = 0;
- window = 0;
- done = 0;
- c = NULL;
+
+ gifConfPtr->reader.bitsInWindow = 0;
+ gifConfPtr->reader.bytes = 0;
+ gifConfPtr->reader.window = 0;
+ gifConfPtr->reader.done = 0;
+ gifConfPtr->reader.c = NULL;
return 0;
}
- while (bitsInWindow < code_size) {
+ while (gifConfPtr->reader.bitsInWindow < code_size) {
/*
* Not enough bits in our window to cover the request.
*/
- if (done) {
+
+ if (gifConfPtr->reader.done) {
return -1;
}
- if (bytes == 0) {
+ if (gifConfPtr->reader.bytes == 0) {
/*
* Not enough bytes in our buffer to add to the window.
*/
- bytes = GetDataBlock(chan, buf);
- c = buf;
- if (bytes <= 0) {
- done = 1;
+
+ gifConfPtr->reader.bytes =
+ GetDataBlock(gifConfPtr, chan, gifConfPtr->workingBuffer);
+ gifConfPtr->reader.c = gifConfPtr->workingBuffer;
+ if (gifConfPtr->reader.bytes <= 0) {
+ gifConfPtr->reader.done = 1;
break;
}
}
+
/*
* Tack another byte onto the window, see if that's enough.
*/
- window += (*c) << bitsInWindow;
- c++;
- bitsInWindow += 8;
- bytes--;
- }
+ gifConfPtr->reader.window +=
+ (*gifConfPtr->reader.c) << gifConfPtr->reader.bitsInWindow;
+ gifConfPtr->reader.c++;
+ gifConfPtr->reader.bitsInWindow += 8;
+ gifConfPtr->reader.bytes--;
+ }
/*
* The next code will always be the last code_size bits of the window.
*/
- ret = window & ((1 << code_size) - 1);
-
+
+ ret = gifConfPtr->reader.window & ((1 << code_size) - 1);
+
/*
* Shift data in the window to put the next code at the end.
*/
- window >>= code_size;
- bitsInWindow -= code_size;
+
+ gifConfPtr->reader.window >>= code_size;
+ gifConfPtr->reader.bitsInWindow -= code_size;
return ret;
}
@@ -1116,27 +1184,27 @@ GetCode(chan, code_size, flag)
*
* Minit -- --
*
- * This procedure initializes a base64 decoder handle
+ * This function initializes a base64 decoder handle
*
* Results:
- * none
+ * None
*
* Side effects:
- * the base64 handle is initialized
+ * The base64 handle is initialized
*
*----------------------------------------------------------------------
*/
static void
-mInit(string, length, handle)
- unsigned char *string; /* string containing initial mmencoded data */
- int length; /* Length of string */
- MFile *handle; /* mmdecode "file" handle */
+mInit(
+ unsigned char *string, /* string containing initial mmencoded data */
+ MFile *handle, /* mmdecode "file" handle */
+ int length) /* Number of bytes in string */
{
handle->data = string;
- handle->length = length;
handle->state = 0;
handle->c = 0;
+ handle->length = length;
}
/*
@@ -1144,9 +1212,9 @@ mInit(string, length, handle)
*
* Mread --
*
- * This procedure is invoked by the GIF file reader as a
- * temporary replacement for "fread", to get GIF data out
- * of a string (using Mgetc).
+ * This function is invoked by the GIF file reader as a temporary
+ * replacement for "fread", to get GIF data out of a string (using
+ * Mgetc).
*
* Results:
* The return value is the number of characters "read"
@@ -1158,50 +1226,45 @@ mInit(string, length, handle)
*/
static int
-Mread(dst, chunkSize, numChunks, handle)
- unsigned char *dst; /* where to put the result */
- size_t chunkSize; /* size of each transfer */
- size_t numChunks; /* number of chunks */
- MFile *handle; /* mmdecode "file" handle */
+Mread(
+ unsigned char *dst, /* where to put the result */
+ size_t chunkSize, /* size of each transfer */
+ size_t numChunks, /* number of chunks */
+ MFile *handle) /* mmdecode "file" handle */
{
register int i, c;
int count = chunkSize * numChunks;
- for(i=0; i<count && (c=Mgetc(handle)) != GIF_DONE; i++) {
+ for (i=0; i<count && (c=Mgetc(handle)) != GIF_DONE; i++) {
*dst++ = c;
}
return i;
}
-
-/*
- * get the next decoded character from an mmencode handle
- * This causes at least 1 character to be "read" from the encoded string
- */
/*
*----------------------------------------------------------------------
*
* Mgetc --
*
- * This procedure decodes and returns the next byte from a base64
- * encoded string.
+ * This function gets the next decoded character from an mmencode handle.
+ * This causes at least 1 character to be "read" from the encoded string.
*
* Results:
- * The next byte (or GIF_DONE) is returned.
+ * The next byte (or GIF_DONE) is returned.
*
* Side effects:
- * The base64 handle will change state.
+ * The base64 handle will change state.
*
*----------------------------------------------------------------------
*/
static int
-Mgetc(handle)
- MFile *handle; /* Handle containing decoder data and state */
+Mgetc(
+ MFile *handle) /* Handle containing decoder data and state */
{
int c;
- int result = 0; /* Initialization needed only to prevent
- * gcc compiler warning. */
+ int result = 0; /* Initialization needed only to prevent gcc
+ * compiler warning. */
if (handle->state == GIF_DONE) {
return GIF_DONE;
@@ -1209,7 +1272,6 @@ Mgetc(handle)
do {
if (handle->length-- <= 0) {
- handle->state = GIF_DONE;
return GIF_DONE;
}
c = char64(*handle->data);
@@ -1247,21 +1309,22 @@ Mgetc(handle)
*
* char64 --
*
- * This procedure converts a base64 ascii character into its binary
- * equivalent. This code is a slightly modified version of the
- * char64 proc in N. Borenstein's metamail decoder.
+ * This function converts a base64 ascii character into its binary
+ * equivalent. This code is a slightly modified version of the char64
+ * function in N. Borenstein's metamail decoder.
*
* Results:
* The binary value, or an error code.
*
* Side effects:
* None.
+ *
*----------------------------------------------------------------------
*/
static int
-char64(c)
-int c;
+char64(
+ int c)
{
switch(c) {
case 'A': return 0; case 'B': return 1; case 'C': return 2;
@@ -1303,52 +1366,53 @@ int c;
*
* Fread --
*
- * This procedure calls either fread or Mread to read data
- * from a file or a base64 encoded string.
+ * This function calls either fread or Mread to read data from a file or
+ * a base64 encoded string.
*
- * Results: - same as fread
+ * Results: - same as POSIX fread() or Tcl Tcl_Read()
*
*----------------------------------------------------------------------
*/
static int
-Fread(dst, hunk, count, chan)
- unsigned char *dst; /* where to put the result */
- size_t hunk,count; /* how many */
- Tcl_Channel chan;
+Fread(
+ GIFImageConfig *gifConfPtr,
+ unsigned char *dst, /* where to put the result */
+ size_t hunk, size_t count, /* how many */
+ Tcl_Channel chan)
{
- ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
- Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
- MFile *handle;
-
- switch (tsdPtr->fromData) {
- case 1:
+ if (gifConfPtr->fromData == INLINE_DATA_BASE64) {
return Mread(dst, hunk, count, (MFile *) chan);
- case 2:
- handle = (MFile *) chan;
- if (handle->length <= 0 || (size_t)handle->length < (size_t) (hunk * count)) {
+ }
+
+ if (gifConfPtr->fromData == INLINE_DATA_BINARY) {
+ MFile *handle = (MFile *) chan;
+
+ if (handle->length <= 0 || (size_t) handle->length < hunk*count) {
return -1;
}
- memcpy((VOID *)dst, (VOID *) handle->data, (size_t) (hunk * count));
+ memcpy(dst, handle->data, (size_t) (hunk * count));
handle->data += hunk * count;
- handle->length -= hunk * count;
return (int)(hunk * count);
- default:
- return Tcl_Read(chan, (char *) dst, (int) (hunk * count));
}
-}
+ /*
+ * Otherwise we've got a real file to read.
+ */
+
+ return Tcl_Read(chan, (char *) dst, (int) (hunk * count));
+}
/*
* ChanWriteGIF - 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
+ * 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 <j.nijtmans@chello.nl>
@@ -1356,60 +1420,65 @@ Fread(dst, hunk, count, chan)
*----------------------------------------------------------------------
* FileWriteGIF-
*
- * This procedure is called by the photo image type to write
- * GIF format data from a photo image into a given file
+ * This function 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 interp->result.
+ * A standard TCL completion code. If TCL_ERROR is returned then an error
+ * message is left in interp->result.
*
*----------------------------------------------------------------------
*/
- /*
- * Types, defines and variables needed to write and compress a GIF.
- */
-
-typedef int (* ifunptr) _ANSI_ARGS_((void));
-
-#define LSB(a) ((unsigned char) (((short)(a)) & 0x00FF))
-#define MSB(a) ((unsigned char) (((short)(a)) >> 8))
-
-#define GIFBITS 12
-#define HSIZE 5003 /* 80% occupancy */
+/*
+ * Types, defines and variables needed to write and compress a GIF.
+ */
-static int ssize;
-static int csize;
-static int rsize;
-static unsigned char *pixelo;
-static int pixelSize;
-static int pixelPitch;
-static int greenOffset;
-static int blueOffset;
-static int alphaOffset;
-static int num;
-static unsigned char mapa[MAXCOLORMAPSIZE][3];
+typedef int (* ifunptr) (ClientData clientData);
+
+#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;
/*
- * Definition of new functions to write GIFs
+ * Definition of new functions to write GIFs
*/
-static int color _ANSI_ARGS_((int red,int green, int blue,
- unsigned char mapa[MAXCOLORMAPSIZE][3]));
-static void compress _ANSI_ARGS_((int init_bits, Tcl_Channel handle,
- ifunptr readValue));
-static int nuevo _ANSI_ARGS_((int red, int green ,int blue,
- unsigned char mapa[MAXCOLORMAPSIZE][3]));
-static void savemap _ANSI_ARGS_((Tk_PhotoImageBlock *blockPtr,
- unsigned char mapa[MAXCOLORMAPSIZE][3]));
-static int ReadValue _ANSI_ARGS_((void));
-
+static int color(GifWriterState *statePtr,
+ int red, int green, int blue,
+ unsigned char mapa[MAXCOLORMAPSIZE][3]);
+static void compress(int initBits, Tcl_Channel handle,
+ ifunptr readValue, ClientData clientData);
+static int nuevo(GifWriterState *statePtr,
+ int red, int green, int blue,
+ unsigned char mapa[MAXCOLORMAPSIZE][3]);
+static void savemap(GifWriterState *statePtr,
+ Tk_PhotoImageBlock *blockPtr,
+ unsigned char mapa[MAXCOLORMAPSIZE][3]);
+static int ReadValue(ClientData clientData);
+
static int
-FileWriteGIF(interp, filename, format, blockPtr)
- Tcl_Interp *interp; /* Interpreter to use for reporting errors. */
- CONST char *filename;
- Tcl_Obj *format;
- Tk_PhotoImageBlock *blockPtr;
+FileWriteGIF(
+ Tcl_Interp *interp, /* Interpreter to use for reporting errors. */
+ const char *filename,
+ Tcl_Obj *format,
+ Tk_PhotoImageBlock *blockPtr)
{
Tcl_Channel chan = NULL;
int result;
@@ -1418,167 +1487,168 @@ FileWriteGIF(interp, filename, format, blockPtr)
if (!chan) {
return TCL_ERROR;
}
- if (Tcl_SetChannelOption(interp, chan, "-translation", "binary") != TCL_OK) {
+ if (Tcl_SetChannelOption(interp, chan, "-translation",
+ "binary") != TCL_OK) {
Tcl_Close(NULL, chan);
return TCL_ERROR;
}
result = CommonWriteGIF(interp, chan, format, blockPtr);
+
if (Tcl_Close(interp, chan) == TCL_ERROR) {
return TCL_ERROR;
}
return result;
}
-
-#define Mputc(c,handle) Tcl_Write(handle,(char *) &c,1)
-
+
static int
-CommonWriteGIF(interp, handle, format, blockPtr)
- Tcl_Interp *interp;
- Tcl_Channel handle;
- Tcl_Obj *format;
- Tk_PhotoImageBlock *blockPtr;
+CommonWriteGIF(
+ Tcl_Interp *interp,
+ Tcl_Channel handle,
+ Tcl_Obj *format,
+ Tk_PhotoImageBlock *blockPtr)
{
- int resolution;
-
- long width,height,x;
+ GifWriterState state, *statePtr = &state;
+ int resolution;
+ long width, height, x;
unsigned char c;
- unsigned int top,left;
+ unsigned int top, left;
top = 0;
left = 0;
- pixelSize = blockPtr->pixelSize;
- greenOffset = blockPtr->offset[1]-blockPtr->offset[0];
- blueOffset = blockPtr->offset[2]-blockPtr->offset[0];
- alphaOffset = blockPtr->offset[0];
- if (alphaOffset < blockPtr->offset[2]) {
- alphaOffset = blockPtr->offset[2];
+ memset(statePtr, 0, sizeof(state));
+
+ statePtr->pixelSize = blockPtr->pixelSize;
+ statePtr->greenOffset = blockPtr->offset[1]-blockPtr->offset[0];
+ statePtr->blueOffset = blockPtr->offset[2]-blockPtr->offset[0];
+ statePtr->alphaOffset = blockPtr->offset[0];
+ if (statePtr->alphaOffset < blockPtr->offset[2]) {
+ statePtr->alphaOffset = blockPtr->offset[2];
}
- if (++alphaOffset < pixelSize) {
- alphaOffset -= blockPtr->offset[0];
+ if (++statePtr->alphaOffset < statePtr->pixelSize) {
+ statePtr->alphaOffset -= blockPtr->offset[0];
} else {
- alphaOffset = 0;
+ statePtr->alphaOffset = 0;
}
- Tcl_Write(handle, (char *) (alphaOffset ? GIF89a : GIF87a), 6);
+ Tcl_Write(handle, (char *) (statePtr->alphaOffset ? GIF89a : GIF87a), 6);
for (x=0 ; x<MAXCOLORMAPSIZE ; x++) {
- mapa[x][CM_RED] = 255;
- mapa[x][CM_GREEN] = 255;
- mapa[x][CM_BLUE] = 255;
+ statePtr->mapa[x][CM_RED] = 255;
+ statePtr->mapa[x][CM_GREEN] = 255;
+ statePtr->mapa[x][CM_BLUE] = 255;
}
-
width = blockPtr->width;
height = blockPtr->height;
- pixelo = blockPtr->pixelPtr + blockPtr->offset[0];
- pixelPitch = blockPtr->pitch;
- savemap(blockPtr,mapa);
- if (num >= MAXCOLORMAPSIZE) {
- Tcl_AppendResult(interp, "too many colors", (char *) NULL);
+ statePtr->pixelo = blockPtr->pixelPtr + blockPtr->offset[0];
+ statePtr->pixelPitch = blockPtr->pitch;
+ savemap(statePtr, blockPtr, statePtr->mapa);
+ if (statePtr->num >= MAXCOLORMAPSIZE) {
+ Tcl_AppendResult(interp, "too many colors", NULL);
return TCL_ERROR;
}
- if (num<2) {
- num = 2;
+ if (statePtr->num<2) {
+ statePtr->num = 2;
}
c = LSB(width);
- Mputc(c,handle);
+ Tcl_Write(handle, (char *) &c, 1);
c = MSB(width);
- Mputc(c,handle);
+ Tcl_Write(handle, (char *) &c, 1);
c = LSB(height);
- Mputc(c,handle);
+ Tcl_Write(handle, (char *) &c, 1);
c = MSB(height);
- Mputc(c,handle);
+ Tcl_Write(handle, (char *) &c, 1);
resolution = 0;
- while (num >> resolution) {
+ while (statePtr->num >> resolution) {
resolution++;
}
c = 111 + resolution * 17;
- Mputc(c,handle);
+ Tcl_Write(handle, (char *) &c, 1);
- num = 1 << resolution;
+ statePtr->num = 1 << resolution;
/*
- * background color
+ * Background color
*/
c = 0;
- Mputc(c,handle);
+ Tcl_Write(handle, (char *) &c, 1);
/*
- * zero for future expansion.
+ * Zero for future expansion.
*/
- Mputc(c,handle);
+ Tcl_Write(handle, (char *) &c, 1);
- for (x=0 ; x<num ; x++) {
- c = mapa[x][CM_RED];
- Mputc(c,handle);
- c = mapa[x][CM_GREEN];
- Mputc(c,handle);
- c = mapa[x][CM_BLUE];
- Mputc(c,handle);
+ for (x=0 ; x<statePtr->num ; x++) {
+ c = statePtr->mapa[x][CM_RED];
+ Tcl_Write(handle, (char *) &c, 1);
+ c = statePtr->mapa[x][CM_GREEN];
+ Tcl_Write(handle, (char *) &c, 1);
+ c = statePtr->mapa[x][CM_BLUE];
+ Tcl_Write(handle, (char *) &c, 1);
}
/*
* Write out extension for transparent colour index, if necessary.
*/
- if (alphaOffset) {
+ if (statePtr->alphaOffset) {
c = GIF_EXTENSION;
- Mputc(c, handle);
+ Tcl_Write(handle, (char *) &c, 1);
Tcl_Write(handle, "\371\4\1\0\0\0", 7);
}
c = GIF_START;
- Mputc(c,handle);
+ Tcl_Write(handle, (char *) &c, 1);
c = LSB(top);
- Mputc(c,handle);
+ Tcl_Write(handle, (char *) &c, 1);
c = MSB(top);
- Mputc(c,handle);
+ Tcl_Write(handle, (char *) &c, 1);
c = LSB(left);
- Mputc(c,handle);
+ Tcl_Write(handle, (char *) &c, 1);
c = MSB(left);
- Mputc(c,handle);
+ Tcl_Write(handle, (char *) &c, 1);
c = LSB(width);
- Mputc(c,handle);
+ Tcl_Write(handle, (char *) &c, 1);
c = MSB(width);
- Mputc(c,handle);
+ Tcl_Write(handle, (char *) &c, 1);
c = LSB(height);
- Mputc(c,handle);
+ Tcl_Write(handle, (char *) &c, 1);
c = MSB(height);
- Mputc(c,handle);
+ Tcl_Write(handle, (char *) &c, 1);
c = 0;
- Mputc(c,handle);
+ Tcl_Write(handle, (char *) &c, 1);
c = resolution;
- Mputc(c,handle);
+ Tcl_Write(handle, (char *) &c, 1);
- ssize = rsize = blockPtr->width;
- csize = blockPtr->height;
- compress(resolution+1, handle, ReadValue);
+ statePtr->ssize = statePtr->rsize = blockPtr->width;
+ statePtr->csize = blockPtr->height;
+ compress(resolution+1, handle, ReadValue, (ClientData) statePtr);
- c = 0;
- Mputc(c,handle);
+ c = 0;
+ Tcl_Write(handle, (char *) &c, 1);
c = GIF_TERMINATOR;
- Mputc(c,handle);
+ Tcl_Write(handle, (char *) &c, 1);
- return TCL_OK;
+ return TCL_OK;
}
-
+
static int
-color(red, green, blue, mapa)
- int red;
- int green;
- int blue;
- unsigned char mapa[MAXCOLORMAPSIZE][3];
+color(
+ GifWriterState *statePtr,
+ int red, int green, int blue,
+ unsigned char mapa[MAXCOLORMAPSIZE][3])
{
- int x;
- for (x=(alphaOffset != 0) ; x<=MAXCOLORMAPSIZE ; x++) {
+ int x = (statePtr->alphaOffset != 0);
+
+ for (; x<=MAXCOLORMAPSIZE ; x++) {
if ((mapa[x][CM_RED] == red) && (mapa[x][CM_GREEN] == green) &&
(mapa[x][CM_BLUE] == blue)) {
return x;
@@ -1586,15 +1656,16 @@ color(red, green, blue, mapa)
}
return -1;
}
-
static int
-nuevo(red, green, blue, mapa)
- int red,green,blue;
- unsigned char mapa[MAXCOLORMAPSIZE][3];
+nuevo(
+ GifWriterState *statePtr,
+ int red, int green, int blue,
+ unsigned char mapa[MAXCOLORMAPSIZE][3])
{
- int x = (alphaOffset != 0);
- for (; x<=num ; x++) {
+ int x = (statePtr->alphaOffset != 0);
+
+ for (; x<=statePtr->num ; x++) {
if ((mapa[x][CM_RED] == red) && (mapa[x][CM_GREEN] == green) &&
(mapa[x][CM_BLUE] == blue)) {
return 0;
@@ -1602,74 +1673,76 @@ nuevo(red, green, blue, mapa)
}
return 1;
}
-
+
static void
-savemap(blockPtr,mapa)
- Tk_PhotoImageBlock *blockPtr;
- unsigned char mapa[MAXCOLORMAPSIZE][3];
+savemap(
+ GifWriterState *statePtr,
+ Tk_PhotoImageBlock *blockPtr,
+ unsigned char mapa[MAXCOLORMAPSIZE][3])
{
unsigned char *colores;
- int x,y;
- unsigned char red,green,blue;
+ int x, y;
+ unsigned char red, green, blue;
- if (alphaOffset) {
- num = 0;
+ if (statePtr->alphaOffset) {
+ statePtr->num = 0;
mapa[0][CM_RED] = 0xd9;
mapa[0][CM_GREEN] = 0xd9;
mapa[0][CM_BLUE] = 0xd9;
} else {
- num = -1;
+ statePtr->num = -1;
}
- for(y=0 ; y<blockPtr->height ; y++) {
- colores = blockPtr->pixelPtr + blockPtr->offset[0]
- + y * blockPtr->pitch;
- for(x=0 ; x<blockPtr->width ; x++) {
- if (!alphaOffset || (colores[alphaOffset] != 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[greenOffset];
- blue = colores[blueOffset];
- if (nuevo(red,green,blue,mapa)) {
- num++;
- if (num >= MAXCOLORMAPSIZE) {
+ green = colores[statePtr->greenOffset];
+ blue = colores[statePtr->blueOffset];
+ if (nuevo(statePtr, red, green, blue, mapa)) {
+ statePtr->num++;
+ if (statePtr->num >= MAXCOLORMAPSIZE) {
return;
}
- mapa[num][CM_RED] = red;
- mapa[num][CM_GREEN] = green;
- mapa[num][CM_BLUE] = blue;
+ mapa[statePtr->num][CM_RED] = red;
+ mapa[statePtr->num][CM_GREEN] = green;
+ mapa[statePtr->num][CM_BLUE] = blue;
}
}
- colores += pixelSize;
+ colores += statePtr->pixelSize;
}
}
- return;
}
-
+
static int
-ReadValue()
+ReadValue(
+ ClientData clientData)
{
+ GifWriterState *statePtr = (GifWriterState *) clientData;
unsigned int col;
- if (csize == 0) {
+ if (statePtr->csize == 0) {
return EOF;
}
- if (alphaOffset && (pixelo[alphaOffset] == 0)) {
+ if (statePtr->alphaOffset && statePtr->pixelo[statePtr->alphaOffset]==0) {
col = 0;
} else {
- col = color(pixelo[0], pixelo[greenOffset], pixelo[blueOffset], mapa);
+ col = color(statePtr, statePtr->pixelo[0],
+ statePtr->pixelo[statePtr->greenOffset],
+ statePtr->pixelo[statePtr->blueOffset], statePtr->mapa);
}
- pixelo += pixelSize;
- if (--ssize <= 0) {
- ssize = rsize;
- csize--;
- pixelo += pixelPitch - (rsize * pixelSize);
+ statePtr->pixelo += statePtr->pixelSize;
+ if (--statePtr->ssize <= 0) {
+ statePtr->ssize = statePtr->rsize;
+ statePtr->csize--;
+ statePtr->pixelo += statePtr->pixelPitch
+ - (statePtr->rsize * statePtr->pixelSize);
}
return col;
}
-
-
/*
*-----------------------------------------------------------------------
*
@@ -1681,30 +1754,27 @@ ReadValue()
* http://www.hasc.com
* info@hasc.com
*
- * 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." The Hutchison Avenue Software Corporation
- * disclaims all warranties, either express or implied, including but
- * not limited to implied warranties of merchantability and fitness
- * for a particular purpose, with respect to this code and
+ * 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." The Hutchison Avenue
+ * Software Corporation disclaims all warranties, either express or implied,
+ * including but not limited to implied warranties of merchantability and
+ * fitness for a particular purpose, with respect to this code and
* accompanying documentation.
- *
- * The miGIF compression routines do not, strictly speaking, generate
- * files conforming to the GIF spec, since the image data is not
- * LZW-compressed (this is the point: in order to avoid transgression
- * of the Unisys patent on the LZW algorithm.) However, miGIF
- * generates data streams that any reasonably sane LZW decompresser
- * will decompress to what we want.
- *
- * miGIF compression uses run length encoding. It compresses
- * horizontal runs of pixels of the same color. This type of
- * compression gives good results on images with many runs, for
- * example images with lines, text and solid shapes on a solid-colored
- * background. It gives little or no compression on images with few
- * runs, for example digital or scanned photos.
+ *
+ * The miGIF compression routines do not, strictly speaking, generate files
+ * conforming to the GIF spec, since the image data is not LZW-compressed
+ * (this is the point: in order to avoid transgression of the Unisys patent on
+ * the LZW algorithm.) However, miGIF generates data streams that any
+ * reasonably sane LZW decompresser will decompress to what we want.
+ *
+ * miGIF compression uses run length encoding. It compresses horizontal runs
+ * of pixels of the same color. This type of compression gives good results on
+ * images with many runs, for example images with lines, text and solid shapes
+ * on a solid-colored background. It gives little or no compression on images
+ * with few runs, for example digital or scanned photos.
*
* der Mouse
* mouse@rodents.montreal.qc.ca
@@ -1712,35 +1782,36 @@ ReadValue()
*
* ivo@hasc.com
*
- * The Graphics Interchange Format(c) is the Copyright property of
- * CompuServe Incorporated. GIF(sm) is a Service Mark property of
- * CompuServe Incorporated.
+ * The Graphics Interchange Format(c) is the Copyright property of CompuServe
+ * Incorporated. GIF(sm) is a Service Mark property of CompuServe Incorporated.
*
*-----------------------------------------------------------------------
*/
-static int rl_pixel;
-static int rl_basecode;
-static int rl_count;
-static int rl_table_pixel;
-static int rl_table_max;
-static int just_cleared;
-static int out_bits;
-static int out_bits_init;
-static int out_count;
-static int out_bump;
-static int out_bump_init;
-static int out_clear;
-static int out_clear_init;
-static int max_ocodes;
-static int code_clear;
-static int code_eof;
-static unsigned int obuf;
-static int obits;
-static Tcl_Channel ofile;
-static unsigned char oblock[256];
-static int oblen;
-
+typedef struct {
+ int runlengthPixel;
+ int runlengthBaseCode;
+ int runlengthCount;
+ int runlengthTablePixel;
+ int runlengthTableMax;
+ int justCleared;
+ int outputBits;
+ int outputBitsInit;
+ int outputCount;
+ int outputBump;
+ int outputBumpInit;
+ int outputClear;
+ int outputClearInit;
+ int maxOcodes;
+ int codeClear;
+ int codeEOF;
+ unsigned int obuf;
+ int obits;
+ Tcl_Channel ofile;
+ unsigned char oblock[256];
+ int oblen;
+} miGIFState_t;
+
/*
* Used only when debugging GIF compression code
*/
@@ -1748,23 +1819,28 @@ static int oblen;
#ifdef MIGIF_DEBUGGING_ENVARS
-static int verbose_set = 0;
+/*
+ * This debugging code is _absolutely_ not thread-safe. It's also not normally
+ * enabled either.
+ */
+
+static int verboseSet = 0;
static int verbose;
-#define MIGIF_VERBOSE (verbose_set?verbose:set_verbose())
-#define DEBUGMSG(printf_args) if (MIGIF_VERBOSE) { printf printf_args; }
+#define MIGIF_VERBOSE (verboseSet?verbose:setVerbose())
+#define DEBUGMSG(printfArgs) if (MIGIF_VERBOSE) { printf printfArgs; }
static int
-set_verbose(void)
+setVerbose(void)
{
verbose = !!getenv("MIGIF_VERBOSE");
- verbose_set = 1;
+ verboseSet = 1;
return verbose;
}
-static CONST char *
-binformat(v, nbits)
- unsigned int v;
- int nbits;
+static const char *
+binformat(
+ unsigned int v,
+ int nbits)
{
static char bufs[8][64];
static int bhand = 0;
@@ -1786,112 +1862,119 @@ binformat(v, nbits)
*bp = '\0';
return &bufs[bhand][0];
}
-
-#else
-
-#define MIGIF_VERBOSE 0
-#define DEBUGMSG(printf_args) /* do nothing */
-
+#else /* !MIGIF_DEBUGGING_ENVARS */
+#define DEBUGMSG(printfArgs) /* do nothing */
#endif
-
+
static void
-write_block()
+writeBlock(
+ miGIFState_t *statePtr)
{
- int i;
unsigned char c;
+#ifdef MIGIF_DEBUGGING_ENVARS
if (MIGIF_VERBOSE) {
- printf("write_block %d:", oblen);
- for (i=0 ; i<oblen ; i++) {
- printf(" %02x", oblock[i]);
+ int i;
+ printf("writeBlock %d:", statePtr->oblen);
+ for (i=0 ; i<statePtr->oblen ; i++) {
+ printf(" %02x", statePtr->oblock[i]);
}
printf("\n");
}
- c = oblen;
- Tcl_Write(ofile, (char *) &c, 1);
- Tcl_Write(ofile, (char *) &oblock[0], oblen);
- oblen = 0;
+#endif
+ c = statePtr->oblen;
+ Tcl_Write(statePtr->ofile, (char *) &c, 1);
+ Tcl_Write(statePtr->ofile, (char *) &statePtr->oblock[0], statePtr->oblen);
+ statePtr->oblen = 0;
}
-
+
static void
-block_out(c)
- unsigned char c;
+blockOut(
+ miGIFState_t *statePtr,
+ unsigned c)
{
- DEBUGMSG(("block_out %s\n", binformat(c, 8)));
- oblock[oblen++] = c;
- if (oblen >= 255) {
- write_block();
+ DEBUGMSG(("blockOut %s\n", binformat(c, 8)));
+ statePtr->oblock[statePtr->oblen++] = (unsigned char) c;
+ if (statePtr->oblen >= 255) {
+ writeBlock(statePtr);
}
}
-
+
static void
-block_flush()
+blockFlush(
+ miGIFState_t *statePtr)
{
- DEBUGMSG(("block_flush\n"));
- if (oblen > 0) {
- write_block();
+ DEBUGMSG(("blockFlush\n"));
+ if (statePtr->oblen > 0) {
+ writeBlock(statePtr);
}
}
-
+
static void
-output(val)
- int val;
+output(
+ miGIFState_t *statePtr,
+ int val)
{
- DEBUGMSG(("output %s [%s %d %d]\n", binformat(val, out_bits),
- binformat(obuf, obits), obits, out_bits));
- obuf |= val << obits;
- obits += out_bits;
- while (obits >= 8) {
- block_out(UCHAR(obuf&0xff));
- obuf >>= 8;
- obits -= 8;
- }
- DEBUGMSG(("output leaving [%s %d]\n", binformat(obuf, obits), obits));
+ DEBUGMSG(("output %s [%s %d %d]\n", binformat(val, statePtr->outputBits),
+ binformat(statePtr->obuf, statePtr->obits), statePtr->obits,
+ statePtr->outputBits));
+ statePtr->obuf |= val << statePtr->obits;
+ statePtr->obits += statePtr->outputBits;
+ while (statePtr->obits >= 8) {
+ blockOut(statePtr, statePtr->obuf & 0xff);
+ statePtr->obuf >>= 8;
+ statePtr->obits -= 8;
+ }
+ DEBUGMSG(("output leaving [%s %d]\n",
+ binformat(statePtr->obuf, statePtr->obits), statePtr->obits));
}
-
+
static void
-output_flush()
+outputFlush(
+ miGIFState_t *statePtr)
{
- DEBUGMSG(("output_flush\n"));
- if (obits > 0) {
- block_out(UCHAR(obuf));
+ DEBUGMSG(("outputFlush\n"));
+ if (statePtr->obits > 0) {
+ blockOut(statePtr, statePtr->obuf);
}
- block_flush();
+ blockFlush(statePtr);
}
-
+
static void
-did_clear()
+didClear(
+ miGIFState_t *statePtr)
{
- DEBUGMSG(("did_clear\n"));
- out_bits = out_bits_init;
- out_bump = out_bump_init;
- out_clear = out_clear_init;
- out_count = 0;
- rl_table_max = 0;
- just_cleared = 1;
+ DEBUGMSG(("didClear\n"));
+ statePtr->outputBits = statePtr->outputBitsInit;
+ statePtr->outputBump = statePtr->outputBumpInit;
+ statePtr->outputClear = statePtr->outputClearInit;
+ statePtr->outputCount = 0;
+ statePtr->runlengthTableMax = 0;
+ statePtr->justCleared = 1;
}
-
+
static void
-output_plain(c)
- int c;
+outputPlain(
+ miGIFState_t *statePtr,
+ int c)
{
- DEBUGMSG(("output_plain %s\n", binformat(c, out_bits)));
- just_cleared = 0;
- output(c);
- out_count++;
- if (out_count >= out_bump) {
- out_bits++;
- out_bump += 1 << (out_bits - 1);
- }
- if (out_count >= out_clear) {
- output(code_clear);
- did_clear();
+ DEBUGMSG(("outputPlain %s\n", binformat(c, statePtr->outputBits)));
+ statePtr->justCleared = 0;
+ output(statePtr, c);
+ statePtr->outputCount++;
+ if (statePtr->outputCount >= statePtr->outputBump) {
+ statePtr->outputBits++;
+ statePtr->outputBump += 1 << (statePtr->outputBits - 1);
+ }
+ if (statePtr->outputCount >= statePtr->outputClear) {
+ output(statePtr, statePtr->codeClear);
+ didClear(statePtr);
}
}
-
+
static unsigned int
-isqrt(x)
- unsigned int x;
+isqrt(
+ unsigned int x)
{
unsigned int r;
unsigned int v;
@@ -1908,11 +1991,11 @@ isqrt(x)
r = v;
}
}
-
-static unsigned int
-compute_triangle_count(count, nrepcodes)
- unsigned int count;
- unsigned int nrepcodes;
+
+static int
+computeTriangleCount(
+ unsigned int count,
+ unsigned int nrepcodes)
{
unsigned int perrep;
unsigned int cost;
@@ -1924,8 +2007,8 @@ compute_triangle_count(count, nrepcodes)
count -= perrep;
}
if (count > 0) {
- unsigned int n;
- n = isqrt(count);
+ unsigned int n = isqrt(count);
+
while (n*(n+1) >= 2*count) {
n--;
}
@@ -1934,204 +2017,233 @@ compute_triangle_count(count, nrepcodes)
}
cost += n;
}
- return cost;
+ return (int) cost + 1;
}
-
+
static void
-max_out_clear()
+maxOutputClear(
+ miGIFState_t *statePtr)
{
- out_clear = max_ocodes;
+ statePtr->outputClear = statePtr->maxOcodes;
}
-
+
static void
-reset_out_clear()
+resetOutputClear(
+ miGIFState_t *statePtr)
{
- out_clear = out_clear_init;
- if (out_count >= out_clear) {
- output(code_clear);
- did_clear();
+ statePtr->outputClear = statePtr->outputClearInit;
+ if (statePtr->outputCount >= statePtr->outputClear) {
+ output(statePtr, statePtr->codeClear);
+ didClear(statePtr);
}
}
-
+
static void
-rl_flush_fromclear(count)
- int count;
+runlengthFlushFromClear(
+ miGIFState_t *statePtr,
+ int count)
{
int n;
- DEBUGMSG(("rl_flush_fromclear %d\n", count));
- max_out_clear();
- rl_table_pixel = rl_pixel;
+ DEBUGMSG(("runlengthFlushFromClear %d\n", count));
+ maxOutputClear(statePtr);
+ statePtr->runlengthTablePixel = statePtr->runlengthPixel;
n = 1;
while (count > 0) {
if (n == 1) {
- rl_table_max = 1;
- output_plain(rl_pixel);
+ statePtr->runlengthTableMax = 1;
+ outputPlain(statePtr, statePtr->runlengthPixel);
count--;
} else if (count >= n) {
- rl_table_max = n;
- output_plain(rl_basecode+n-2);
+ statePtr->runlengthTableMax = n;
+ outputPlain(statePtr, statePtr->runlengthBaseCode+n-2);
count -= n;
} else if (count == 1) {
- rl_table_max++;
- output_plain(rl_pixel);
+ statePtr->runlengthTableMax++;
+ outputPlain(statePtr, statePtr->runlengthPixel);
count = 0;
} else {
- rl_table_max++;
- output_plain(rl_basecode+count-2);
+ statePtr->runlengthTableMax++;
+ outputPlain(statePtr, statePtr->runlengthBaseCode+count-2);
count = 0;
}
- if (out_count == 0) {
+ if (statePtr->outputCount == 0) {
n = 1;
} else {
n++;
}
}
- reset_out_clear();
- DEBUGMSG(("rl_flush_fromclear leaving table_max=%d\n", rl_table_max));
+ resetOutputClear(statePtr);
+ DEBUGMSG(("runlengthFlushFromClear leaving tableMax=%d\n",
+ statePtr->runlengthTableMax));
}
-
+
static void
-rl_flush_clearorrep(count)
- int count;
+runlengthFlushClearOrRep(
+ miGIFState_t *statePtr,
+ int count)
{
int withclr;
- DEBUGMSG(("rl_flush_clearorrep %d\n", count));
- withclr = 1 + compute_triangle_count(count, max_ocodes);
+ DEBUGMSG(("runlengthFlushClearOrRep %d\n", count));
+ withclr = computeTriangleCount((unsigned) count,
+ (unsigned) statePtr->maxOcodes);
if (withclr < count) {
- output(code_clear);
- did_clear();
- rl_flush_fromclear(count);
+ output(statePtr, statePtr->codeClear);
+ didClear(statePtr);
+ runlengthFlushFromClear(statePtr, count);
} else {
for (; count>0 ; count--) {
- output_plain(rl_pixel);
+ outputPlain(statePtr, statePtr->runlengthPixel);
}
}
}
-
+
static void
-rl_flush_withtable(count)
- int count;
+runlengthFlushWithTable(
+ miGIFState_t *statePtr,
+ int count)
{
int repmax;
int repleft;
int leftover;
- DEBUGMSG(("rl_flush_withtable %d\n", count));
- repmax = count / rl_table_max;
- leftover = count % rl_table_max;
+ DEBUGMSG(("runlengthFlushWithTable %d\n", count));
+ repmax = count / statePtr->runlengthTableMax;
+ leftover = count % statePtr->runlengthTableMax;
repleft = (leftover ? 1 : 0);
- if (out_count+repmax+repleft > max_ocodes) {
- repmax = max_ocodes - out_count;
- leftover = count - (repmax * rl_table_max);
- repleft = 1 + compute_triangle_count(leftover, max_ocodes);
+ if (statePtr->outputCount+repmax+repleft > statePtr->maxOcodes) {
+ repmax = statePtr->maxOcodes - statePtr->outputCount;
+ leftover = count - (repmax * statePtr->runlengthTableMax);
+ repleft = computeTriangleCount((unsigned) leftover,
+ (unsigned) statePtr->maxOcodes);
}
- DEBUGMSG(("rl_flush_withtable repmax=%d leftover=%d repleft=%d\n",
+ DEBUGMSG(("runlengthFlushWithTable repmax=%d leftover=%d repleft=%d\n",
repmax, leftover, repleft));
- if (1+(int)compute_triangle_count(count, max_ocodes) < repmax+repleft) {
- output(code_clear);
- did_clear();
- rl_flush_fromclear(count);
+ if (computeTriangleCount((unsigned) count, (unsigned) statePtr->maxOcodes)
+ < repmax+repleft) {
+ output(statePtr, statePtr->codeClear);
+ didClear(statePtr);
+ runlengthFlushFromClear(statePtr, count);
return;
}
- max_out_clear();
+ maxOutputClear(statePtr);
for (; repmax>0 ; repmax--) {
- output_plain(rl_basecode + rl_table_max - 2);
+ outputPlain(statePtr,
+ statePtr->runlengthBaseCode + statePtr->runlengthTableMax - 2);
}
if (leftover) {
- if (just_cleared) {
- rl_flush_fromclear(leftover);
+ if (statePtr->justCleared) {
+ runlengthFlushFromClear(statePtr, leftover);
} else if (leftover == 1) {
- output_plain(rl_pixel);
+ outputPlain(statePtr, statePtr->runlengthPixel);
} else {
- output_plain(rl_basecode + leftover - 2);
+ outputPlain(statePtr, statePtr->runlengthBaseCode + leftover - 2);
}
}
- reset_out_clear();
+ resetOutputClear(statePtr);
}
-
+
static void
-rl_flush()
+runlengthFlush(
+ miGIFState_t *statePtr)
{
- DEBUGMSG(("rl_flush [ %d %d\n", rl_count, rl_pixel));
- if (rl_count == 1) {
- output_plain(rl_pixel);
- rl_count = 0;
- DEBUGMSG(("rl_flush ]\n"));
+ DEBUGMSG(("runlengthFlush [ %d %d\n", statePtr->runlengthCount,
+ statePtr->runlengthPixel));
+ if (statePtr->runlengthCount == 1) {
+ outputPlain(statePtr, statePtr->runlengthPixel);
+ statePtr->runlengthCount = 0;
+ DEBUGMSG(("runlengthFlush ]\n"));
return;
}
- if (just_cleared) {
- rl_flush_fromclear(rl_count);
- } else if ((rl_table_max < 2) || (rl_table_pixel != rl_pixel)) {
- rl_flush_clearorrep(rl_count);
+ if (statePtr->justCleared) {
+ runlengthFlushFromClear(statePtr, statePtr->runlengthCount);
+ } else if ((statePtr->runlengthTableMax < 2)
+ || (statePtr->runlengthTablePixel != statePtr->runlengthPixel)) {
+ runlengthFlushClearOrRep(statePtr, statePtr->runlengthCount);
} else {
- rl_flush_withtable(rl_count);
+ runlengthFlushWithTable(statePtr, statePtr->runlengthCount);
}
- DEBUGMSG(("rl_flush ]\n"));
- rl_count = 0;
+ DEBUGMSG(("runlengthFlush ]\n"));
+ statePtr->runlengthCount = 0;
}
-
-
+
static void
-compress(init_bits, handle, readValue)
- int init_bits;
- Tcl_Channel handle;
- ifunptr readValue;
+compress(
+ int initBits,
+ Tcl_Channel handle,
+ ifunptr readValue,
+ ClientData clientData)
{
int c;
+ miGIFState_t state, *statePtr = &state;
+
+ memset(statePtr, 0, sizeof(state));
+
+ statePtr->ofile = handle;
+ statePtr->obuf = 0;
+ statePtr->obits = 0;
+ statePtr->oblen = 0;
+ statePtr->codeClear = 1 << (initBits - 1);
+ statePtr->codeEOF = statePtr->codeClear + 1;
+ statePtr->runlengthBaseCode = statePtr->codeEOF + 1;
+ statePtr->outputBumpInit = (1 << (initBits - 1)) - 1;
- ofile = handle;
- obuf = 0;
- obits = 0;
- oblen = 0;
- code_clear = 1 << (init_bits - 1);
- code_eof = code_clear + 1;
- rl_basecode = code_eof + 1;
- out_bump_init = (1 << (init_bits - 1)) - 1;
/*
- * For images with a lot of runs, making out_clear_init larger
- * will give better compression.
+ * For images with a lot of runs, making outputClearInit larger will give
+ * better compression.
*/
- out_clear_init = (init_bits <= 3) ? 9 : (out_bump_init-1);
+
+ statePtr->outputClearInit =
+ (initBits <= 3) ? 9 : (statePtr->outputBumpInit-1);
#ifdef MIGIF_DEBUGGING_ENVARS
{
- const char *ocienv;
- ocienv = getenv("MIGIF_OUT_CLEAR_INIT");
+ const char *ocienv = getenv("MIGIF_OUT_CLEAR_INIT");
+
if (ocienv) {
- out_clear_init = atoi(ocienv);
- DEBUGMSG(("[overriding out_clear_init to %d]\n", out_clear_init));
+ statePtr->outputClearInit = atoi(ocienv);
+ DEBUGMSG(("[overriding outputClearInit to %d]\n",
+ statePtr->outputClearInit));
}
}
#endif
- out_bits_init = init_bits;
- max_ocodes = (1 << GIFBITS) - ((1 << (out_bits_init - 1)) + 3);
- did_clear();
- output(code_clear);
- rl_count = 0;
+ statePtr->outputBitsInit = initBits;
+ statePtr->maxOcodes =
+ (1 << GIFBITS) - ((1 << (statePtr->outputBitsInit - 1)) + 3);
+ didClear(statePtr);
+ output(statePtr, statePtr->codeClear);
+ statePtr->runlengthCount = 0;
while (1) {
- c = readValue();
- if ((rl_count > 0) && (c != rl_pixel)) {
- rl_flush();
+ c = readValue(clientData);
+ if (statePtr->runlengthCount>0 && statePtr->runlengthPixel!=c) {
+ runlengthFlush(statePtr);
}
if (c == EOF) {
break;
}
- if (rl_pixel == c) {
- rl_count++;
+ if (statePtr->runlengthPixel == c) {
+ statePtr->runlengthCount++;
} else {
- rl_pixel = c;
- rl_count = 1;
+ statePtr->runlengthPixel = c;
+ statePtr->runlengthCount = 1;
}
}
- output(code_eof);
- output_flush();
+ output(statePtr, statePtr->codeEOF);
+ outputFlush(statePtr);
}
/*
*-----------------------------------------------------------------------
*
- * End of miGIF section - See copyright notice at start of section.
+ * End of miGIF section - See copyright notice at start of section.
*
*-----------------------------------------------------------------------
*/
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */