Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 999
Jay D. Avatar asked Jun 05 '17 13:06

Jay D.


3 Answers

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')
like image 96
estevo Avatar answered Oct 26 '22 17:10

estevo


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.

like image 38
Jay D. Avatar answered Oct 26 '22 16:10

Jay D.


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)
like image 31
Aditya Rajgor Avatar answered Oct 26 '22 17:10

Aditya Rajgor