如果 max_width 使用 PIL 超过 x,如何调整图像大小?
How to resize image if max_width exceeds x with PIL?
我正在使用 Django-resized 库自动调整上传图像的大小。我遇到的问题是,当调整图像大小时,尽管将质量设置为 100,但图像质量还是会下降。我对 PIL 的了解还不够多,无法乱用这段代码,而且我也不知道该怎么做增加智商,所以我想做的是放在一个条件中,如果图像宽度 > 600 然后调整图像大小(这样在一定宽度内的图像不会被调整大小并且会影响智商)。我的问题是,我应该将 if 条件放在 ResizedImageField 的构造函数中吗?或者我应该把它放在 ResizedImageFileField 的保存方法中吗?
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 以外的其他图像格式,此参数将被忽略,因此您始终可以放心地传递它。
如果使用 pillow(PIL 分支),您可以使用 quality='keep'
来使用与原始图像相同的量化 table。否则,您可以将质量百分比显式指定为整数(不要使用 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)
我正在使用 Django-resized 库自动调整上传图像的大小。我遇到的问题是,当调整图像大小时,尽管将质量设置为 100,但图像质量还是会下降。我对 PIL 的了解还不够多,无法乱用这段代码,而且我也不知道该怎么做增加智商,所以我想做的是放在一个条件中,如果图像宽度 > 600 然后调整图像大小(这样在一定宽度内的图像不会被调整大小并且会影响智商)。我的问题是,我应该将 if 条件放在 ResizedImageField 的构造函数中吗?或者我应该把它放在 ResizedImageFileField 的保存方法中吗?
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 以外的其他图像格式,此参数将被忽略,因此您始终可以放心地传递它。
如果使用 pillow(PIL 分支),您可以使用 quality='keep'
来使用与原始图像相同的量化 table。否则,您可以将质量百分比显式指定为整数(不要使用 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)