mirror of
				https://github.com/python-pillow/Pillow.git
				synced 2025-11-04 01:47:47 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			147 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			147 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * THIS IS WORK IN PROGRESS
 | 
						|
 *
 | 
						|
 * The Python Imaging Library.
 | 
						|
 * $Id$
 | 
						|
 *
 | 
						|
 * decoder for SUN RLE data.
 | 
						|
 *
 | 
						|
 * history:
 | 
						|
 *      97-01-04 fl     Created
 | 
						|
 *
 | 
						|
 * Copyright (c) Fredrik Lundh 1997.
 | 
						|
 * Copyright (c) Secret Labs AB 1997.
 | 
						|
 *
 | 
						|
 * See the README file for information on usage and redistribution.
 | 
						|
 */
 | 
						|
 | 
						|
 | 
						|
#include "Imaging.h"
 | 
						|
 | 
						|
 | 
						|
int
 | 
						|
ImagingSunRleDecode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
 | 
						|
{
 | 
						|
    int n;
 | 
						|
    UINT8* ptr;
 | 
						|
    UINT8 extra_data = 0;
 | 
						|
    UINT8 extra_bytes = 0;
 | 
						|
 | 
						|
    ptr = buf;
 | 
						|
 | 
						|
    for (;;) {
 | 
						|
 | 
						|
        if (bytes < 1)
 | 
						|
            return ptr - buf;
 | 
						|
 | 
						|
        if (ptr[0] == 0x80) {
 | 
						|
 | 
						|
            if (bytes < 2)
 | 
						|
                break;
 | 
						|
 | 
						|
            n = ptr[1];
 | 
						|
 | 
						|
 | 
						|
            if (n == 0) {
 | 
						|
 | 
						|
                /* Literal 0x80 (2 bytes) */
 | 
						|
                n = 1;
 | 
						|
 | 
						|
                state->buffer[state->x] = 0x80;
 | 
						|
 | 
						|
                ptr += 2;
 | 
						|
                bytes -= 2;
 | 
						|
 | 
						|
            } else {
 | 
						|
 | 
						|
                /* Run (3 bytes) */
 | 
						|
                if (bytes < 3)
 | 
						|
                    break;
 | 
						|
 | 
						|
                /* from (http://www.fileformat.info/format/sunraster/egff.htm)
 | 
						|
 | 
						|
                   For example, a run of 100 pixels with the value of
 | 
						|
                   0Ah would encode as the values 80h 64h 0Ah. A
 | 
						|
                   single pixel value of 80h would encode as the
 | 
						|
                   values 80h 00h. The four unencoded bytes 12345678h
 | 
						|
                   would be stored in the RLE stream as 12h 34h 56h
 | 
						|
                   78h.  100 pixels, n=100, not 100 pixels, n=99.
 | 
						|
 | 
						|
                   But Wait! There's More! 
 | 
						|
                   (http://www.fileformat.info/format/sunraster/spec/598a59c4fac64c52897585d390d86360/view.htm)
 | 
						|
 | 
						|
                   If the first byte is 0x80, and the second byte is
 | 
						|
                   not zero, the record is three bytes long. The
 | 
						|
                   second byte is a count and the third byte is a
 | 
						|
                   value. Output (count+1) pixels of that value.
 | 
						|
 | 
						|
                   2 specs, same site, but Imagemagick and GIMP seem
 | 
						|
                   to agree on the second one.
 | 
						|
                */
 | 
						|
                n += 1; 
 | 
						|
 | 
						|
                if (state->x + n > state->bytes) {
 | 
						|
                    extra_bytes = n;  /* full value */
 | 
						|
                    n = state->bytes - state->x;
 | 
						|
                    extra_bytes -= n;
 | 
						|
                    extra_data = ptr[2];
 | 
						|
                }
 | 
						|
 | 
						|
                memset(state->buffer + state->x, ptr[2], n);
 | 
						|
 | 
						|
                ptr += 3;
 | 
						|
                bytes -= 3;
 | 
						|
 | 
						|
            }
 | 
						|
 | 
						|
        } else {
 | 
						|
 | 
						|
            /* Literal byte */ 
 | 
						|
            n = 1; 
 | 
						|
 | 
						|
            state->buffer[state->x] = ptr[0];
 | 
						|
 | 
						|
            ptr += 1;
 | 
						|
            bytes -= 1;
 | 
						|
 | 
						|
        }
 | 
						|
 | 
						|
        for (;;) {
 | 
						|
            state->x += n;
 | 
						|
        
 | 
						|
            if (state->x >= state->bytes) {
 | 
						|
 | 
						|
                /* 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;
 | 
						|
                }
 | 
						|
            }
 | 
						|
            
 | 
						|
            if (extra_bytes == 0) {
 | 
						|
                break;
 | 
						|
            }
 | 
						|
 | 
						|
            if (state->x > 0) {
 | 
						|
                break; // assert
 | 
						|
            }
 | 
						|
 | 
						|
            if (extra_bytes >= state->bytes) {
 | 
						|
                n = state->bytes;
 | 
						|
            } else {
 | 
						|
                n = extra_bytes;
 | 
						|
            }
 | 
						|
            memset(state->buffer + state->x, extra_data, n);
 | 
						|
            extra_bytes -= n;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    return ptr - buf;
 | 
						|
}
 |