PIL : How to write array to image ???

Scott David Daniels Scott.Daniels at Acm.Org
Tue Oct 6 11:49:48 EDT 2009


Mart. wrote:
> On Oct 5, 5:14 pm, Martin <Mar... at Hvidberg.net> wrote:
>> 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 think what Martin is telling you is:

Look to numpy to continue working on the array first.

     byte_store = imgL.astype(np.uint8)
     Image.fromarray(byte_store).save('_a%s.png' % lev)

--Scott David Daniels
Scott.Daniels at Acm.Org



More information about the Python-list mailing list