[Image-SIG] Bug in the mode recognition code of Image.fromarray?

Zhang Chiyuan pluskid at gmail.com
Mon Jan 12 08:09:28 CET 2009

Hi all,

I have a transparent png file and load it with PIL:

from PIL import Image
from numpy import array

im = Image.open('foo.png')
a = array(im)
im2 = Image.fromarray(a)

It should automatically determine that the mode is 'RGBA' but it
failed to do so. And the result im2 is not a correct image. I looked
at the code of fromarray:

def fromarray(obj, mode=None):
    arr = obj.__array_interface__
    shape = arr['shape']
    ndim = len(shape)
        strides = arr['strides']
    except KeyError:
        strides = None
    if mode is None:
        typestr = arr['typestr']
        if not (typestr[0] == '|' or typestr[0] == _ENDIAN or
                typestr[1:] not in ['u1', 'b1', 'i4', 'f4']):
            raise TypeError("cannot handle data-type")
        typestr = typestr[:2]
        if typestr == 'i4':
            mode = 'I'
        elif typestr == 'f4':
            mode = 'F'
        elif typestr == 'b1':
            mode = '1'
        elif ndim == 2:
            mode = 'L'
        elif ndim == 3:
            mode = 'RGB'
        elif ndim == 4:
            mode = 'RGBA'
            raise TypeError("Do not understand data.")
    ndmax = 4
    if mode in ['1','L','I','P','F']:
        ndmax = 2
    elif mode == 'RGB':
        ndmax = 3
    if ndim > ndmax:
        raise ValueError("Too many dimensions.")

    size = shape[:2][::-1]
    if strides is not None:
        obj = obj.tostring()

    return frombuffer(mode, size, obj, "raw", mode, 0, 1)

it seems that when ndim is 4, the mode is set to RGBA. I'm not familiar with
the various image modes. However, I think it should be that shape[-1] == 4
instead of ndim == 4. And the same thing holds for 'RGB' and == 3.

Can anyone confirm me and fix this bug? Or correct me and provide a solution?

BTW: I'm not on this mailing list, please CC me when replying. Thanks!


More information about the Image-SIG mailing list