diff options
author | William Joye <wjoye@cfa.harvard.edu> | 2019-03-25 19:27:17 (GMT) |
---|---|---|
committer | William Joye <wjoye@cfa.harvard.edu> | 2019-03-25 19:27:17 (GMT) |
commit | 0f94d10d23323c1ff8342a851d52d657ded10ffd (patch) | |
tree | 8dae0c755ef742195ab4c5ae3a4f6ca388e0e6cd /tkagif | |
parent | b9a5220b856f832c4f5a1abb3d754827b828bf57 (diff) | |
download | blt-0f94d10d23323c1ff8342a851d52d657ded10ffd.zip blt-0f94d10d23323c1ff8342a851d52d657ded10ffd.tar.gz blt-0f94d10d23323c1ff8342a851d52d657ded10ffd.tar.bz2 |
support animated gif
Diffstat (limited to 'tkagif')
-rw-r--r-- | tkagif/tkagif.C | 144 | ||||
-rw-r--r-- | tkagif/tkagif.h | 60 |
2 files changed, 98 insertions, 106 deletions
diff --git a/tkagif/tkagif.C b/tkagif/tkagif.C index 7311199..911c394 100644 --- a/tkagif/tkagif.C +++ b/tkagif/tkagif.C @@ -93,15 +93,20 @@ TkAGIF::TkAGIF(Tcl_Interp* interp) pict_ =NULL; pictCount_ =0; + // Compress + initialBits_ =0; + numBits_ =0; + currentBits_ =0; + maxCode_ =0; clearCode_ =0; eofCode_ =0; - initialBits_ =0; - numBits_ =0; - clearFlag_ =0; freeEntry_ =0; + + accumulatedByteCount_ =0; + currentAccumulated_ =0; } int TkAGIF::create(int argc, const char* argv[]) @@ -613,36 +618,40 @@ void TkAGIF::noCompress() void TkAGIF::compress() { - unsigned int codeTable[HSIZE]; - // LZW minium code size out_->write((char*)&resolution_,1); - memset(&state_, 0, sizeof(state_)); + unsigned int codeTable[HSIZE]; + int outCount = 0; + int inCount = 1; + // init initialBits_ = resolution_+1; + numBits_ = initialBits_; + currentBits_ = 0; - int outCount = 0; - int inCount = 1; - clearFlag_ = 0; - maxCode_ = MAXCODE(numBits_ = initialBits_); + maxCode_ = MAXCODE(numBits_); clearCode_ = 1 << (initialBits_ - 1); eofCode_ = clearCode_ + 1; + + clearFlag_ = 0; freeEntry_ = clearCode_ + 2; - charInit(); + accumulatedByteCount_ = 0; + currentAccumulated_ = 0; + long ent = input(); int hshift =0; long fcode =0; - for (fcode = (long)HSIZE; fcode < 65536L; fcode *= 2L) + for (fcode = (long)HSIZE; fcode < 65536L; fcode *= 2L) hshift++; // Set hash code range bound hshift = 8 - hshift; long hSize = HSIZE; - clearHashTable(hSize); + clearHashTable(); output((long)clearCode_); @@ -721,18 +730,18 @@ void TkAGIF::output(long code) 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF }; - state_.currentAccumulated &= masks[state_.currentBits]; - if (state_.currentBits > 0) { - state_.currentAccumulated |= ((long) code << state_.currentBits); + currentAccumulated_ &= masks[currentBits_]; + if (currentBits_ > 0) { + currentAccumulated_ |= ((long) code << currentBits_); } else { - state_.currentAccumulated = code; + currentAccumulated_ = code; } - state_.currentBits += numBits_; + currentBits_ += numBits_; - while (state_.currentBits >= 8) { - charOut((unsigned)(state_.currentAccumulated & 0xff)); - state_.currentAccumulated >>= 8; - state_.currentBits -= 8; + while (currentBits_ >= 8) { + charOut((unsigned)(currentAccumulated_ & 0xff)); + currentAccumulated_ >>= 8; + currentBits_ -= 8; } // If the next entry is going to be too big for the code size, then @@ -754,10 +763,10 @@ void TkAGIF::output(long code) if (code == eofCode_) { // At EOF, write the rest of the buffer. - while (state_.currentBits > 0) { - charOut((unsigned)(state_.currentAccumulated & 0xff)); - state_.currentAccumulated >>= 8; - state_.currentBits -= 8; + while (currentBits_ > 0) { + charOut((unsigned)(currentAccumulated_ & 0xff)); + currentAccumulated_ >>= 8; + currentBits_ -= 8; } flushChar(); } @@ -765,65 +774,56 @@ void TkAGIF::output(long code) void TkAGIF::clearForBlock() { - clearHashTable(HSIZE); - freeEntry_ = clearCode_ + 2; - clearFlag_ = 1; - - output((long)clearCode_); -} + clearHashTable(); + freeEntry_ = clearCode_ + 2; + clearFlag_ = 1; -void TkAGIF::clearHashTable(int hSize) -{ - register int *hashTablePtr = hashTable_ + hSize; - register long i; - register long m1 = -1; - - i = hSize - 16; - do { /* might use Sys V memset(3) here */ - *(hashTablePtr-16) = m1; - *(hashTablePtr-15) = m1; - *(hashTablePtr-14) = m1; - *(hashTablePtr-13) = m1; - *(hashTablePtr-12) = m1; - *(hashTablePtr-11) = m1; - *(hashTablePtr-10) = m1; - *(hashTablePtr-9) = m1; - *(hashTablePtr-8) = m1; - *(hashTablePtr-7) = m1; - *(hashTablePtr-6) = m1; - *(hashTablePtr-5) = m1; - *(hashTablePtr-4) = m1; - *(hashTablePtr-3) = m1; - *(hashTablePtr-2) = m1; - *(hashTablePtr-1) = m1; - hashTablePtr -= 16; - } while ((i -= 16) >= 0); - - for (i += 16; i > 0; i--) { - *--hashTablePtr = m1; - } + output((long)clearCode_); } -void TkAGIF::charInit() +void TkAGIF::clearHashTable() { - state_.accumulatedByteCount = 0; - state_.currentAccumulated = 0; - state_.currentBits = 0; + int *hashTablePtr = hashTable_ + HSIZE; + long m1 = -1; + long ii = HSIZE - 16; + + do { + *(hashTablePtr-16) = m1; + *(hashTablePtr-15) = m1; + *(hashTablePtr-14) = m1; + *(hashTablePtr-13) = m1; + *(hashTablePtr-12) = m1; + *(hashTablePtr-11) = m1; + *(hashTablePtr-10) = m1; + *(hashTablePtr-9) = m1; + *(hashTablePtr-8) = m1; + *(hashTablePtr-7) = m1; + *(hashTablePtr-6) = m1; + *(hashTablePtr-5) = m1; + *(hashTablePtr-4) = m1; + *(hashTablePtr-3) = m1; + *(hashTablePtr-2) = m1; + *(hashTablePtr-1) = m1; + hashTablePtr -= 16; + } while ((ii -= 16) >= 0); + + for (ii += 16; ii > 0; ii--) + *--hashTablePtr = m1; } void TkAGIF::charOut(int cc) { - state_.packetAccumulator[state_.accumulatedByteCount++] = cc; - if (state_.accumulatedByteCount >= 254) + packetAccumulator_[accumulatedByteCount_++] = cc; + if (accumulatedByteCount_ >= 254) flushChar(); } void TkAGIF::flushChar() { - if (state_.accumulatedByteCount > 0) { - unsigned char cc = state_.accumulatedByteCount; + if (accumulatedByteCount_ > 0) { + unsigned char cc = accumulatedByteCount_; out_->write((char*)&cc,1); - out_->write((char*)state_.packetAccumulator, state_.accumulatedByteCount); - state_.accumulatedByteCount = 0; + out_->write((char*)packetAccumulator_, accumulatedByteCount_); + accumulatedByteCount_ = 0; } } diff --git a/tkagif/tkagif.h b/tkagif/tkagif.h index aaecc06..a2a284c 100644 --- a/tkagif/tkagif.h +++ b/tkagif/tkagif.h @@ -5,37 +5,28 @@ #ifndef __tkagif_h__ #define __tkagif_h__ +/* + * Algorithm: use open addressing double hashing (no chaining) on the + * prefix code / next character combination. We do a variant of Knuth's + * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime + * secondary probe. Here, the modular division first probe is gives way to + * a faster exclusive-or manipulation. Also do block compression with an + * adaptive reset, whereby the code table is cleared when the compression + * ratio decreases, but after the table fills. The variable-length output + * codes are re-sized at this point, and a special CLEAR code is generated + * for the decompressor. Late addition: construct the table according to + * file size for noticeable speed improvement on small files. Please + * direct questions about this implementation to ames!jaw. + * + * To save much memory, we overlay the table used by compress() with those + * used by decompress(). The tab_prefix table is the same size and type as + * the codeTable. The tab_suffix table needs 2**GIFBITS characters. We get + * this from the beginning of hashTable. The output stack uses the rest of + * hashTable, and contains characters. There is plenty of room for any + * possible stack (stack used to be 8000 characters). + */ + #define HSIZE 5003 /* 80% occupancy */ -typedef struct { - /* - * Algorithm: use open addressing double hashing (no chaining) on the - * prefix code / next character combination. We do a variant of Knuth's - * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime - * secondary probe. Here, the modular division first probe is gives way to - * a faster exclusive-or manipulation. Also do block compression with an - * adaptive reset, whereby the code table is cleared when the compression - * ratio decreases, but after the table fills. The variable-length output - * codes are re-sized at this point, and a special CLEAR code is generated - * for the decompressor. Late addition: construct the table according to - * file size for noticeable speed improvement on small files. Please - * direct questions about this implementation to ames!jaw. - */ - - - /* - * To save much memory, we overlay the table used by compress() with those - * used by decompress(). The tab_prefix table is the same size and type as - * the codeTable. The tab_suffix table needs 2**GIFBITS characters. We get - * this from the beginning of hashTable. The output stack uses the rest of - * hashTable, and contains characters. There is plenty of room for any - * possible stack (stack used to be 8000 characters). - */ - - unsigned long currentAccumulated; - int currentBits; - int accumulatedByteCount; - unsigned char packetAccumulator[256]; -} GIFState_t; class TkAGIF { private: @@ -49,8 +40,6 @@ private: int colorTableSize_; int resolution_; - GIFState_t state_; - unsigned char* pict_; long pictCount_; @@ -60,11 +49,15 @@ private: int initialBits_; int numBits_; + int currentBits_; int clearFlag_; int freeEntry_; // First unused entry int hashTable_[HSIZE]; + unsigned char packetAccumulator_[256]; + int accumulatedByteCount_; + unsigned long currentAccumulated_; private: void noCompress(); @@ -73,8 +66,7 @@ private: int input(); void output(long); void clearForBlock(); - void clearHashTable(int); - void charInit(); + void clearHashTable(); void charOut(int); void flushChar(); |