简体   繁体   中英

How to resize image and save it - django

I have an app that for storing uploaded files (images, zip, videos..etc). I use model FileField to handle the upload. The thing is when upload image I want to resize the image and save it in another field (thumb) in the model.

here is my models.py

class Files(models.Model):
    file = models.FileField(upload_to=upload_path())
    thumb =  models.CharField(max_length=255,default=None,blank=True , null=True)
    user = models.ForeignKey(User, null=True,blank=True)
    date =  models.DateTimeField('date added',blank=True, null=True)

The file is for store the original file url, and the thumb is to store the thumbnail url.

I know we can use PIL to do the resize, but I am novice in python, I don't how can I use it and save it in the app.

It's a module I wrote for my flask application website but you can change it for Django application and use it. It creates thumbnails and crops images. Pretty useful for me:

"""
usage: <img src="{{ thumbnail('files/'+media.path, '150x150') }}" alt="" />
"""

# python imports
import os
import errno
import traceback

try:
    from PIL import Image, ImageOps
except ImportError:
    raise RuntimeError('Image module of PIL needs to be installed')


class Thumbnail(object):

    def __init__(self, app=None):
        if app is not None:
            self.init_app(self.app)
        else:
            self.app = None

    def init_app(self, app):
        self.app = app

        if not self.app.config.get('MEDIA_FOLDER', None):
            raise RuntimeError('You\'re using the flask-thumbnail app '
                               'without having set the required MEDIA_FOLDER setting.')

        if not self.app.config.get('THUMBNAIL_FOLDER', None):
            raise RuntimeError(
                'You didn\'t set THUMBNAIL_FOLDER setting.')

        app.config.setdefault('THUMBNAIL_FOLDER', os.path.join(self.app.config['MEDIA_FOLDER'], 'thumbnail'))
        app.config.setdefault('MEDIA_URL', '/media/')
        app.config.setdefault('THUMBNAIL_URL', os.path.join(self.app.config['MEDIA_URL'], 'thumbnail'))

        app.jinja_env.globals['thumbnail'] = self.thumbnail

    def thumbnail(self, img_url, size, crop=None, bg=None, quality=92):
        """

        :param img_url: url img - '/assets/media/summer.jpg'
        :param size: size return thumb - '100x100'
        :param crop: crop return thumb - 'fit' or None
        :param bg: tuple color or None - (255, 255, 255, 0)
        :param quality: JPEG quality 1-100
        :return: :thumb_url:
        """
        try:
            width, height = [int(x) for x in size.split('x')]
            url_path, img_name = os.path.split(img_url)
            name, fm = os.path.splitext(img_name)

            miniature = self._get_name(name, fm, size, crop, bg, quality)

            original_filename = os.path.join(
                self.app.config['MEDIA_FOLDER'],
                url_path,
                img_name)
            thumb_filename = os.path.join(
                self.app.config['THUMBNAIL_FOLDER'],
                miniature)

            # create folders
            self._get_path(thumb_filename)

            thumb_url = os.path.join(
                self.app.config['THUMBNAIL_URL'],
                miniature)

            if os.path.exists(thumb_filename):
                return thumb_url

            elif not os.path.exists(thumb_filename):
                thumb_size = (width, height)
                try:
                    image = Image.open(original_filename)
                except IOError:
                    return None

                if crop == 'fit':
                    img = ImageOps.fit(image, thumb_size, Image.ANTIALIAS)
                else:
                    img = image.copy()
                    img.thumbnail((width, height), Image.ANTIALIAS)

                if bg:
                    img = self._bg_square(img, bg)

                img.save(thumb_filename, image.format, quality=quality)

                return thumb_url
        except Exception, e:
            traceback.print_exc()
            print(e.message)

    @staticmethod
    def _bg_square(img, color=0xff):
        size = (max(img.size),) * 2
        layer = Image.new('L', size, color)
        layer.paste(
            img, tuple(map(lambda x: (x[0] - x[1]) / 2, zip(size, img.size))))
        return layer

    @staticmethod
    def _get_path(full_path):
        directory = os.path.dirname(full_path)

        try:
            if not os.path.exists(full_path):
                os.makedirs(directory)
        except OSError as e:
            if e.errno != errno.EEXIST:
                raise

    @staticmethod
    def _get_name(name, fm, *args):
        for v in args:
            if v:
                name += '_%s' % v
        name += fm

        return name

This is how I make it work.

from django.core.files.uploadedfile import InMemoryUploadedFile

def create_thumbnail(obj, ext=None):
    imaged, imgformat = resize_and_crop(obj.file, (150, 150),crop_type='middle' )
    thumb_io = BytesIO()
    imaged.save(thumb_io,  format=imgformat, quality=92)
    new_file_name = u'thumb-' + str(obj.file.name)
    thumbfile = InMemoryUploadedFile(thumb_io,
                            u"thumb", # important to specify field name here
                            new_file_name,
                            ext,
                            thumb_io,
                            None)
    return thumbfile

class Files(models.Model):
    file = models.FileField(upload_to=upload_path())
    thumb =  models.FileField(max_length=255,default=None,blank=True , null=True)
    user = models.ForeignKey(User, null=True,blank=True)
    date =  models.DateTimeField('date added',blank=True, null=True)

    def save(self, *args, **kwargs):
        self.url = create_thumbnail(self, ext)       
        return super(MediaUpload, self).save(*args, **kwargs)

The resize_and_crop() was refer to this excellent script .

The point at here is using the InMemoryUploadedFile to save the file in the memory and pass it to the FileField to do the rest of the job.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM