Support creating BGR;15, BGR;16 and BGR;24 images

This commit is contained in:
Andrew Murray 2023-03-20 00:30:10 +11:00
parent 01cdfb6b27
commit 11d100ce5d
5 changed files with 56 additions and 22 deletions

View File

@ -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")
)
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))

View File

@ -363,8 +363,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)
@ -379,6 +379,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),
@ -407,11 +412,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")

View File

@ -58,9 +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"),
"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"),

View File

@ -517,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;
} }
} }
@ -596,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;
}
} }
} }

View File

@ -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,7 +147,7 @@ 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;