I’m getting an error from the following Python3 code, in the indicated lines.
x, y, and z are all plain 2D numpy arrays identical but for size, and ought to work the same. Yet they act differently, with y and z crashing while x works fine.
import numpy as np
from PIL import Image
a = np.ones( ( 3,3,3), dtype='uint8' )
x = a[1,:,:]
y = a[:,1,:]
z = a[:,:,1]
imx = Image.fromarray(x) # ok
imy = Image.fromarray(y) # error
imz = Image.fromarray(z) # error
but this works
z1 = 1*z
imz = Image.fromarray(z1) # ok
The error is:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Python3\lib\site-packages\PIL\Image.py", line 1918, in fromarray
obj = obj.tobytes()
AttributeError: 'numpy.ndarray' object has no attribute 'tobytes'
So what’s different between x, y, z, z1? Nothing that I can tell.
>>> z.dtype
dtype('uint8')
>>> z1.dtype
dtype('uint8')
>>> z.shape
(3, 4)
>>> z1.shape
(3, 4)
I’m using Python 3.2.3 on a Windows 7 Enterprise machine, with everything 64 bit.
I can reproduce on ubuntu 12.04 with Python 3.2.3, numpy 1.6.1, and PIL 1.1.7-for-Python 3 at http://www.lfd.uci.edu/~gohlke/pythonlibs/#pil. The difference happens because the array_interface of x doesn’t have a strides value but y’s and z’s do:
and so a different branch is taken here:
The documentation mentions
tostring, nottobytes:And the Python 2 source of PIL 1.1.7 uses
tostring:so I suspect that this was an error introduced during a 2-to-3 conversion in which str/bytes changes were made. Simply replace
tobytes()bytostring()inImage.pyand it should work: