python - Django - 使用 PIL 在保存方法中动态调整图像大小和创建缩略图
问题描述
我需要在我的django 2.1.7应用程序中调整图像大小并创建缩略图。我决定通过 PIL 以覆盖的 SAVE 方法来完成。
我现在有 2 个版本的代码,一个可以正常工作,一个不能正常工作。问题是我真的不明白发生了什么,因为我会说两个版本都应该工作。那么任何人都可以向我解释下面代码中的问题在哪里:
#models.py
#I am getting error OSError: cannot identify image file <_io.BytesIO object at 0x105a10200>
from django.db import models
import os
import PIL
from PIL import Image
from io import BytesIO
from django.core.files.uploadedfile import InMemoryUploadedFile
class Photo(models.Model):
image = models.ImageField(upload_to=change_image_name, null=True, blank=True, help_text = "")
thumb = models.ImageField(upload_to=change_thumb_name, null=True, blank=True, help_text = "")
gallery = models.ForeignKey(PhotoGallery, on_delete=models.CASCADE, related_name='image')
def save(self, *args, **kwargs):
maxsize = (1920, 1080) # max_size for image
th_maxsize = (1000,1000) #ma_size for thubnail
width,height = get_image_dimensions(self.image)
with Image.open(BytesIO(self.image.read())) as thumb:
if width > 1000:
print ('image for thumb wider then 1000, doing resize')
new_thumb = thumb.thumbnail(th_maxsize, PIL.Image.ANTIALIAS)
output_1000 = BytesIO()
thumb.save(output_1000, format='JPEG', quality=90)
output_1000.seek(0)
new_size = len(output_1000.getvalue())
self.thumb = InMemoryUploadedFile(file=output_1000, field_name='ImageField', name="%s.jpg" % self.image.name.split('.')[0], content_type='image/jpeg', size=new_size, charset=None)
else:
print ('saving thumbnail, no resize')
output_thumb = BytesIO()
thumb.save(output_thumb, format='JPEG', quality='keep')
output_thumb.seek(0)
new_size = len(output_thumb.getvalue())
self.thumb = InMemoryUploadedFile(file=output_thumb, field_name='ImageField', name="%s.jpg" % self.image.name.split('.')[0], content_type='image/jpeg', size=new_size, charset=None)
if width > 1920:
with Image.open(BytesIO(self.image.read())) as img: #error appear here
print ('image wider then 1920, doing resize')
new_image = img.thumbnail(maxsize, PIL.Image.ANTIALIAS)
output = BytesIO()
img.save(output, format='JPEG', quality=90)
output.seek(0)
new_size = len(output.getvalue())
self.image = InMemoryUploadedFile(file=output, field_name='ImageField', name="%s.jpg" % self.image.name.split('.')[0], content_type='image/jpeg', size=new_size, charset=None)
super(Photo, self).save(*args, **kwargs)
最后是代码,我只移动了有条件的部分
如果宽度 > 1920
到顶部。这段代码完美运行,我不明白为什么第一个没有。有人可以解释这里发生了什么。
def save(self, *args, **kwargs):
maxsize = (1920, 1080) # max_size for image
th_maxsize = (1000,1000) #ma_size for thubnail
width,height = get_image_dimensions(self.image)
if width > 1920:
with Image.open(BytesIO(self.image.read())) as img:
print ('image wider then 1920, doing resize')
new_image = img.thumbnail(maxsize, PIL.Image.ANTIALIAS)
output = BytesIO()
img.save(output, format='JPEG', quality=90)
output.seek(0)
new_size = len(output.getvalue())
self.image = InMemoryUploadedFile(file=output, field_name='ImageField', name="%s.jpg" % self.image.name.split('.')[0], content_type='image/jpeg', size=new_size, charset=None)
with Image.open(BytesIO(self.image.read())) as thumb:
if width > 1000:
print ('image for thumb wider then 1000, doing resize')
new_thumb = thumb.thumbnail(th_maxsize, PIL.Image.ANTIALIAS)
output_1000 = BytesIO()
thumb.save(output_1000, format='JPEG', quality=90)
output_1000.seek(0)
new_size = len(output_1000.getvalue())
self.thumb = InMemoryUploadedFile(file=output_1000, field_name='ImageField', name="%s.jpg" % self.image.name.split('.')[0], content_type='image/jpeg', size=new_size, charset=None)
else:
print ('saving thubnail, no resize')
output_thumb = BytesIO()
thumb.save(output_thumb, format='JPEG', quality='keep')
output_thumb.seek(0)
new_size = len(output_thumb.getvalue())
self.thumb = InMemoryUploadedFile(file=output_thumb, field_name='ImageField', name="%s.jpg" % self.image.name.split('.')[0], content_type='image/jpeg', size=new_size, charset=None)
super(Photo, self).save(*args, **kwargs)
非常感谢您的解释。
解决方案
推荐阅读
- react-native - 项目构建失败
- json - JSON 模式的正则表达式
- android - Android Studio 调试器工作但不更新布局
- python - 使用 scipy.curve_fit 进行全局拟合
- spring-boot - 如何在 application.yml 文件中添加类路径资源
- salesforce - 通过触发器运行异步 Apex 类
- php - 使用 PHP 替换 xml/plist 文件中的字符串
- javascript - React 路由器更改 url 但未更新上下文
- javascript - 如何从另一个线程向多个线程发送消息?
- python - 将 linspace 向量发送到函数会使向量在函数开始之前全为零