how to go from django image field to PIL image and back?
Asked Answered
D

2

21

Given a django image field, how do I create a PIL image and vice-versa?

Simple question, but hard to google :(

(I'm going to use django-imagekit 's processor to rotate an image already stored as model attribute.)

edit

In [41]: m.image_1.__class__
Out[41]: django.db.models.fields.files.ImageFieldFile

In [42]: f = StringIO(m.image_1.read())

In [43]: Image.open(f)
---------------------------------------------------------------------------
IOError                                   Traceback (most recent call last)
<ipython-input-43-39949b3b74b3> in <module>()
----> 1 Image.open(f)

/home/eugenekim/virtualenvs/zibann/local/lib/python2.7/site-packages/PIL/Image.pyc in open(fp, mode)
   2023                 pass
   2024
-> 2025     raise IOError("cannot identify image file")
   2026
   2027 #

IOError: cannot identify image file

In [44]:
Darby answered 26/2, 2014 at 8:36 Comment(2)
Doesn't this import Image; pil_image = Image.open(my_image_from_image_field.name) work?Areopagite
@Bernhard, .name is relative to the MEDIA_ROOT. it can be omitted because the ImageField/FileField act like file object.Selfjustifying
S
27

The first question:

import Image

pil_image_obj = Image.open(model_instance.image_field)

The second question:

from cStringIO import StringIO
from django.core.files.base import ContentFile

f = StringIO()
try:
    pil_image_obj.save(f, format='png')
    s = f.getvalue()
    model_instance.image_field.save(model_instance.image_field.name,
                                    ContentFile(s))
    #model_instance.save()
finally:
    f.close()

UPDATE

According to OP's comment, replacing import Image with from PIL import Image solved his problem.

Selfjustifying answered 26/2, 2014 at 8:55 Comment(11)
(Pdb) p Image.open(obj.image_1) p Image.open(obj.image_1) *** IOError: IOError('cannot identify image file',) for the #1..Darby
@eugene, How about pil_image_obj = Image.open(model_instance.image_field.path) ?Selfjustifying
it says path not implemented because because backend(s3boto) doesn't support absolute pathDarby
@eugene, You'd better to mention that the image is stored in s3 in the question.Selfjustifying
@eugene, Please try this and let me know whether that works or not: pastebin.com/cqMmBa57Selfjustifying
@falsetrue: sorry didn't know it was the issue. what's pil_image_obj in the pastebin code? I tried Image.open(StringIO(model_instance.image_field.read())) but same error.Darby
@eugene, It's a typo. It should be model_instance. Make sure the file is actually image.Selfjustifying
@falsetrue, updated the question with my shell outputDarby
@eugene, Could you show output of following line? m.image_1.read()[:100]Selfjustifying
In [57]: m.image_1.read()[:100] Out[57]: '\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01\x00\x00\x01\x00\x01\x00\x00\xff\xdb\x00C\x00\x05\x03\x04\x04\x04\x03\x05\x04\x04\x04\x05\x05\x05\x06\x07\x0c\x08\x07\x07\x07\x07\x0f\x0b\x0b\t\x0c\x11\x0f\x12\x12\x11\x0f\x11\x11\x13\x16\x1c\x17\x13\x14\x1a\x15\x11\x11\x18!\x18\x1a\x1d\x1d\x1f\x1f\x1f\x13\x17"$"\x1e$\x1c\x1e\x1f\x1e\xff\xdb\x00C\x01\x05\x05\x05\x07\x06\x07'Darby
@eugene, Thank you for feedback. I added the solution given in that answer.Selfjustifying
P
27

To go from PIL image to Django ImageField, I used falsetru's answer, but I had to update it for Python 3.

First, StringIO has been replaced by io as per: StringIO in python3

Second, When I tried io.StringIO(), I recieved an error saying: "*** TypeError: string argument expected, got 'bytes'". So I changed it to io.BytesIO() and it all worked.

from PIL import Image
from io import BytesIO
from django.core.files.base import ContentFile

f = BytesIO()
try:
    pil_image_obj.save(f, format='png')
    model_instance.image_field.save(model_instance.image_field.name,
                                   ContentFile(f.getvalue()))
#model_instance.save()
finally:
    f.close()
Pestilent answered 29/1, 2015 at 7:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.