15

I have successfully created and rotated an image that was uploaded via email to a directory on my server using the following code:

      image = ContentFile(b64decode(part.get_payload()))
      im = Image.open(image)
      tempfile = im.rotate(90)
      tempfile.save("/srv/www/mysite.com/public_html/media/images/rotate.jpg", "JPEG")
      img = Photo(user=user)
      img.img.save('rotate.jpg', tempfile)
      img.save()

The rotated image exists in the directory, however when I try to add that image to my model, it is not saving. What am I missing? Any help would be greatly appreciated.

django-d
  • 2,210
  • 3
  • 23
  • 41
  • Is there a specific error that appears? Can you share your model definition for Photo? – Matt Hampel Jun 15 '11 at 15:20
  • I'm pretty sure it's not the model. If I replace the "tempfile" in the "img.img.save('rotate.jpg',tempfile) with "image", then it saves correctly. So, it appears as though I'm not correctly accessing the newly created and rotated image file once the image has been saved. – django-d Jun 17 '11 at 13:48
  • Does it have the same problem if you save `im` instead of `tempfile`? – Matt Hampel Jun 17 '11 at 16:02
  • Yes, tried several things and still can't seem to get it to work. It's as if the image isn't a valid file object. – django-d Jun 17 '11 at 17:54
  • I'm afraid I don't have many good ideas. You could go roundabout for now. Close the tempfile, when `open` and save it using the path. Not great if you're looking for efficiency, but should work as a stop-gap. Have you looked at `issubclass` and similar on `tempfile`? – Matt Hampel Jun 17 '11 at 20:31

2 Answers2

19

I solved the issue with the following code:

       image = ContentFile(b64decode(part.get_payload()))
       im = Image.open(image)
       tempfile = im.rotate(270)
       tempfile_io =StringIO.StringIO()
       tempfile.save(tempfile_io, format='JPEG')
       image_file = InMemoryUploadedFile(tempfile_io, None, 'rotate.jpg','image/jpeg',tempfile_io.len, None)
       img = Photo(user=user)
       img.img.save('rotate.jpg', image_file)
       img.save()

I found the answer here How do you convert a PIL `Image` to a Django `File`?. Works flawlessly!!!

Community
  • 1
  • 1
django-d
  • 2,210
  • 3
  • 23
  • 41
  • 3
    Can you put in your imports so that we know where you grabbed all the required Classes, Thank in advance! – Charles Haro Nov 15 '14 at 04:08
  • 2
    Note: From the python3 changelog: The StringIO and cStringIO modules are gone. Instead, import the io module and use io.StringIO or io.BytesIO for text and data respectively. – Jeffrey Klardie Nov 14 '16 at 14:43
0
from django.db import models
from .abstract_classes import DateTimeCreatedModified
from PIL import Image
from io import BytesIO
from django.core.files.base import ContentFile
from enum import Enum

class MediaSize(Enum):
    #             size       base file name
    DEFAULT = ((1080, 1080), 'bus_default')
    MEDIUM = ((612, 612), 'bus_medium')
    THUMBNAIL = ((161, 161), 'bus_thumbnail')


class Media(DateTimeCreatedModified):

    # The original image.
    original = models.ImageField()
    # Resized images...
    default = models.ImageField()
    medium = models.ImageField()
    thumbnail = models.ImageField()




    def resizeImg(self, img_size):
        img: Image.Image = Image.open(self.original)
        img.thumbnail(img_size, Image.ANTIALIAS)

        outputIO = BytesIO()
        img.save(outputIO, format=img.format, quality=100)

        return outputIO, img


    def handleResize(self, mediaSize: MediaSize):

        imgSize = mediaSize.value[0]
        imgName = mediaSize.value[1]

        outputIO, img = self.resizeImg(imgSize)

        return {
            # Files aren't be overwritten
            # because `AWS_S3_FILE_OVERWRITE = False`
            # is set in `settings.py`.
            'name': f'{imgName}.{img.format}',
            'content': ContentFile(outputIO.getvalue()),
            'save': False,
        }



    def save(self, **kwargs):

        if not self.default:
            self.default.save(
                **self.handleResize(MediaSize.DEFAULT)
            )

        if not self.medium:
            self.medium.save(
                **self.handleResize(MediaSize.MEDIUM)
            )

        if not self.thumbnail:
            self.thumbnail.save(
                **self.handleResize(MediaSize.THUMBNAIL)
            )

        super().save(**kwargs)