0
def rotate_picture_90_left(img: Image) -> Image: img_width, img_height = img.size pixels = img.load() # create the pixel map # for every pixel for i in range(img_width): for j in range(img_height): r, g, b = pixels[i, j] pixels[j,i] = (r,g,b) return img 

I am using pillow to assist me trying to manipulate the image and make it rotate clockwise by reversing the width and length to get the clockwise rotation of the image, but the result is just unable to compute,I was wondering how do i do this correctly?

3
  • Think about how the i,j coordinates work and you’ll see that your code can’t possibly work to modify img in-place if the image isn’t square. Commented Apr 3, 2020 at 6:55
  • Could you please complete your code with what Image is and possibly an appropriate set of imports? Commented Apr 3, 2020 at 7:01
  • all of my sample test image are squares, maybe I should change it to pixels[i , j ] = pixels [j, i]? will that swap of coordinate work? Commented Apr 3, 2020 at 7:14

1 Answer 1

0

There are 3 main issues with your code:

  • you do not return a modified image, you just return the original one, since the modifications are done on pixels
  • the modification you do will not rotate the image if you do them inplace, because by the time you modify the pixel at (0, 1) with the pixel at (1, 0) you would have lost what you had in (0, 1) originally.
  • the algorithm would not produce a 90° rotation but a transposition!

If the image is square, the second issue can be addressed with swapping. Otherwise, all issues can be addressed by creating an empty result and filling it in using some algorithm similar to what you used.

However, note that unless you are doing this to learn, NumPy offers both np.rot90() and np.transpose().


In code, you can separate the array handling from the image handling. The image handling can be delegated to the following function:

import numpy as np import PIL as pil def modify_image(img: pil.Image, func: callable, *args, **kws): arr = np.array(img) # transform to NumPy array result = func(arr, *args, **kws) return pil.Image.fromarray(result) # transform to PIL image 

As for the transformation, you could use np.rot90(), np.transpose() or something else:

new_img = modify_image(img, np.rot90) 

Assuming you want to see how a 90° rotation can be implemented manually (to be clear: I would never use this code in production), you could use:

def rot90(arr): if arr.ndim > 2: shape = arr.shape[1::-1] + arr.shape[2:] elif arr.ndim == 2: shape = arr.shape[::-1] else: raise ValueError('Input dim must be 2 or more') result = np.empty(shape, dtype=arr.dtype) for i in range(shape[0]): for j in range(shape[1]): result[shape[0] - i - 1, j, ...] = arr[j, i, ...] return result 

to be used as before:

new_img = modify_image(img, rot90) 
Sign up to request clarification or add additional context in comments.

6 Comments

yes, i am doing this to learn, and I am still a bit confused, so should i be creating a new blank image and fill that image with the reversal of length and width of image, and should i not be using for loops because from my understanding of the second point is that if i use for loop everytime i loop the previous coordinate would of been changed by the time it gets there
You have to create a new blank image, and you can use for loops, but inside the for loops you shall use: target_pixels[i, j] = source_pixels[j, i] or similar.
do i need to create a new: 'target_img_width, target_img_height = target_img.size target_pixels = target_img.load()'? and than match the: target_pixels [i,j] = pixels[ j, i]?
Why do want to use target_img.load()?
does that create a new blank image load?
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.