mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-07-10 16:22:22 +03:00
Merge pull request #7010 from radarhere/bgr32
This commit is contained in:
commit
20293e1f76
|
@ -48,6 +48,9 @@ class TestImage:
|
||||||
"RGBX",
|
"RGBX",
|
||||||
"RGBA",
|
"RGBA",
|
||||||
"RGBa",
|
"RGBa",
|
||||||
|
"BGR;15",
|
||||||
|
"BGR;16",
|
||||||
|
"BGR;24",
|
||||||
"CMYK",
|
"CMYK",
|
||||||
"YCbCr",
|
"YCbCr",
|
||||||
"LAB",
|
"LAB",
|
||||||
|
@ -57,9 +60,7 @@ class TestImage:
|
||||||
def test_image_modes_success(self, mode):
|
def test_image_modes_success(self, mode):
|
||||||
Image.new(mode, (1, 1))
|
Image.new(mode, (1, 1))
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize("mode", ("", "bad", "very very long"))
|
||||||
"mode", ("", "bad", "very very long", "BGR;15", "BGR;16", "BGR;24", "BGR;32")
|
|
||||||
)
|
|
||||||
def test_image_modes_fail(self, mode):
|
def test_image_modes_fail(self, mode):
|
||||||
with pytest.raises(ValueError) as e:
|
with pytest.raises(ValueError) as e:
|
||||||
Image.new(mode, (1, 1))
|
Image.new(mode, (1, 1))
|
||||||
|
|
|
@ -353,8 +353,8 @@ class TestCffi(AccessTest):
|
||||||
|
|
||||||
|
|
||||||
class TestImagePutPixelError(AccessTest):
|
class TestImagePutPixelError(AccessTest):
|
||||||
IMAGE_MODES1 = ["L", "LA", "RGB", "RGBA"]
|
IMAGE_MODES1 = ["LA", "RGB", "RGBA", "BGR;15"]
|
||||||
IMAGE_MODES2 = ["I", "I;16", "BGR;15"]
|
IMAGE_MODES2 = ["L", "I", "I;16"]
|
||||||
INVALID_TYPES = ["foo", 1.0, None]
|
INVALID_TYPES = ["foo", 1.0, None]
|
||||||
|
|
||||||
@pytest.mark.parametrize("mode", IMAGE_MODES1)
|
@pytest.mark.parametrize("mode", IMAGE_MODES1)
|
||||||
|
@ -369,6 +369,11 @@ class TestImagePutPixelError(AccessTest):
|
||||||
(
|
(
|
||||||
("L", (0, 2), "color must be int or single-element tuple"),
|
("L", (0, 2), "color must be int or single-element tuple"),
|
||||||
("LA", (0, 3), "color must be int, or tuple of one or two elements"),
|
("LA", (0, 3), "color must be int, or tuple of one or two elements"),
|
||||||
|
(
|
||||||
|
"BGR;15",
|
||||||
|
(0, 2),
|
||||||
|
"color must be int, or tuple of one or three elements",
|
||||||
|
),
|
||||||
(
|
(
|
||||||
"RGB",
|
"RGB",
|
||||||
(0, 2, 5),
|
(0, 2, 5),
|
||||||
|
@ -397,11 +402,6 @@ class TestImagePutPixelError(AccessTest):
|
||||||
with pytest.raises(OverflowError):
|
with pytest.raises(OverflowError):
|
||||||
im.putpixel((0, 0), 2**80)
|
im.putpixel((0, 0), 2**80)
|
||||||
|
|
||||||
def test_putpixel_unrecognized_mode(self):
|
|
||||||
im = hopper("BGR;15")
|
|
||||||
with pytest.raises(ValueError, match="unrecognized image mode"):
|
|
||||||
im.putpixel((0, 0), 0)
|
|
||||||
|
|
||||||
|
|
||||||
class TestEmbeddable:
|
class TestEmbeddable:
|
||||||
@pytest.mark.xfail(reason="failing test")
|
@pytest.mark.xfail(reason="failing test")
|
||||||
|
|
|
@ -62,7 +62,6 @@ Pillow also provides limited support for a few additional modes, including:
|
||||||
* ``BGR;15`` (15-bit reversed true colour)
|
* ``BGR;15`` (15-bit reversed true colour)
|
||||||
* ``BGR;16`` (16-bit reversed true colour)
|
* ``BGR;16`` (16-bit reversed true colour)
|
||||||
* ``BGR;24`` (24-bit reversed true colour)
|
* ``BGR;24`` (24-bit reversed true colour)
|
||||||
* ``BGR;32`` (32-bit reversed true colour)
|
|
||||||
|
|
||||||
Premultiplied alpha is where the values for each other channel have been
|
Premultiplied alpha is where the values for each other channel have been
|
||||||
multiplied by the alpha. For example, an RGBA pixel of ``(10, 20, 30, 127)``
|
multiplied by the alpha. For example, an RGBA pixel of ``(10, 20, 30, 127)``
|
||||||
|
|
|
@ -70,9 +70,18 @@ Added support for saving PDFs in RGBA mode
|
||||||
|
|
||||||
Using the JPXDecode filter, PDFs can now be saved in RGBA mode.
|
Using the JPXDecode filter, PDFs can now be saved in RGBA mode.
|
||||||
|
|
||||||
|
|
||||||
Improved I;16N support
|
Improved I;16N support
|
||||||
^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
Support has been added for I;16N access, packing and unpacking. Conversion to
|
Support has been added for I;16N access, packing and unpacking. Conversion to
|
||||||
and from L mode has also been added.
|
and from L mode has also been added.
|
||||||
|
|
||||||
|
BGR;* modes
|
||||||
|
^^^^^^^^^^^
|
||||||
|
|
||||||
|
It is now possible to create new BGR;15, BGR;16 and BGR;24 images. Conversely, BGR;32
|
||||||
|
has been removed from ImageMode and its associated methods, dropping the little support
|
||||||
|
Pillow had for the mode.
|
||||||
|
|
||||||
|
With that, all modes listed under :ref:`concept-modes` can now be used to create a new
|
||||||
|
image.
|
||||||
|
|
|
@ -58,10 +58,9 @@ def getmode(mode):
|
||||||
"HSV": ("RGB", "L", ("H", "S", "V"), "|u1"),
|
"HSV": ("RGB", "L", ("H", "S", "V"), "|u1"),
|
||||||
# extra experimental modes
|
# extra experimental modes
|
||||||
"RGBa": ("RGB", "L", ("R", "G", "B", "a"), "|u1"),
|
"RGBa": ("RGB", "L", ("R", "G", "B", "a"), "|u1"),
|
||||||
"BGR;15": ("RGB", "L", ("B", "G", "R"), endian + "u2"),
|
"BGR;15": ("RGB", "L", ("B", "G", "R"), "|u1"),
|
||||||
"BGR;16": ("RGB", "L", ("B", "G", "R"), endian + "u2"),
|
"BGR;16": ("RGB", "L", ("B", "G", "R"), "|u1"),
|
||||||
"BGR;24": ("RGB", "L", ("B", "G", "R"), endian + "u3"),
|
"BGR;24": ("RGB", "L", ("B", "G", "R"), "|u1"),
|
||||||
"BGR;32": ("RGB", "L", ("B", "G", "R"), endian + "u4"),
|
|
||||||
"LA": ("L", "L", ("L", "A"), "|u1"),
|
"LA": ("L", "L", ("L", "A"), "|u1"),
|
||||||
"La": ("L", "L", ("L", "a"), "|u1"),
|
"La": ("L", "L", ("L", "a"), "|u1"),
|
||||||
"PA": ("RGB", "L", ("P", "A"), "|u1"),
|
"PA": ("RGB", "L", ("P", "A"), "|u1"),
|
||||||
|
|
|
@ -491,7 +491,7 @@ getink(PyObject *color, Imaging im, char *ink) {
|
||||||
int g = 0, b = 0, a = 0;
|
int g = 0, b = 0, a = 0;
|
||||||
double f = 0;
|
double f = 0;
|
||||||
/* Windows 64 bit longs are 32 bits, and 0xFFFFFFFF (white) is a
|
/* Windows 64 bit longs are 32 bits, and 0xFFFFFFFF (white) is a
|
||||||
python long (not int) that raises an overflow error when trying
|
Python long (not int) that raises an overflow error when trying
|
||||||
to return it into a 32 bit C long
|
to return it into a 32 bit C long
|
||||||
*/
|
*/
|
||||||
PY_LONG_LONG r = 0;
|
PY_LONG_LONG r = 0;
|
||||||
|
@ -502,8 +502,12 @@ getink(PyObject *color, Imaging im, char *ink) {
|
||||||
be cast to either UINT8 or INT32 */
|
be cast to either UINT8 or INT32 */
|
||||||
|
|
||||||
int rIsInt = 0;
|
int rIsInt = 0;
|
||||||
if (PyTuple_Check(color) && PyTuple_GET_SIZE(color) == 1) {
|
int tupleSize;
|
||||||
color = PyTuple_GetItem(color, 0);
|
if (PyTuple_Check(color)) {
|
||||||
|
tupleSize = PyTuple_GET_SIZE(color);
|
||||||
|
if (tupleSize == 1) {
|
||||||
|
color = PyTuple_GetItem(color, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (im->type == IMAGING_TYPE_UINT8 || im->type == IMAGING_TYPE_INT32 ||
|
if (im->type == IMAGING_TYPE_UINT8 || im->type == IMAGING_TYPE_INT32 ||
|
||||||
im->type == IMAGING_TYPE_SPECIAL) {
|
im->type == IMAGING_TYPE_SPECIAL) {
|
||||||
|
@ -513,15 +517,13 @@ getink(PyObject *color, Imaging im, char *ink) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
rIsInt = 1;
|
rIsInt = 1;
|
||||||
} else if (im->type == IMAGING_TYPE_UINT8) {
|
} else if (im->bands == 1) {
|
||||||
if (!PyTuple_Check(color)) {
|
|
||||||
PyErr_SetString(PyExc_TypeError, "color must be int or tuple");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
PyErr_SetString(
|
PyErr_SetString(
|
||||||
PyExc_TypeError, "color must be int or single-element tuple");
|
PyExc_TypeError, "color must be int or single-element tuple");
|
||||||
return NULL;
|
return NULL;
|
||||||
|
} else if (!PyTuple_Check(color)) {
|
||||||
|
PyErr_SetString(PyExc_TypeError, "color must be int or tuple");
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -531,7 +533,7 @@ getink(PyObject *color, Imaging im, char *ink) {
|
||||||
if (im->bands == 1) {
|
if (im->bands == 1) {
|
||||||
/* unsigned integer, single layer */
|
/* unsigned integer, single layer */
|
||||||
if (rIsInt != 1) {
|
if (rIsInt != 1) {
|
||||||
if (PyTuple_GET_SIZE(color) != 1) {
|
if (tupleSize != 1) {
|
||||||
PyErr_SetString(PyExc_TypeError, "color must be int or single-element tuple");
|
PyErr_SetString(PyExc_TypeError, "color must be int or single-element tuple");
|
||||||
return NULL;
|
return NULL;
|
||||||
} else if (!PyArg_ParseTuple(color, "L", &r)) {
|
} else if (!PyArg_ParseTuple(color, "L", &r)) {
|
||||||
|
@ -541,7 +543,6 @@ getink(PyObject *color, Imaging im, char *ink) {
|
||||||
ink[0] = (char)CLIP8(r);
|
ink[0] = (char)CLIP8(r);
|
||||||
ink[1] = ink[2] = ink[3] = 0;
|
ink[1] = ink[2] = ink[3] = 0;
|
||||||
} else {
|
} else {
|
||||||
a = 255;
|
|
||||||
if (rIsInt) {
|
if (rIsInt) {
|
||||||
/* compatibility: ABGR */
|
/* compatibility: ABGR */
|
||||||
a = (UINT8)(r >> 24);
|
a = (UINT8)(r >> 24);
|
||||||
|
@ -549,7 +550,7 @@ getink(PyObject *color, Imaging im, char *ink) {
|
||||||
g = (UINT8)(r >> 8);
|
g = (UINT8)(r >> 8);
|
||||||
r = (UINT8)r;
|
r = (UINT8)r;
|
||||||
} else {
|
} else {
|
||||||
int tupleSize = PyTuple_GET_SIZE(color);
|
a = 255;
|
||||||
if (im->bands == 2) {
|
if (im->bands == 2) {
|
||||||
if (tupleSize != 1 && tupleSize != 2) {
|
if (tupleSize != 1 && tupleSize != 2) {
|
||||||
PyErr_SetString(PyExc_TypeError, "color must be int, or tuple of one or two elements");
|
PyErr_SetString(PyExc_TypeError, "color must be int, or tuple of one or two elements");
|
||||||
|
@ -593,6 +594,41 @@ getink(PyObject *color, Imaging im, char *ink) {
|
||||||
ink[1] = (UINT8)(r >> 8);
|
ink[1] = (UINT8)(r >> 8);
|
||||||
ink[2] = ink[3] = 0;
|
ink[2] = ink[3] = 0;
|
||||||
return ink;
|
return ink;
|
||||||
|
} else {
|
||||||
|
if (rIsInt) {
|
||||||
|
b = (UINT8)(r >> 16);
|
||||||
|
g = (UINT8)(r >> 8);
|
||||||
|
r = (UINT8)r;
|
||||||
|
} else if (tupleSize != 3) {
|
||||||
|
PyErr_SetString(PyExc_TypeError, "color must be int, or tuple of one or three elements");
|
||||||
|
return NULL;
|
||||||
|
} else if (!PyArg_ParseTuple(color, "Lii", &r, &g, &b)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (!strcmp(im->mode, "BGR;15")) {
|
||||||
|
UINT16 v = ((((UINT16)r) << 7) & 0x7c00) +
|
||||||
|
((((UINT16)g) << 2) & 0x03e0) +
|
||||||
|
((((UINT16)b) >> 3) & 0x001f);
|
||||||
|
|
||||||
|
ink[0] = (UINT8)v;
|
||||||
|
ink[1] = (UINT8)(v >> 8);
|
||||||
|
ink[2] = ink[3] = 0;
|
||||||
|
return ink;
|
||||||
|
} else if (!strcmp(im->mode, "BGR;16")) {
|
||||||
|
UINT16 v = ((((UINT16)r) << 8) & 0xf800) +
|
||||||
|
((((UINT16)g) << 3) & 0x07e0) +
|
||||||
|
((((UINT16)b) >> 3) & 0x001f);
|
||||||
|
ink[0] = (UINT8)v;
|
||||||
|
ink[1] = (UINT8)(v >> 8);
|
||||||
|
ink[2] = ink[3] = 0;
|
||||||
|
return ink;
|
||||||
|
} else if (!strcmp(im->mode, "BGR;24")) {
|
||||||
|
ink[0] = (UINT8)b;
|
||||||
|
ink[1] = (UINT8)g;
|
||||||
|
ink[2] = (UINT8)r;
|
||||||
|
ink[3] = 0;
|
||||||
|
return ink;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -131,7 +131,7 @@ ImagingNewPrologueSubtype(const char *mode, int xsize, int ysize, int size) {
|
||||||
} else if (strcmp(mode, "BGR;15") == 0) {
|
} else if (strcmp(mode, "BGR;15") == 0) {
|
||||||
/* EXPERIMENTAL */
|
/* EXPERIMENTAL */
|
||||||
/* 15-bit reversed true colour */
|
/* 15-bit reversed true colour */
|
||||||
im->bands = 1;
|
im->bands = 3;
|
||||||
im->pixelsize = 2;
|
im->pixelsize = 2;
|
||||||
im->linesize = (xsize * 2 + 3) & -4;
|
im->linesize = (xsize * 2 + 3) & -4;
|
||||||
im->type = IMAGING_TYPE_SPECIAL;
|
im->type = IMAGING_TYPE_SPECIAL;
|
||||||
|
@ -139,7 +139,7 @@ ImagingNewPrologueSubtype(const char *mode, int xsize, int ysize, int size) {
|
||||||
} else if (strcmp(mode, "BGR;16") == 0) {
|
} else if (strcmp(mode, "BGR;16") == 0) {
|
||||||
/* EXPERIMENTAL */
|
/* EXPERIMENTAL */
|
||||||
/* 16-bit reversed true colour */
|
/* 16-bit reversed true colour */
|
||||||
im->bands = 1;
|
im->bands = 3;
|
||||||
im->pixelsize = 2;
|
im->pixelsize = 2;
|
||||||
im->linesize = (xsize * 2 + 3) & -4;
|
im->linesize = (xsize * 2 + 3) & -4;
|
||||||
im->type = IMAGING_TYPE_SPECIAL;
|
im->type = IMAGING_TYPE_SPECIAL;
|
||||||
|
@ -147,19 +147,11 @@ ImagingNewPrologueSubtype(const char *mode, int xsize, int ysize, int size) {
|
||||||
} else if (strcmp(mode, "BGR;24") == 0) {
|
} else if (strcmp(mode, "BGR;24") == 0) {
|
||||||
/* EXPERIMENTAL */
|
/* EXPERIMENTAL */
|
||||||
/* 24-bit reversed true colour */
|
/* 24-bit reversed true colour */
|
||||||
im->bands = 1;
|
im->bands = 3;
|
||||||
im->pixelsize = 3;
|
im->pixelsize = 3;
|
||||||
im->linesize = (xsize * 3 + 3) & -4;
|
im->linesize = (xsize * 3 + 3) & -4;
|
||||||
im->type = IMAGING_TYPE_SPECIAL;
|
im->type = IMAGING_TYPE_SPECIAL;
|
||||||
|
|
||||||
} else if (strcmp(mode, "BGR;32") == 0) {
|
|
||||||
/* EXPERIMENTAL */
|
|
||||||
/* 32-bit reversed true colour */
|
|
||||||
im->bands = 1;
|
|
||||||
im->pixelsize = 4;
|
|
||||||
im->linesize = (xsize * 4 + 3) & -4;
|
|
||||||
im->type = IMAGING_TYPE_SPECIAL;
|
|
||||||
|
|
||||||
} else if (strcmp(mode, "RGBX") == 0) {
|
} else if (strcmp(mode, "RGBX") == 0) {
|
||||||
/* 32-bit true colour images with padding */
|
/* 32-bit true colour images with padding */
|
||||||
im->bands = im->pixelsize = 4;
|
im->bands = im->pixelsize = 4;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user