67 lines
2.0 KiB
Python
67 lines
2.0 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
|