Florian Pellegrin Florian Pellegrin - 4 months ago 17
Python Question

Python Error: IndexError: image index out of range (im.putpixel)

Newbie here. =) I tried to reverse an image but there's an error and I don't know why :/

The Error:

Traceback (most recent call last):
File "C:/Users/Florian/Documents/ISN/S10/défi11.py", line 10, in <module>
im.putpixel((x,600-y),(p[0],p[1],p[2]))
File "C:\Python27\lib\site-packages\PIL\Image.py", line 1267, in putpixel
return self.im.putpixel(xy, value)
IndexError: image index out of range


The Code:

# -*- coding: cp1252 -*-
from PIL import Image
im=Image.open("H:\Belem.png")
L,H=im.size
for y in range(H):
for x in range(L):
p=im.getpixel((x,y))
im.putpixel((x,600-y),(p[0],p[1],p[2]))
im.save("H:\defi11.png")

Answer

I you mean to flip the image vertically, then you should do this:

for y in range(H/2):
    for x in range(L):
        p1=im.getpixel((x,y))
        p2=im.getpixel((x,H-1-y))
        im.putpixel((x,H-1-y),p1)
        im.putpixel((x,y),p2)

This avoid overwriting pixels you will need later. It only loops over the first half of the lines, and exchanges them with the other half of the lines. Another approach would be to create a different output image with the same shape to write to:

im2 = im.copy()
for y in range(H):
    for x in range(L):
        p=im.getpixel((x,y))
        im2.putpixel((x,H-1-y),p1)
im2.save("flipped.png")

This has the same effect as the version above, but uses more memory.

I guess the 600 in your example is a hardcoded version of H, but you have to subtract one extra from that (like I do above) in order to take into account that the indices go from 0 to H-1, not from 1 to H. On the first loop of your program y is zero, so 600-y is 600. If 600 is the height of the image, then you are going one beyond the last index (600-1), and hence triggering an IndexError exception.

If you have numpy installed, then a faster and simpler way to achieve the same thing is:

import numpy as np, PIL
original=PIL.Image.open("original.png")
arr = np.array(im)
flipped = PIL.Image.fromarray(arr[::-1])
flipped.save("flipped.png")

The numpy format also makes it easy to perform other operations like doing maths on the pixels.

Comments