123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 |
- /*
- * 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, Py_ssize_t 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 (https://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!
- (https://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;
- }
|