Does Python PIL resize maintain the aspect ratio?

Viewed 86919

Does PIL resize to the exact dimensions I give it no matter what? Or will it try to keep the aspect ratio if I give it something like the Image.ANTIALIAS argument?

10 Answers

Recent Pillow version (since 8.3) have the following method to have an image resized to fit in given box with keeping aspect ratio.

image = ImageOps.contain(image, (2048,2048))

No, it does not. But you can do something like the following:

im = PIL.Image.open("email.jpg"))
width, height = im.size
im = im.resize((width//2, height//2))

Here the height and width are divided by the same number, keeping the same aspect ratio.

Okay, so this requires a couple of lines of code to get what you want.

First you find the ratio, then you fix a dimension of the image that you want (height or width). In my case, I wanted height as 100px and let the width adjust accordingly, and finally use that ratio to find new height or new width.

So first find the dimensions:

width, height = logo_img.size
ratio = width / height
      

Then, fix one of the dimension:

new_height = 100

Then find new width for that height:

new_width = int(ratio * new_height)
            
logo_img = logo_img.resize((new_width, new_height))

It depends on your demand, if you want you can set a fixed height and width or if you want you can resize it with aspect-ratio.

For the aspect-ratio-wise resize you can try with the below codes :

To make the new image half the width and half the height of the original image:

from PIL import Image
im = Image.open("image.jpg")
resized_im = im.resize((round(im.size[0]*0.5), round(im.size[1]*0.5)))
        
#Save the cropped image
resized_im.save('resizedimage.jpg')

To resize with fixed width and ratio wise dynamic height :

from PIL import Image
new_width = 300
im = Image.open("img/7.jpeg")
concat = int(new_width/float(im.size[0]))
size = int((float(im.size[1])*float(concat)))
resized_im = im.resize((new_width,size), Image.ANTIALIAS)
#Save the cropped image
resized_im.save('resizedimage.jpg')

Recent versions of Pillow have some useful methods in PIL.ImageOps.

Depending on exactly what you're trying to achieve, you may be looking for one of these:

  • ImageOps.fit(image, size [, …]) (docs) – resizes your image, maintaining its aspect ratio, and crops it to fit the given size

  • ImageOps.contain(image, size [, …]) (docs) – resizes your image, maintaining its aspect ratio, so that it fits within the given size

One complete example:

import PIL.Image


class ImageUtils(object):
    @classmethod
    def resize_image(cls, image: PIL.Image.Image, width=None, height=None) -> PIL.Image.Image:
        if height is None and width is not None:
            height = image.height * width // image.width
        elif width is None and height is not None:
            width = image.width * height // image.height
        elif height is None and width is None:
            raise RuntimeError("At lease one of width and height must be present")
        return image.resize((width, height))


def main():
    ImageUtils.resize_image(PIL.Image.open("old.png"), width=100).save("new.png")


if __name__ == '__main__':
    main()

I think following is the easiest way to do:

Img1 = img.resize((img.size),PIL.Image.ANTIALIAS)
Related