summaryrefslogtreecommitdiff
path: root/tk/generic/tkImgGIF.c
diff options
context:
space:
mode:
Diffstat (limited to 'tk/generic/tkImgGIF.c')
-rw-r--r--tk/generic/tkImgGIF.c1280
1 files changed, 695 insertions, 585 deletions
diff --git a/tk/generic/tkImgGIF.c b/tk/generic/tkImgGIF.c
index f9588892b4a..632f900165f 100644
--- a/tk/generic/tkImgGIF.c
+++ b/tk/generic/tkImgGIF.c
@@ -19,14 +19,14 @@
* 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. |
+ * +--------------------------------------------------------------------+
+ * | 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. |
* +-------------------------------------------------------------------+
*
* RCS: @(#) $Id$
@@ -41,7 +41,7 @@
* Any other invalid character is treated as an EOF
*/
-#define GIF_SPECIAL (256)
+#define GIF_SPECIAL (256)
#define GIF_PAD (GIF_SPECIAL+1)
#define GIF_SPACE (GIF_SPECIAL+2)
#define GIF_BAD (GIF_SPECIAL+3)
@@ -72,13 +72,15 @@ typedef struct mFile {
* encoding independant.
*/
-static CONST char GIF87a[] =
- { 0x47, 0x49, 0x46, 0x38, 0x37, 0x61, 0x00 }; /* ASCII GIF87a */
-static CONST char GIF89a[] =
- { 0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 0x00 }; /* ASCII GIF89a */
-# define GIF_TERMINATOR 0x3b /* ASCII ; */
-# define GIF_EXTENSION 0x21 /* ASCII ! */
-# define GIF_START 0x2c /* ASCII , */
+static CONST char GIF87a[] = { /* ASCII GIF87a */
+ 0x47, 0x49, 0x46, 0x38, 0x37, 0x61, 0x00
+};
+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 , */
/*
* HACK ALERT!! HACK ALERT!! HACK ALERT!!
@@ -96,10 +98,10 @@ static Tcl_ThreadDataKey dataKey;
* The format record for the GIF file format:
*/
-static int FileMatchGIF _ANSI_ARGS_((Tcl_Channel chan, CONST char *fileName,
+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,
+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));
@@ -118,13 +120,13 @@ static int CommonWriteGIF _ANSI_ARGS_((Tcl_Interp *interp,
Tk_PhotoImageBlock *blockPtr));
Tk_PhotoImageFormat tkImgFmtGIF = {
- "gif", /* name */
- FileMatchGIF, /* fileMatchProc */
- StringMatchGIF, /* stringMatchProc */
- FileReadGIF, /* fileReadProc */
- StringReadGIF, /* stringReadProc */
- FileWriteGIF, /* fileWriteProc */
- NULL, /* stringWriteProc */
+ "gif", /* name */
+ FileMatchGIF, /* fileMatchProc */
+ StringMatchGIF, /* stringMatchProc */
+ FileReadGIF, /* fileReadProc */
+ StringReadGIF, /* stringReadProc */
+ FileWriteGIF, /* fileWriteProc */
+ NULL, /* stringWriteProc */
};
#define INTERLACE 0x40
@@ -136,7 +138,7 @@ Tk_PhotoImageFormat tkImgFmtGIF = {
#define CM_BLUE 2
#define CM_ALPHA 3
#define MAX_LWZ_BITS 12
-#define LM_to_uint(a,b) (((b)<<8)|(a))
+#define LM_to_uint(a,b) (((b)<<8)|(a))
#define ReadOK(file,buffer,len) (Fread(buffer, len, 1, file) != 0)
/*
@@ -216,7 +218,7 @@ FileMatchGIF(chan, fileName, format, widthPtr, heightPtr, interp)
*
* Results:
* A standard TCL completion code. If TCL_ERROR is returned
- * then an error message is left in interp->result.
+ * 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
@@ -249,7 +251,7 @@ FileReadGIF(interp, chan, fileName, format, imageHandle, destX, destY,
int bitPixel;
unsigned char colorMap[MAXCOLORMAPSIZE][4];
int transparent = -1;
- static char *optionStrings[] = {
+ static CONST char *optionStrings[] = {
"-index", NULL
};
@@ -288,7 +290,7 @@ FileReadGIF(interp, chan, fileName, format, imageHandle, destX, destY,
}
bitPixel = 2<<(buf[0]&0x07);
- if (BitSet(buf[0], LOCALCOLORMAP)) { /* Global Colormap */
+ if (BitSet(buf[0], LOCALCOLORMAP)) { /* Global Colormap */
if (!ReadColorMap(chan, bitPixel, colorMap)) {
Tcl_AppendResult(interp, "error reading color map",
(char *) NULL);
@@ -345,12 +347,14 @@ FileReadGIF(interp, chan, fileName, format, imageHandle, destX, destY,
*/
if (Fread(buf, 1, 1, chan) != 1) {
- interp->result =
- "error reading extension function code in GIF image";
+ Tcl_SetResult(interp,
+ "error reading extension function code in GIF image",
+ TCL_STATIC);
goto error;
}
if (DoExtension(chan, buf[0], &transparent) < 0) {
- interp->result = "error reading extension in GIF image";
+ Tcl_SetResult(interp, "error reading extension in GIF image",
+ TCL_STATIC);
goto error;
}
continue;
@@ -364,7 +368,9 @@ FileReadGIF(interp, chan, fileName, format, imageHandle, destX, destY,
}
if (Fread(buf, 1, 9, chan) != 9) {
- interp->result = "couldn't read left/top/width/height in GIF image";
+ Tcl_SetResult(interp,
+ "couldn't read left/top/width/height in GIF image",
+ TCL_STATIC);
goto error;
}
@@ -374,7 +380,9 @@ FileReadGIF(interp, chan, fileName, format, imageHandle, destX, destY,
bitPixel = 1<<((buf[8]&0x07)+1);
if (index--) {
- /* this is not the image we want to read: skip it. */
+ /*
+ * This is not the image we want to read: skip it.
+ */
if (BitSet(buf[8], LOCALCOLORMAP)) {
if (!ReadColorMap(chan, bitPixel, colorMap)) {
Tcl_AppendResult(interp,
@@ -383,7 +391,9 @@ FileReadGIF(interp, chan, fileName, format, imageHandle, destX, destY,
}
}
- /* If we've not yet allocated a trash buffer, do so now */
+ /*
+ * If we've not yet allocated a trash buffer, do so now.
+ */
if (trashBuffer == NULL) {
nBytes = fileWidth * fileHeight * 3;
trashBuffer =
@@ -391,28 +401,32 @@ FileReadGIF(interp, chan, fileName, format, imageHandle, destX, destY,
}
/*
- * 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, fileWidth,
- fileHeight, colorMap, 0, 0, 0, 0, 0, -1) != TCL_OK) {
- goto error;
+ fileHeight, colorMap, 0, 0, 0, 0, 0, -1) != TCL_OK) {
+ goto error;
}
continue;
}
- /* If a trash buffer has been allocated, free it now */
+ /*
+ * If a trash buffer has been allocated, free it now.
+ */
if (trashBuffer != NULL) {
ckfree((char *)trashBuffer);
trashBuffer = NULL;
@@ -455,19 +469,20 @@ FileReadGIF(interp, chan, fileName, format, imageHandle, destX, destY,
block.height = height;
block.pixelSize = (transparent>=0) ? 4 : 3;
block.offset[3] = (transparent>=0) ? 3 : 0;
- block.pitch = block.pixelSize * width;
- nBytes = block.pitch * height;
+ block.pitch = block.pixelSize * fileWidth;
+ nBytes = block.pitch * fileHeight;
block.pixelPtr = (unsigned char *) ckalloc((unsigned) nBytes);
- if (ReadImage(interp, (char *) block.pixelPtr, chan, width,
- height, colorMap, fileWidth, fileHeight, srcX, srcY,
+ if (ReadImage(interp, (char *) block.pixelPtr, chan, fileWidth,
+ fileHeight, colorMap, fileWidth, fileHeight, srcX, srcY,
BitSet(buf[8], INTERLACE), transparent) != TCL_OK) {
goto error;
}
break;
}
- Tk_PhotoPutBlock(imageHandle, &block, destX, destY, width, height);
+ Tk_PhotoPutBlock(imageHandle, &block, destX, destY, width, height,
+ TK_PHOTO_COMPOSITE_SET);
noerror:
if (block.pixelPtr) {
@@ -516,25 +531,31 @@ StringMatchGIF(dataObj, format, widthPtr, heightPtr, interp)
data = Tcl_GetByteArrayFromObj(dataObj, &length);
- /* Header is a minimum of 10 bytes */
+ /*
+ * Header is a minimum of 10 bytes.
+ */
if (length < 10) {
- return 0;
+ return 0;
}
- /* Check whether the data is Base64 encoded */
+ /*
+ * Check whether the data is Base64 encoded.
+ */
if ((strncmp(GIF87a, (char *) data, 6) != 0) &&
- (strncmp(GIF89a, (char *) data, 6) != 0)) {
- /* Try interpreting the data as Base64 encoded */
- mInit((unsigned char *) data, &handle);
- got = Mread(header, 10, 1, &handle);
- if (got != 10
- || ((strncmp(GIF87a, (char *) header, 6) != 0)
- && (strncmp(GIF89a, (char *) header, 6) != 0))) {
- return 0;
- }
+ (strncmp(GIF89a, (char *) data, 6) != 0)) {
+ /*
+ * Try interpreting the data as Base64 encoded
+ */
+ mInit((unsigned char *) data, &handle);
+ got = Mread(header, 10, 1, &handle);
+ 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((VOID *) header, (VOID *) data, 10);
}
*widthPtr = LM_to_uint(header[6],header[7]);
*heightPtr = LM_to_uint(header[8],header[9]);
@@ -552,7 +573,7 @@ StringMatchGIF(dataObj, format, widthPtr, heightPtr, interp)
*
* Results:
* A standard TCL completion code. If TCL_ERROR is returned
- * then an error message is left in interp->result.
+ * then an error message is left in the interp's result.
*
* Side effects:
* new data is added to the image given by imageHandle. This
@@ -570,13 +591,13 @@ StringReadGIF(interp, dataObj, format, imageHandle,
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 width, height; /* image to copy */
int srcX, srcY;
{
int result;
MFile handle;
ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
- Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
Tcl_Channel dataSrc;
char *data;
@@ -584,8 +605,7 @@ StringReadGIF(interp, dataObj, format, imageHandle,
* Check whether the data is Base64 encoded
*/
data = (char *) Tcl_GetByteArrayFromObj(dataObj, NULL);
- if ((strncmp(GIF87a, data, 6) != 0) &&
- (strncmp(GIF89a, data, 6) != 0)) {
+ if ((strncmp(GIF87a, data, 6) != 0) && (strncmp(GIF89a, data, 6) != 0)) {
mInit((unsigned char *)data, &handle);
tsdPtr->fromData = 1;
dataSrc = (Tcl_Channel) &handle;
@@ -597,7 +617,7 @@ StringReadGIF(interp, dataObj, format, imageHandle,
result = FileReadGIF(interp, dataSrc, "inline data",
format, imageHandle, destX, destY, width, height, srcX, srcY);
tsdPtr->fromData = 0;
- return(result);
+ return result;
}
/*
@@ -652,65 +672,65 @@ ReadGIFHeader(chan, widthPtr, heightPtr)
static int
ReadColorMap(chan, number, buffer)
- Tcl_Channel chan;
- int number;
- unsigned char buffer[MAXCOLORMAPSIZE][4];
+ Tcl_Channel chan;
+ int number;
+ unsigned char buffer[MAXCOLORMAPSIZE][4];
{
- int i;
- unsigned char rgb[3];
+ int i;
+ unsigned char rgb[3];
- for (i = 0; i < number; ++i) {
- if (! ReadOK(chan, 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 ;
- }
+ for (i = 0; i < number; ++i) {
+ if (! ReadOK(chan, rgb, sizeof(rgb))) {
+ return 0;
}
- return 1;
+
+ 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(chan, label, transparent)
- Tcl_Channel chan;
- int label;
- int *transparent;
+ Tcl_Channel chan;
+ int label;
+ int *transparent;
{
static unsigned char buf[256];
int count;
switch (label) {
- case 0x01: /* Plain Text Extension */
- break;
-
- case 0xff: /* Application Extension */
- break;
+ case 0x01: /* Plain Text Extension */
+ break;
- case 0xfe: /* Comment Extension */
- do {
- count = GetDataBlock(chan, (unsigned char*) buf);
- } while (count > 0);
- return count;
+ case 0xff: /* Application Extension */
+ break;
- case 0xf9: /* Graphic Control Extension */
+ case 0xfe: /* Comment Extension */
+ do {
count = GetDataBlock(chan, (unsigned char*) buf);
- if (count < 0) {
- return 1;
- }
- if ((buf[0] & 0x1) != 0) {
- *transparent = buf[3];
- }
+ } while (count > 0);
+ return count;
+
+ case 0xf9: /* Graphic Control Extension */
+ count = GetDataBlock(chan, (unsigned char*) buf);
+ if (count < 0) {
+ return 1;
+ }
+ if ((buf[0] & 0x1) != 0) {
+ *transparent = buf[3];
+ }
- do {
- count = GetDataBlock(chan, (unsigned char*) buf);
- } while (count > 0);
- return count;
+ do {
+ count = GetDataBlock(chan, (unsigned char*) buf);
+ } while (count > 0);
+ return count;
}
do {
@@ -723,8 +743,8 @@ static int ZeroDataBlock = 0;
static int
GetDataBlock(chan, buf)
- Tcl_Channel chan;
- unsigned char *buf;
+ Tcl_Channel chan;
+ unsigned char *buf;
{
unsigned char count;
@@ -749,17 +769,17 @@ GetDataBlock(chan, buf)
* ReadImage --
*
* Process a GIF image from a given source, with a given height,
- * width, transparency, etc.
+ * width, transparency, etc.
*
- * This code is based on the code found in the ImageMagick GIF decoder,
- * which is (c) 2000 ImageMagick Studio.
+ * 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.
+ * 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.
+ * 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.
@@ -773,15 +793,15 @@ 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;
+ 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;
{
unsigned char initialCodeSize;
int v;
@@ -793,9 +813,9 @@ ReadImage(interp, imagePtr, chan, len, rows, cmap,
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;
-
+ int codeSize, clearCode, inCode, endCode, oldCode, maxCode;
+ int code, firstCode;
+
/*
* Initialize the decoder
*/
@@ -804,7 +824,7 @@ ReadImage(interp, imagePtr, chan, len, rows, cmap,
Tcl_PosixError(interp), (char *) NULL);
return TCL_ERROR;
}
- if (transparent!=-1) {
+ if (transparent != -1) {
cmap[transparent][CM_RED] = 0;
cmap[transparent][CM_GREEN] = 0;
cmap[transparent][CM_BLUE] = 0;
@@ -813,19 +833,21 @@ ReadImage(interp, imagePtr, chan, len, rows, cmap,
pixelPtr = imagePtr;
- /* Initialize the decoder */
- /* Set values for "special" numbers:
+ /*
+ * 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;
+ 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));
@@ -836,12 +858,16 @@ ReadImage(interp, imagePtr, chan, len, rows, cmap,
GetCode(chan, 0, 1);
- /* Read until we finish the image */
+ /*
+ * 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);
if (code < 0) {
return TCL_OK;
@@ -860,10 +886,12 @@ ReadImage(interp, imagePtr, chan, len, rows, cmap,
}
if (code == clearCode) {
- /* Reset the decoder */
- codeSize = initialCodeSize + 1;
- maxCode = clearCode + 2;
- oldCode = -1;
+ /*
+ * Reset the decoder.
+ */
+ codeSize = initialCodeSize + 1;
+ maxCode = clearCode + 2;
+ oldCode = -1;
continue;
}
@@ -876,7 +904,7 @@ ReadImage(interp, imagePtr, chan, len, rows, cmap,
* roll this into the clearCode test above, because
* at that point we have not yet read the next code.
*/
- *top++=append[code];
+ *top++ = append[code];
oldCode = code;
firstCode = code;
continue;
@@ -912,15 +940,20 @@ ReadImage(interp, imagePtr, chan, len, rows, cmap,
return TCL_OK;
}
- /* Push the head of the string onto the stack */
+ /*
+ * Push the head of the string onto the stack.
+ */
*top++ = firstCode;
- /* Add a new string to the string table */
+ /*
+ * 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.
+ /*
+ * 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.
@@ -932,7 +965,9 @@ ReadImage(interp, imagePtr, chan, len, rows, cmap,
oldCode = inCode;
}
- /* Pop the next color index off the stack */
+ /*
+ * Pop the next color index off the stack.
+ */
v = *(--top);
if (v < 0) {
return TCL_OK;
@@ -953,7 +988,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 >= height) {
@@ -977,23 +1014,23 @@ ReadImage(interp, imagePtr, chan, len, rows, cmap,
*
* 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: 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
+ * 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: 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
*
* Results:
- * code the next compression code
+ * code the next compression code
*
* Side effects:
* May consume more input from chan.
@@ -1003,9 +1040,9 @@ ReadImage(interp, imagePtr, chan, len, rows, cmap,
static int
GetCode(chan, code_size, flag)
- Tcl_Channel chan;
- int code_size;
- int flag;
+ Tcl_Channel chan;
+ int code_size;
+ int flag;
{
static unsigned char buf[280];
static int bytes = 0, done;
@@ -1016,7 +1053,9 @@ GetCode(chan, code_size, flag)
int ret;
if (flag) {
- /* Initialize the decoder */
+ /*
+ * Initialize the decoder.
+ */
bitsInWindow = 0;
bytes = 0;
window = 0;
@@ -1026,12 +1065,16 @@ GetCode(chan, code_size, flag)
}
while (bitsInWindow < code_size) {
- /* Not enough bits in our window to cover the request */
+ /*
+ * Not enough bits in our window to cover the request.
+ */
if (done) {
return -1;
}
if (bytes == 0) {
- /* Not enough bytes in our buffer to add to the window */
+ /*
+ * Not enough bytes in our buffer to add to the window.
+ */
bytes = GetDataBlock(chan, buf);
c = buf;
if (bytes <= 0) {
@@ -1039,17 +1082,24 @@ GetCode(chan, code_size, flag)
break;
}
}
- /* Tack another byte onto the window, see if that's enough */
+ /*
+ * Tack another byte onto the window, see if that's enough.
+ */
window += (*c) << bitsInWindow;
c++;
bitsInWindow += 8;
bytes--;
}
- /* The next code will always be the last code_size bits of the window */
+
+ /*
+ * The next code will always be the last code_size bits of the window.
+ */
ret = window & ((1 << code_size) - 1);
- /* Shift data in the window to put the next code at the end */
+ /*
+ * Shift data in the window to put the next code at the end.
+ */
window >>= code_size;
bitsInWindow -= code_size;
return ret;
@@ -1139,45 +1189,45 @@ Mread(dst, chunkSize, numChunks, handle)
static int
Mgetc(handle)
- MFile *handle; /* Handle containing decoder data and state. */
+ MFile *handle; /* Handle containing decoder data and state */
{
int c;
int result = 0; /* Initialization needed only to prevent
* gcc compiler warning. */
-
+
if (handle->state == GIF_DONE) {
- return(GIF_DONE);
+ return GIF_DONE;
}
do {
c = char64(*handle->data);
handle->data++;
- } while (c==GIF_SPACE);
+ } while (c == GIF_SPACE);
if (c>GIF_SPECIAL) {
handle->state = GIF_DONE;
- return(handle->state ? handle->c : GIF_DONE);
+ return handle->c;
}
switch (handle->state++) {
- case 0:
- handle->c = c<<2;
- result = Mgetc(handle);
- break;
- case 1:
- result = handle->c | (c>>4);
- handle->c = (c&0xF)<<4;
- break;
- case 2:
- result = handle->c | (c>>2);
- handle->c = (c&0x3) << 6;
- break;
- case 3:
- result = handle->c | c;
- handle->state = 0;
- break;
- }
- return(result);
+ case 0:
+ handle->c = c<<2;
+ result = Mgetc(handle);
+ break;
+ case 1:
+ result = handle->c | (c>>4);
+ handle->c = (c&0xF)<<4;
+ break;
+ case 2:
+ result = handle->c | (c>>2);
+ handle->c = (c&0x3) << 6;
+ break;
+ case 3:
+ result = handle->c | c;
+ handle->state = 0;
+ break;
+ }
+ return result;
}
/*
@@ -1202,33 +1252,37 @@ char64(c)
int c;
{
switch(c) {
- case 'A': return(0); case 'B': return(1); case 'C': return(2);
- case 'D': return(3); case 'E': return(4); case 'F': return(5);
- case 'G': return(6); case 'H': return(7); case 'I': return(8);
- case 'J': return(9); case 'K': return(10); case 'L': return(11);
- case 'M': return(12); case 'N': return(13); case 'O': return(14);
- case 'P': return(15); case 'Q': return(16); case 'R': return(17);
- case 'S': return(18); case 'T': return(19); case 'U': return(20);
- case 'V': return(21); case 'W': return(22); case 'X': return(23);
- case 'Y': return(24); case 'Z': return(25); case 'a': return(26);
- case 'b': return(27); case 'c': return(28); case 'd': return(29);
- case 'e': return(30); case 'f': return(31); case 'g': return(32);
- case 'h': return(33); case 'i': return(34); case 'j': return(35);
- case 'k': return(36); case 'l': return(37); case 'm': return(38);
- case 'n': return(39); case 'o': return(40); case 'p': return(41);
- case 'q': return(42); case 'r': return(43); case 's': return(44);
- case 't': return(45); case 'u': return(46); case 'v': return(47);
- case 'w': return(48); case 'x': return(49); case 'y': return(50);
- case 'z': return(51); case '0': return(52); case '1': return(53);
- case '2': return(54); case '3': return(55); case '4': return(56);
- case '5': return(57); case '6': return(58); case '7': return(59);
- case '8': return(60); case '9': return(61); case '+': return(62);
- case '/': return(63);
-
- case ' ': case '\t': case '\n': case '\r': case '\f': return(GIF_SPACE);
- case '=': return(GIF_PAD);
- case '\0': return(GIF_DONE);
- default: return(GIF_BAD);
+ case 'A': return 0; case 'B': return 1; case 'C': return 2;
+ case 'D': return 3; case 'E': return 4; case 'F': return 5;
+ case 'G': return 6; case 'H': return 7; case 'I': return 8;
+ case 'J': return 9; case 'K': return 10; case 'L': return 11;
+ case 'M': return 12; case 'N': return 13; case 'O': return 14;
+ case 'P': return 15; case 'Q': return 16; case 'R': return 17;
+ case 'S': return 18; case 'T': return 19; case 'U': return 20;
+ case 'V': return 21; case 'W': return 22; case 'X': return 23;
+ case 'Y': return 24; case 'Z': return 25; case 'a': return 26;
+ case 'b': return 27; case 'c': return 28; case 'd': return 29;
+ case 'e': return 30; case 'f': return 31; case 'g': return 32;
+ case 'h': return 33; case 'i': return 34; case 'j': return 35;
+ case 'k': return 36; case 'l': return 37; case 'm': return 38;
+ case 'n': return 39; case 'o': return 40; case 'p': return 41;
+ case 'q': return 42; case 'r': return 43; case 's': return 44;
+ case 't': return 45; case 'u': return 46; case 'v': return 47;
+ case 'w': return 48; case 'x': return 49; case 'y': return 50;
+ case 'z': return 51; case '0': return 52; case '1': return 53;
+ case '2': return 54; case '3': return 55; case '4': return 56;
+ case '5': return 57; case '6': return 58; case '7': return 59;
+ case '8': return 60; case '9': return 61; case '+': return 62;
+ case '/': return 63;
+
+ case ' ': case '\t': case '\n': case '\r': case '\f':
+ return GIF_SPACE;
+ case '=':
+ return GIF_PAD;
+ case '\0':
+ return GIF_DONE;
+ default:
+ return GIF_BAD;
}
}
@@ -1252,18 +1306,18 @@ Fread(dst, hunk, count, chan)
Tcl_Channel chan;
{
ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
- Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
MFile *handle;
switch (tsdPtr->fromData) {
- case 1:
- return(Mread(dst, hunk, count, (MFile *) chan));
- case 2:
+ case 1:
+ return Mread(dst, hunk, count, (MFile *) chan);
+ case 2:
handle = (MFile *) chan;
memcpy((VOID *)dst, (VOID *) handle->data, (size_t) (hunk * count));
handle->data += hunk * count;
- return((int) (hunk * count));
- default:
+ return (int)(hunk * count);
+ default:
return Tcl_Read(chan, (char *) dst, (int) (hunk * count));
}
}
@@ -1272,13 +1326,13 @@ Fread(dst, hunk, count, chan)
/*
* ChanWriteGIF - writes a image in GIF format.
*-------------------------------------------------------------------------
- * Author: Lolo
- * Engeneering Projects Area
- * Department of Mining
- * University of Oviedo
+ * 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
+ * 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>
@@ -1302,11 +1356,11 @@ Fread(dst, hunk, count, chan)
typedef int (* ifunptr) _ANSI_ARGS_((void));
-#define LSB(a) ((unsigned char) (((short)(a)) & 0x00FF))
-#define MSB(a) ((unsigned char) (((short)(a)) >> 8))
+#define LSB(a) ((unsigned char) (((short)(a)) & 0x00FF))
+#define MSB(a) ((unsigned char) (((short)(a)) >> 8))
#define GIFBITS 12
-#define HSIZE 5003 /* 80% occupancy */
+#define HSIZE 5003 /* 80% occupancy */
static int ssize;
static int csize;
@@ -1335,7 +1389,7 @@ static void savemap _ANSI_ARGS_((Tk_PhotoImageBlock *blockPtr,
static int ReadValue _ANSI_ARGS_((void));
static int
-FileWriteGIF (interp, filename, format, blockPtr)
+FileWriteGIF(interp, filename, format, blockPtr)
Tcl_Interp *interp; /* Interpreter to use for reporting errors. */
CONST char *filename;
Tcl_Obj *format;
@@ -1349,6 +1403,7 @@ FileWriteGIF (interp, filename, format, blockPtr)
return TCL_ERROR;
}
if (Tcl_SetChannelOption(interp, chan, "-translation", "binary") != TCL_OK) {
+ Tcl_Close(NULL, chan);
return TCL_ERROR;
}
@@ -1377,9 +1432,9 @@ CommonWriteGIF(interp, handle, format, blockPtr)
top = 0;
left = 0;
- pixelSize=blockPtr->pixelSize;
- greenOffset=blockPtr->offset[1]-blockPtr->offset[0];
- blueOffset=blockPtr->offset[2]-blockPtr->offset[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];
@@ -1392,30 +1447,32 @@ CommonWriteGIF(interp, handle, format, blockPtr)
Tcl_Write(handle, (char *) (alphaOffset ? GIF89a : GIF87a), 6);
- for (x=0;x<MAXCOLORMAPSIZE;x++) {
+ for (x=0 ; x<MAXCOLORMAPSIZE ; x++) {
mapa[x][CM_RED] = 255;
mapa[x][CM_GREEN] = 255;
mapa[x][CM_BLUE] = 255;
}
- width=blockPtr->width;
- height=blockPtr->height;
- pixelo=blockPtr->pixelPtr + blockPtr->offset[0];
- pixelPitch=blockPtr->pitch;
+ width = blockPtr->width;
+ height = blockPtr->height;
+ pixelo = blockPtr->pixelPtr + blockPtr->offset[0];
+ pixelPitch = blockPtr->pitch;
savemap(blockPtr,mapa);
- if (num>=MAXCOLORMAPSIZE) {
+ if (num >= MAXCOLORMAPSIZE) {
Tcl_AppendResult(interp, "too many colors", (char *) NULL);
return TCL_ERROR;
}
- if (num<2) num=2;
- c=LSB(width);
+ if (num<2) {
+ num = 2;
+ }
+ c = LSB(width);
Mputc(c,handle);
- c=MSB(width);
+ c = MSB(width);
Mputc(c,handle);
- c=LSB(height);
+ c = LSB(height);
Mputc(c,handle);
- c=MSB(height);
+ c = MSB(height);
Mputc(c,handle);
resolution = 0;
@@ -1427,16 +1484,20 @@ CommonWriteGIF(interp, handle, format, blockPtr)
num = 1 << resolution;
- /* background color */
+ /*
+ * background color
+ */
c = 0;
Mputc(c,handle);
- /* zero for future expansion */
+ /*
+ * zero for future expansion.
+ */
Mputc(c,handle);
- for (x=0; x<num ;x++) {
+ for (x=0 ; x<num ; x++) {
c = mapa[x][CM_RED];
Mputc(c,handle);
c = mapa[x][CM_GREEN];
@@ -1457,28 +1518,28 @@ CommonWriteGIF(interp, handle, format, blockPtr)
c = GIF_START;
Mputc(c,handle);
- c=LSB(top);
+ c = LSB(top);
Mputc(c,handle);
- c=MSB(top);
+ c = MSB(top);
Mputc(c,handle);
- c=LSB(left);
+ c = LSB(left);
Mputc(c,handle);
- c=MSB(left);
+ c = MSB(left);
Mputc(c,handle);
- c=LSB(width);
+ c = LSB(width);
Mputc(c,handle);
- c=MSB(width);
+ c = MSB(width);
Mputc(c,handle);
- c=LSB(height);
+ c = LSB(height);
Mputc(c,handle);
- c=MSB(height);
+ c = MSB(height);
Mputc(c,handle);
- c=0;
+ c = 0;
Mputc(c,handle);
- c=resolution;
+ c = resolution;
Mputc(c,handle);
ssize = rsize = blockPtr->width;
@@ -1501,9 +1562,9 @@ color(red, green, blue, mapa)
unsigned char mapa[MAXCOLORMAPSIZE][3];
{
int x;
- for (x=(alphaOffset != 0);x<=MAXCOLORMAPSIZE;x++) {
- if ((mapa[x][CM_RED]==red) && (mapa[x][CM_GREEN]==green) &&
- (mapa[x][CM_BLUE]==blue)) {
+ for (x=(alphaOffset != 0) ; x<=MAXCOLORMAPSIZE ; x++) {
+ if ((mapa[x][CM_RED] == red) && (mapa[x][CM_GREEN] == green) &&
+ (mapa[x][CM_BLUE] == blue)) {
return x;
}
}
@@ -1516,10 +1577,10 @@ nuevo(red, green, blue, mapa)
int red,green,blue;
unsigned char mapa[MAXCOLORMAPSIZE][3];
{
- int x;
- for (x=(alphaOffset != 0);x<=num;x++) {
- if ((mapa[x][CM_RED]==red) && (mapa[x][CM_GREEN]==green) &&
- (mapa[x][CM_BLUE]==blue)) {
+ int x = (alphaOffset != 0);
+ for (; x<=num ; x++) {
+ if ((mapa[x][CM_RED] == red) && (mapa[x][CM_GREEN] == green) &&
+ (mapa[x][CM_BLUE] == blue)) {
return 0;
}
}
@@ -1531,9 +1592,9 @@ savemap(blockPtr,mapa)
Tk_PhotoImageBlock *blockPtr;
unsigned char mapa[MAXCOLORMAPSIZE][3];
{
- unsigned char *colores;
+ unsigned char *colores;
int x,y;
- unsigned char red,green,blue;
+ unsigned char red,green,blue;
if (alphaOffset) {
num = 0;
@@ -1544,22 +1605,22 @@ savemap(blockPtr,mapa)
num = -1;
}
- for(y=0;y<blockPtr->height;y++) {
- colores=blockPtr->pixelPtr + blockPtr->offset[0]
+ for(y=0 ; y<blockPtr->height ; y++) {
+ colores = blockPtr->pixelPtr + blockPtr->offset[0]
+ y * blockPtr->pitch;
- for(x=0;x<blockPtr->width;x++) {
+ for(x=0 ; x<blockPtr->width ; x++) {
if (!alphaOffset || (colores[alphaOffset] != 0)) {
red = colores[0];
green = colores[greenOffset];
blue = colores[blueOffset];
if (nuevo(red,green,blue,mapa)) {
num++;
- if (num>=MAXCOLORMAPSIZE) {
+ if (num >= MAXCOLORMAPSIZE) {
return;
}
- mapa[num][CM_RED]=red;
- mapa[num][CM_GREEN]=green;
- mapa[num][CM_BLUE]=blue;
+ mapa[num][CM_RED] = red;
+ mapa[num][CM_GREEN] = green;
+ mapa[num][CM_BLUE] = blue;
}
}
colores += pixelSize;
@@ -1576,10 +1637,10 @@ ReadValue()
if (csize == 0) {
return EOF;
}
- if (alphaOffset && (pixelo[alphaOffset]==0)) {
+ if (alphaOffset && (pixelo[alphaOffset] == 0)) {
col = 0;
} else {
- col = color(pixelo[0],pixelo[greenOffset],pixelo[blueOffset], mapa);
+ col = color(pixelo[0], pixelo[greenOffset], pixelo[blueOffset], mapa);
}
pixelo += pixelSize;
if (--ssize <= 0) {
@@ -1593,48 +1654,53 @@ ReadValue()
-/*-----------------------------------------------------------------------
+/*
+ *-----------------------------------------------------------------------
*
* miGIF Compression - mouse and ivo's GIF-compatible compression
*
- * -run length encoding compression routines-
+ * -run length encoding compression routines-
*
* Copyright (C) 1998 Hutchison Avenue Software Corporation
- * 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 accompanying
- * documentation.
+ * 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
+ * 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.
- *
- * der Mouse
- * mouse@rodents.montreal.qc.ca
- * 7D C8 61 52 5D E7 2D 39 4E F1 31 3E E8 B3 27 4B
- *
- * ivo@hasc.com
+ * 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
+ * 7D C8 61 52 5D E7 2D 39 4E F1 31 3E E8 B3 27 4B
+ *
+ * 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.
*
+ *-----------------------------------------------------------------------
*/
static int rl_pixel;
@@ -1659,145 +1725,172 @@ static Tcl_Channel ofile;
static unsigned char oblock[256];
static int oblen;
-/* Used only when debugging GIF compression code */
-/* #define DEBUGGING_ENVARS */
+/*
+ * Used only when debugging GIF compression code
+ */
+/* #define MIGIF_DEBUGGING_ENVARS */
-#ifdef DEBUGGING_ENVARS
+#ifdef MIGIF_DEBUGGING_ENVARS
static int verbose_set = 0;
static int verbose;
-#define VERBOSE (verbose_set?verbose:set_verbose())
+#define MIGIF_VERBOSE (verbose_set?verbose:set_verbose())
+#define DEBUGMSG(printf_args) if (MIGIF_VERBOSE) { printf printf_args; }
-static int set_verbose(void)
+static int
+set_verbose(void)
{
- verbose = !!getenv("GIF_VERBOSE");
- verbose_set = 1;
- return(verbose);
+ verbose = !!getenv("MIGIF_VERBOSE");
+ verbose_set = 1;
+ return verbose;
}
-#else
-
-#define VERBOSE 0
-
-#endif
-
-
static CONST char *
binformat(v, nbits)
unsigned int v;
int nbits;
{
- static char bufs[8][64];
- static int bhand = 0;
- unsigned int bit;
- int bno;
- char *bp;
-
- bhand --;
- if (bhand < 0) bhand = (sizeof(bufs)/sizeof(bufs[0]))-1;
- bp = &bufs[bhand][0];
- for (bno=nbits-1,bit=((unsigned int)1)<<bno;bno>=0;bno--,bit>>=1)
- { *bp++ = (v & bit) ? '1' : '0';
- if (((bno&3) == 0) && (bno != 0)) *bp++ = '.';
- }
- *bp = '\0';
- return(&bufs[bhand][0]);
+ static char bufs[8][64];
+ static int bhand = 0;
+ unsigned int bit;
+ int bno;
+ char *bp;
+
+ bhand--;
+ if (bhand < 0) {
+ bhand = (sizeof(bufs) / sizeof(bufs[0])) - 1;
+ }
+ bp = &bufs[bhand][0];
+ for (bno=nbits-1,bit=((unsigned int)1)<<bno ; bno>=0 ; bno--,bit>>=1) {
+ *bp++ = (v & bit) ? '1' : '0';
+ if (((bno&3) == 0) && (bno != 0)) {
+ *bp++ = '.';
+ }
+ }
+ *bp = '\0';
+ return &bufs[bhand][0];
}
-static void write_block()
+#else
+
+#define MIGIF_VERBOSE 0
+#define DEBUGMSG(printf_args) /* do nothing */
+
+#endif
+
+static void
+write_block()
{
- int i;
- unsigned char c;
-
- if (VERBOSE)
- { printf("write_block %d:",oblen);
- for (i=0;i<oblen;i++) printf(" %02x",oblock[i]);
- printf("\n");
- }
- c = oblen;
- Tcl_Write(ofile, (char *) &c, 1);
- Tcl_Write(ofile, (char *) &oblock[0], oblen);
- oblen = 0;
+ int i;
+ unsigned char c;
+
+ if (MIGIF_VERBOSE) {
+ printf("write_block %d:", oblen);
+ for (i=0 ; i<oblen ; i++) {
+ printf(" %02x", oblock[i]);
+ }
+ printf("\n");
+ }
+ c = oblen;
+ Tcl_Write(ofile, (char *) &c, 1);
+ Tcl_Write(ofile, (char *) &oblock[0], oblen);
+ oblen = 0;
}
static void
block_out(c)
unsigned char c;
{
- if (VERBOSE) printf("block_out %s\n",binformat(c,8));
- oblock[oblen++] = c;
- if (oblen >= 255) write_block();
+ DEBUGMSG(("block_out %s\n", binformat(c, 8)));
+ oblock[oblen++] = c;
+ if (oblen >= 255) {
+ write_block();
+ }
}
-static void block_flush()
+static void
+block_flush()
{
- if (VERBOSE) printf("block_flush\n");
- if (oblen > 0) write_block();
+ DEBUGMSG(("block_flush\n"));
+ if (oblen > 0) {
+ write_block();
+ }
}
-static void output(val)
+static void
+output(val)
int val;
{
- if (VERBOSE) printf("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(obuf&0xff);
- obuf >>= 8;
- obits -= 8;
- }
- if (VERBOSE) printf("output leaving [%s %d]\n",binformat(obuf,obits),obits);
+ 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(obuf&0xff);
+ obuf >>= 8;
+ obits -= 8;
+ }
+ DEBUGMSG(("output leaving [%s %d]\n", binformat(obuf, obits), obits));
}
-static void output_flush()
+static void
+output_flush()
{
- if (VERBOSE) printf("output_flush\n");
- if (obits > 0) block_out(obuf);
- block_flush();
+ DEBUGMSG(("output_flush\n"));
+ if (obits > 0) {
+ block_out(obuf);
+ }
+ block_flush();
}
-static void did_clear()
+static void
+did_clear()
{
- if (VERBOSE) printf("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(("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;
}
static void
output_plain(c)
int c;
{
- if (VERBOSE) printf("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(("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();
+ }
}
-static unsigned int isqrt(x)
+static unsigned int
+isqrt(x)
unsigned int x;
{
- unsigned int r;
- unsigned int v;
-
- if (x < 2) return(x);
- for (v=x,r=1;v;v>>=2,r<<=1) ;
- while (1)
- { v = ((x / r) + r) / 2;
- if ((v == r) || (v == r+1)) return(r);
- r = v;
- }
+ unsigned int r;
+ unsigned int v;
+
+ if (x < 2) {
+ return x;
+ }
+ for (v=x,r=1 ; v ; v>>=2,r<<=1);
+ while (1) {
+ v = ((x / r) + r) / 2;
+ if (v==r || v==r+1) {
+ return r;
+ }
+ r = v;
+ }
}
static unsigned int
@@ -1805,207 +1898,224 @@ compute_triangle_count(count, nrepcodes)
unsigned int count;
unsigned int nrepcodes;
{
- unsigned int perrep;
- unsigned int cost;
-
- cost = 0;
- perrep = (nrepcodes * (nrepcodes+1)) / 2;
- while (count >= perrep)
- { cost += nrepcodes;
- count -= perrep;
- }
- if (count > 0)
- { unsigned int n;
- n = isqrt(count);
- while ((n*(n+1)) >= 2*count) n --;
- while ((n*(n+1)) < 2*count) n ++;
- cost += n;
- }
- return(cost);
+ unsigned int perrep;
+ unsigned int cost;
+
+ cost = 0;
+ perrep = (nrepcodes * (nrepcodes+1)) / 2;
+ while (count >= perrep) {
+ cost += nrepcodes;
+ count -= perrep;
+ }
+ if (count > 0) {
+ unsigned int n;
+ n = isqrt(count);
+ while (n*(n+1) >= 2*count) {
+ n--;
+ }
+ while (n*(n+1) < 2*count) {
+ n++;
+ }
+ cost += n;
+ }
+ return cost;
}
-static void max_out_clear()
+static void
+max_out_clear()
{
- out_clear = max_ocodes;
+ out_clear = max_ocodes;
}
-static void reset_out_clear()
+static void
+reset_out_clear()
{
- out_clear = out_clear_init;
- if (out_count >= out_clear)
- { output(code_clear);
- did_clear();
- }
+ out_clear = out_clear_init;
+ if (out_count >= out_clear) {
+ output(code_clear);
+ did_clear();
+ }
}
static void
rl_flush_fromclear(count)
int count;
{
- int n;
-
- if (VERBOSE) printf("rl_flush_fromclear %d\n",count);
- max_out_clear();
- rl_table_pixel = rl_pixel;
- n = 1;
- while (count > 0)
- { if (n == 1)
- { rl_table_max = 1;
- output_plain(rl_pixel);
- count --;
- }
- else if (count >= n)
- { rl_table_max = n;
- output_plain(rl_basecode+n-2);
- count -= n;
- }
- else if (count == 1)
- { rl_table_max ++;
- output_plain(rl_pixel);
- count = 0;
- }
- else
- { rl_table_max ++;
- output_plain(rl_basecode+count-2);
- count = 0;
- }
- if (out_count == 0) n = 1; else n ++;
- }
- reset_out_clear();
- if (VERBOSE) printf("rl_flush_fromclear leaving table_max=%d\n",rl_table_max);
+ int n;
+
+ DEBUGMSG(("rl_flush_fromclear %d\n", count));
+ max_out_clear();
+ rl_table_pixel = rl_pixel;
+ n = 1;
+ while (count > 0) {
+ if (n == 1) {
+ rl_table_max = 1;
+ output_plain(rl_pixel);
+ count--;
+ } else if (count >= n) {
+ rl_table_max = n;
+ output_plain(rl_basecode+n-2);
+ count -= n;
+ } else if (count == 1) {
+ rl_table_max++;
+ output_plain(rl_pixel);
+ count = 0;
+ } else {
+ rl_table_max++;
+ output_plain(rl_basecode+count-2);
+ count = 0;
+ }
+ if (out_count == 0) {
+ n = 1;
+ } else {
+ n++;
+ }
+ }
+ reset_out_clear();
+ DEBUGMSG(("rl_flush_fromclear leaving table_max=%d\n", rl_table_max));
}
-static void rl_flush_clearorrep(count)
+static void
+rl_flush_clearorrep(count)
int count;
{
- int withclr;
-
- if (VERBOSE) printf("rl_flush_clearorrep %d\n",count);
- withclr = 1 + compute_triangle_count(count,max_ocodes);
- if (withclr < count)
- { output(code_clear);
- did_clear();
- rl_flush_fromclear(count);
- }
- else
- { for (;count>0;count--) output_plain(rl_pixel);
- }
+ int withclr;
+
+ DEBUGMSG(("rl_flush_clearorrep %d\n", count));
+ withclr = 1 + compute_triangle_count(count, max_ocodes);
+ if (withclr < count) {
+ output(code_clear);
+ did_clear();
+ rl_flush_fromclear(count);
+ } else {
+ for (; count>0 ; count--) {
+ output_plain(rl_pixel);
+ }
+ }
}
-static void rl_flush_withtable(count)
+static void
+rl_flush_withtable(count)
int count;
{
- int repmax;
- int repleft;
- int leftover;
-
- if (VERBOSE) printf("rl_flush_withtable %d\n",count);
- repmax = count / rl_table_max;
- leftover = count % rl_table_max;
- 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 (VERBOSE) printf("rl_flush_withtable 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);
- return;
- }
- max_out_clear();
- for (;repmax>0;repmax--) output_plain(rl_basecode+rl_table_max-2);
- if (leftover)
- { if (just_cleared)
- { rl_flush_fromclear(leftover);
- }
- else if (leftover == 1)
- { output_plain(rl_pixel);
- }
- else
- { output_plain(rl_basecode+leftover-2);
- }
- }
- reset_out_clear();
+ int repmax;
+ int repleft;
+ int leftover;
+
+ DEBUGMSG(("rl_flush_withtable %d\n", count));
+ repmax = count / rl_table_max;
+ leftover = count % rl_table_max;
+ 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);
+ }
+ DEBUGMSG(("rl_flush_withtable 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);
+ return;
+ }
+ max_out_clear();
+ for (; repmax>0 ; repmax--) {
+ output_plain(rl_basecode + rl_table_max - 2);
+ }
+ if (leftover) {
+ if (just_cleared) {
+ rl_flush_fromclear(leftover);
+ } else if (leftover == 1) {
+ output_plain(rl_pixel);
+ } else {
+ output_plain(rl_basecode + leftover - 2);
+ }
+ }
+ reset_out_clear();
}
-static void rl_flush()
+static void
+rl_flush()
{
- if (VERBOSE) printf("rl_flush [ %d %d\n",rl_count,rl_pixel);
- if (rl_count == 1)
- { output_plain(rl_pixel);
+ 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"));
+ 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);
+ } else {
+ rl_flush_withtable(rl_count);
+ }
+ DEBUGMSG(("rl_flush ]\n"));
rl_count = 0;
- if (VERBOSE) printf("rl_flush ]\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);
- }
- else
- { rl_flush_withtable(rl_count);
- }
- if (VERBOSE) printf("rl_flush ]\n");
- rl_count = 0;
}
-static void compress( init_bits, handle, readValue )
+static void
+compress(init_bits, handle, readValue)
int init_bits;
Tcl_Channel handle;
ifunptr readValue;
{
- int c;
-
- 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. */
- out_clear_init = (init_bits <= 3) ? 9 : (out_bump_init-1);
-#ifdef DEBUGGING_ENVARS
- { const char *ocienv;
- ocienv = getenv("GIF_OUT_CLEAR_INIT");
- if (ocienv)
- { out_clear_init = atoi(ocienv);
- if (VERBOSE) printf("[overriding out_clear_init to %d]\n",out_clear_init);
- }
- }
+ int c;
+
+ 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.
+ */
+ out_clear_init = (init_bits <= 3) ? 9 : (out_bump_init-1);
+#ifdef MIGIF_DEBUGGING_ENVARS
+ {
+ const char *ocienv;
+ ocienv = getenv("MIGIF_OUT_CLEAR_INIT");
+ if (ocienv) {
+ out_clear_init = atoi(ocienv);
+ DEBUGMSG(("[overriding out_clear_init to %d]\n", out_clear_init));
+ }
+ }
#endif
- out_bits_init = init_bits;
- max_ocodes = (1 << GIFBITS) - ((1 << (out_bits_init - 1)) + 3);
- did_clear();
- output(code_clear);
- rl_count = 0;
- while (1)
- { c = readValue();
- if ((rl_count > 0) && (c != rl_pixel)) rl_flush();
- if (c == EOF) break;
- if (rl_pixel == c)
- { rl_count ++;
- }
- else
- { rl_pixel = c;
- rl_count = 1;
- }
- }
- output(code_eof);
- output_flush();
+ out_bits_init = init_bits;
+ max_ocodes = (1 << GIFBITS) - ((1 << (out_bits_init - 1)) + 3);
+ did_clear();
+ output(code_clear);
+ rl_count = 0;
+ while (1) {
+ c = readValue();
+ if ((rl_count > 0) && (c != rl_pixel)) {
+ rl_flush();
+ }
+ if (c == EOF) {
+ break;
+ }
+ if (rl_pixel == c) {
+ rl_count++;
+ } else {
+ rl_pixel = c;
+ rl_count = 1;
+ }
+ }
+ output(code_eof);
+ output_flush();
}
-/*-----------------------------------------------------------------------
+/*
+ *-----------------------------------------------------------------------
*
* End of miGIF section - See copyright notice at start of section.
*
- *-----------------------------------------------------------------------*/
-
-
+ *-----------------------------------------------------------------------
+ */