1 /*****
2 * LZWStream.c : LZW uncompressor that doesn't use the LZW algorithm but
3 *				converts LZW compressed data to compress LZW data and
4 *				calls compress to do the uncompressing.
5 *
6 * This file Version	$Revision: 1.6 $
7 *
8 * Creation date:		Thu May  8 04:53:42 GMT+0100 1997
9 * Last modification: 	$Date: 1998/04/27 06:55:01 $
10 * By:					$Author: newt $
11 * Current State:		$State: Exp $
12 *
13 * Author:				newt
14 *
15 * Copyright (C) 1994-1997 by Ripley Software Development
16 * All Rights Reserved
17 *
18 * This file is part of the XmHTML Widget Library.
19 *
20 * Permission to use, copy, modify, and distribute this software and its
21 * documentation for any purpose and without fee is hereby granted, provided
22 * that the above copyright notice appear in all copies and that both that
23 * copyright notice and this permission notice appear in supporting
24 * documentation.  This software is provided "as is" without express or
25 * implied warranty.
26 *
27 * Based on an idea from Derek D. Noonburg <derekn@ece.cmu.edu>, author of
28 * the public domain xpdf package, a PDF viewer.
29 *
30 *****/
31 /*****
32 * ChangeLog
33 * $Log: LZWStream.c,v $
34 * Revision 1.6  1998/04/27 06:55:01  newt
35 * tka stuff
36 *
37 * Revision 1.5  1998/04/04 06:27:47  newt
38 * XmHTML Beta 1.1.3
39 *
40 * Revision 1.4  1997/10/23 00:24:33  newt
41 * XmHTML Beta 1.1.0 release
42 *
43 * Revision 1.3  1997/08/30 00:23:48  newt
44 * Removed XmHTML dependencies.
45 *
46 * Revision 1.2  1997/08/01 12:52:18  newt
47 * Progressive image loading changes
48 *
49 * Revision 1.1  1997/05/28 01:27:00  newt
50 * Initial Revision
51 *
52 *****/
53 #ifdef HAVE_CONFIG_H
54 #include "config.h"
55 #endif
56 
57 #include <stdio.h>
58 #include <stdlib.h>
59 #include <string.h>
60 #ifndef WINNT
61 #include <unistd.h>
62 #endif
63 
64 #ifndef NO_XmHTML			/* defined when compiling for standalone */
65 #include "toolkit.h"
66 #include XmHTMLPrivateHeader
67 #else
68 #include "ImBuffer.h"		/* ImageBuffer stuff */
69 typedef unsigned char Boolean;
70 #define True	1
71 #define False	0
72 #endif
73 
74 #include <LZWStream.h>
75 
76 /*** External Function Prototype Declarations ***/
77 
78 /*** Public Variable Declarations ***/
79 #ifdef DEBUG
80 int lzw_debug = False;
81 #endif
82 
83 /*** Private Datatype Declarations ****/
84 
85 #define INIT_BITS		9					/* minimum compress codeSize */
86 #define MAX_LZW_BITS	12					/* maximum GIF LZW codeSize */
87 #define MAX_BITS		13					/* maximum compress codeSize */
88 #define MAX_LZW_CODE	(1<<MAX_LZW_BITS)	/* maximum code GIF signal value */
89 #define MAX_CODE		(1<<MAX_BITS)		/* maximum code signal value */
90 #define FIRST			257					/* first free slot in compress */
91 #define CLEAR			256					/* compress clearcode signal */
92 
93 /****
94 * Note: we set the maximum bits available for compress to 13 instead of 12.
95 * This ensures that the compress code storage keeps in sync with the GIF LZW
96 * codes when the gif code size is less than 8. Using 12 bits for compress
97 * would overflow the compress tables before the GIF clearCode signal is
98 * received.
99 ****/
100 
101 /*** Private Function Prototype Declarations ****/
102 static int  LZWStreamUncompressData(LZWStream *lzw);
103 static void LZWStreamPackBits(LZWStream *lzw, int code);
104 static void LZWStreamConvertBelow8(LZWStream *lzw);
105 static void LZWStreamConvert8OrAbove(LZWStream *lzw);
106 
107 /****
108 * Two macros for buffered output; reduces the no of function calls.
109 * BUFFERSIZE determines the size of the output buffer and is defined in
110 * LZWStream.h (default is 512).
111 ****/
112 /* flush output buffer if it contains something */
113 #define flushBuf { if(lzw->acount > 0) \
114 		{ \
115 			fwrite(lzw->accum, (size_t)1, (size_t)lzw->acount, lzw->f); \
116 			lzw->acount = 0; \
117 		} \
118 }
119 
120 /* buffer output and flush when full */
121 #define charOut(C) { lzw->accum[lzw->acount++] = (unsigned char)C; \
122 	if(lzw->acount >= BUFFERSIZE-1) \
123 		flushBuf; \
124 }
125 
126 #define MAXCODE(n_bits) ((1L << (n_bits)) - 1)
127 
128 /*** Private Variable Declarations ***/
129 #ifdef DEBUG
130 static int bytes_out;
131 #endif
132 
133 static char msg_buf[1024];
134 static char *err_str = "LZWStream Error: ";
135 
136 /* bit packing masks */
137 static Byte lmask[9] = {0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00};
138 static Byte rmask[9] = {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
139 
140 /*****
141 * Name: 		LZWStreamGetCode MACRO
142 * Return Type: 	N/A
143 * Description: 	gets next code signal from the LZW stream
144 * In:
145 *	lzw:		current LZWStream
146 *	code:		value to update
147 * Returns:
148 *	N/A
149 * Note:
150 *	This is a macro instead of a function, since this is used for every
151 *	byte of data...
152 *****/
153 #define LZWStreamGetCode(lzw,code) do { \
154 	register int i, j; \
155 	code = 0; \
156 	if(lzw->error) \
157 	{ \
158 		lzw->error = 0; \
159 		code = lzw->clearCode; \
160 	} \
161 	else \
162 	{ \
163 		if((lzw->curBit + lzw->codeBits) >= lzw->lastBit) \
164 		{ \
165 			int count; \
166 			if(lzw->done) \
167 				code = -1; \
168 			else \
169 			{ \
170 				lzw->buf[0] = (int)((Byte)lzw->buf[lzw->lastByte-2]); \
171 				lzw->buf[1] = (int)((Byte)lzw->buf[lzw->lastByte-1]); \
172 				if((count = (int)lzw->getData(lzw->ib, \
173 					(Byte*)&(lzw->buf[2]))) == 0) \
174 					lzw->done = 1; \
175 				lzw->lastByte = 2 + count; \
176 				lzw->curBit = (lzw->curBit - lzw->lastBit) + 16; \
177 				lzw->lastBit = (2+count)*8 ; \
178 			} \
179 		} \
180 		if(code == 0) \
181 			for(i = lzw->curBit, j = 0; j < lzw->codeBits; ++i, ++j) \
182 				code |= (((int)((Byte)lzw->buf[i/8]) & (1<<(i%8)))!= 0)<<j; \
183 		lzw->curBit += lzw->codeBits; \
184 	} \
185 }while(0)
186 
187 /*****
188 * Name: 		LZWStreamUncompressData
189 * Return Type: 	int
190 * Description:  calls "uncompress" to uncompress the LZW-compressed GIF raster
191 *				data
192 * In:
193 *	lzw:		current LZWStream
194 * Returns:
195 *	True upon success, False on error.
196 *****/
197 static int
LZWStreamUncompressData(LZWStream * lzw)198 LZWStreamUncompressData(LZWStream *lzw)
199 {
200 	/* no error */
201 	lzw->err_msg = NULL;
202 
203 	if(lzw->zPipe == NULL)
204 	{
205 		/* flush output file */
206 		fflush(lzw->f);
207 
208 		/* call uncompress on our converted GIF lzw data */
209 		if(system(lzw->zCmd))
210 		{
211 			sprintf(msg_buf, "%sCouldn't exec '%s'.", err_str,
212 				lzw->zCmd);
213 			lzw->err_msg = msg_buf;
214 			unlink(lzw->zName);
215 			lzw->error = True;
216 			return(False);
217 		}
218 		/* open the output file */
219 		lzw->zName[strlen(lzw->zName) - 2] = '\0';
220 		if((lzw->zPipe = fopen(lzw->zName, "r")) == NULL)
221 		{
222 			sprintf(msg_buf, "%sCouldn't open uncompress file '%s'. "
223 				"Corrupt data?", err_str, lzw->zName);
224 			lzw->err_msg = msg_buf;
225 			unlink(lzw->zName);
226 			lzw->error = True;
227 			return(False);
228 		}
229 	}
230 	lzw->uncompressed = True;
231 	return(True);
232 }
233 
234 /*****
235 * Name: 		LZWStreamPackBits
236 * Return Type: 	void
237 * Description: 	buffers LZW codes and writes them out when the buffer is full.
238 * In:
239 *	lzw:		current LZWStream
240 *	code:		LZW code to be written.
241 * Returns:
242 *	nothing
243 * Note:
244 *	This routine is for gif images with less than 8 bits per pixel (= codeSize)
245 *	and packs the LZW codes the same way compress does. This is ABSOLUTELY
246 *	REQUIRED since compress only deals with codes between 8 and 15 bits.
247 *	This piece of code has been lifted almost literally from the public domain
248 *	compress.
249 *****/
250 static void
LZWStreamPackBits(LZWStream * lzw,int code)251 LZWStreamPackBits(LZWStream *lzw, int code)
252 {
253 	register int r_off = lzw->offset;	/* current offset in output buffer */
254 	register int bits = lzw->n_bits;	/* bits per pixel */
255 	register char *bp = lzw->outBuf;	/* ptr to current pos in buffer */
256 
257 #ifdef DEBUG
258     static int col = 0;
259 	if(lzw_debug == 2)
260 	    fprintf(stderr, "%5d%c", code,
261 		    (col+=6) >= 74 ? (col = 0, '\n') : ' ' );
262 #endif /* DEBUG */
263 
264 	if(code >= 0)
265 	{
266 		/* Get to the first byte. */
267 		bp += (r_off >> 3);
268 		r_off &= 7;
269 		/*
270 		* Since code is always >= 8 bits, only need to mask the first
271 		* hunk on the left.
272 		*/
273 		*bp = (*bp & rmask[r_off]) | ((code << r_off) & lmask[r_off]);
274 		bp++;
275 		bits -= (8 - r_off);
276 		code >>= 8 - r_off;
277 
278 		/* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
279 		if(bits >= 8)
280 		{
281 			*bp++ = code;
282 			code >>= 8;
283 			bits -= 8;
284 		}
285 		/* Last bits. */
286 		if(bits)
287 			*bp = code;
288 
289 		lzw->offset += lzw->n_bits;
290 		if(lzw->offset == (lzw->n_bits << 3))
291 		{
292 			bp = lzw->outBuf;
293 			bits = lzw->n_bits;
294 #ifdef DEBUG
295 			bytes_out += bits;
296 #endif
297 			do
298 			{
299 				charOut(*bp++);
300 			}
301 			while(--bits);
302 			lzw->offset = 0;
303 		}
304 
305 		/*
306 		* If the next entry is going to be too big for the code size,
307 		* then increase it, if possible.
308 		*/
309 		if(lzw->freeEntry > lzw->maxcode8 || lzw->clearFlag)
310 		{
311 			/* flush contents of output buffer */
312 			flushBuf;
313 
314 			/*
315 			* Write the whole buffer, because the input side won't
316 			* discover the size increase until after it has read it.
317 			*/
318 		    if(lzw->offset > 0)
319 			{
320 				fwrite(lzw->outBuf, 1, lzw->n_bits, lzw->f);
321 #ifdef DEBUG
322 				bytes_out += lzw->n_bits;
323 #endif
324 		    }
325 		    lzw->offset = 0;
326 
327 			if(lzw->clearFlag)
328 			{
329 				lzw->maxcode8 = MAXCODE(lzw->n_bits = INIT_BITS);
330 				lzw->clearFlag = False;
331 			}
332 			else
333 			{
334 				lzw->n_bits++;
335 				if (lzw->n_bits == MAX_BITS)
336 					lzw->maxcode8 = MAX_CODE;
337 				else
338 					lzw->maxcode8 = MAXCODE(lzw->n_bits);
339 			}
340 #ifdef DEBUG
341 			if(lzw_debug == 2)
342 			{
343 				fprintf(stderr, "\nChange to %d bits\n", lzw->n_bits );
344 				col = 0;
345 			}
346 #endif /* DEBUG */
347 		}
348 	}
349 	/* flush rest of buffer at EOF */
350 	else
351 	{
352 		/* flush contents of output buffer */
353 		flushBuf;
354 
355 #ifdef DEBUG
356 		if(lzw_debug == 2)
357 		    fprintf(stderr, "\n" );
358 #endif /* DEBUG */
359 		if(lzw->offset > 0)
360 		{
361 			/* flush out remaining chars */
362 			fwrite(lzw->outBuf, 1, (lzw->offset+7)/8, lzw->f);
363 
364 #ifdef DEBUG
365 			bytes_out += (lzw->offset + 7)/8;
366 #endif
367 			lzw->offset = 0;
368 			fflush(lzw->f);
369 		}
370 	}
371 }
372 
373 /*****
374 * Name: 		LZWStreamConvertBelow8
375 * Return Type: 	void
376 * Description: 	converts the GIF LZW compressed raster data to the compress
377 *				compressed data format. codeSize < 8
378 * In:
379 *	lzw:		current LZWStream object
380 * Returns:
381 *	nothing
382 *****/
383 static void
LZWStreamConvertBelow8(LZWStream * lzw)384 LZWStreamConvertBelow8(LZWStream *lzw)
385 {
386 	int inCode;	/* input code */
387 	Boolean eod = False;	/* set when end-of-data is reached */
388 	Boolean first;			/* indicates first code word after clear */
389 	int offset;
390 
391 #ifdef DEBUG
392 	bytes_out = 3;	/* includes 3-byte header mojo */
393 #endif
394 
395 	/* clear table */
396 	first = True;
397 	offset = 255 - lzw->clearCode;
398 	lzw->error = True;			/* skips first clearCode in raster data */
399 	lzw->nextCode = lzw->maxCode;
400 	lzw->freeEntry = FIRST;
401 
402 	/*
403 	* mimic compress behaviour but get LZW code instead of computing it.
404 	* GIF LZW code needs to be corrected to match fixed compress codes so we
405 	* can properly reset the tables if required. We also must keep track of
406 	* the LZW codesize since it influences the values of the LZW codes.
407 	*/
408 	while(!eod)
409 	{
410 		LZWStreamGetCode(lzw,inCode);
411 		if(inCode == -1)
412 			break;
413 		/*****
414 		* First part: verify and adjust GIF LZW code signal.
415 		*****/
416 
417 		/*
418 		* clearCode sets everything back to their initial values and then
419 		* reads the next code.
420 		*/
421 		if(inCode == lzw->clearCode)
422 		{
423 			/* reset code table */
424 			lzw->codeBits    = lzw->codeSize + 1;
425 			lzw->clearCode   = 1 << lzw->codeSize;
426 			lzw->endCode     = lzw->clearCode + 1;
427 			lzw->maxCodeSize = 2*lzw->clearCode;
428 			lzw->maxCode     = lzw->clearCode + 2;
429 			lzw->nextCode    = lzw->maxCode - 1;
430 			offset = 255 - lzw->clearCode;
431 
432 			/* keep output side in sync */
433 			if(first)
434 				first = False;
435 			else
436 			{
437 				lzw->freeEntry = FIRST;
438 				lzw->clearFlag = True;
439 				LZWStreamPackBits(lzw, CLEAR);
440 #ifdef DEBUG
441 				if(lzw_debug == 2)
442 					fprintf(stderr, "clear\n");
443 #endif /* DEBUG */
444 			}
445 			/* get next code */
446 			do
447 			{
448 				LZWStreamGetCode(lzw, inCode);
449 				if (inCode == -1)
450 				{
451 					/* end-of-data, break out of it */
452 					eod = True;
453 					inCode = lzw->endCode;
454 					break;
455 				}
456 			}while(inCode == lzw->clearCode);
457 		}
458 
459 		/* End-of-data, compress doesn't have this , so just break */
460 		if(inCode == lzw->endCode)
461 		{
462 			eod = True;
463 			break;
464 		}
465 		/*
466 		* Check input code size and adjust if the next code would overflow
467 		* the LZW tables. Compressed GIF raster data uses a range starting
468 		* at codeSize + 1 up to 12 bits per code.
469 		*/
470 		if((++lzw->nextCode >= lzw->maxCodeSize) &&
471 			(lzw->maxCodeSize < MAX_LZW_CODE))
472 		{
473 			lzw->maxCodeSize *= 2;
474 			lzw->codeBits++;
475 		}
476 
477 		/*****
478 		* Second part: write corrected LZW code
479 		*
480 		* write output block: the output buffer contains a series of bytes
481 		* with lengths anywhere between 3 and 12. Compress can only handle
482 		* codeSize 8 or up, anything below must be packed according to the
483 		* format compress expects.
484 		* This was the most difficult part to figure out, but its as simple
485 		* as this: the GIF lzw codes are just increased with the difference
486 		* of compress clearCode (fixed value of 256) and the current GIF
487 		* clearCode...
488 		*****/
489 
490 		/* correct and flush */
491 		LZWStreamPackBits(lzw,
492 			inCode < lzw->clearCode ? inCode : inCode + offset);
493 
494 		if(lzw->freeEntry < MAX_CODE)
495 			lzw->freeEntry++;
496 	}
497 	/* flush output buffer */
498 	LZWStreamPackBits(lzw, -1);
499 
500 	/* and close output file */
501 	fflush(lzw->f);
502 	fclose(lzw->f);
503 	lzw->f = NULL;
504 }
505 
506 /*****
507 * Name: 		LZWStreamConvert8OrAbove
508 * Return Type: 	void
509 * Description: 	converts the GIF LZW compressed raster data to the compress
510 *				compressed data format. codeSize >= 8
511 * In:
512 *	lzw:		current LZWStream object
513 * Returns:
514 *	nothing
515 *****/
516 static void
LZWStreamConvert8OrAbove(LZWStream * lzw)517 LZWStreamConvert8OrAbove(LZWStream *lzw)
518 {
519 	int outBuf[8];
520 	int inCode, outCode;	/* input and output codes */
521 	int outCodeBits;		/* size of output code */
522 	int maxOutSize;			/* maximum output signal */
523 	Boolean eod = False;	/* set when end-of-data is reached */
524 	Boolean clear;			/* set if table needs to be cleared */
525 	Boolean first;			/* indicates first code word after clear */
526 	int i, j;
527 	int outData, outBits;
528 
529 #ifdef DEBUG
530 	bytes_out = 3;	/* includes 3-byte header mojo */
531 #endif
532 
533 	/* init output side */
534 	outCodeBits = lzw->codeBits;
535 	maxOutSize  = 2*lzw->clearCode;
536 
537 	/* clear table */
538 	first = True;
539 	lzw->error = True;		/* skips first clearCode in raster data */
540 	lzw->nextCode = lzw->maxCode - 1;
541 	clear = False;
542 
543 	do
544 	{
545 		/* create output buffer */
546 		for (i = 0; i < 8; ++i)
547 		{
548 			/* check for table overflow */
549 			if(lzw->nextCode + 1 > 0x1001)
550 			{
551 				/* clear string table */
552 				inCode = 256;
553 			}
554 			/* read input code */
555 			else
556 			{
557 				do
558 				{
559 					LZWStreamGetCode(lzw, inCode);
560 					if (inCode == -1)
561 					{
562 						eod = True;
563 						inCode = 0;
564 					}
565 				}while (first && inCode == lzw->clearCode);
566 				first = False;
567 			}
568 
569 			/*
570 			* code signal less than clear code signal: compressed data,
571 			* store it.
572 			*/
573 			if (inCode < lzw->clearCode)
574 			{
575 				outCode = inCode;
576 			}
577 			/*
578 			* code signal equals clear code. Set flag so string table will
579 			* be cleared. GIF clearCode signal value is dynamic, whereas
580 			* compress uses a fixed value of 256.
581 			*/
582 			else if (inCode == lzw->clearCode)
583 			{
584 				outCode = 256;
585 				clear = True;
586 				first = False;
587 			}
588 			/*
589 			* end code signal. Compress does not have this signal so just set
590 			* the end-of-data flag.
591 			*/
592 			else if (inCode == lzw->endCode)
593 			{
594 				outCode = 0;
595 				eod = True;
596 			}
597 			else
598 				/*
599 				* code signal higher than end code signal: compressed data,
600 				* store it.
601 				*/
602 				outCode = inCode - 1;
603 
604 			outBuf[i] = outCode;
605 
606 			/*
607 			* check input code size. Compressed GIF raster data uses a range
608 			* starting at codeSize + 1 up to 12 bits per code.
609 			*/
610 			if((++lzw->nextCode >= lzw->maxCodeSize) &&
611 				(lzw->maxCodeSize < MAX_LZW_CODE))
612 			{
613 				lzw->maxCodeSize *= 2;
614 				++lzw->codeBits;
615 			}
616 
617 			/* check for eod/clear */
618 			if (eod)
619 			{
620 				break;
621 			}
622 			if(clear)
623 			{
624 				i = 8;
625 				break;
626 			}
627 		}
628 
629 		/*
630 		* write output block: the output buffer contains a series of bytes
631 		* with lengths anywhere between 8 and 12. The output buffer is just
632 		* packed in the same way an LZW gif *writer* does it.
633 		*/
634 		outBits = 0;	/* max output code */
635 		outData = 0;	/* temporary output buffer */
636 		j = 0;
637 		while(j < i || outBits > 0)
638 		{
639 			/* package all codes */
640 			if(outBits < 8 && j < i)
641 			{
642 				outData = outData | (outBuf[j++] << outBits);
643 				outBits += outCodeBits;
644 			}
645 			charOut(outData & 0xff);
646 			outData >>= 8;
647 			outBits -= 8;
648 		}
649 
650 #ifdef DEBUG
651 		bytes_out += outCodeBits;
652 #endif
653 		if(lzw->nextCode - 1 == maxOutSize)
654 		{
655 			outCodeBits = lzw->codeBits;
656 			maxOutSize *= 2;
657 		}
658 
659 		/* clear table if necessary */
660 		if(clear)
661 		{
662 			lzw->codeBits    = lzw->codeSize + 1;
663 			lzw->clearCode   = 1 << lzw->codeSize;
664 			lzw->endCode     = lzw->clearCode + 1;
665 			lzw->maxCodeSize = 2*lzw->clearCode;
666 			lzw->maxCode     = lzw->clearCode + 2;
667 			lzw->nextCode    = lzw->maxCode - 1;
668 			maxOutSize       = 2*lzw->clearCode;
669 			outCodeBits      = lzw->codeBits;
670 			clear = False;
671 		}
672 	}while (!eod);
673 
674 	/* flush any chars left */
675 	flushBuf;
676 
677 	/* and close output file */
678 	fflush(lzw->f);
679 	fclose(lzw->f);
680 	lzw->f = NULL;
681 }
682 
683 /*******
684 *** Public Functions
685 *******/
686 
687 /*****
688 * Name: 		LZWStreamConvert
689 * Return Type: 	void
690 * Description: 	LZW decoder driver
691 * In:
692 *	lzw:		current LZWStream
693 * Returns:
694 *	nothing
695 *****/
696 void
LZWStreamConvert(LZWStream * lzw)697 LZWStreamConvert(LZWStream *lzw)
698 {
699 	if(lzw->codeSize >= 8)
700 		LZWStreamConvert8OrAbove(lzw);
701 	else
702 		LZWStreamConvertBelow8(lzw);
703 }
704 
705 /*****
706 * Name: 		LZWStreamInit
707 * Return Type: 	int
708 * Description: 	initializes the given stream
709 * In:
710 *	lzw:		current LZWStream
711 * Returns:
712 *	0 when codeSize is wrong, -1 when no temporary file could be created,
713 *	1 otherwise.
714 *****/
715 int
LZWStreamInit(LZWStream * lzw)716 LZWStreamInit(LZWStream *lzw)
717 {
718 	Byte c;
719 	int i;
720 
721 #ifdef DEBUG
722 	char *chPtr = getenv("LZW_DEBUG");
723 
724 	if(chPtr == '1')
725 		lzw_debug = 1;
726 	else if(chPtr == '2')
727 		lzw_debug = 2;
728 #endif
729 	/* no error */
730 	lzw->err_msg = NULL;
731 
732 	/* check if we have the read functions */
733 	if(lzw->readOK == NULL || lzw->getData == NULL)
734 	{
735 		sprintf(msg_buf, "%sno read functions attached!", err_str);
736 		lzw->err_msg = msg_buf;
737 		return(-2);
738 	}
739 
740 	/* init input side */
741 	lzw->done = 0;
742 	lzw->curBit = 0;
743 	lzw->lastBit = 0;
744 	lzw->lastByte = 2;
745 
746 	for(i = 0; i < 280; i++)
747 		lzw->buf[i] = 0;
748 	for(i = 0; i < 16; i++)
749 		lzw->outBuf[i] = 0;
750 
751 	/* initialize buffered output */
752 	memset(lzw->accum, '\0', BUFFERSIZE);
753 	lzw->acount = 0;
754 
755 	/* close any open files */
756 	if(lzw->zPipe)
757 	{
758 		fclose(lzw->zPipe);
759 		lzw->zPipe = NULL;
760 	}
761 	if(lzw->f)
762 	{
763 		fclose(lzw->f);
764 		lzw->f = NULL;
765 		unlink(lzw->zName);
766 	}
767 
768 	/* no data to uncompress yet */
769 	lzw->error = False;
770 	lzw->uncompressed = False;
771 
772 	/* temporary output file */
773 	tmpnam(lzw->zName);
774 	strcat(lzw->zName, ".Z");
775 
776 	/* open it */
777 	if(!(lzw->f = fopen(lzw->zName, "w")))
778 	{
779 		sprintf(msg_buf, "%scouldn't open temporary file '%s'.",
780 			err_str, lzw->zName);
781 		lzw->err_msg = msg_buf;
782 		return(-1);
783 	}
784 
785 	/*
786 	* get codeSize (= how many bits each pixel takes) from ImageBuffer.
787 	*/
788 	if((lzw->readOK(lzw->ib, &c, 1)) == 0)
789 	{
790 		sprintf(msg_buf, "%scouldn't read GIF codesize.", err_str);
791 		lzw->err_msg = msg_buf;
792 		return(0);
793 	}
794 
795 	/* GIF lzw codes */
796 	lzw->codeSize = (int)((Byte)c);	/* initial bits per pixel */
797 
798 	/* initialize input side */
799 	lzw->codeBits    = lzw->codeSize + 1;
800 	lzw->clearCode   = 1 << lzw->codeSize;
801 	lzw->endCode     = lzw->clearCode + 1;
802 	lzw->maxCodeSize = 2*lzw->clearCode;
803 	lzw->maxCode     = lzw->clearCode + 2;
804 	lzw->nextCode    = lzw->maxCode;
805 
806 	/* initialize codeSize < 8 output side */
807 	lzw->offset    = 0;
808 	lzw->clearFlag = False;
809 	lzw->n_bits    = INIT_BITS;
810 	lzw->maxcode8  = MAXCODE(lzw->n_bits);
811 	lzw->freeEntry = FIRST;
812 
813 	/* check clearCode value */
814 	if(lzw->clearCode >= MAX_LZW_CODE)
815 	{
816 		sprintf(msg_buf, "%scorrupt raster data: bad GIF codesize (%i).",
817 			err_str, lzw->codeSize);
818 		lzw->err_msg = msg_buf;
819 		return(0);
820 	}
821 
822 	/* Write compress header */
823 	charOut(0x1f);
824 	charOut(0x9d);
825 
826 	/* gif max code length + 1, block mode flag */
827 	charOut((MAX_BITS & 0x1f) | 0x80);
828 
829 	return(1);
830 }
831 
832 /*****
833 * Name: 		LZWStreamCreate
834 * Return Type: 	LZWStream
835 * Description: 	allocates a new stream
836 * In:
837 *	ib:			data input buffer
838 * Returns:
839 *	a newly created stream object.
840 *****/
841 LZWStream*
LZWStreamCreate(ImageBuffer * ib,char * zCmd)842 LZWStreamCreate(ImageBuffer *ib, char *zCmd)
843 {
844 	static LZWStream *lzw;
845 
846 	/* create a new stream */
847 	if((lzw = (LZWStream*)calloc(1, sizeof(LZWStream))) == NULL)
848 		return(NULL);
849 
850 	/* store ptr to input buffer */
851 	lzw->ib = ib;
852 
853 	/* create uncompress command */
854 	strcpy(lzw->zCmd, zCmd != NULL ? zCmd : "uncompress");
855 	strcat(lzw->zCmd, "  ");
856 
857 	/* offset for temporary file in which compressed data is to be stored */
858 	lzw->zName = lzw->zCmd + strlen(lzw->zCmd);
859 
860 	/* no default readOK and getData, they need to be set by caller */
861 
862 	/* and return the new stream */
863 	return(lzw);
864 }
865 
866 /*****
867 * Name: 		LZWStreamDestroy
868 * Return Type: 	void
869 * Description: 	destroys the given LZW stream
870 * In:
871 *	lzw:		LZWStream to destroy
872 * Returns:
873 *	nothing.
874 *****/
875 void
LZWStreamDestroy(LZWStream * lzw)876 LZWStreamDestroy(LZWStream *lzw)
877 {
878 	if(lzw == NULL)
879 		return;
880 
881 	if(lzw->zPipe)
882 		fclose(lzw->zPipe);
883 	if(lzw->f)
884 		fclose(lzw->f);
885 	unlink(lzw->zName);
886 	free(lzw);
887 }
888 
889 /*****
890 * Name: 		LZWStreamFillBuffer
891 * Return Type: 	int
892 * Description:	read uncompressed data from the stream
893 * In:
894 *	lzw:		current LZWStream object
895 *	data:		output buffer
896 *	size:		size of output buffer
897 * Returns:
898 *	no of chars read from stream
899 *****/
900 int
LZWStreamFillBuffer(LZWStream * lzw,unsigned char * data,int size)901 LZWStreamFillBuffer(LZWStream *lzw, unsigned char *data, int size)
902 {
903 	int n;
904 
905 	if(lzw->error)
906 		return(0);
907 
908 	/* uncompress data if not yet done */
909 	if(!lzw->uncompressed || lzw->zPipe == NULL)
910 	{
911 		if(!(LZWStreamUncompressData(lzw)))
912 			return(0);
913 	}
914 	n = fread(data, 1, size, lzw->zPipe);
915 	return(n);
916 }
917 
918 /*****
919 * Name: 		LZWStreamUncompress
920 * Return Type: 	unsigned char *
921 * Description:	return an allocated buffer with uncompressed stream data
922 * In:
923 *	lzw:		current LZWStream
924 *	size:		size of data read, filled upon return.
925 * Returns:
926 *	An allocated buffer when succesfully uncompressed and size is updated to
927 *	contain the no of characters read. Upon error, NULL is returned and size
928 *	is set to 0.
929 *****/
930 unsigned char *
LZWStreamUncompress(LZWStream * lzw,int * size)931 LZWStreamUncompress(LZWStream *lzw, int *size)
932 {
933 	static unsigned char *data;
934 
935 	*size = 0;
936 
937 	if(lzw->error)
938 		return(NULL);
939 
940 	/* no error */
941 	lzw->err_msg = NULL;
942 
943 	/* uncompress data if not yet done */
944 	if(!lzw->uncompressed || lzw->zPipe == NULL)
945 	{
946 		if(!(LZWStreamUncompressData(lzw)))
947 			return(NULL);
948 	}
949 
950 	fseek(lzw->zPipe, 0L, SEEK_END);
951 	*size = ftell(lzw->zPipe);
952 
953 	/* sanity check */
954 	if(*size == 0)
955 	{
956 		sprintf(msg_buf, "%szero-length data file.", err_str);
957 		lzw->err_msg = msg_buf;
958 		return(NULL);
959 	}
960 
961 	rewind(lzw->zPipe);
962 
963 	data = (unsigned char*)malloc(*size*sizeof(unsigned char));
964 
965 	/* read it all */
966 	(void)fread(data, *size, 1, lzw->zPipe);
967 
968 	/* close and remove file */
969 	if(lzw->zPipe)
970 	{
971 		fclose(lzw->zPipe);
972 		lzw->zPipe = NULL;
973 	}
974 	if(lzw->f)
975 	{
976 		fclose(lzw->f);
977 		lzw->f = NULL;
978 		unlink(lzw->zName);
979 	}
980 	/* and return it */
981 	return(data);
982 }
983 
984 int
LZWStreamGetCodeSize(LZWStream * lzw)985 LZWStreamGetCodeSize(LZWStream *lzw)
986 {
987 	return(lzw->codeSize);
988 }
989