How do I make PIL take into account the shortest side when creating a thumbnail?

Currently, for my function below...the image will be resized based on the longest side.

Basically the image has a larger height, the height will be 200px. The width will be just...whatever...

If the image has a larger width, the width will be 200px, and the height will adjust accordingly.

How do I flip this around!? I want this function to take into account the shortest side.

Am I writing this function incorrectly??

def create_thumbnail(f, width=200, height=None, pad = False):
    #resizes the longest side!!! doesn't even care about the shortest side
    #this function maintains aspect ratio.
    if height==None: height=width
    im = Image.open(StringIO(f))
    imagex = int(im.size[0])
    imagey = int(im.size[1])
    if imagex < width or imagey < height:
        pass
        #return None
    if im.mode not in ('L', 'RGB', 'RGBA'):
        im = im.convert('RGB')
    im.thumbnail((width, height), Image.ANTIALIAS)
    thumbnail_file = StringIO()
    im.save(thumbnail_file, 'JPEG')
    thumbnail_file.seek(0)
    return thumbnail_file

Answers


Use resize instead of thumbnail.

The point behind thumbnail is to make it easy to scale an image down to fit within a particular bounding box preserving aspect ratio. That means that if your bounding box is a square, the longer side of the image determines the scale used.

resize gives you more direct control -- you specify exactly what size you want.

Actually, since you want to preserve aspect you could still use thumbnail, but you need to fudge the bounding box. Before your call to thumbnail, try doing this:

old_aspect = float(imagex)/float(imagey)
new_aspect = float(width)/float(height)
if old_aspect < new_aspect:
  height = int(width / old_aspect)
else:
  width = int(height * old_aspect)

i put together this function a while ago:

def thumbnail(img, size=150):

    from math import floor
    from PIL import Image

    img = img.copy()

    if img.mode not in ('L', 'RGB'):
        img = img.convert('RGB')

    width, height = img.size

    if width == height:
        img.thumbnail((size, size), Image.ANTIALIAS)

    elif height > width:
        ratio = float(width) / float(height)
        newwidth = ratio * size
        img = img.resize((int(floor(newwidth)), size), Image.ANTIALIAS)

    elif width > height:
        ratio = float(height) / float(width)
        newheight = ratio * size
        img = img.resize((size, int(floor(newheight))), Image.ANTIALIAS)

    return img

image = thumbnail(image, size=600)

it resizes an image down to at most size on its longest size preserving aspect ratio


Need Your Help

Show codebehinde in aspx

c# asp.net

Hi i just open new page in VS and added one simple line, question why date time isn't showing? There is just blak page.

Format Nullable DataTime in a WPF DataGrid

c# wpf xaml converter ivalueconverter

In a WPF application, i display data in a datagrid.

Custom UItabBarItem with green color

objective-c ios

i would like to put a green image to my Tabbar button ( item). Can i do this or it's forbidden by Apple ?