mirror of
https://github.com/python-pillow/Pillow.git
synced 2024-12-25 17:36:18 +03:00
149 lines
3.6 KiB
C
149 lines
3.6 KiB
C
/*
|
|
* 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;
|
|
|
|
}
|
|
}
|