[Image-SIG] fromarray rotates image

Chris Barker chris.barker at noaa.gov
Tue Jan 31 19:18:22 CET 2012

<putting the image-sig list back on the thread... >

On Tue, Jan 31, 2012 at 8:38 AM, Cousoulis, Paul
<pcousoulis at meso-scale.com> wrote:
> I'm sorry but I still think there is a bug.

I still don't think so: explanation below.

By the way, there is another problem with your example -- I get an
all-black second image. I think you need to specify the image mode
when you create the new image:

newimage = Image.fromarray(npArray, mode=image1.mode)

though that still makes a mess of it! -- more debugging to be done
here -- see below

> In [4]: print image1.size
> (516, 356)
> In [5]: npArray = np.array(image1.getdata())
> In [6]: print npArray.shape
> (183696L,)

OK so far

> In [7]: npArray.shape = image1.size

> In [8]: print npArray.shape
> (516L, 356L)

here I would swap -- as numpy naturally stores data the other way:

and now it works:

In [8]: run pil-numpy-test.py
<PIL.TiffImagePlugin.TiffImageFile image mode=L size=516x356 at 0x3A86468>
input image size: (516, 356)
numpy image shape before: (183696,)
numpy image shape after: (356, 516)
<PIL.Image.Image image mode=L size=516x356 at 0x176C1E8>
new image size (516, 356)

(though the colors are still screwed up -- I don't know what's up with that...)

I can see how you'd expect it to work the way you had it, but I think
the problem is that you are mixing two ways to push raw data to/froim
numpy arrays:

npArray = np.array(image1.getdata())

is using PIL's getdata() to put the raw data in a string, then turning
that into a numpy array (oh, and that may be the source of teh data
mess up too...np.array is expecting a sequence of numbers or
something, not raw data -- you want:

OOPS, actually, getdata returns something else altogether:


im.getdata() => sequence

Returns the contents of an image as a sequence object containing pixel
values. The sequence object is flattened, so that values for line one
follow directly after the values of line zero, and so on.

Note that the sequence object returned by this method is an internal
PIL data type, which only supports certain sequence operations,
including iteration and basic sequence access. To convert it to an
ordinary sequence (e.g. for printing), use list(im.getdata()).
so it should be:

npArray = np.fromstring(image1.tostring(), dtype=np.uint8)

npArray.shape = (image1.size[1], image1.size[0] )

and that now works -- correct size, and correct final image.


newimage = Image.fromarray(npArray)

is using the numpy "array protocol", which is a bit different than
fromstring/tostring -- it carries shape information -- hence the need
to specify the shape of the numpy array as I did.

you can use that protocol both ways:

npArray = np.asarray(image1)

which then preserved size info.

Here's my new version:

from PIL import Image
import numpy as np

image1 = Image.open("LineGraph.tif")
print image1
print "input image size:", image1.size

npArray = np.asarray(image1)

print "numpy image shape after:", npArray.shape

newimage = Image.fromarray(npArray, mode=image1.mode)

print newimage
print "new image size", newimage.size


NOTE: if you do fromstring/tostring (or tobuffer) consistently, then
it doesn't matter what shape you make the numpy array:

image1 = Image.open("LineGraph.tif")
print image1
print "input image size:", image1.size

npArray = np.fromstring(image1.tostring(), dtype=np.uint8)

print "numpy image shape:", npArray.shape

newimage = Image.fromstring(image1.mode, image1.size, npArray.tostring())

print newimage
print "new image size", newimage.size


But that's less efficient, and messier.

NOTE: it might have been nicer if the array protocol were used such
that the array created was fortran-order, and thus (w,h) in shape, but
so it goes.




Christopher Barker, Ph.D.

Emergency Response Division
NOAA/NOS/OR&R            (206) 526-6959   voice
7600 Sand Point Way NE   (206) 526-6329   fax
Seattle, WA  98115       (206) 526-6317   main reception

Chris.Barker at noaa.gov

More information about the Image-SIG mailing list