20

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]:
Walucas
  • 2,549
  • 1
  • 21
  • 44
eugene
  • 39,839
  • 68
  • 255
  • 489
  • Doesn't this `import Image; pil_image = Image.open(my_image_from_image_field.name)` work? – Bernhard Feb 26 '14 at 08:52
  • @Bernhard, `.name` is relative to the `MEDIA_ROOT`. it can be omitted because the ImageField/FileField act like file object. – falsetru Feb 26 '14 at 09:01

2 Answers2

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()
Community
  • 1
  • 1
FeFiFoFu
  • 1,069
  • 1
  • 11
  • 15
25

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.

falsetru
  • 357,413
  • 63
  • 732
  • 636
  • (Pdb) p Image.open(obj.image_1) p Image.open(obj.image_1) *** IOError: IOError('cannot identify image file',) for the #1.. – eugene Feb 27 '14 at 03:41
  • @eugene, How about `pil_image_obj = Image.open(model_instance.image_field.path)` ? – falsetru Feb 27 '14 at 03:42
  • it says path not implemented because because backend(s3boto) doesn't support absolute path – eugene Feb 27 '14 at 03:49
  • @eugene, You'd better to mention that the image is stored in s3 in the question. – falsetru Feb 27 '14 at 03:52
  • @eugene, Please try this and let me know whether that works or not: http://pastebin.com/cqMmBa57 – falsetru Feb 27 '14 at 03:57
  • @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. – eugene Feb 27 '14 at 04:00
  • @eugene, It's a typo. It should be `model_instance`. Make sure the file is actually image. – falsetru Feb 27 '14 at 04:03
  • @falsetrue, updated the question with my shell output – eugene Feb 27 '14 at 04:12
  • @eugene, Could you show output of following line? `m.image_1.read()[:100]` – falsetru Feb 27 '14 at 04:34
  • 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' – eugene Feb 27 '14 at 04:56
  • @eugene, Thank you for feedback. I added the solution given in that answer. – falsetru Feb 27 '14 at 05:25