What is causing dimension-dependent AttributeError in PIL fromarray function?
attributeerror, numpy, python, python-imaging-library
Solution
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:
>>> x.__array_interface__['strides']
>>> y.__array_interface__['strides']
(9, 1)
>>> z.__array_interface__['strides']
(9, 3)
and so a different branch is taken here:
if strides is not None:
obj = obj.tobytes()
The documentation mentions `tostring`, not `tobytes`:
# If obj is not contiguous, then the tostring method is called
# and {@link frombuffer} is used.
And the Python 2 source of PIL 1.1.7 uses `tostring`:
if strides is not None:
obj = obj.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()` by `tostring()` in `Image.py` and it should work:
Python 3.2.3 (default, May 3 2012, 15:54:42)
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 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) # now no error!
>>> imz = Image.fromarray(z) # now no error!
>>>
Problem
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.