1 /************************************************************************/
2 /* */
3 /* Simple io streams, encoding/decoding into/from 12 bits LZW format. */
4 /* */
5 /* NOTE that the initial 'CodeSize' byte of the LZW stream is NOT */
6 /* read nor written by this library. It is passed as an argument to */
7 /* the stream open routines. This allows us to ignore the fact that */
8 /* files have the compressed data in a special format. The indirection */
9 /* GIF stream takes care of that. */
10 /* */
11 /* This is an isolated and optimized version of code found in 'giflib' */
12 /* The Original Authors: */
13 /* */
14 /* 14 Jun 89 - Version 1.0 by Gershon Elber. */
15 /* 3 Sep 90 - Version 1.1 by Gershon Elber (Support for Gif89, */
16 /* Unique names). */
17 /* 26 Jun 96 - Version 3.0 by Eric S. Raymond (Full GIF89 support) */
18 /* */
19 /* Also includes fragments borrowed from the ImageMagick code. */
20 /* */
21 /************************************************************************/
22
23 # include "appUtilConfig.h"
24
25 # include <stdlib.h>
26 # include <string.h>
27
28 # include "sioLzw.h"
29 # include <appDebugon.h>
30
31 /************************************************************************/
32 /* */
33 /* Common LZW Compression/Decompression state variables. */
34 /* */
35 /************************************************************************/
36
37 # define LZ_MAX_CODE 4095 /* Biggest code possible in 12 bits. */
38 # define LZ_BITS 12
39 # define FIRST_CODE 4097 /* Impossible code, to signal first. */
40 # define NO_SUCH_CODE 4098 /* Impossible code, to signal empty. */
41
42 typedef struct LzwState
43 {
44 int lsCurrentCode;
45 /************************************************/
46 /* The code last issued, or a bogus value to */
47 /* indicate that we are at the beginning of */
48 /* the output. */
49 /************************************************/
50 int lsNextCode;
51 /************************************************/
52 /* The next code the algorithm can generate. */
53 /************************************************/
54 int lsCurrentCodeSize;
55 /************************************************/
56 /* The number of bits required to represent */
57 /* RunningCode. */
58 /************************************************/
59 int lsMaxCode1;
60 /************************************************/
61 /* 1 bigger than max. possible code, in */
62 /* RunningBits bits. */
63 /************************************************/
64 int lsInitialCodeSize;
65 /************************************************/
66 /* The number of bits needed to hold all */
67 /* symbold in the original alphabet. */
68 /************************************************/
69 int lsClearCode;
70 int lsEOFCode;
71 /************************************************/
72 /* Special Codes. */
73 /************************************************/
74 int lsBitsAccumulated;
75 unsigned long lsAccumulator;
76 /************************************************/
77 /* For collecting codes in bytes. */
78 /* - Number of bits in CrntShiftDWord */
79 /* - To hold the byte values. */
80 /************************************************/
81 } LzwState;
82
83 /************************************************************************/
84 /* */
85 /* Initialise the state of a compressor/decompressor. */
86 /* */
87 /************************************************************************/
88
sioLzwInitState(LzwState * ls,int codeSize)89 static void sioLzwInitState( LzwState * ls,
90 int codeSize )
91 {
92 ls->lsInitialCodeSize= codeSize;
93 ls->lsClearCode= ( 1 << codeSize );
94 ls->lsEOFCode= ls->lsClearCode+ 1;
95 ls->lsNextCode= ls->lsEOFCode+ 1;
96 ls->lsCurrentCodeSize= codeSize + 1;
97 ls->lsMaxCode1= 1 << ls->lsCurrentCodeSize;
98 ls->lsBitsAccumulated= 0;
99 ls->lsAccumulator= 0;
100
101 ls->lsCurrentCode= FIRST_CODE;
102
103 return;
104 }
105
106 /************************************************************************/
107 /* */
108 /* 12 bits LZW decompression specific data. */
109 /* */
110 /************************************************************************/
111
112 typedef struct LzwInputStream
113 {
114 LzwState lisState;
115 SimpleInputStream * lisSisLzw;
116
117 int lisExhausted;
118 int lisLastCode;
119 /************************************************/
120 /* The code before the current code. */
121 /************************************************/
122 int lisStackPtr;
123 /************************************************/
124 /* For character stack (see below). */
125 /************************************************/
126 unsigned char lisStack[LZ_MAX_CODE];
127 /************************************************/
128 /* Decoded pixels are stacked here. */
129 /************************************************/
130 unsigned char lisSuffix[LZ_MAX_CODE+1];
131 unsigned int lisPrefix[LZ_MAX_CODE+1];
132 /************************************************/
133 /* Keep track of the meaning of the Codes. */
134 /************************************************/
135 } LzwInputStream;
136
137
138 /************************************************************************/
139 /* */
140 /* Decompress a 12 bits LZW input stream. */
141 /* */
142 /************************************************************************/
143
144 /************************************************************************/
145 /* */
146 /* The LZ decompression input routine: */
147 /* */
148 /* This routine is responsable for the decompression of the bit */
149 /* stream from 8 bits (bytes) packets, into the real codes. */
150 /* Returns 0 if read succesfully, -1 otherwise. */
151 /* */
152 /* 1) As long as we need to get more bytes from input stream for */
153 /* next code */
154 /* 2) Extract the code. */
155 /* 3) And shift it away. */
156 /* 4) Increment the next code to be implicitly expected. (What the */
157 /* encoder is supposed to send next) and if it is beyond what fits */
158 /* in the current number of bits increment the number of bits. */
159 /* NOTE however that codes above 4095 are used for special */
160 /* signaling. */
161 /* */
162 /************************************************************************/
163
sioInLzwReadCode(LzwInputStream * lis,int * pCode)164 static int sioInLzwReadCode( LzwInputStream * lis,
165 int * pCode )
166
167 {
168 LzwState * ls= &(lis->lisState);
169
170 static unsigned int CodeMasks[]=
171 {
172 0x0000,
173 0x0001,
174 0x0003,
175 0x0007,
176 0x000f,
177 0x001f,
178 0x003f,
179 0x007f,
180 0x00ff,
181 0x01ff,
182 0x03ff,
183 0x07ff,
184 0x0fff
185 };
186
187 /* 1 */
188 while( ls->lsBitsAccumulated < ls->lsCurrentCodeSize )
189 {
190 int byte;
191
192 byte= sioInGetByte( lis->lisSisLzw );
193 if ( byte == EOF )
194 { XDEB(byte); return -1; }
195
196 ls->lsAccumulator |= ((unsigned long) byte) << ls->lsBitsAccumulated;
197 ls->lsBitsAccumulated += 8;
198 }
199
200 /* 2 */
201 *pCode = ls->lsAccumulator & CodeMasks[ls->lsCurrentCodeSize];
202
203 /* 3 */
204 ls->lsAccumulator >>= ls->lsCurrentCodeSize;
205 ls->lsBitsAccumulated -= ls->lsCurrentCodeSize;
206
207 /* 4 */
208 if ( ++ls->lsNextCode > ls->lsMaxCode1 &&
209 ls->lsCurrentCodeSize < LZ_BITS )
210 {
211 ls->lsMaxCode1 <<= 1;
212 ls->lsCurrentCodeSize++;
213 }
214
215 return 0;
216 }
217
218 /************************************************************************/
219 /* */
220 /* Routine to trace the Prefixes linked list until we get a prefix */
221 /* which is not a code, but a pixel value (less than ClearCode). */
222 /* Returns that pixel value. */
223 /* If the image is defective, we might loop here forever, so we limit */
224 /* the loops to the maximum possible when the image is image Ok: */
225 /* LZ_MAX_CODE times. */
226 /* */
227 /************************************************************************/
228
sioInLzwGetPrefixChar(const unsigned int * Prefix,int Code,int ClearCode)229 static int sioInLzwGetPrefixChar( const unsigned int * Prefix,
230 int Code,
231 int ClearCode )
232 {
233 int i = 0;
234
235 while( Code > ClearCode &&
236 i++ <= LZ_MAX_CODE )
237 { Code = Prefix[Code]; }
238
239 return Code;
240 }
241
242 /************************************************************************/
243 /* */
244 /* The LZ decompression routine: */
245 /* */
246 /* This version decompress the given gif file into Line of length */
247 /* LineLen. */
248 /* This routine can be called few times (one per scan line, for */
249 /* example), in order to complete the whole image. */
250 /* */
251 /* 1) To not try to continue after the end of input has been found */
252 /* nor after a previous error. */
253 /* 2) Pop the contents of the stack before reading the input stream. */
254 /* 3) Until a sufficient number of bytes is returned, read codes from */
255 /* the input stream and process them. */
256 /* */
257 /************************************************************************/
258
sioInLzwReadBytes(void * voidlis,unsigned char * buffer,unsigned int count)259 static int sioInLzwReadBytes( void * voidlis,
260 unsigned char * buffer,
261 unsigned int count )
262 {
263 int i = 0;
264 int j;
265 int CrntCode;
266 int EOFCode;
267 int ClearCode;
268 int CrntPrefix;
269 int LastCode;
270 int StackPtr;
271 unsigned char * Stack;
272 unsigned char * Suffix;
273 unsigned int * Prefix;
274
275 LzwInputStream * lis= (LzwInputStream *)voidlis;
276 LzwState * ls= &(lis->lisState);
277
278 StackPtr= lis->lisStackPtr;
279 Prefix = lis->lisPrefix;
280 Suffix = lis->lisSuffix;
281 Stack = lis->lisStack;
282 EOFCode = ls->lsEOFCode;
283 ClearCode = ls->lsClearCode;
284 LastCode= lis->lisLastCode;
285
286 /* 1 */
287 if ( lis->lisExhausted )
288 { LDEB(lis->lisExhausted); return 0; }
289
290 /* 2 */
291 while( StackPtr > 0 && i < count )
292 { buffer[i++]= Stack[--StackPtr]; }
293
294 /* 3 */
295 while( i < count )
296 {
297 if ( sioInLzwReadCode( lis, &CrntCode ) )
298 { LDEB(1); return -1; }
299
300 if ( CrntCode == EOFCode )
301 { lis->lisExhausted= 1; i++; break; }
302 else if (CrntCode == ClearCode) {
303 /* We need to start over again: */
304 for (j = 0; j <= LZ_MAX_CODE; j++) Prefix[j] = NO_SUCH_CODE;
305 ls->lsNextCode = ls->lsEOFCode + 1;
306 ls->lsCurrentCodeSize = ls->lsInitialCodeSize + 1;
307 ls->lsMaxCode1 = 1 << ls->lsCurrentCodeSize;
308 LastCode= lis->lisLastCode= NO_SUCH_CODE;
309 }
310 else {
311 /* Its regular code - if in pixel range simply add it to output */
312 /* stream, otherwise trace to codes linked list until the prefix */
313 /* is in pixel range: */
314 if (CrntCode < ClearCode) {
315 /* This is simple - its pixel scalar, so add it to output: */
316 buffer[i++] = CrntCode;
317 }
318 else {
319 /* Its a code to needed to be traced: trace the linked list */
320 /* until the prefix is a pixel, while pushing the suffix */
321 /* pixels on our stack. If we done, pop the stack in reverse */
322 /* (thats what stack is good for!) order to output. */
323 if (Prefix[CrntCode] == NO_SUCH_CODE) {
324 /* Only allowed if CrntCode is exactly the running code: */
325 /* In that case CrntCode = XXXCode, CrntCode or the */
326 /* prefix code is last code and the suffix char is */
327 /* exactly the prefix of last code! */
328 if (CrntCode == ls->lsNextCode - 2) {
329 CrntPrefix = LastCode;
330 Suffix[ls->lsNextCode - 2] =
331 Stack[StackPtr++] = sioInLzwGetPrefixChar(Prefix,
332 LastCode, ClearCode);
333 }
334 else {
335 LDEB(1); return -1;
336 }
337 }
338 else
339 CrntPrefix = CrntCode;
340
341 /* Now (if image is O.K.) we should not get an NO_SUCH_CODE */
342 /* During the trace. As we might loop forever, in case of */
343 /* defective image, we count the number of loops we trace */
344 /* and stop if we got LZ_MAX_CODE. obviously we can not */
345 /* loop more than that. */
346 j = 0;
347 while (j++ <= LZ_MAX_CODE &&
348 CrntPrefix > ClearCode &&
349 CrntPrefix <= LZ_MAX_CODE) {
350 Stack[StackPtr++] = Suffix[CrntPrefix];
351 CrntPrefix = Prefix[CrntPrefix];
352 }
353 if (j >= LZ_MAX_CODE || CrntPrefix > LZ_MAX_CODE) {
354 LLLDEB(j,CrntPrefix,LZ_MAX_CODE);
355 return -1;
356 }
357 /* Push the last character on stack: */
358 Stack[StackPtr++] = CrntPrefix;
359
360 /* Now lets pop all the stack into output: */
361 while (StackPtr != 0 && i < count)
362 buffer[i++] = Stack[--StackPtr];
363 }
364 if (LastCode != NO_SUCH_CODE) {
365 Prefix[ls->lsNextCode - 2] = LastCode;
366
367 if (CrntCode == ls->lsNextCode - 2) {
368 /* Only allowed if CrntCode is exactly the running code: */
369 /* In that case CrntCode = XXXCode, CrntCode or the */
370 /* prefix code is last code and the suffix char is */
371 /* exactly the prefix of last code! */
372 Suffix[ls->lsNextCode - 2] =
373 sioInLzwGetPrefixChar(Prefix, LastCode, ClearCode);
374 }
375 else {
376 Suffix[ls->lsNextCode - 2] =
377 sioInLzwGetPrefixChar(Prefix, CrntCode, ClearCode);
378 }
379 }
380 LastCode = CrntCode;
381 }
382 }
383
384 lis->lisLastCode= LastCode;
385 lis->lisStackPtr= StackPtr;
386
387 return i;
388 }
389
390
391 /************************************************************************/
392 /* */
393 /* Close an Lzw Input stream. */
394 /* */
395 /* 1) First drain it. */
396 /* */
397 /************************************************************************/
398
sioInLzwClose(void * voidlis)399 static int sioInLzwClose( void * voidlis )
400 {
401 int rval= 0;
402 LzwInputStream * lis= (LzwInputStream *)voidlis;
403
404 /* 1 */
405 while( ! lis->lisExhausted )
406 {
407 unsigned char buffer[SIOsizBUF];
408
409 if ( sioInLzwReadBytes( voidlis, buffer, SIOsizBUF ) < 0 )
410 { LDEB(1); rval= -1; break; }
411 }
412
413 free( voidlis );
414
415 return rval;
416 }
417
sioInLzwGifOpen(SimpleInputStream * sisLzw,int codeSize)418 SimpleInputStream * sioInLzwGifOpen( SimpleInputStream * sisLzw,
419 int codeSize )
420 {
421 SimpleInputStream * sis;
422 LzwInputStream * lis;
423
424 int i;
425 unsigned int * p;
426
427 lis= (LzwInputStream *)malloc( sizeof(LzwInputStream) );
428 if ( ! lis )
429 { XDEB(lis); return (SimpleInputStream *)0; }
430
431 lis->lisSisLzw= sisLzw;
432 lis->lisExhausted= 0;
433
434 lis->lisStackPtr= 0;
435 lis->lisLastCode= NO_SUCH_CODE;
436
437 sioLzwInitState( &(lis->lisState), codeSize );
438
439 p= lis->lisPrefix;
440 for ( i = 0; i <= LZ_MAX_CODE; p++, i++ )
441 { *p= NO_SUCH_CODE; }
442
443 sis= sioInOpen( (void *)lis, sioInLzwReadBytes, sioInLzwClose );
444
445 if ( ! sis )
446 { XDEB(sis); free( lis ); return (SimpleInputStream *)0; }
447
448 return sis;
449 }
450
451 /************************************************************************/
452 /* */
453 /* SimpleOutputStreams doing LZW compression. */
454 /* */
455 /* 1) Mask nonsense bits from the input of the compressor. */
456 /* */
457 /************************************************************************/
458
459 static const unsigned char SIO_LZW_OutMasks[]=
460 {
461 0x00,
462 0x01,
463 0x03,
464 0x07,
465 0x0f,
466 0x1f,
467 0x3f,
468 0x7f,
469 0xff
470 };
471
472 #define HT_SIZE 8192 /* 12bits = 4096 or twice as big! */
473 #define HT_KEY_MASK 0x1FFF /* 13bits keys */
474 #define HT_KEY_NUM_BITS 13 /* 13bits keys */
475 #define HT_MAX_KEY 8191 /* 13bits - 1, maximal code possible */
476 #define HT_MAX_CODE 4095 /* Biggest code possible in 12 bits. */
477
478 /* The 32 bits of the long are divided into two parts for the key & code: */
479 /* 1. The code is 12 bits as our compression algorithm is limited to 12bits */
480 /* 2. The key is 12 bits Prefix code + 8 bit new char or 20 bits. */
481 #define HT_GET_KEY(l) (l >> 12)
482 #define HT_GET_CODE(l) (l & 0x0FFF)
483 #define HT_PUT_KEY(l) (l << 12)
484 #define HT_PUT_CODE(l) (l & 0x0FFF)
485
486 typedef struct GifHashTableType {
487 unsigned long HTable[HT_SIZE];
488 } GifHashTableType;
489
490 /******************************************************************************
491 * Routine to generate an HKey for the hashtable out of the given unique key. *
492 * The given Key is assumed to be 20 bits as follows: lower 8 bits are the *
493 * new postfix character, while the upper 12 bits are the prefix code. *
494 * Because the average hit ratio is only 2 (2 hash references per entry), *
495 * evaluating more complex keys (such as twin prime keys) is not worth it! *
496 ******************************************************************************/
497
498 # define KeyItem(Item) \
499 ((((unsigned long)(Item) >> 12) ^ (unsigned long)(Item)) & HT_KEY_MASK)
500
501 /******************************************************************************
502 * Routine to clear the HashTable to an empty state. *
503 * This part is a little machine depended. Use the commented part otherwise. *
504 ******************************************************************************/
505
_ClearHashTable(GifHashTableType * HashTable)506 static void _ClearHashTable(GifHashTableType *HashTable)
507 {
508 memset(HashTable -> HTable, 0xFF, HT_SIZE * sizeof(long));
509 }
510
511 /******************************************************************************
512 * Routine to insert a new Item into the HashTable. The data is assumed to be *
513 * new one. *
514 ******************************************************************************/
515
_InsertHashTable(GifHashTableType * HashTable,unsigned long Key,int Code)516 static void _InsertHashTable(GifHashTableType *HashTable, unsigned long Key, int Code)
517 {
518 int HKey = KeyItem(Key);
519 unsigned long *HTable = HashTable -> HTable;
520
521 while (HT_GET_KEY(HTable[HKey]) != 0xFFFFFL) {
522 HKey = (HKey + 1) & HT_KEY_MASK;
523 }
524 HTable[HKey] = HT_PUT_KEY(Key) | HT_PUT_CODE(Code);
525 }
526
527 /******************************************************************************
528 * Routine to test if given Key exists in HashTable and if so returns its code *
529 * Returns the Code if key was found, -1 if not. *
530 ******************************************************************************/
531
_ExistsHashTable(GifHashTableType * HashTable,unsigned long Key)532 static int _ExistsHashTable( GifHashTableType * HashTable,
533 unsigned long Key )
534 {
535 int HKey= KeyItem(Key);
536 unsigned long * HTable= HashTable -> HTable, HTKey;
537
538 while ((HTKey = HT_GET_KEY(HTable[HKey])) != 0xFFFFFL) {
539 if (Key == HTKey) return HT_GET_CODE(HTable[HKey]);
540 HKey = (HKey + 1) & HT_KEY_MASK;
541 }
542
543 return -1;
544 }
545
546 /************************************************************************/
547 /* */
548 /* Actual Output stream object. */
549 /* */
550 /************************************************************************/
551
552 typedef struct LzwGifOutputStream
553 {
554 GifHashTableType losHashTable;
555 LzwState losState;
556 SimpleOutputStream * losSosLzw;
557 } LzwGifOutputStream;
558
559 /************************************************************************/
560 /* */
561 /* The actual output routine to the (blocked) stream: */
562 /* This routine is responsible for the translation of the bit stream */
563 /* into 8 bits (byte) packets. */
564 /* */
565 /* 1) Emit full bytes. */
566 /* */
567 /************************************************************************/
568
sioOutLzwGifWriteCode(LzwGifOutputStream * los,int code)569 static int sioOutLzwGifWriteCode( LzwGifOutputStream * los,
570 int code )
571 {
572 LzwState * ls= &(los->losState);
573 int rval= 0;
574
575 ls->lsAccumulator |= ( (long)code ) << ls->lsBitsAccumulated;
576 ls->lsBitsAccumulated += ls->lsCurrentCodeSize;
577
578 while( ls->lsBitsAccumulated >= 8 )
579 {
580 /* 1 */
581 if ( sioOutPutByte( ls->lsAccumulator & 0xff,
582 los->losSosLzw ) == EOF )
583 { rval= -1; }
584
585 ls->lsAccumulator >>= 8;
586 ls->lsBitsAccumulated -= 8;
587 }
588
589 return rval;
590 }
591
592 /************************************************************************/
593 /* */
594 /* Close an LZW output stream. */
595 /* */
596 /* 1) As the encoding process is one code behind, issue the last */
597 /* code. */
598 /* 2) Issue the EOF code. */
599 /* 3) Emit all bits that are heaped up in the encoder. */
600 /* 4) Free memory. */
601 /* */
602 /************************************************************************/
603
sioOutLzwGifClose(void * voidlos)604 static int sioOutLzwGifClose( void * voidlos )
605 {
606 int rval= 0;
607 LzwGifOutputStream * los= (LzwGifOutputStream *)voidlos;
608 LzwState * ls= &(los->losState);
609
610 /* 1 */
611 if ( sioOutLzwGifWriteCode( los, ls->lsCurrentCode ) )
612 { XDEB(ls->lsCurrentCode); rval= -1; }
613
614 /* 2 */
615 if ( sioOutLzwGifWriteCode( los, ls->lsEOFCode ) )
616 { XDEB(ls->lsEOFCode); rval= -1; }
617
618 /* 3 */
619 while( ls->lsBitsAccumulated > 0 )
620 {
621 if ( sioOutPutByte( ls->lsAccumulator & 0xff,
622 los->losSosLzw ) == EOF )
623 { LDEB(1); rval= -1; }
624
625 ls->lsAccumulator >>= 8;
626 ls->lsBitsAccumulated -= 8;
627 }
628
629 /* 4 */
630 free( los );
631
632 return rval;
633 }
634
635 /************************************************************************/
636 /* */
637 /* The LZ compression routine: */
638 /* This version compress the given buffer of length count. */
639 /* This routine can be called several times (one per scan line, for */
640 /* example), in order to compress the whole image */
641 /* */
642 /* 1) If the Current code is the initial value that serves to */
643 /* flag this, set the current code to the first character to */
644 /* compress. (and consume it) */
645 /* 2) Make a new key to search the hash table. */
646 /* 3) Lookup in hash table. */
647 /* 4) If it is there, simply take the new code as the current code. */
648 /* 5) If not, emit the current code and set the current code to the */
649 /* pixel value. */
650 /* If next code cannot fit into the current code size, must raise */
651 /* the code size. */
652 /* 6) BUT.. If the hash table is full, send a Clear code and clear */
653 /* the hash table as well. */
654 /* */
655 /************************************************************************/
656
sioOutLzwGifWriteBytes(void * voidlos,const unsigned char * buffer,int count)657 static int sioOutLzwGifWriteBytes(
658 void * voidlos,
659 const unsigned char * buffer,
660 int count )
661 {
662 LzwGifOutputStream * los= (LzwGifOutputStream *)voidlos;
663 LzwState * ls= &(los->losState);
664
665 int i= 0;
666
667 /* 1 */
668 if ( ls->lsCurrentCode == FIRST_CODE )
669 {
670 ls->lsCurrentCode=
671 buffer[i++] & SIO_LZW_OutMasks[ls->lsInitialCodeSize];
672 }
673
674 while( i < count )
675 {
676 int val= buffer[i++] & SIO_LZW_OutMasks[ls->lsInitialCodeSize];
677 int nextKey;
678 int nextCode;
679
680 /* 2 */
681 nextKey= ( ((unsigned long) ls->lsCurrentCode ) << 8) + val;
682
683 /* 3 */
684 nextCode= _ExistsHashTable( &(los->losHashTable), nextKey );
685
686 /* 4 */
687 if ( nextCode >= 0 )
688 { ls->lsCurrentCode= nextCode; }
689 else{
690 /* 5 */
691 if ( sioOutLzwGifWriteCode( los, ls->lsCurrentCode ) )
692 { LDEB(ls->lsCurrentCode); return -1; }
693
694 ls->lsCurrentCode= val;
695
696 if ( ls->lsNextCode >= ls->lsMaxCode1 )
697 { ls->lsMaxCode1= 1 << ++(ls->lsCurrentCodeSize); }
698
699 /* 6 */
700 if ( ls->lsCurrentCodeSize > 12 )
701 {
702 ls->lsCurrentCodeSize= 12;
703
704 if ( sioOutLzwGifWriteCode( los, ls->lsClearCode ) )
705 { LDEB(ls->lsCurrentCode); return -1; }
706
707 ls->lsNextCode= ls->lsEOFCode+ 1;
708 ls->lsCurrentCodeSize= ls->lsInitialCodeSize+ 1;
709 ls->lsMaxCode1= 1 << ls->lsCurrentCodeSize;
710
711 _ClearHashTable( &(los->losHashTable) );
712 }
713 else{
714 _InsertHashTable( &(los->losHashTable),
715 nextKey, ls->lsNextCode );
716 ls->lsNextCode++;
717 }
718 }
719 }
720
721 return count;
722 }
723
724 /************************************************************************/
725 /* */
726 /* Open a 12 bit LZW output stream. */
727 /* */
728 /* NOTE that the initial code size has been communicated outside the */
729 /* compressed stream. In the GIF case even before the packeted */
730 /* stream packet header of the first packet. */
731 /* */
732 /* 1) Allocate memory and remember the output stream. */
733 /* 2) Initialize the hash table by clearing it. */
734 /* 3) Initialize the general LZW administration for the current code */
735 /* size. */
736 /* 4) General SioOut administration. */
737 /* Z) Start with a clear code to be sure that the decoder has also */
738 /* cleared its hash table. */
739 /* */
740 /************************************************************************/
741
sioOutLzwGifOpen(SimpleOutputStream * sosLzw,int codeSize)742 SimpleOutputStream * sioOutLzwGifOpen( SimpleOutputStream * sosLzw,
743 int codeSize )
744 {
745 SimpleOutputStream * sos;
746 LzwGifOutputStream * los;
747
748 /* 1 */
749 los= (LzwGifOutputStream *)malloc( sizeof(LzwGifOutputStream) );
750 if ( ! los )
751 { XDEB(los); return (SimpleOutputStream *)0; }
752
753 los->losSosLzw= sosLzw;
754
755 /* 2 */
756 _ClearHashTable( &(los->losHashTable) );
757
758 /* 3 */
759 sioLzwInitState( &(los->losState), codeSize );
760
761 /* 4 */
762 sos= sioOutOpen( (void *)los, sioOutLzwGifWriteBytes, sioOutLzwGifClose );
763
764 if ( ! sos )
765 { XDEB(sos); free( los ); return (SimpleOutputStream *)0; }
766
767 /* Z */
768 if ( sioOutLzwGifWriteCode( los, los->losState.lsClearCode ) )
769 { LDEB(1); sioOutClose( sos ); return (SimpleOutputStream *)0; }
770
771 return sos;
772 }
773
774