【发布时间】:2019-08-08 06:42:31
【问题描述】:
上下文
我制作了一个简单的网络应用程序,用于将内容上传到博客。前端向后端发送 AJAX 请求(使用 FormData),后端是在 Python 3.7 上运行的 Bottle。文本内容保存到 MySQL 数据库,图像保存到服务器上的文件夹。一切正常。
图像处理和 PIL/Pillow
现在,我想启用对上传图像的处理以使其标准化(我需要将它们全部调整大小和/或裁剪为 700x400 像素)。
我希望为此使用 Pillow。我的问题是从 Bottle 中的文件对象创建一个 PIL Image 对象。我无法初始化一个有效的 Image 对象。
代码
# AJAX sends request to this route
@post('/update')
def update():
# Form data
title = request.forms.get("title")
body = request.forms.get("body")
image = request.forms.get("image")
author = request.forms.get("author")
# Image upload
file = request.files.get("file")
if file:
extension = file.filename.split(".")[-1]
if extension not in ('png', 'jpg', 'jpeg'):
return {"result" : 0, "message": "File Format Error"}
save_path = "my/save/path"
file.save(save_path)
问题
这一切都按预期工作,但我无法使用pillow 创建有效的Image 对象进行处理。我什至尝试使用保存路径重新加载保存的图像,但这也不起作用。
其他尝试
下面的代码不起作用。它导致了内部服务器错误,尽管我无法设置更详细的 Python 调试。
path = save_path + "/" + file.filename
image_data = open(path, "rb")
image = Image.open(image_data)
当手动记录时,path 是一个有效的相对 URL ("../domain-folder/images"),我已经检查过我确实使用 PIL.PILLOW_VERSION 正确导入了 PIL (Pillow)。
我尝试适应this answer:
image = Image.frombytes('RGBA', (128,128), image_data, 'raw')
但是,在创建 Image 对象之前,我不会知道大小。我也尝试过使用io:
image = Image.open(io.BytesIO(image_data))
这也不起作用。在每种情况下,只有尝试初始化 Image 对象的行会导致问题。
总结
Bottle 文档说上传的文件是一个类似文件的对象,但我在创建我可以处理的 Image 对象方面没有取得多大成功。
我应该怎么做?我对保存之前或之后的处理没有偏好。我对处理感到满意,它正在初始化导致问题的 Image 对象。
编辑 - 解决方案
我通过改编eatmeimadanish 的答案来实现这一点。我必须使用 io.BytesIO 对象从 Bottle 保存文件,然后从那里用 Pillow 加载它。处理后,可以正常保存。
obj = io.BytesIO()
file.save(obj) # This saves the file retrieved by Bottle to the BytesIO object
path = save_path + "/" + file.filename
# Image processing
im = Image.open(obj) # Reopen the object with PIL
im = im.resize((700,400))
im.save(path, optimize=True)
我从Pillow documentation 中发现了这个可能也有用的不同功能。
PIL.Image.frombuffer(模式、大小、数据、decoder_name='raw'、*args)
请注意,此函数仅解码像素数据,而不是整个图像。 如果您有一个字符串中的整个图像文件,请将其包装在一个 BytesIO 对象中,然后使用 open() 来加载它。
【问题讨论】:
标签: python python-3.x image-processing python-imaging-library bottle