Pillow/libImaging/PcxEncode.c

149 lines
3.6 KiB
C
Raw Normal View History

2010-07-31 06:52:47 +04:00
/*
* The Python Imaging Library.
* $Id$
*
* 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;
}
}