mirror of
https://github.com/python-pillow/Pillow.git
synced 2024-12-25 17:36:18 +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
|
# bytes per plane
|
||||||
stride = (im.size[0] * bits + 7) // 8
|
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
|
# under windows, we could determine the current screen size with
|
||||||
# "Image.core.display_mode()[1]", but I think that's overkill...
|
# "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;
|
UINT8* ptr;
|
||||||
int this;
|
int this;
|
||||||
|
int bytes_per_line = 0;
|
||||||
|
int padding = 0;
|
||||||
|
int stride = 0;
|
||||||
|
int bpp = 0;
|
||||||
|
int planes = 1;
|
||||||
|
int i;
|
||||||
|
|
||||||
ptr = buf;
|
ptr = buf;
|
||||||
|
|
||||||
|
@ -35,12 +41,25 @@ ImagingPcxEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
|
||||||
state->errcode = IMAGING_CODEC_END;
|
state->errcode = IMAGING_CODEC_END;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
state->bytes = (state->xsize*state->bits + 7) / 8;
|
|
||||||
state->state = FETCH;
|
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 (;;) {
|
for (;;) {
|
||||||
|
|
||||||
switch (state->state) {
|
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
|
/* when we arrive here, "count" contains the number of
|
||||||
bytes having the value of "LAST" that we've already
|
bytes having the value of "LAST" that we've already
|
||||||
seen */
|
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 (state->count == 63) {
|
if (bytes < 2)
|
||||||
/* 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;
|
return ptr - buf;
|
||||||
}
|
*ptr++ = 0xff;
|
||||||
*ptr++ = state->LAST;
|
*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 {
|
} else {
|
||||||
if (state->count > 0) {
|
/* start a new run */
|
||||||
if (bytes < 2) {
|
if (state->count == 1 && (state->LAST < 0xc0)) {
|
||||||
|
if (bytes < 1) {
|
||||||
return ptr - buf;
|
return ptr - buf;
|
||||||
}
|
}
|
||||||
*ptr++ = 0xc0 | state->count;
|
|
||||||
*ptr++ = state->LAST;
|
*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 */
|
/* end of line; flush the current run */
|
||||||
if (state->count == 1 && (state->LAST < 0xc0)) {
|
if (state->count == 1 && (state->LAST < 0xc0)) {
|
||||||
if (bytes < 1) {
|
if (bytes < 1 + padding) {
|
||||||
return ptr - buf;
|
|
||||||
}
|
|
||||||
*ptr++ = state->LAST;
|
|
||||||
bytes--;
|
|
||||||
} else {
|
|
||||||
if (state->count > 0) {
|
|
||||||
if (bytes < 2) {
|
|
||||||
return ptr - buf;
|
return ptr - buf;
|
||||||
}
|
}
|
||||||
*ptr++ = 0xc0 | state->count;
|
|
||||||
*ptr++ = state->LAST;
|
*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 */
|
/* read next line */
|
||||||
state->state = FETCH;
|
state->state = FETCH;
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user