45 votes

Rotation d'une image avec l'orientation spécifiée dans l'EXIF en utilisant Python sans PIL y compris la vignette

J'ai le scénario suivant :

  • J'envoie une image de l'iPhone avec les informations EXIF à mon serveur de socket Pyhon.
  • J'ai besoin que l'image soit correctement orientée en fonction de l'orientation réelle au moment où l'image a été prise. Je sais qu'IOS enregistre toujours l'image en tant que paysage à gauche et ajoute l'orientation réelle comme champ EXIF (EXIF.Image.Orientation).
  • Je lis le champ EXIF pour voir l'orientation réelle. Puis je fais pivoter l'image à l'aide de wxpython pour obtenir l'orientation correcte.

J'utilise pyexiv2 pour la manipulation des données EXIF.

Problème : Les informations EXIF, y compris les vignettes, sont perdues lors de la rotation de l'image à l'aide de wxpython.

Ce que j'ai fait : Je lis l'EXIF avant de faire pivoter l'image. Je réinitialise le champ d'orientation dans l'EXIF. Puis je le remets en place après la rotation.

Le problème :

La vignette à l'intérieur de l'EXIF n'est pas tournée. Ainsi, l'image et la vignette ont des orientations différentes.

Des questions ?

Existe-t-il un module autre que PIL pour faire pivoter une image en conservant ses informations EXIF ?

Existe-t-il un champ EXIF distinct pour l'orientation des vignettes ?

Existe-t-il un moyen de faire pivoter la vignette seule ?

Merci pour votre aide...

113voto

scabbiaza Points 36

Cette solution fonctionne pour moi : La vignette du PIL fait tourner mon image ?

Pas besoin de vérifier si c'est un iPhone ou un iPad : si la photo a une étiquette d'orientation - faites-la pivoter.

from PIL import Image, ExifTags

try:
    image=Image.open(filepath)

    for orientation in ExifTags.TAGS.keys():
        if ExifTags.TAGS[orientation]=='Orientation':
            break

    exif = image._getexif()

    if exif[orientation] == 3:
        image=image.rotate(180, expand=True)
    elif exif[orientation] == 6:
        image=image.rotate(270, expand=True)
    elif exif[orientation] == 8:
        image=image.rotate(90, expand=True)

    image.save(filepath)
    image.close()
except (AttributeError, KeyError, IndexError):
    # cases: image don't have getexif
    pass

Avant :

Before

Après : After

61voto

GaretJax Points 3345

Si vous utilisez Oreiller >= 6.0.0 vous pouvez utiliser la fonction intégrée ImageOps.exif_transpose permet de faire pivoter correctement une image en fonction de sa balise exif :

from PIL import ImageOps

image = ImageOps.exif_transpose(image)

6voto

Hyagoro Points 65

À peu près la même réponse que @scabbiaza, mais en utilisant la transposition au lieu de la rotation (pour des raisons de performance).

from PIL import Image, ExifTags

try:
    image=Image.open(filepath)
    for orientation in ExifTags.TAGS.keys():
        if ExifTags.TAGS[orientation]=='Orientation':
            break
    exif=dict(image._getexif().items())

    if exif[orientation] == 3:
        image=image.transpose(Image.ROTATE_180)
    elif exif[orientation] == 6:
        image=image.transpose(Image.ROTATE_270)
    elif exif[orientation] == 8:
        image=image.transpose(Image.ROTATE_90)
    image.save(filepath)
    image.close()

except (AttributeError, KeyError, IndexError):
    # cases: image don't have getexif
    pass

1voto

Abdur Rahman Points 13
from PIL import Image

def reorient_img(pil_img):
    img_exif = pil_img.getexif()

    if len(img_exif):
        if img_exif[274] == 3:
            pil_img = pil_img.transpose(Image.ROTATE_180)
        elif img_exif[274] == 6:
            pil_img = pil_img.transpose(Image.ROTATE_270)
        elif img_exif[274] == 8:
            pil_img = pil_img.transpose(Image.ROTATE_90)

    return pil_img

0voto

joelvarma Points 111

https://medium.com/@giovanni_cortes/rotate-image-in-django-when-saved-in-a-model-8fd98aac8f2a

Cet article de blog l'explique clairement. Assurez-vous simplement que vous essayez de garder le @receiver.. code dans forms.py o models.py comme je l'ai fait cannot import model/view erreurs .

garder le rotate_image méthode dans models.py & @receiver.. également dans models.py .

J'ai également obtenu des erreurs telles que "No such directory". Assurez-vous que full_path est correctement réglé sur le dossier média.

J'ai utilisé cette ligne

fullpath = os.path.join(os.path.dirname(BASE_DIR)) + instance.fimage.url

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X