From 9bd574058e46b192ae8ec631991e521aa8655e4f Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Wed, 26 Jul 2023 19:13:56 +1000 Subject: [PATCH] Support BGR;15, BGR;16 and BGR;24 in putdata --- Tests/test_image_putdata.py | 9 +++++++ src/_imaging.c | 49 ++++++++++++++++++++++++++++--------- 2 files changed, 46 insertions(+), 12 deletions(-) diff --git a/Tests/test_image_putdata.py b/Tests/test_image_putdata.py index 0e6293349..4e40aec74 100644 --- a/Tests/test_image_putdata.py +++ b/Tests/test_image_putdata.py @@ -76,6 +76,15 @@ def test_mode_F(): assert list(im.getdata()) == target +@pytest.mark.parametrize("mode", ("BGR;15", "BGR;16", "BGR;24")) +def test_mode_BGR(mode): + data = [(16, 32, 49), (32, 32, 98)] + im = Image.new(mode, (1, 2)) + im.putdata(data) + + assert list(im.getdata()) == data + + def test_array_B(): # shouldn't segfault # see https://github.com/python-pillow/Pillow/issues/1008 diff --git a/src/_imaging.c b/src/_imaging.c index c331669a7..95e1f4c08 100644 --- a/src/_imaging.c +++ b/src/_imaging.c @@ -1573,21 +1573,46 @@ if (PySequence_Check(op)) { \ PyErr_SetString(PyExc_TypeError, must_be_sequence); return NULL; } - int endian = strncmp(image->mode, "I;16", 4) == 0 ? (strcmp(image->mode, "I;16B") == 0 ? 2 : 1) : 0; double value; - for (i = x = y = 0; i < n; i++) { - set_value_to_item(seq, i); - if (scale != 1.0 || offset != 0.0) { - value = value * scale + offset; + if (image->bands == 1) { + int bigendian; + if (image->type == IMAGING_TYPE_SPECIAL) { + // I;16* + bigendian = strcmp(image->mode, "I;16B") == 0; } - if (endian == 0) { - image->image8[y][x] = (UINT8)CLIP8(value); - } else { - image->image8[y][x * 2 + (endian == 2 ? 1 : 0)] = CLIP8((int)value % 256); - image->image8[y][x * 2 + (endian == 2 ? 0 : 1)] = CLIP8((int)value >> 8); + for (i = x = y = 0; i < n; i++) { + set_value_to_item(seq, i); + if (scale != 1.0 || offset != 0.0) { + value = value * scale + offset; + } + if (image->type == IMAGING_TYPE_SPECIAL) { + image->image8[y][x * 2 + (bigendian ? 1 : 0)] = CLIP8((int)value % 256); + image->image8[y][x * 2 + (bigendian ? 0 : 1)] = CLIP8((int)value >> 8); + } else { + image->image8[y][x] = (UINT8)CLIP8(value); + } + if (++x >= (int)image->xsize) { + x = 0, y++; + } } - if (++x >= (int)image->xsize) { - x = 0, y++; + } else { + // BGR;* + int b; + for (i = x = y = 0; i < n; i++) { + char ink[4]; + + op = PySequence_Fast_GET_ITEM(seq, i); + if (!op || !getink(op, image, ink)) { + Py_DECREF(seq); + return NULL; + } + /* FIXME: what about scale and offset? */ + for (b = 0; b < image->pixelsize; b++) { + image->image8[y][x * image->pixelsize + b] = ink[b]; + } + if (++x >= (int)image->xsize) { + x = 0, y++; + } } } PyErr_Clear(); /* Avoid weird exceptions */