【问题标题】:How to put an image resized with Pillow into GridFS?如何将使用 Pillow 调整大小的图像放入 GridFS?
【发布时间】:2014-08-26 17:08:08
【问题描述】:

场景

我使用 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?

疑难解答

这仍然没有解决,但我只是尝试通过使用解释器来了解文件类型等在流程的不同阶段发生了什么:

>>> 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。

【问题讨论】:

    标签: python-2.7 gridfs pillow


    【解决方案1】:

    我刚刚找到了一个简单的方法来用烧瓶做到这一点。

    在上传到 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()
    

    【讨论】:

      【解决方案2】:

      解决方案

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

      1. 表单上传图片,
      2. Pillow 可以调整三种不同的大小,
      3. 使用 StringIO 将 Pillow 对象转换为字符串
      4. 将调整大小的图像作为字符串放入 GridFS。

      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 的机制。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-06-04
        • 2020-05-05
        • 2020-02-16
        • 2014-07-18
        • 2019-02-10
        • 2022-01-23
        相关资源
        最近更新 更多