HenryM
HenryM

Reputation: 5793

Images getting rotated in Django Template

I am loading some images into a Django model.

When I display these images through a Django template, portrait images are rotated. If I view these same images through Django Admin by clicking on the link they display as I would expect.

This is my view to load the images:

def upload_profile(request, user_id):
    variables = {}
    if request.POST:
        user_form = UserForm(request.POST, instance=User.objects.get(id=request.user.id))
        myuser_form = MyUserForm(request.POST, request.FILES, instance=MyUser.objects.get(user__id=request.user.id))

        if user_form.is_valid() and myuser_form.is_valid():
            user_form.save()
            myuser = myuser_form.save()
            myuser.photo = apply_orientation(myuser.photo)
            myuser.save()

            return game_selection(request)

    variables['user_form'] = user_form
    variables['myuser_form'] = myuser_form

    return render(request, 'esc/profile.html', variables)

And this is how I am applying the rotation:

def flip_horizontal(im): return im.transpose(Image.FLIP_LEFT_RIGHT)
def flip_vertical(im): return im.transpose(Image.FLIP_TOP_BOTTOM)
def rotate_180(im): return im.transpose(Image.ROTATE_180)
def rotate_90(im): return im.transpose(Image.ROTATE_90)
def rotate_270(im): return im.transpose(Image.ROTATE_270)
def transpose(im): return rotate_90(flip_horizontal(im))
def transverse(im): return rotate_90(flip_vertical(im))
orientation_funcs = [None,
                 lambda x: x,
                 flip_horizontal,
                 rotate_180,
                 flip_vertical,
                 transpose,
                 rotate_270,
                 transverse,
                 rotate_90
                ]

def apply_orientation(im):
    """
    Extract the oritentation EXIF tag from the image, which should be a PIL Image instance,
    and if there is an orientation tag that would rotate the image, apply that rotation to
    the Image instance given to do an in-place rotation.

    :param Image im: Image instance to inspect
    :return: A possibly transposed image instance
    """

    try:
        kOrientationEXIFTag = 0x0112
        if hasattr(im, '_getexif'): # only present in JPEGs
            e = im._getexif()       # returns None if no EXIF data
            if e is not None:
                #log.info('EXIF data found: %r', e)
                orientation = e[kOrientationEXIFTag]
                f = orientation_funcs[orientation]
                return f(im)
    except:
        # We'd be here with an invalid orientation value or some random error?
        pass # log.exception("Error applying EXIF Orientation tag")
    return im

My code never seems to pass the condition if hasattr(im, '_getexif'):

**** EDIT ****

So it's not getting through because no matter what image I load there is no '_getexif'.

If I add print getattr(im, '_getexif') I get the following error, with all images

'ImageFieldFile' object has no attribute '_getexif'

Upvotes: 1

Views: 1370

Answers (1)

HenryM
HenryM

Reputation: 5793

So I dropped all the code above and replaced it with the following

from imagekit.models import ImageSpecField
from imagekit.processors import ResizeToFill, Transpose, SmartResize

class MyUser(models.Model):
  avatar = models.ImageField(upload_to='upload/avatars', max_length=255, blank=True, null=True)
  avatar_thumbnail = ImageSpecField(
    source='avatar',
    processors = [Transpose(),SmartResize(200, 200)],
    format = 'JPEG',
    options = {'quality': 75}
  )

It works

Upvotes: 3

Related Questions