diff --git a/Tests/test_color_lut.py b/Tests/test_color_lut.py index 4cd10b739..2d4ff592c 100644 --- a/Tests/test_color_lut.py +++ b/Tests/test_color_lut.py @@ -317,6 +317,47 @@ class TestColorLut3DFilter(PillowTestCase): table[0] = 33 self.assertEqual(lut.table[0], 33) + @unittest.skipIf(numpy is None, "Numpy is not installed") + def test_numpy_formats(self): + g = Image.linear_gradient('L') + im = Image.merge('RGB', [g, g.transpose(Image.ROTATE_90), + g.transpose(Image.ROTATE_180)]) + + lut = ImageFilter.Color3DLUT.generate((7, 9, 11), + lambda r, g, b: (r, g, b)) + lut.table = numpy.array(lut.table, dtype=numpy.float32)[:-1] + with self.assertRaisesRegexp(ValueError, "should have table_channels"): + im.filter(lut) + + lut = ImageFilter.Color3DLUT.generate((7, 9, 11), + lambda r, g, b: (r, g, b)) + lut.table = (numpy.array(lut.table, dtype=numpy.float32) + .reshape((7 * 9 * 11), 3)) + with self.assertRaisesRegexp(ValueError, "should have table_channels"): + im.filter(lut) + + lut = ImageFilter.Color3DLUT.generate((7, 9, 11), + lambda r, g, b: (r, g, b)) + lut.table = numpy.array(lut.table, dtype=numpy.float16) + self.assert_image_equal(im, im.filter(lut)) + + lut = ImageFilter.Color3DLUT.generate((7, 9, 11), + lambda r, g, b: (r, g, b)) + lut.table = numpy.array(lut.table, dtype=numpy.float32) + self.assert_image_equal(im, im.filter(lut)) + + lut = ImageFilter.Color3DLUT.generate((7, 9, 11), + lambda r, g, b: (r, g, b)) + lut.table = numpy.array(lut.table, dtype=numpy.float64) + self.assert_image_equal(im, im.filter(lut)) + + lut = ImageFilter.Color3DLUT.generate((7, 9, 11), + lambda r, g, b: (r, g, b)) + lut.table = numpy.array(lut.table, dtype=numpy.int32) + im.filter(lut) + lut.table = numpy.array(lut.table, dtype=numpy.int8) + im.filter(lut) + def test_repr(self): lut = ImageFilter.Color3DLUT(2, [0, 1, 2] * 8) self.assertEqual(repr(lut), diff --git a/src/_imaging.c b/src/_imaging.c index 2fcd1b2ee..3c9456549 100644 --- a/src/_imaging.c +++ b/src/_imaging.c @@ -729,19 +729,50 @@ static INT16* _prepare_lut_table(PyObject* table, Py_ssize_t table_size) { int i; - float item; + Py_buffer buffer_info; INT32 data_type = TYPE_FLOAT32; - void* table_data; + float item = 0; + void* table_data = NULL; + int free_table_data = 0; INT16* prepared; /* NOTE: This value should be the same as in ColorLUT.c */ #define PRECISION_BITS (16 - 8 - 2) - table_data = getlist(table, &table_size, - "The table should have table_channels * " - "size1D * size2D * size3D float items.", TYPE_FLOAT32); + const char* wrong_size = ("The table should have table_channels * " + "size1D * size2D * size3D float items."); + + if (PyObject_CheckBuffer(table)) { + if ( ! PyObject_GetBuffer(table, &buffer_info, + PyBUF_CONTIG_RO | PyBUF_FORMAT)) { + if (buffer_info.ndim == 1 && buffer_info.shape[0] == table_size) { + if (strlen(buffer_info.format) == 1) { + switch (buffer_info.format[0]) { + case 'e': + data_type = TYPE_FLOAT16; + table_data = buffer_info.buf; + break; + case 'f': + data_type = TYPE_FLOAT32; + table_data = buffer_info.buf; + break; + case 'd': + data_type = TYPE_DOUBLE; + table_data = buffer_info.buf; + break; + } + } + } + PyBuffer_Release(&buffer_info); + } + } + if ( ! table_data) { - return NULL; + free_table_data = 1; + table_data = getlist(table, &table_size, wrong_size, TYPE_FLOAT32); + if ( ! table_data) { + return NULL; + } } /* malloc check ok, max is 2 * 4 * 65**3 = 2197000 */ @@ -781,7 +812,9 @@ _prepare_lut_table(PyObject* table, Py_ssize_t table_size) } #undef PRECISION_BITS - free(table_data); + if (free_table_data) { + free(table_data); + } return prepared; } diff --git a/src/libImaging/ImPlatform.h b/src/libImaging/ImPlatform.h index 3e49cf330..b2d4db785 100644 --- a/src/libImaging/ImPlatform.h +++ b/src/libImaging/ImPlatform.h @@ -71,7 +71,7 @@ #endif /* assume IEEE; tweak if necessary (patches are welcome) */ -#define FLOAT16 UINT16 +#define FLOAT16 UINT16 #define FLOAT32 float #define FLOAT64 double