如何将使用Pillow调整大小的图像放入GridFS?

时间:2014-07-05 19:33:01

标签: python-2.7 gridfs pillow

方案

我使用formData表单通过ajax上传图像,然后将其添加到MongoDB GridFS数据库。

这是有效的:

my_image = request.files.my_image
raw = my_image.file.read()
fs.put(raw)

所需行为

我希望在添加到GridFS之前使用Pillow调整图像大小。

我尝试过什么

我将上述内容改为:

my_image = request.files.my_image
raw = Image.open(my_image.file.read())
raw_resized = raw.resize((new_dimensions))
fs.put(raw_resized)

实际行为

我现在得到500个错误。尾巴表演:

TypeError: file() argument 1 must be encoded string without NULL bytes, not str

问题

如何正确处理Pillow图像对象,以便将其添加到GridFS?

Troubelshooting

这仍然没有得到解决,但我只是通过使用解释器添加我尝试了解文件类型等在过程的不同阶段发生的事情:

>>> my_image = open("my_great_image.jpg")
>>> my_image
<open file 'my_great_image.jpg', mode 'r' at 0x0259CF40>
>>> type(my_image)
<type 'file'>
>>> my_image_read = my_image.read()
>>> my_image_read
# lots of image data
>>> type(my_image_read)
<type 'str'>
>>> my_pil_image = Image.open("my_great_image.jpg")
>>> my_pil_image
<PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=400x267 at 0x2760CD8>
>>> type(my_pil_image)
<type 'instance'>

因此,我认为我可以推断出,最初,GridFS接受了从read()方法生成的图像的字符串版本。

所以我认为我需要以某种方式使Pillow图像对象成为一个字符串,以便将其导入GridFS。

2 个答案:

答案 0 :(得分:1)

<强>解决方案

哇,看看这个,它有效,逻辑是:

  1. 表格上传图片,
  2. Pillow有三种不同的尺寸,
  3. 使用StringIO将Pillow对象转换为字符串
  4. 在GridFS中将调整大小的图像作为字符串。
  5. <强>的Python

    from PIL import Image
    import StringIO
    
    # define three new image sizes
    card_dimensions = (108,108)
    main_dimensions = (42,38)
    thumb_dimensions = (18,14)
    # covert uploaded image to Pillow object
    raw_pil = Image.open(my_image.file)
    # conversion to card size
    raw_card_output = StringIO.StringIO()
    raw_card = raw_pil.resize((card_dimensions))
    raw_card.save(raw_card_output,format=raw_pil.format)
    raw_card_output_contents = raw_card_output.getvalue()
    # conversion to main size
    raw_main_output = StringIO.StringIO()
    raw_main = raw_pil.resize((main_dimensions))
    raw_main.save(raw_main_output,format=raw_pil.format)
    raw_main_output_contents = raw_main_output.getvalue()
    #conversion to thumb size
    raw_thumb_output = StringIO.StringIO()
    raw_thumb = raw_pil.resize((thumb_dimensions))
    raw_thumb.save(raw_thumb_output,format=raw_pil.format)
    raw_thumb_output_contents = raw_thumb_output.getvalue()
    # put card image into GridFS
    fs.put(raw_card_output_contents)
    # put main image into GridFS
    fs.put(raw_main_output_contents)
    # put thumb image into GridFS
    fs.put(raw_thumb_output_contents)
    

    进一步说明

    基本上我推断GridFS接受一个字符串,因此我需要将Pillow对象转换为字符串。

    下面的口译员故障排除应该使一些动态更清晰,并从原始帖子中的故障排除继续:

    >>> my_pil_image
    <PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=400x267 at 0x2760CD8>
    >>> my_pil_image_resized = my_pil_image.resize((50,50))
    >>> my_pil_image_resized
    <PIL.Image.Image image mode=RGB size=50x50 at 0x2898710>
    >>> output = StringIO.StringIO()
    >>> my_pil_image_resized.save(output,format="JPEG")
    >>> contents = output.getvalue()
    >>> type(contents)
    <type 'str'>
    >>> contents
    # lots of image data
    

    所以基本上上面的过程显示了如何将Pillow对象转换为字符串的机制,然后可以将其添加到GridFS中。

答案 1 :(得分:0)

我只有一个简单的方法可以用flask。

在上传到gridFS之前,我正在使用FileStorage作为文件持有者。 调整大小后,还可以帮助我从枕头上包裹图像。

文档看起来像这样。

from mongoengine import Document ImageField


class SomeDocument(Document):
    icon = ImageField(required=False, collection_name="collection_name")

控制器是

from io import BytesIO
from werkzeug.datastructures import FileStorage
from PIL import Image

im = Image.open(request.files.get('icon'))
im.thumbnail((400, 400))

output = BytesIO()

im.save(output, format=im.format, quality=90)

original_extension = request.files.get('icon').filename.rsplit('.', 1)[1].lower()

SomeDocument.icon.put(FileStorage(output, content_type=f"image/{original_extension"))
SomeDocument.save()
im.close()