mirror of
				https://github.com/python-pillow/Pillow.git
				synced 2025-10-25 05:01:26 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			231 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			231 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * The Python Imaging Library.
 | |
|  * $Id$
 | |
|  *
 | |
|  * a fast, suspendable TIFF LZW decoder
 | |
|  *
 | |
|  * description:
 | |
|  *	This code is based on the GIF decoder.  There are some
 | |
|  *	subtle differences between GIF and TIFF LZW, though:
 | |
|  *	- The fill order is different. In the TIFF file, you
 | |
|  *	  must shift new bits in to the right, not to the left.
 | |
|  *	- There is no blocking in the input data stream.
 | |
|  *	- The code size is increased one step earlier than
 | |
|  *	  for GIF
 | |
|  *	- Image data are seen as a byte stream, not a pixel
 | |
|  *	  stream. This means that the code size will always
 | |
|  *	  start at 9 bits.
 | |
|  *
 | |
|  * history:
 | |
|  *	95-09-13 fl	Created (derived from GifDecode.c)
 | |
|  *	96-03-28 fl	Revised API, integrated with PIL
 | |
|  *	97-01-05 fl	Added filter support, added extra consistency checks
 | |
|  *
 | |
|  * Copyright (c) Fredrik Lundh 1995-97.
 | |
|  * Copyright (c) Secret Labs AB 1997.
 | |
|  *
 | |
|  * See the README file for information on usage and redistribution.
 | |
|  */
 | |
| 
 | |
| 
 | |
| #include "Imaging.h"
 | |
| 
 | |
| #include <stdio.h>
 | |
| #include <stdlib.h>	/* memcpy() */
 | |
| 
 | |
| #include "Lzw.h"
 | |
| 
 | |
| 
 | |
| int
 | |
| ImagingLzwDecode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
 | |
| {
 | |
|     UINT8* p;
 | |
|     int c, i;
 | |
|     int thiscode;
 | |
|     LZWSTATE* context = (LZWSTATE*) state->context;
 | |
| 
 | |
|     unsigned char *ptr = buf;
 | |
| 
 | |
|     if (!state->state) {
 | |
| 
 | |
| 	/* Clear code */
 | |
| 	context->clear = 1 << 8;
 | |
| 
 | |
| 	/* End code */
 | |
| 	context->end = context->clear + 1;
 | |
| 
 | |
| 	state->state = 1;
 | |
|     }
 | |
| 
 | |
|     for (;;) {
 | |
| 
 | |
| 	if (state->state == 1) {
 | |
| 
 | |
| 	    /* First free entry in table */
 | |
| 	    context->next = context->clear + 2;
 | |
| 
 | |
| 	    /* Initial code size */
 | |
| 	    context->codesize = 8 + 1;
 | |
| 	    context->codemask = (1 << context->codesize) - 1;
 | |
| 
 | |
| 	    /* Buffer pointer.  We fill the buffer from right, which
 | |
| 	       allows us to return all of it in one operation. */
 | |
| 	    context->bufferindex = LZWBUFFER;
 | |
| 
 | |
| 	    state->state = 2;
 | |
| 	}
 | |
| 
 | |
| 	if (context->bufferindex < LZWBUFFER) {
 | |
| 
 | |
| 	    /* Return whole buffer in one chunk */
 | |
| 	    i = LZWBUFFER - context->bufferindex;
 | |
| 	    p = &context->buffer[context->bufferindex];
 | |
| 
 | |
| 	    context->bufferindex = LZWBUFFER;
 | |
| 
 | |
| 	} else {
 | |
| 
 | |
| 	    /* Get current symbol */
 | |
| 	    while (context->bitcount < context->codesize) {
 | |
| 
 | |
| 		if (bytes < 1)
 | |
| 		    return ptr - buf;;
 | |
| 
 | |
| 		/* Read next byte */
 | |
| 		c = *ptr++; bytes--;
 | |
| 
 | |
| 		/* New bits are shifted in from from the right. */
 | |
| 		context->bitbuffer = (context->bitbuffer << 8) | c;
 | |
| 		context->bitcount += 8;
 | |
| 
 | |
| 	    }
 | |
| 
 | |
| 	    /* Extract current symbol from bit buffer. */
 | |
| 	    c = (context->bitbuffer >> (context->bitcount -
 | |
| 					 context->codesize))
 | |
| 		& context->codemask;
 | |
| 
 | |
| 	    /* Adjust buffer */
 | |
| 	    context->bitcount -= context->codesize;
 | |
| 
 | |
| 	    /* If c is less than clear, it's a data byte.  Otherwise,
 | |
| 	       it's either clear/end or a code symbol which should be
 | |
| 	       expanded. */
 | |
| 
 | |
| 	    if (c == context->clear) {
 | |
| 		if (state->state != 2)
 | |
| 		    state->state = 1;
 | |
| 		continue;
 | |
| 	    }
 | |
| 
 | |
| 	    if (c == context->end)
 | |
| 		break;
 | |
| 
 | |
| 	    i = 1;
 | |
| 	    p = &context->lastdata;
 | |
| 
 | |
| 	    if (state->state == 2) {
 | |
| 
 | |
| 		/* First valid symbol after clear; use as is */
 | |
| 		if (c > context->clear) {
 | |
| 		    state->errcode = IMAGING_CODEC_BROKEN;
 | |
| 		    return -1;
 | |
| 		}
 | |
| 
 | |
| 		context->lastdata = context->lastcode = c;
 | |
| 		state->state = 3;
 | |
| 
 | |
| 	    } else {
 | |
| 
 | |
| 		thiscode = c;
 | |
| 
 | |
| 		if (c > context->next) {
 | |
| 		    state->errcode = IMAGING_CODEC_BROKEN;
 | |
| 		    return -1;
 | |
| 		}
 | |
| 
 | |
| 		if (c == context->next) {
 | |
| 
 | |
| 		    /* c == next is allowed, by some strange reason */
 | |
| 		    if (context->bufferindex <= 0) {
 | |
| 			state->errcode = IMAGING_CODEC_BROKEN;
 | |
| 			return -1;
 | |
| 		    }
 | |
| 
 | |
| 		    context->buffer[--context->bufferindex] = context->lastdata;
 | |
| 		    c = context->lastcode;
 | |
| 		}
 | |
| 
 | |
| 		while (c >= context->clear) {
 | |
| 
 | |
| 		    /* Copy data string to buffer (beginning from right) */
 | |
| 
 | |
| 		    if (context->bufferindex <= 0 || c >= LZWTABLE) {
 | |
| 			state->errcode = IMAGING_CODEC_BROKEN;
 | |
| 			return -1;
 | |
| 		    }
 | |
| 
 | |
| 		    context->buffer[--context->bufferindex] =
 | |
| 			context->data[c];
 | |
| 		    c = context->link[c];
 | |
| 		}
 | |
| 
 | |
| 		context->lastdata = c;
 | |
| 
 | |
| 		if (context->next < LZWTABLE) {
 | |
| 
 | |
| 		    /* While we still have room for it, add this
 | |
| 		       symbol to the table. */
 | |
| 		    context->data[context->next] = c;
 | |
| 		    context->link[context->next] = context->lastcode;
 | |
| 
 | |
| 		    context->next++;
 | |
| 
 | |
| 		    if (context->next == context->codemask &&
 | |
| 			context->codesize < LZWBITS) {
 | |
| 
 | |
| 			/* Expand code size */
 | |
| 			context->codesize++;
 | |
| 			context->codemask = (1 << context->codesize) - 1;
 | |
| 
 | |
| 		    }
 | |
| 		}
 | |
| 		context->lastcode = thiscode;
 | |
| 	    }
 | |
| 	}
 | |
| 
 | |
| 	/* Update the output image */
 | |
| 	for (c = 0; c < i; c++) {
 | |
| 
 | |
| 	    state->buffer[state->x] = p[c];
 | |
| 
 | |
| 	    if (++state->x >= state->bytes) {
 | |
| 
 | |
| 		int x, bpp;
 | |
| 
 | |
| 		/* Apply filter */
 | |
| 		switch (context->filter) {
 | |
| 		case 2:
 | |
| 		    /* Horizontal differing ("prior") */
 | |
| 		    bpp = (state->bits + 7) / 8;
 | |
| 		    for (x = bpp; x < state->bytes; x++)
 | |
| 			state->buffer[x] += state->buffer[x-bpp];
 | |
| 		}
 | |
| 
 | |
| 		/* Got a full line, unpack it */
 | |
| 		state->shuffle((UINT8*) im->image[state->y + state->yoff] +
 | |
| 			       state->xoff * im->pixelsize, state->buffer,
 | |
| 			       state->xsize);
 | |
| 
 | |
| 		state->x = 0;
 | |
| 
 | |
| 		if (++state->y >= state->ysize)
 | |
| 		    /* End of file (errcode = 0) */
 | |
| 		    return -1;
 | |
| 	    }
 | |
| 	}
 | |
|     }
 | |
| 
 | |
|     return ptr - buf;
 | |
| }
 |