autoimport/autoimport/select/metadata.py

67 lines
1.8 KiB
Python

import logging
import json
from PIL import Image, ExifTags
import exifread
def extract_metadata_from_file(filename):
logger = logging.getLogger(__name__)
logger.info("handling: {}".format(filename))
try:
img = Image.open(filename)
except Exception as e:
logger.error("failed to open and load '{}'".format(filename))
img.close()
raise e
if(hasattr(img, "_getexif")):
try:
exif = {ExifTags.TAGS[k]: v for k, v in img._getexif().items() if k in ExifTags.TAGS}
except Exception as e:
logger.error("failed to read EXIF data from '{}'".format(filename))
raise e
finally:
img.close()
else:
img.close()
# We cannot use PIL because PIL is crap. So we use
# exifread. This is a little slower but will produce
# results more safely.
exif = get_exif_with_exifread(filename)
values_no_preprocessing = {"DateTime"
, "DateTimeDigitized"
, "DateTimeOriginal"
, "Model"
, "Make"
, "Software"}
for k in values_no_preprocessing:
if(not k in exif):
logger.error("missing EXIF value {} in '{}'".format(
k, filename))
raise KeyError("missing EXIF value {}".format(k))
result = {k: exif[k] for k in values_no_preprocessing}
return result
def get_exif_with_exifread(filename):
with open(filename, "rb") as image:
tags = exifread.process_file(image)
exif_tag_header = "EXIF "
exif_tag_header_length = len(exif_tag_header)
data = {k[exif_tag_header_length:]: v.values for k,v in tags.items()
if k.startswith(exif_tag_header)}
# Not all the tags we want are in the EXIF section.
data_from_image_section = {"DateTime", "Make", "Software", "Model"}
image_tag_header = "Image "
data.update({key: tags[real_key].values for key, real_key in
((i, image_tag_header + i) for i in data_from_image_section)})
return data