Pillow
188 строк · 6.0 Кб
1/*
2* The Python Imaging Library.
3* $Id$
4*
5* encoder for PCX data
6*
7* history:
8* 99-02-07 fl created
9*
10* Copyright (c) Fredrik Lundh 1999.
11* Copyright (c) Secret Labs AB 1999.
12*
13* See the README file for information on usage and redistribution.
14*/
15
16#include "Imaging.h"17
18enum { INIT, FETCH, ENCODE };19
20/* we're reusing "ystep" to store the last value */
21#define LAST ystep22
23int
24ImagingPcxEncode(Imaging im, ImagingCodecState state, UINT8 *buf, int bytes) {25UINT8 *ptr;26int this;27int bytes_per_line = 0;28int padding = 0;29int stride = 0;30int bpp = 0;31int planes = 1;32int i;33
34ptr = buf;35
36if (!state->state) {37/* sanity check */38if (state->xsize <= 0 || state->ysize <= 0) {39state->errcode = IMAGING_CODEC_END;40return 0;41}42state->state = FETCH;43}44
45bpp = state->bits;46if (state->bits == 24) {47planes = 3;48bpp = 8;49}50
51bytes_per_line = (state->xsize * bpp + 7) / 8;52/* The stride here needs to be kept in sync with the version in53PcxImagePlugin.py. If it's not, the header and the body of the
54image will be out of sync and bad things will happen on decode.
55*/
56stride = bytes_per_line + (bytes_per_line % 2);57
58padding = stride - bytes_per_line;59
60for (;;) {61switch (state->state) {62case FETCH:63
64/* get a line of data */65if (state->y >= state->ysize) {66state->errcode = IMAGING_CODEC_END;67return ptr - buf;68}69
70state->shuffle(71state->buffer,72(UINT8 *)im->image[state->y + state->yoff] +73state->xoff * im->pixelsize,74state->xsize75);76
77state->y += 1;78
79state->count = 1;80state->LAST = state->buffer[0];81
82state->x = 1;83
84state->state = ENCODE;85/* fall through */86
87case ENCODE:88/* compress this line */89
90/* when we arrive here, "count" contains the number of91bytes having the value of "LAST" that we've already
92seen */
93do {94/* If we're encoding an odd width file, and we've95got more than one plane, we need to pad each
96color row with padding bytes at the end. Since
97The pixels are stored RRRRRGGGGGBBBBB, so we need
98to have the padding be RRRRRPGGGGGPBBBBBP. Hence
99the double loop
100*/
101while (state->x % bytes_per_line) {102if (state->count == 63) {103/* this run is full; flush it */104if (bytes < 2) {105return ptr - buf;106}107ptr[0] = 0xff;108ptr[1] = state->LAST;109ptr += 2;110bytes -= 2;111
112state->count = 0;113}114
115this = state->buffer[state->x];116
117if (this == state->LAST) {118/* extend the current run */119state->x += 1;120state->count += 1;121
122} else {123/* start a new run */124if (state->count == 1 && (state->LAST < 0xc0)) {125if (bytes < 1) {126return ptr - buf;127}128ptr[0] = state->LAST;129ptr += 1;130bytes -= 1;131} else {132if (state->count > 0) {133if (bytes < 2) {134return ptr - buf;135}136ptr[0] = 0xc0 | state->count;137ptr[1] = state->LAST;138ptr += 2;139bytes -= 2;140}141}142
143state->LAST = this;144state->count = 1;145
146state->x += 1;147}148}149
150/* end of line; flush the current run */151if (state->count == 1 && (state->LAST < 0xc0)) {152if (bytes < 1 + padding) {153return ptr - buf;154}155ptr[0] = state->LAST;156ptr += 1;157bytes -= 1;158} else {159if (state->count > 0) {160if (bytes < 2 + padding) {161return ptr - buf;162}163ptr[0] = 0xc0 | state->count;164ptr[1] = state->LAST;165ptr += 2;166bytes -= 2;167}168}169/* add the padding */170for (i = 0; i < padding; i++) {171ptr[0] = 0;172ptr += 1;173bytes -= 1;174}175/* reset for the next color plane. */176if (state->x < planes * bytes_per_line) {177state->count = 1;178state->LAST = state->buffer[state->x];179state->x += 1;180}181} while (state->x < planes * bytes_per_line);182
183/* read next line */184state->state = FETCH;185break;186}187}188}
189