PIL : How to write array to image ???

Martin Martin at Hvidberg.net
Mon Oct 5 18:14:25 CEST 2009


On Oct 4, 10:16 pm, "Mart." <mdeka... at gmail.com> wrote:
> On Oct 4, 9:47 am, Martin <Mar... at Hvidberg.net> wrote:
>
>
>
> > On Oct 3, 11:56 pm, Peter Otten <__pete... at web.de> wrote:
>
> > > Martin wrote:
> > > > Dear group
>
> > > > I'm trying to use PIL to write an array (a NumPy array to be exact) to
> > > > an image.
> > > > Peace of cake, but it comes out looking strange.
>
> > > > I use the below mini code, that I wrote for the purpose. The print of
> > > > a looks like expected:
>
> > > > [[ 200.  200.  200. ...,    0.    0.    0.]
> > > >  [ 200.  200.  200. ...,    0.    0.    0.]
> > > >  [ 200.  200.  200. ...,    0.    0.    0.]
> > > >  ...,
> > > >  [   0.    0.    0. ...,  200.  200.  200.]
> > > >  [   0.    0.    0. ...,  200.  200.  200.]
> > > >  [   0.    0.    0. ...,  200.  200.  200.]]
>
> > > > But the image looks nothing like that.
>
> > > > Please see the images on:
> > > >http://hvidberg.net/Martin/temp/quat_col.png
> > > >http://hvidberg.net/Martin/temp/quat_bw.png
>
> > > > or run the code to see them locally.
>
> > > > Please – what do I do wrong in the PIL part ???
>
> > > > :-? Martin
>
> > > > import numpy as np
> > > > from PIL import Image
> > > > from PIL import ImageOps
>
> > > > maxcol = 100
> > > > maxrow = 100
>
> > > > a = np.zeros((maxcol,maxrow),float)
>
> > > > for i in range(maxcol):
> > > >     for j in range(maxrow):
> > > >         if (i<(maxcol/2) and j<(maxrow/2)) or (i>=(maxcol/2) and j>=
> > > > (maxrow/2)):
> > > >             a[i,j] = 200
> > > >         else:
> > > >             a[i,j] = 0
>
> > > > print a
>
> > > > pilImage = Image.fromarray(a,'RGB')
> > > > pilImage.save('quat_col.png')
> > > > pilImage = ImageOps.grayscale(pilImage)
> > > > pilImage.save('quat_bw.png')
>
> > > The PIL seems to copy the array contents directly from memory without any
> > > conversions or sanity check. In your example The float values determine the
> > > gray value of 8 consecutive pixels.
>
> > > If you want a[i,j] to become the color of the pixel (i, j) you have to use
> > > an array with a memory layout that is compatible to the Image.
> > > Here are a few examples:
>
> > > >>> import numpy
> > > >>> from PIL import Image
> > > >>> a = numpy.zeros((100, 100), numpy.uint8)
> > > >>> a[:50, :50] = a[50:, 50:] = 255
> > > >>> Image.fromarray(a).save("tmp1.png")
> > > >>> b = numpy.zeros((100, 100, 3), numpy.uint8)
> > > >>> b[:50, :50, :] = b[50:, 50:, :] = [255, 0, 0]
> > > >>> Image.fromarray(b).save("tmp2.png")
> > > >>> c = numpy.zeros((100, 100), numpy.uint32)
> > > >>> c[:50, :50] = c[50:, 50:] = 0xff808000
> > > >>> Image.fromarray(c, "RGBA").save("tmp3.png")
>
> > > Peter
>
> > Thanks All - That helped a lot...
>
> > The working code ended with:
>
> >         imga = np.zeros((imgL.shape[1],imgL.shape[0]),np.uint8)
> >         for ro in range(imgL.shape[1]):
> >             for co in range(imgL.shape[0]):
> >                 imga[ro,co] = imgL[ro,co]
> >         Image.fromarray(imga).save('_a'+str(lev)+'.png')
>
> Without knowing how big your image is (can't remember if you said!).
> Perhaps rather than looping in the way you might in C for example, the
> numpy where might be quicker if you have a big image. Just a
> thought...

And a good thought too... I use to teach ansi C at Univ. many ears
ago, and it's still one of my favorits. But I prefere Python for this
type of work. Python have a much faster develop time, is much easier
to write (fewer linees, simpler syntax) and is much more 'hot' in
these days. Finally my favorit GIS and RS applications support Python
out-of-the-box.

:-) Martin



More information about the Python-list mailing list