mirror of
https://github.com/python-pillow/Pillow.git
synced 2024-12-26 01:46:18 +03:00
BF: fix conversion of bit images to numpy arrays
Numpy cannot form arrays from bits. To convert bit images to numpy, convert bits to bytes. From suggestion by Alexander Karpinsky, with thanks. Fixes gh-350.
This commit is contained in:
parent
f12febf3a9
commit
824a0c232c
14
PIL/Image.py
14
PIL/Image.py
|
@ -246,7 +246,7 @@ else:
|
||||||
|
|
||||||
_MODE_CONV = {
|
_MODE_CONV = {
|
||||||
# official modes
|
# official modes
|
||||||
"1": ('|b1', None), # broken
|
"1": ('|b1', None), # Bits need to be extended to bytes
|
||||||
"L": ('|u1', None),
|
"L": ('|u1', None),
|
||||||
"LA": ('|u1', 2),
|
"LA": ('|u1', 2),
|
||||||
"I": (_ENDIAN + 'i4', None),
|
"I": (_ENDIAN + 'i4', None),
|
||||||
|
@ -615,17 +615,21 @@ class Image(object):
|
||||||
self.save(b, 'PNG')
|
self.save(b, 'PNG')
|
||||||
return b.getvalue()
|
return b.getvalue()
|
||||||
|
|
||||||
def __getattr__(self, name):
|
@property
|
||||||
if name == "__array_interface__":
|
def __array_interface__(self):
|
||||||
# numpy array interface support
|
# numpy array interface support
|
||||||
new = {}
|
new = {}
|
||||||
shape, typestr = _conv_type_shape(self)
|
shape, typestr = _conv_type_shape(self)
|
||||||
new['shape'] = shape
|
new['shape'] = shape
|
||||||
new['typestr'] = typestr
|
new['typestr'] = typestr
|
||||||
new['data'] = self.tobytes()
|
|
||||||
new['version'] = 3
|
new['version'] = 3
|
||||||
|
if self.mode == '1':
|
||||||
|
# Binary images need to be extended from bits to bytes
|
||||||
|
# See: https://github.com/python-pillow/Pillow/issues/350
|
||||||
|
new['data'] = self.tobytes('raw', 'L')
|
||||||
|
else:
|
||||||
|
new['data'] = self.tobytes()
|
||||||
return new
|
return new
|
||||||
raise AttributeError(name)
|
|
||||||
|
|
||||||
def __getstate__(self):
|
def __getstate__(self):
|
||||||
return [
|
return [
|
||||||
|
|
|
@ -25,13 +25,26 @@ class TestImageArray(PillowTestCase):
|
||||||
self.assertEqual(test("RGBX"), (3, (100, 128, 4), '|u1', 51200))
|
self.assertEqual(test("RGBX"), (3, (100, 128, 4), '|u1', 51200))
|
||||||
|
|
||||||
def test_fromarray(self):
|
def test_fromarray(self):
|
||||||
|
|
||||||
|
class Wrapper(object):
|
||||||
|
""" Class with API matching Image.fromarray """
|
||||||
|
|
||||||
|
def __init__(self, img, arr_params):
|
||||||
|
self.img = img
|
||||||
|
self.__array_interface__ = arr_params
|
||||||
|
|
||||||
|
def tobytes(self):
|
||||||
|
return self.img.tobytes()
|
||||||
|
|
||||||
def test(mode):
|
def test(mode):
|
||||||
i = im.convert(mode)
|
i = im.convert(mode)
|
||||||
a = i.__array_interface__
|
a = i.__array_interface__
|
||||||
a["strides"] = 1 # pretend it's non-contiguous
|
a["strides"] = 1 # pretend it's non-contigous
|
||||||
i.__array_interface__ = a # patch in new version of attribute
|
# Make wrapper instance for image, new array interface
|
||||||
out = Image.fromarray(i)
|
wrapped = Wrapper(i, a)
|
||||||
|
out = Image.fromarray(wrapped)
|
||||||
return out.mode, out.size, list(i.getdata()) == list(out.getdata())
|
return out.mode, out.size, list(i.getdata()) == list(out.getdata())
|
||||||
|
|
||||||
# self.assertEqual(test("1"), ("1", (128, 100), True))
|
# self.assertEqual(test("1"), ("1", (128, 100), True))
|
||||||
self.assertEqual(test("L"), ("L", (128, 100), True))
|
self.assertEqual(test("L"), ("L", (128, 100), True))
|
||||||
self.assertEqual(test("I"), ("I", (128, 100), True))
|
self.assertEqual(test("I"), ("I", (128, 100), True))
|
||||||
|
|
|
@ -117,6 +117,15 @@ class TestNumpy(PillowTestCase):
|
||||||
self._test_img_equals_nparray(img, np_img)
|
self._test_img_equals_nparray(img, np_img)
|
||||||
self.assertEqual(np_img.dtype, numpy.dtype('<u2'))
|
self.assertEqual(np_img.dtype, numpy.dtype('<u2'))
|
||||||
|
|
||||||
|
def test_1bit(self):
|
||||||
|
# Test that 1-bit arrays convert to numpy and back
|
||||||
|
# See: https://github.com/python-pillow/Pillow/issues/350
|
||||||
|
arr = numpy.array([[1, 0, 0, 1, 0], [0, 1, 0, 0, 0]], 'u1')
|
||||||
|
img = Image.fromarray(arr * 255).convert('1')
|
||||||
|
self.assertEqual(img.mode, '1')
|
||||||
|
arr_back = numpy.array(img)
|
||||||
|
numpy.testing.assert_array_equal(arr, arr_back)
|
||||||
|
|
||||||
def test_save_tiff_uint16(self):
|
def test_save_tiff_uint16(self):
|
||||||
'''
|
'''
|
||||||
Open a single-channel uint16 greyscale image and verify that it can be saved without
|
Open a single-channel uint16 greyscale image and verify that it can be saved without
|
||||||
|
|
Loading…
Reference in New Issue
Block a user