diff options
Diffstat (limited to 'Imaging/libImaging/PcxEncode.c')
-rw-r--r-- | Imaging/libImaging/PcxEncode.c | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/Imaging/libImaging/PcxEncode.c b/Imaging/libImaging/PcxEncode.c new file mode 100644 index 0000000..2c9d250 --- /dev/null +++ b/Imaging/libImaging/PcxEncode.c @@ -0,0 +1,148 @@ +/* + * The Python Imaging Library. + * $Id: PcxEncode.c 2134 2004-10-06 08:55:20Z fredrik $ + * + * encoder for PCX data + * + * history: + * 99-02-07 fl created + * + * Copyright (c) Fredrik Lundh 1999. + * Copyright (c) Secret Labs AB 1999. + * + * See the README file for information on usage and redistribution. + */ + + +#include "Imaging.h" + +enum { INIT, FETCH, ENCODE }; + +/* we're reusing "ystep" to store the last value */ +#define LAST ystep + +int +ImagingPcxEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) +{ + UINT8* ptr; + int this; + + ptr = buf; + + if (!state->state) { + + /* sanity check */ + if (state->xsize <= 0 || state->ysize <= 0) { + state->errcode = IMAGING_CODEC_END; + return 0; + } + + state->bytes = (state->xsize*state->bits + 7) / 8; + state->state = FETCH; + + } + + for (;;) + + switch (state->state) { + case FETCH: + + /* get a line of data */ + if (state->y >= state->ysize) { + state->errcode = IMAGING_CODEC_END; + return ptr - buf; + } + + state->shuffle(state->buffer, + (UINT8*) im->image[state->y + state->yoff] + + state->xoff * im->pixelsize, state->xsize); + + state->y++; + + state->count = 1; + state->LAST = state->buffer[0]; + + state->x = 1; + + state->state = ENCODE; + /* fall through */ + + case ENCODE: + + /* compress this line */ + + /* when we arrive here, "count" contains the number of + bytes having the value of "LAST" that we've already + seen */ + + while (state->x < state->bytes) { + + if (state->count == 63) { + + /* this run is full; flush it */ + if (bytes < 2) + return ptr - buf; + *ptr++ = 0xff; + *ptr++ = state->LAST; + bytes -= 2; + + state->count = 0; + + } + + this = state->buffer[state->x]; + + if (this == state->LAST) { + + /* extend the current run */ + state->x++; + state->count++; + + } else { + + /* start a new run */ + if (state->count == 1 && (state->LAST < 0xc0)) { + if (bytes < 1) + return ptr - buf; + *ptr++ = state->LAST; + bytes--; + } else { + if (state->count > 0) { + if (bytes < 2) + return ptr - buf; + *ptr++ = 0xc0 | state->count; + *ptr++ = state->LAST; + bytes -= 2; + } + } + + state->LAST = this; + state->count = 1; + + state->x++; + + } + } + + /* end of line; flush the current run */ + if (state->count == 1 && (state->LAST < 0xc0)) { + if (bytes < 1) + return ptr - buf; + *ptr++ = state->LAST; + bytes--; + } else { + if (state->count > 0) { + if (bytes < 2) + return ptr - buf; + *ptr++ = 0xc0 | state->count; + *ptr++ = state->LAST; + bytes -= 2; + } + } + + /* read next line */ + state->state = FETCH; + break; + + } +} |