diff options
author | dkf <donal.k.fellows@manchester.ac.uk> | 2002-02-19 14:05:43 (GMT) |
---|---|---|
committer | dkf <donal.k.fellows@manchester.ac.uk> | 2002-02-19 14:05:43 (GMT) |
commit | c7d9b8120ab7ba175c080cf1e27fddbbf8a72eb0 (patch) | |
tree | 51ca4798eca1680b060d4a990f3b9717c468e84f /generic/tkImgGIF.c | |
parent | 8332d4e900c4e848b093ddb4fbb8ce6926d8f03b (diff) | |
download | tk-c7d9b8120ab7ba175c080cf1e27fddbbf8a72eb0.zip tk-c7d9b8120ab7ba175c080cf1e27fddbbf8a72eb0.tar.gz tk-c7d9b8120ab7ba175c080cf1e27fddbbf8a72eb0.tar.bz2 |
tkImgGIF.c was not following the Tcl C style; fixed...
Diffstat (limited to 'generic/tkImgGIF.c')
-rw-r--r-- | generic/tkImgGIF.c | 1247 |
1 files changed, 676 insertions, 571 deletions
diff --git a/generic/tkImgGIF.c b/generic/tkImgGIF.c index 5b79558..6fe4ed9 100644 --- a/generic/tkImgGIF.c +++ b/generic/tkImgGIF.c @@ -19,17 +19,17 @@ * 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: tkImgGIF.c,v 1.19 2002/01/17 05:13:11 dgp Exp $ + * RCS: @(#) $Id: tkImgGIF.c,v 1.20 2002/02/19 14:05:43 dkf Exp $ */ /* @@ -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) /* @@ -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); @@ -378,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, @@ -387,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 = @@ -395,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; @@ -520,25 +530,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]); @@ -574,13 +590,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; @@ -588,8 +604,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; @@ -601,7 +616,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; } /* @@ -656,65 +671,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; + } + + 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; + } + 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 { @@ -727,8 +742,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; @@ -753,17 +768,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. @@ -777,15 +792,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; @@ -797,9 +812,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 */ @@ -808,7 +823,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; @@ -817,19 +832,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)); @@ -840,12 +857,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; @@ -864,10 +885,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; } @@ -880,7 +903,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; @@ -916,15 +939,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. @@ -936,7 +964,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; @@ -957,7 +987,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) { @@ -981,23 +1013,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. @@ -1007,9 +1039,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; @@ -1020,7 +1052,9 @@ GetCode(chan, code_size, flag) int ret; if (flag) { - /* Initialize the decoder */ + /* + * Initialize the decoder. + */ bitsInWindow = 0; bytes = 0; window = 0; @@ -1030,12 +1064,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) { @@ -1043,7 +1081,9 @@ 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; @@ -1051,10 +1091,14 @@ GetCode(chan, code_size, flag) } - /* 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; @@ -1144,20 +1188,20 @@ 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; @@ -1165,24 +1209,24 @@ Mgetc(handle) } 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; } /* @@ -1207,33 +1251,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; } } @@ -1257,18 +1305,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)); } } @@ -1277,13 +1325,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> @@ -1307,11 +1355,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; @@ -1340,7 +1388,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; @@ -1383,9 +1431,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]; @@ -1398,30 +1446,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; @@ -1433,16 +1483,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]; @@ -1463,28 +1517,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; @@ -1507,9 +1561,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; } } @@ -1522,10 +1576,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; } } @@ -1537,9 +1591,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; @@ -1550,22 +1604,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; @@ -1582,10 +1636,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) { @@ -1599,48 +1653,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; @@ -1665,145 +1724,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 @@ -1811,205 +1897,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. * - *-----------------------------------------------------------------------*/ + *----------------------------------------------------------------------- + */ |