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)