1993.09.21 01:51 "Patch to tif_lzw.c for Wi", by Eric Herrmann

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
>