
Thread
1993.09.21 01:51 "Patch to tif_lzw.c for Wi", by Eric Herrmann
Sam,
Here are diffs to make lzw code work on 80x86, Windows 3.1, using Microsoft Visual C++ 1.0 compiler. The LZW code uses a hash table for encoding that is slightly larger than 64K; accessing larger than that is inefficient on this architecture. The following changes are necessary:
- Setting HSIZE to 8179 makes sizeof(LZWEncode) < 64K.
- The code at about line 1013 in LZWEncode says:
if ((hp -= disp) < sp->enc_hashtab)
hp += HSIZE;
This pointer arithmetic fails on 80x86 because the offset is an unsigned short and wraps around to be higher than the desired address. A patch to perform the correct arithmetic is included.
- About line 999:
h = (c << HSHIFT) ^ ent; /* xor hashing */
This can generate indexes that are > 8179. The patch code will generate a few more collisions but this should be insignificant.
Eric Herrmann
Light Source
LS.BANZAI@AppleLink.Apple.Com
------------------- tif_lzw.c
65c65
< #define MAXCODE(n) ((1<<(n))-1)
---
> #define MAXCODE(n) ((1L<<(n))-1)
77c77,92
< #define HSIZE 9001 /* 91% occupancy */
---
>
> #ifdef _WINDOWS
> /*
> * Can't have bigger than 64K. Use a prime less than
> * 8192-sizeof(struct part of LZWEncodeState) = 8186.
> */
> #define HSIZE 8179L
>
> /*
> * Must do some special pointer arithmetic.
> */
> #include <windows.h>
> #else
> #define HSIZE 9001L /* 91% occupancy */
> #endif
>
334c349
< tif->tif_data = _TIFFmalloc(sizeof (LZWDecodeState));
---
> tif->tif_data = (tidata_t)_TIFFmalloc(sizeof (LZWDecodeState));
891c906
< tif->tif_data = _TIFFmalloc(sizeof (LZWEncodeState));
---
> tif->tif_data = (tidata_t)_TIFFmalloc(sizeof (LZWEncodeState));
999a1015,1022
> #ifdef _WINDOWS
> /*
> * Check hash index to see if we've overflowed the table.
> * This increases the chance of a collision by a very small amount.
> */
> if ( h >= HSIZE )
> h -= HSIZE;
> #endif
1012a1036,1050
> #ifdef _WINDOWS
> /*
> * 64K segment pointer arithmetic! Yuk!
> * Subtracting a value from a pointer can easily become
> * negative, but with a segment:offset pointer the
> * offset is unsigned and thus wraps around.
> * This code is for MSVC 1.0.
> */
> register long offset;
>
> offset = (long) OFFSETOF( hp ) - disp * sizeof( hash_t );
> if ( offset < FIELDOFFSET( LZWEncodeState, enc_hashtab ) )
> offset += HSIZE * sizeof( hash_t);
> hp = (hash_t *) MAKELP( SELECTOROF( hp ), offset );
> #else
1014a1053
> #endif
1218a1258
>