mirror of
https://github.com/python-pillow/Pillow.git
synced 2024-12-25 01:16:16 +03:00
Use even stride when saving odd sized .pcx files
This commit is contained in:
parent
a3371ee9fe
commit
89cb3c7e85
|
@ -134,6 +134,16 @@ def _save(im, fp, filename, check=0):
|
|||
|
||||
# bytes per plane
|
||||
stride = (im.size[0] * bits + 7) // 8
|
||||
# stride should be even
|
||||
stride = stride + (stride % 2)
|
||||
# Stride needs to be kept in sync with the PcxEncode.c version.
|
||||
# Ideally it should be passed in in the state, but the bytes value
|
||||
# gets overwritten.
|
||||
|
||||
|
||||
if Image.DEBUG:
|
||||
print ("PcxImagePlugin._save: xwidth: %d, bits: %d, stride: %d" % (
|
||||
im.size[0], bits, stride))
|
||||
|
||||
# under windows, we could determine the current screen size with
|
||||
# "Image.core.display_mode()[1]", but I think that's overkill...
|
||||
|
|
|
@ -26,6 +26,12 @@ ImagingPcxEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
|
|||
{
|
||||
UINT8* ptr;
|
||||
int this;
|
||||
int bytes_per_line = 0;
|
||||
int padding = 0;
|
||||
int stride = 0;
|
||||
int bpp = 0;
|
||||
int planes = 1;
|
||||
int i;
|
||||
|
||||
ptr = buf;
|
||||
|
||||
|
@ -35,12 +41,25 @@ ImagingPcxEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
|
|||
state->errcode = IMAGING_CODEC_END;
|
||||
return 0;
|
||||
}
|
||||
|
||||
state->bytes = (state->xsize*state->bits + 7) / 8;
|
||||
state->state = FETCH;
|
||||
|
||||
}
|
||||
|
||||
bpp = state->bits;
|
||||
if (state->bits == 24){
|
||||
planes = 3;
|
||||
bpp = 8;
|
||||
}
|
||||
|
||||
bytes_per_line = (state->xsize*bpp + 7) / 8;
|
||||
/* The stride here needs to be kept in sync with the version in
|
||||
PcxImagePlugin.py. If it's not, the header and the body of the
|
||||
image will be out of sync and bad things will happen on decode.
|
||||
*/
|
||||
stride = bytes_per_line + (bytes_per_line % 2);
|
||||
|
||||
padding = stride - bytes_per_line;
|
||||
|
||||
|
||||
for (;;) {
|
||||
|
||||
switch (state->state) {
|
||||
|
@ -72,74 +91,94 @@ ImagingPcxEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
|
|||
/* when we arrive here, "count" contains the number of
|
||||
bytes having the value of "LAST" that we've already
|
||||
seen */
|
||||
while (state->x < planes * bytes_per_line) {
|
||||
/* If we're encoding an odd width file, and we've
|
||||
got more than one plane, we need to pad each
|
||||
color row with padding bytes at the end. Since
|
||||
The pixels are stored RRRRRGGGGGBBBBB, so we need
|
||||
to have the padding be RRRRRPGGGGGPBBBBBP. Hence
|
||||
the double loop
|
||||
*/
|
||||
while (state->x % bytes_per_line) {
|
||||
|
||||
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) {
|
||||
if (state->count == 63) {
|
||||
/* this run is full; flush it */
|
||||
if (bytes < 2)
|
||||
return ptr - buf;
|
||||
}
|
||||
*ptr++ = 0xff;
|
||||
*ptr++ = state->LAST;
|
||||
bytes--;
|
||||
bytes -= 2;
|
||||
|
||||
state->count = 0;
|
||||
|
||||
}
|
||||
|
||||
this = state->buffer[state->x];
|
||||
|
||||
if (this == state->LAST) {
|
||||
/* extend the current run */
|
||||
state->x++;
|
||||
state->count++;
|
||||
|
||||
} else {
|
||||
if (state->count > 0) {
|
||||
if (bytes < 2) {
|
||||
/* start a new run */
|
||||
if (state->count == 1 && (state->LAST < 0xc0)) {
|
||||
if (bytes < 1) {
|
||||
return ptr - buf;
|
||||
}
|
||||
*ptr++ = 0xc0 | state->count;
|
||||
*ptr++ = state->LAST;
|
||||
bytes -= 2;
|
||||
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++;
|
||||
|
||||
}
|
||||
|
||||
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) {
|
||||
/* end of line; flush the current run */
|
||||
if (state->count == 1 && (state->LAST < 0xc0)) {
|
||||
if (bytes < 1 + padding) {
|
||||
return ptr - buf;
|
||||
}
|
||||
*ptr++ = 0xc0 | state->count;
|
||||
*ptr++ = state->LAST;
|
||||
bytes -= 2;
|
||||
bytes--;
|
||||
} else {
|
||||
if (state->count > 0) {
|
||||
if (bytes < 2 + padding) {
|
||||
return ptr - buf;
|
||||
}
|
||||
*ptr++ = 0xc0 | state->count;
|
||||
*ptr++ = state->LAST;
|
||||
bytes -= 2;
|
||||
}
|
||||
}
|
||||
if (bytes < padding) {
|
||||
return ptr - buf;
|
||||
}
|
||||
/* add the padding */
|
||||
for (i=0;i<padding;i++){
|
||||
*ptr++=0;
|
||||
bytes--;
|
||||
}
|
||||
/* reset for the next color plane. */
|
||||
if (state->x < planes * bytes_per_line) {
|
||||
state->count = 1;
|
||||
state->LAST = state->buffer[state->x];
|
||||
state->x++;
|
||||
}
|
||||
}
|
||||
|
||||
/* read next line */
|
||||
state->state = FETCH;
|
||||
break;
|
||||
|
|
Loading…
Reference in New Issue
Block a user