5

I'm attempting to rotate an image in python by copying each individual pixel into a new blank image, (I know, probably not the best way to do it but this is what I have the theoretical knowledge basis for). The original image is 360 pixels wide and 480 pixels tall. I'm getting errors throughout my code so I've pasted both relevant functions. The only time I dont get an error is when my range for y is less than three.

def rotate(img):
    height = int(img.getHeight())
    width = int(img.getWidth())
    turn = image.EmptyImage(height, width)
    xs = 0
    ys = 0
    for y in range(height):
        for x in range(width):
            px = img.getPixel(x, y)
            r = px.getRed()
            g = px.getGreen()
            b = px.getBlue()
            turnpx = image.Pixel(r, g, b)
            turn.setPixel(x+(width-xs), y, turnpx)
            xs+=1
    return turn

def main():
    img6 = image.Image("images//arch.gif")
    img7 = rotate(img6)
    if img7:
        win7 = image.ImageWin(img7.getWidth(), img7.getHeight(), "Win7")
        img7.draw(win7)

main()

The error messages I'm receiving are:

Traceback (most recent call last):
  File "C:\programs\test.py", line 28, in <module>
    main()
  File "C:\programs\test.py", line 23, in main
    img7 = rotate(img6)
  File "C:\programs\test.py", line 17, in rotate
    turn.setPixel(x+(width-xs), y, turnpx)
  File "C:\programs\image.py", line 467, in setPILPixel
    self.im.putpixel((x,y),pixel.getColorTuple())
  File "C:\programs\anaconda3\Lib\site-packages\PIL\Image.py", line 2136, in putpixel
    return self.im.putpixel(xy, value)
IndexError: image index out of range
10
  • (1) Are you sure that EmptyImage(height, width) is correct, and not EmptyImage(width, height); (2) if you print the values of x+(width-xs) in the loop, are they what you expect? Commented Nov 2 at 21:23
  • If you are getting Pixel(x, y), then for the turned image it would be setPixel(y, x, turnpx). x+(width-xs) would be mirroring the image, not turning Commented Nov 2 at 21:32
  • 1
    Please ensure your question is a proper minimal reproducible example. Without import statements, it certainly is not. Commented Nov 2 at 21:37
  • 1
    I don't understand why you split px into r,g,b and later use it to create turnpx - you get exaclty turnpx = px Commented Nov 2 at 23:20
  • 1
    I don't understand why you don't use Pillow's fast, efficient, built-in methods - flip(), mirror(), rotate()? Commented Nov 3 at 11:01

1 Answer 1

4

Your calculation is wrong you should move (x, y) to (y, x)
or to be more precise

  • (y, width - 1 - x) for -90
  • (height - 1 - y, x) for +90.

Your calculation rather match for mirror/flip.

  • (width - 1 - x, y) for horizontal flip
  • (x, height - 1 - y) for vertical flip

Full working code using pillow.

I added also sys.argv so I could test it with different files.

import sys
from PIL import Image


def rotate(img):

    width, height = img.size

    result = Image.new(img.mode, (height, width))

    for y in range(height):
        for x in range(width):
            px = img.getpixel((x, y))
            result.putpixel((y, width - 1 - x), px)  # rotate left   -90
            #result.putpixel((height - 1 - y, x), px)  # rotate right  +90

    return result


def mirror(img):

    width, height = img.size

    result = Image.new(img.mode, (width, height))

    for y in range(height):
        for x in range(width):
            px = img.getpixel((x, y))
            result.putpixel((width - 1 - x, y), px)   # horizontal flip
            #result.putpixel((x, height - 1 - y), px)  # vertical flip

    return result


def main():
    if len(sys.argv) > 1:
        input_filename = sys.argv[1]
    else:
        input_filename = "lenna.png"

    img1 = Image.open(input_filename)

    img2 = rotate(img1)
    img2.save("rotate_" + input_filename)

    img3 = mirror(img1)
    img3.save("mirror_" + input_filename)


main()

For tests I used image lenna.png from Wikipedia

Because original image has size 512x512 so I croped image to 341x512
to make sure it works also with not-square images.


Original (croped to 341x512)

enter image description here

Rotate

enter image description here

Mirror

enter image description here

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

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.