Python 如果PIL的最大宽度超过x,如何调整图像大小?

Python 如果PIL的最大宽度超过x,如何调整图像大小?,python,django,python-imaging-library,Python,Django,Python Imaging Library,我正在使用Django resized库自动调整上传图像的大小。我遇到的问题是,当图像调整大小时,尽管将“质量”设置为100,但图像质量仍会下降。我对PIL的了解还不够,无法处理这段代码,我也不知道如何提高IQ,所以我想做的是加入一个条件,如果图像宽度>600,则调整图像大小(这样,特定宽度内的图像不会调整大小,IQ也不会受到影响)。我的问题是,我应该把if条件放在ResizedImageField的构造函数中吗?还是应该将其放在ResizedImageFileField中的save方法中 DJ

我正在使用Django resized库自动调整上传图像的大小。我遇到的问题是,当图像调整大小时,尽管将“质量”设置为100,但图像质量仍会下降。我对PIL的了解还不够,无法处理这段代码,我也不知道如何提高IQ,所以我想做的是加入一个条件,如果图像宽度>600,则调整图像大小(这样,特定宽度内的图像不会调整大小,IQ也不会受到影响)。我的问题是,我应该把if条件放在ResizedImageField的构造函数中吗?还是应该将其放在ResizedImageFileField中的save方法中

DJANGO模型

class MyModel(models.Model):
    ...
    image = ResizedImageField(max_width=500, max_height=300, upload_to='whatever')
DJANGO-RESIZED FORMS.PY

import os
try:
    from PIL import Image, ImageFile
except ImportError:
    import Image, ImageFile

try:
    # python3
    from io import BytesIO as StringIO
except ImportError:
    # python2
    from StringIO import StringIO

from django.conf import settings
from django.core.files.base import ContentFile

try:
    from sorl.thumbnail import ImageField
except ImportError:
    from django.db.models import ImageField


DEFAULT_SIZE = getattr(settings, 'DJANGORESIZED_DEFAULT_SIZE', [1920, 1080])
DEFAULT_COLOR = (255, 255, 255, 0)


class ResizedImageFieldFile(ImageField.attr_class):

    def save(self, name, content, save=True):
        new_content = StringIO()
        content.file.seek(0)
        thumb = Image.open(content.file)
        thumb.thumbnail((
            self.field.max_width,
            self.field.max_height
            ), Image.ANTIALIAS)

        if self.field.use_thumbnail_aspect_ratio:
            img = Image.new("RGBA", (self.field.max_width, self.field.max_height), self.field.background_color)
            img.paste(thumb, ((self.field.max_width - thumb.size[0]) / 2, (self.field.max_height - thumb.size[1]) / 2))
        else:
            img = thumb

        try:
            img.save(new_content, format=thumb.format, **img.info)
        except IOError:
            ImageFile.MAXBLOCK = img.size[0] * img.size[1]
            img.save(new_content, format=thumb.format, **img.info)

        new_content = ContentFile(new_content.getvalue())

        super(ResizedImageFieldFile, self).save(name, new_content, save)


class ResizedImageField(ImageField):

    attr_class = ResizedImageFieldFile

    def __init__(self, verbose_name=None, name=None, **kwargs):
        //if self.max_width > 400:
        self.max_width = kwargs.pop('max_width', DEFAULT_SIZE[0])
        self.max_height = kwargs.pop('max_height', DEFAULT_SIZE[1])
        self.use_thumbnail_aspect_ratio = kwargs.pop('use_thumbnail_aspect_ratio', False)
        self.background_color = kwargs.pop('background_color', DEFAULT_COLOR)
        super(ResizedImageField, self).__init__(verbose_name, name, **kwargs) 


try:
    from south.modelsinspector import add_introspection_rules
    rules = [
        (
            (ResizedImageField,),
            [],
            {
                "max_width": ["max_width", {'default': DEFAULT_SIZE[0]}],
                "max_height": ["max_height", {'default': DEFAULT_SIZE[1]}],
                "use_thumbnail_aspect_ratio": ["use_thumbnail_aspect_ratio", {'default': False}],
                "background_color": ["background_color", {'default': DEFAULT_COLOR}],
            },
        )
    ]
    add_introspection_rules(rules, ["^django_resized\.forms\.ResizedImageField"])
except ImportError:
    pass

似乎django resized在保存时没有提供
quality
参数。对于JPEG以外的其他图像格式,此参数将被忽略,因此您始终可以无需担心地传递它


如果使用枕头(PIL叉子),您可以使用
quality='keep'
使用与原始图像相同的量化表。否则,您可以显式地将质量百分比指定为整数(不要使用100,它会创建非常大的图像)。

这肯定不好看。我意识到我有很多重复的代码,但这是我唯一能找出如何使其工作的方法

class ResizedImageFieldFile(ImageField.attr_class):

    def save(self, name, content, save=True): 
        new_content = StringIO()
        content.file.seek(0)
        thumb = Image.open(content.file)

        if thumb.size[0] > 900:
            thumb.thumbnail((
                self.field.max_width,
                self.field.max_height
                ), Image.ANTIALIAS)

            if self.field.use_thumbnail_aspect_ratio:
                img = Image.new("RGBA", (self.field.max_width, self.field.max_height), self.field.background_color)
                img.paste(thumb, ((self.field.max_width - thumb.size[0]) / 2, (self.field.max_height - thumb.size[1]) / 2))
            else:
                img = thumb

            try:
                img.save(new_content, format=thumb.format, **img.info)
            except IOError:
                ImageFile.MAXBLOCK = img.size[0] * img.size[1]
                img.save(new_content, format=thumb.format, **img.info)
        else:
            img = thumb
            try:
                img.save(new_content, format=thumb.format, **img.info)
            except IOError:
                ImageFile.MAXBLOCK = img.size[0] * img.size[1]
                img.save(new_content, format=thumb.format, **img.info)

        new_content = ContentFile(new_content.getvalue())

        super(ResizedImageFieldFile, self).save(name, new_content, save)

PIL不太擅长调整大小,是的,我忘了在代码中包含它,但我可以100%的保存质量,我现在想知道的是在哪里放置一个if条件,我已经将它放在save方法中了。我正在工作,所以现在无法尝试,但是我是否应该将save方法的全部内容包装在if条件中?请参阅我在下面发布的答案。因此,如果宽度不超过800 px,则图像保存应该像标准ImageField一样执行,不添加任何参数。(至少这是我所希望的)我想出来了,它肯定不漂亮,虽然哈。