mirror of
				https://github.com/python-pillow/Pillow.git
				synced 2025-11-04 09:57:43 +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;
 | 
						|
}
 |