Padded fit with easy thumbnails
Asked Answered
C

2

7

I'm using easy-thumbnails to make thumbnails for my site. I want to create a thumbnail from an image that's 1500x1023px. The size of the desired thumbnail is 100x100px. What I want is for the thumbnail to show the entire logo rather than cropping or stretching. I've seen this referred to as a padded fit - kind the opposite of a crop. For example, for this image, we'd add 236px of whitespace on the top and 237px of whitespace on the bottom and then resize. Is there any way to do this with easy-thumbnails? If not, any suggestions on how to approach this? Thanks!

Crinum answered 14/8, 2012 at 20:17 Comment(2)
What happens when you don't use the crop option? You are able to manually assign the processors that are performed on the image (i.e. the steps that are taken to create the thumbnail), so you could write your own padded fit and add it to the THUMBNAIL_PROCESSORSDna
That's a great suggestion. Thanks. I'll report back with the code.Crinum
C
9

Thanks for Timmy O'Mahony's suggestion of creating a processor to do the padding. Here's the code for those of you that come up against a similar issue. To get this to work, you'll need something like this in settings:

THUMBNAIL_PROCESSORS = (
    'easy_thumbnails.processors.colorspace',
    'common.thumbnail_processors.pad_image',
    'easy_thumbnails.processors.autocrop',
    'easy_thumbnails.processors.scale_and_crop',
    'easy_thumbnails.processors.filters')

And then you can add this to common/thumbnail_processors.py (or wherever)

import Image

def pad_image(image, **kwargs):
    """ Pad an image to make it the same aspect ratio of the desired thumbnail.
    """

    img_size = image.size
    des_size = kwargs['size']
    fit = [float(img_size[i])/des_size[i] for i in range(0,2)]

    if fit[0] > fit[1]:
        new_image = image.resize((image.size[0],
            int(round(des_size[1]*fit[0]))))
        top = int((new_image.size[1] - image.size[1])/2)
        left = 0
    elif fit[0] < fit[1]:
        new_image = image.resize((int(round(des_size[0]*fit[1])), 
            image.size[1]))
        top = 0
        left = int((new_image.size[0] - image.size[0])/2)
    else:
        return image

    # For transparent
    #mask=Image.new('L', new_image.size, color=0)
    #new_image.putalpha(mask)

    # For white
    new_image.paste((255, 255, 255, 255))

    new_image.paste(image, (left, top))
    return new_image
Crinum answered 15/8, 2012 at 23:54 Comment(0)
C
3

Thanks a lot for that answer, Josh! This is exactly what I was looking for since a few weeks. However, your solution mysteriously doesn't work on some images.

Here is a (fully functionnal) revised version of that thumbnail processor: https://bitbucket.org/bercab/cmsplugin-nivoslider/src/b07db53c1ce4/cmsplugin_nivoslider/thumbnail_processors.py

Calcite answered 7/9, 2012 at 2:46 Comment(2)
Happy it helped @Bertrand. Unless you made significant changes, you might consider simply commenting on my answer rather than writing a separate answer.Crinum
I know, but I'm unable to comment other posts than mine. I guess one needs more "reputation" to achieve this.Calcite

© 2022 - 2024 — McMap. All rights reserved.