簡體   English   中英

如何調整圖像大小並保存-Django

[英]How to resize image and save it - django

我有一個用於存儲上傳文件(圖像,zip,視頻等)的應用。 我使用FileField模型處理上傳。 問題是當我上載圖像時,我想調整圖像的大小並將其保存在模型的另一個字段(縮略圖)中。

這是我的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)

文件用於存儲原始文件的URL, 拇指用於存儲縮略圖的URL。

我知道我們可以使用PIL進行大小調整,但是我是python的新手,我不知道如何使用它並將其保存在應用程序中。

這是我為flask應用程序網站編寫的模塊,但是您可以將其更改為Django應用程序並使用。 它創建縮略圖並裁剪圖像。 對我來說非常有用:

"""
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

這就是我的工作方式。

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)

resize_and_crop()引用了這個出色的腳本

此處的重點是使用InMemoryUploadedFile將文件保存在內存中,然后將其傳遞給FileField來完成其余的工作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM