summaryrefslogtreecommitdiffstats
path: root/tkagif
diff options
context:
space:
mode:
authorWilliam Joye <wjoye@cfa.harvard.edu>2019-03-25 19:27:17 (GMT)
committerWilliam Joye <wjoye@cfa.harvard.edu>2019-03-25 19:27:17 (GMT)
commit0f94d10d23323c1ff8342a851d52d657ded10ffd (patch)
tree8dae0c755ef742195ab4c5ae3a4f6ca388e0e6cd /tkagif
parentb9a5220b856f832c4f5a1abb3d754827b828bf57 (diff)
downloadblt-0f94d10d23323c1ff8342a851d52d657ded10ffd.zip
blt-0f94d10d23323c1ff8342a851d52d657ded10ffd.tar.gz
blt-0f94d10d23323c1ff8342a851d52d657ded10ffd.tar.bz2
support animated gif
Diffstat (limited to 'tkagif')
-rw-r--r--tkagif/tkagif.C144
-rw-r--r--tkagif/tkagif.h60
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();