diff --git a/Tests/test_file_pcx.py b/Tests/test_file_pcx.py index 76fd09dac9b..4cba9ac857b 100644 --- a/Tests/test_file_pcx.py +++ b/Tests/test_file_pcx.py @@ -118,6 +118,14 @@ def test_1px_width(tmp_path: Path) -> None: _roundtrip(tmp_path, im) +def test_rgb_odd_width(tmp_path: Path) -> None: + # An RGB (multi-plane) width whose even-padded stride differs from the + # width must still separate the colour planes correctly. Distinct channel + # values expose a misaligned split. + im = Image.new("RGB", (3, 3), (0x11, 0x22, 0x33)) + _roundtrip(tmp_path, im) + + def test_large_count(tmp_path: Path) -> None: im = Image.new("L", (256, 1)) px = im.load() diff --git a/src/libImaging/PcxDecode.c b/src/libImaging/PcxDecode.c index a65952fb1da..f29feaa701c 100644 --- a/src/libImaging/PcxDecode.c +++ b/src/libImaging/PcxDecode.c @@ -69,10 +69,12 @@ ImagingPcxDecode(Imaging im, ImagingCodecState state, UINT8 *buf, Py_ssize_t byt stride = state->bytes / state->bits; } else { xsize = state->xsize; - bands = state->bytes / state->xsize; - if (bands != 0) { - stride = state->bytes / bands; - } + // state->bytes is planes * stride; derive the stride from the + // known band count rather than guessing it from state->xsize, + // which picks the wrong split when xsize != stride (e.g. an + // odd-width RGB line padded to an even stride). + bands = im->bands; + stride = state->bytes / bands; } if (stride > xsize) { int i;