'Python: Image resizing: keep proportion - add white background
I would like to create a Python script to resize images, but not changing its proportions, just by adding a white background
(So, a : 500*700 px image would transform to a 700*700 px image by adding 100 px of a white band on each side)
The three image types I use are .PNG, .JPG and .GIF. I am not even sure it is possible for Gifs, PNG and JPG would already be awesome.
In my case, they have to be squares. But if any of you manage to do it for adaptable to any proportion, it would benefit the maximum number of people that see this thread and you would be even more awesome !
I saw same threads for other languages but not python, do you guys know how you do this ?
PS : I am using Python 3
What I tried :
Combining 3 images together.
If we take our 500*700 px image : Creating two white images of 100*700px and put one on each side of the image. Inspired by :
Combine several images horizontally with Python
But, I am kind of new on python, and I haven't succeded.
Solution 1:[1]
Finally did it :
def Reformat_Image(ImageFilePath):
from PIL import Image
image = Image.open(ImageFilePath, 'r')
image_size = image.size
width = image_size[0]
height = image_size[1]
if(width != height):
bigside = width if width > height else height
background = Image.new('RGBA', (bigside, bigside), (255, 255, 255, 255))
offset = (int(round(((bigside - width) / 2), 0)), int(round(((bigside - height) / 2),0)))
background.paste(image, offset)
background.save('out.png')
print("Image has been resized !")
else:
print("Image is already a square, it has not been resized !")
Thanks to @Blotosmetek for the suggestion, pasting a centered image is definitely simpler than creating images and combining them !
PS : If you don't have PIL yet, the library's name to install it with pip is "pillow", not PIL. But still, you use it as PIL in the code.
Solution 2:[2]
Thanks @Jay D., here a bit more general version:
from PIL import Image
def resize(image_pil, width, height):
'''
Resize PIL image keeping ratio and using white background.
'''
ratio_w = width / image_pil.width
ratio_h = height / image_pil.height
if ratio_w < ratio_h:
# It must be fixed by width
resize_width = width
resize_height = round(ratio_w * image_pil.height)
else:
# Fixed by height
resize_width = round(ratio_h * image_pil.width)
resize_height = height
image_resize = image_pil.resize((resize_width, resize_height), Image.ANTIALIAS)
background = Image.new('RGBA', (width, height), (255, 255, 255, 255))
offset = (round((width - resize_width) / 2), round((height - resize_height) / 2))
background.paste(image_resize, offset)
return background.convert('RGB')
Solution 3:[3]
The other answer didn't work for me, I rewrote it and this worked:
def resize_with_pad(im, target_width, target_height):
'''
Resize PIL image keeping ratio and using white background.
'''
target_ratio = target_height / target_width
im_ratio = im.height / im.width
if target_ratio > im_ratio:
# It must be fixed by width
resize_width = target_width
resize_height = round(resize_width * im_ratio)
else:
# Fixed by height
resize_height = target_height
resize_width = round(resize_height / im_ratio)
image_resize = im.resize((resize_width, resize_height), Image.ANTIALIAS)
background = Image.new('RGBA', (target_width, target_height), (255, 255, 255, 255))
offset = (round((target_width - resize_width) / 2), round((target_height - resize_height) / 2))
background.paste(image_resize, offset)
return background.convert('RGB')
Solution 4:[4]
The accepted answer is great, I am just happy not to use OpenCV.
As @Nemanja mentioned, if you want to make it work for any aspect ration. Here is the snippet to use. I just twisted the code a bit.
from PIL import Image
def Reformat_Image_With_Ratio(ImageFilePath, desired_aspect_ratio):
image = Image.open(ImageFilePath, 'r')
width = image.width
height = image.height
img_aspect_ratio = width/height
if (img_aspect_ratio != desired_aspect_ratio):
bigside = width if width > height else height
other_side = int(bigside * desired_aspect_ratio)
background = Image.new('RGBA', (other_side, bigside), (255, 0, 0, 255))
offset = (int(round(((bigside - width) / 2), 0)), int(round(((bigside - height) / 2),0)))
background.paste(image, offset)
background.save('out4.png')
print("Image has been resized !")
else:
print("Image is already a valid aspect ratio, it has not been resized !")
Reformat_Image_With_Ratio('test.png', 9/16)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Jay D. |
Solution 2 | |
Solution 3 | pyjamas |
Solution 4 | Aditya Rajgor |