/* The LZW CODEC for GIF is Copyright (c) 1995 David Kaplan Alas, This LZW DECODER doesn't work yet. In fact this file is not used at all. All the GIF stuff is really in lzw.c. -- AYM 1999-09-07 */ #include "deutex.h" /*for types. equivalent of deu.h*/ #if defined DeuTex /*deutex shit*/ #if NEWGIFE || NEWGIFD #include #include #include #include "gifcodec.h" /* local defines */ #define HASHSIZE 5101 #define TABLESIZE 4096 #define HASHBITS 4 #define OK 0 #define EMPTY -1 #define BAD_ALLOC -2 #define OVERFLOW -3 #define OUTOFSYNC -4 static void Enc_clear(void); static void putCode(Int16 code); static Int16 flush(void); static Int16 findStr(Int16 pfx, Int16 sfx); static void putCode(Int16 code); static Int16 putbyte(Int16 byt); static UInt8 buffer[255]; /* the write buffer */ /* tables */ static Int16 *codes; /* the code entry column of the table */ static Int16 *prefix; /* the prefix entry column of the table */ static Int16 *suffix; /* the suffix entry column of the table */ /* codes */ static Int16 clrc; /* the value of the clearcode (the minsize + 1) */ static Int16 endc; /* the value of the endcode (the minsize + 2) */ /* control */ static Int16 nroots; /* how many codes are already in use = bitlength of the pixels*/ /* 1 << pixelsize */ static Int16 minsize; /* the minimum size for the first code (the highest value for the bitlength of the pixels*/ static Int16 cursize; /* the current bitlength being used in the codes */ static Int16 maxsize; /* the maximum bitlength that can be used (8) */ static Int16 curcode; /* the next entry value that is available */ static Int16 maxcode; /* the maximum entry value of the table */ static Int16 bytecode; /* last code read or written */ static Int16 bytemask; /* mask for bytecode */ static Int16 nbytes; /* COD the number of bytes that have been written */ /* DEC bytes in buffer */ static Int16 nbits; /* COD the number of bits being used in the highest empty slot */ /* DEC current element width */ #endif /*NEWGIFE NEWGIFD*/ /* ENCODER */ #if NEWGIFE FILE* outfile; /* the file to be written to */ static Int16 chrc; /* COD the current byte being read */ static Int16 strc; /* COD the number of the last entry to have a match */ static Int16 started; /* a boolean variable used to see if this is the first string */ /* Initializes all the variables (yup, all them up there!) */ Int16 InitEncoder(FILE* out, Int16 bpp) { codes = (Int16 *) malloc(sizeof(Int16)*HASHSIZE); prefix = (Int16 *) malloc(sizeof(Int16)*HASHSIZE); suffix = (Int16 *) malloc(sizeof(Int16)*HASHSIZE); if((codes == NULL) || (prefix == NULL) || (suffix == NULL)) return BAD_ALLOC; outfile = out; chrc = strc = started = 0; minsize = bpp + 1; maxsize = 12; nroots = 1 << bpp; clrc = nroots; endc = clrc + 1; bytecode = 0; bytemask = 1; nbytes = 0; started = 0; Enc_clear(); putCode(clrc); return OK; } Int16 ExitEncoder(void) { flush(); free(codes); free(prefix); free(suffix); return 0; } /* Encodes one string of bytes and writes to the current file pointer */ /* I will comment this part heavily to illustrate the process... */ Int16 Encode(UInt8 *buf, Int32 size) { Int16 pos = 0, index; /* if this is the first table to be used, setup some variables we need such as the table's first entry: the first byte in the array */ if(!started) { strc = buf[pos++]; // changed pos+1 to pos++ started = 1; } /* go through the array of bytes */ while(pos <= size) { chrc = buf[pos++]; /* get the next (or first) character */ /* see if the current string (be it one character or more) is in the table and return the corresponding entry number. If not, return the number of the next available entry */ index = findStr(strc, chrc); /* if the string IS in the index, we will get a number that corresponds to a string in the table: it wont be empty */ if(codes[index] != EMPTY) /* string found! */ { /* set the current string to the one-byte code for the string that was found */ strc = codes[index]; } else /* not found! */ { /* set the next entry in the table to the next available entry number */ codes[index] = curcode; prefix[index] = strc; /* set the prefix entry to the strc */ suffix[index] = chrc; /* set the suffix entry to the chrc */ putCode(strc); /* put the code into the out file (compression!) */ strc = chrc; /* set the prefix to the current char */ curcode++; /* remember that the current entry is now filled */ /* if the number of bytes in the current code is as big as possible, we must reset the table! */ if(curcode > maxcode) { cursize++; /* set the currentsize of the code to the next number */ /* if the current # of bytes being used exceeds the max */ if(cursize > maxsize) { putCode(clrc); /* put a clearcode into the file to tell the decoder */ Enc_clear(); /* reset the table and start over */ } else /* if not */ { nbits = cursize; /* set the number of bits to the current size */ maxcode <<= 1; /* set maxcode to the current char bitshifted once */ if(cursize == maxsize) /* if we are at the last bit-increase */ maxcode--; /* make maxcode one less so curcode can be larger than it */ } } } } return OK; } /* close the table: */ Int16 flush(void) { putCode(endc); /* put an endcode in the file */ if(bytemask != 1) /* if the last string was less than 256 bytes */ { putbyte(bytecode); /* put the last byte into the file */ bytecode = 0; /* and reset the variables*/ bytemask = 1; } if(nbytes > 0) /* if the last string has anything in it */ { fputc(nbytes, outfile); /* write the block out */ fwrite(buffer, nbytes, 1, outfile); nbytes = 0; } return ferror(outfile) ? BAD_ALLOC : OK; } /* put the code in. This is tricky because we use an int and we might have a code that is only using 7 or less bits, we must compensate */ void putCode(Int16 code) { Int16 mask = 1; Int16 n = nbits; while(n-- >0) { if(code & mask) bytecode |= bytemask; if((bytemask <<=1) > 0x80) { putbyte(bytecode); bytecode = 0; bytemask = 1; } mask <<= 1; } } /* clear the table for a new one to be built */ void Enc_clear(void) { Int16 i; cursize = minsize; nbits = cursize; curcode = endc + 1; maxcode = 1 << cursize; for(i=0;i 0) && (nb < rwbytes) ) bytes[nb++] = stack[--stkp]; /* loop until a row has been decoded */ while( nb < rwbytes ) { /*....... get next code */ if( (code=getcode()) < 0 ) break; /*....... check for a clear code*/ if( code == clrc ) { reset_decoder(); if( oldc == endc ) break; bytes[nb++] = oldc; if( nb == rwbytes ) break; } /*....... check for an end code*/ else if( code == endc ) { break; } /*....... code is a data code*/ else { if( code == curcode ) { code = oldc; cond = push( newc ); } else if( code > curcode ) { cond = OUTOFSYNC; break; } while( code > endc ) { cond = push( (suffix[code]&0xFF) ); code = prefix[code]; } cond = push( code ); /* add code to table */ if( curcode < maxcode ) { newc = code; suffix[curcode] = newc; prefix[curcode] = oldc; oldc = bitcode; curcode++; } /* current width exhausted? */ if( curcode >= maxcode ) { if( cursize < maxsize ) { cursize++; nbits = cursize; maxcode <<= 1; } else if( (code=getcode()) == clrc ) { reset_decoder(); if( oldc == endc ) break; bytes[nb++] = oldc; if( nb == rwbytes ) break; } else { cond = OVERFLOW; break; } } /* transfer string from stack to buffer*/ while( (stkp > 0) && (nb < rwbytes) ) bytes[nb++] = stack[--stkp]; } } /*! David I use fmemcpy not memcpy, because data is FAR (char *) */ _fmemcpy( buf, bytes, npxls ); return cond; } void Dec_clear(void) { Int16 i; cursize = minsize; nbits = cursize; clrc = nroots; endc = clrc + 1; curcode = endc + 1; maxcode = 1 << cursize; for(i=0; i 0 ) */ for(n=0; n 0x80 ) { bytemask = 1; if( (bytecode = getbyte()) < 0 ) return -1; } if( bytecode & bytemask ) bitcode |= bitmask; bitmask <<= 1; } return bitcode; } /* get a byte block */ Int16 getbyte( void ) { if( curbyte >= nbytes ) /*need a new block*/ { /*! David the block size is an unsigned char MODIFIED if( (nbytes = fgetc( ifile )&) < 1 ) return -1; */ for(nbytes=0;nbytes==0;) /*get a non zero block*/ { if( (nbytes = fgetc( ifile )) == EOF ) return -1; nbytes &= 0xFF; } if(fread( buffer, nbytes, 1, ifile ) != 1 ) return -1; curbyte = 0; } return buffer[curbyte++]; } void reset_decoder(void) { stkp = 0; Dec_clear(); while( (oldc=getcode()) == clrc ); newc = oldc; } #endif /*NEWGIFD*/ #endif /*DeuTex*/