Search code examples
djangothumbnailseasy-thumbnails

Padded fit with easy thumbnails


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!


Solution

  • 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