2

This turned out to be a very specific bug in a pre-7.0 version of PIL. I'm leaving it here because I've seen other hit the same issue and there isn't a good overview of what you see. There is no programming error here - the solution is "upgrade PIL"

I'm converting a numpy boolean array (ie, a mask) to a PIL image, and seeing a very odd behaviour.

# using PIL pixel access - works as expected
img = Image.new('1', (100, 100)) # '1' for 1-bit image mode
img_pixels = img.load()

for x in range(1, 99):
    for y in range(1, 50):
        img_pixels[x,y] = True

img

PIL Pixel Access version

# Numpy array, turning into a PIL image. 
ary = np.zeros((100,100), dtype=np.bool)

for x in range(1, 99):
    for y in range(1, 50):
        ary[x,y] = True
      
Image.fromarray(ary)

numpy version

If I inspect the values of ary it appears the True values are appropriately set.

So why are these images different?

Edit:

If I reverse x and y for the numpy version I get this. It's clear that something else is going on because if it was just rows and columns reversed I should get the same shape but vertically aligned.

ary = np.zeros((100,100), dtype=np.bool)

for x in range(1, 99):
    for y in range(1, 50):
        ary[y,x] = True # note that rows and columns are reversed
      
Image.fromarray(ary)

numpy using column,row ordering

8
  • numpy array uses [row,col] which means [y,x] Commented Aug 5, 2020 at 2:11
  • I've edited to show the image generated using [y,x] Commented Aug 5, 2020 at 5:50
  • Side note: you could replace the nested for loops in the last snippet by ary[1:51, 1:100] = True Commented Aug 5, 2020 at 7:37
  • when I run your code with [y,x] then it gives me correct image. When I run with [x,y] then it gives me also correct image but rotated 90 degrees. You have to do something else and it makes problem. OR problem is in different place. Commented Aug 5, 2020 at 11:05
  • We can't reproduce your problem so we don't know why you get different results. You can try to save in file and open in diffferent image vewers. BTW: do you run it in some console or notebook. I had to use img.show() to display it. Commented Aug 5, 2020 at 11:13

2 Answers 2

1

PIL has reverse x and y locations. To fix it, exchange x and y in your code:

ary = np.zeros((100,100), dtype=np.bool)

for x in range(1, 99):
    for y in range(1, 50):
        ary[y,x] = True
      
Image.fromarray(ary)

enter image description here

Sign up to request clarification or add additional context in comments.

5 Comments

This doesn't work. I've edited the question to show what happens if you do this, but also if it was as simple as reversing the x and y I'd have the same shape but aligned vertically.
After some debugging, the scrambled images turned out to be caused by a pre-7.0 version of the PIL library. This answer is correct in that there is also a x,y reversal bug in my code, which is easy to see once the bug-free library version is used!
@NickLothian Feel free to accept the answer to close the question. Also, as a recommendation for future posts, if there is an answer with posted desired output, and you do not get the same output as the post, the best is to try and upgrade the libraries.
Sorry - I can't accept this answer because it doesn't correctly solve the issue as posted.
@NickLothian LOL, alright. You can later accept your own answer to close the question anyways.
0

This turned out to be a bug in an earlier version of PIL that was fixed by at least version 7.0

With

  • PIL: 7.2.0
  • numpy: 1.19.1

the behaviour is as expected. Thanks to @furas for his help testing.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.