PIL: Thumbnail and end up with a square image

34,567

Solution 1

Paste the image into a transparent image with the right size as a background

from PIL import Image
size = (36, 36)
image = Image.open(data)
image.thumbnail(size, Image.ANTIALIAS)
background = Image.new('RGBA', size, (255, 255, 255, 0))
background.paste(
    image, (int((size[0] - image.size[0]) / 2), int((size[1] - image.size[1]) / 2))
)
background.save("output.png")

EDIT: fixed syntax error

Solution 2

PIL already has a function to do exactly that:

from PIL import Image, ImageOps
thumb = ImageOps.fit(image, size, Image.ANTIALIAS)

Solution 3

from PIL import Image

import StringIO

def thumbnail_image():
    image = Image.open("image.png")
    image.thumbnail((300, 200))
    thumb_buffer = StringIO.StringIO()
    image.save(thumb_buffer, format=image.format)
    fp = open("thumbnail.png", "w")
    fp.write(thumb_buffer.getvalue())
    fp.close()

Solution 4

Update of Cesar Canassa's answer.

This will create a thumbnail of image.jpg as image_thumb.jpg:

from PIL import Image, ImageOps
fname = 'image.jpg'
size = (48,48)
thumb = ImageOps.fit(Image.open(fname), size, Image.ANTIALIAS)
thumb.save('{}_thumb.jpg'.format(fname[:fname.rfind('.')]), "JPEG")

Solution 5

Why not simply use the resize method ?

from PIL import Image
image = Image.open('/path/to/img.png')
image = image.resize((36,36), Image.ANTIALIAS)

See recommendations for image resizing in this release note: https://pillow.readthedocs.io/en/stable/releasenotes/5.3.0.html

Share:
34,567
Paul Tarjan
Author by

Paul Tarjan

I'm a Distinguished Engineer at Robinhood. I used to be the Tech Lead of Developer Productivity at Stripe where I built Sorbet. Before that I was the CTO and cofounder at Trimian. Before that I was a Software Engineer at Facebook on HHVM and the Open Graph. Before that I was the Tech Lead for Yahoo! SearchMonkey. See my homepage for more.

Updated on December 11, 2020

Comments

  • Paul Tarjan
    Paul Tarjan over 3 years

    Calling

    image = Image.open(data)
    image.thumbnail((36,36), Image.NEAREST)
    

    will maintain the aspect ratio. But I need to end up displaying the image like this:

    <img src="/media/image.png" style="height:36px; width:36px" />
    

    Can I have a letterbox style with either transparent or white around the image?