django-imagekit icon indicating copy to clipboard operation
django-imagekit copied to clipboard

How to preserve exif data with ProcessedImageField

Open zoltan-ky opened this issue 2 years ago • 1 comments

The old options={'keep_exif': True} seems to be gone from imagekit / pilkit / PIL. Now it seems one has to supply the 'exif' data itself from the uploaded source file in options -> params to PIL Image.save() - so how does one do that as it cannot be declared statically as ProcessedImageField options parameter?

zoltan-ky avatar May 18 '23 18:05 zoltan-ky

Here's a workaround I ended up using for facing this issue. Not fancy, I'd prefer doing it by setting an option in the ProcessedImageField. It basically overrides the save method of the original ProcessedImageField by setting the new spec.options dict to contain the same EXIF info as the source image (before processing it)

import os

from django.db.models.fields.files import ImageFieldFile
from django.db import models

from imagekit.models import ProcessedImageField as OriginalProcessedImageField
from imagekit.utils import generate, open_image, suggest_extension


class ProcessedImageExifFieldFile(ImageFieldFile):
    def save(self, name, content, save=True):
        # COPIED FROM OriginalProcessedImageField
        filename, ext = os.path.splitext(name)
        spec = self.field.get_spec(source=content)
        ext = suggest_extension(name, spec.format)
        new_name = f"{filename}{ext}"
        # ADDED CODE START
        if not spec.options:
            spec.options = {}
        if exif := open_image(content).info.get("exif", None):
            spec.options["exif"] = exif        
        # ADDED CODE END
        content = generate(spec)
        return super().save(new_name, content, save)


class ProcessedImageField(OriginalProcessedImageField):
    attr_class = ProcessedImageExifFieldFile

####################

class DummyModel(models.Model)
    image = ProcessedImageField()

epou avatar Jul 12 '23 15:07 epou