Skip to content

Exif

snoop.data.analyzers.exif #

Tasks that extract GPS location and other metadata from images.

Attributes#

EXIFREAD_MIME_TYPES #

Mime types supported for EXIF geographical data extraction.

Extracting exif data is done using ExifRead. The supported filetypes can be found in the Project description.

Functions#

can_extract(blob) #

Checks if we can extract EXIF data from blob.

Source code in snoop/data/analyzers/exif.py
def can_extract(blob):
    """Checks if we can extract EXIF data from blob."""
    return blob.mime_type in EXIFREAD_MIME_TYPES

extract(blob) #

Task to extract EXIF GPS tags from Blob with image.

Source code in snoop/data/analyzers/exif.py
@snoop_task('exif.extract')
@returns_json_blob
def extract(blob):
    """Task to extract EXIF GPS tags from Blob with image."""

    # details=False removes thumbnails and MakerNote (manufacturer specific
    # information). See https://pypi.python.org/pypi/ExifRead#tag-descriptions

    with blob.open(need_seek=True) as f:
        try:
            tags = exifread.process_file(f, details=False)
        except (AttributeError, IndexError) as e:
            raise SnoopTaskBroken("ExifRead failed: " + str(e),
                                  "exifread_failed_attribute_index_error")
        except Exception as e:
            raise SnoopTaskBroken("ExifRead failed: " + str(e),
                                  "exifread_failed_unknown_error")

    if not tags:
        return {}

    data = {}
    try:
        gps = extract_gps_location(tags)
    except ZeroDivisionError as e:
        raise SnoopTaskBroken("zero division error when computing GPS: " + str(e),
                              "exifread_gps_zero_division_error")

    if gps:
        data['location'] = gps

    for key in ['EXIF DateTimeOriginal', 'Image DateTime']:
        if key in tags:
            date = convert_exif_date(str(tags[key]))
            if date:
                data['date-created'] = date
                break

    return data

extract_gps_location(tags) #

Returns GPS "lat lon" string from dict with tags.

Source code in snoop/data/analyzers/exif.py
def extract_gps_location(tags):
    """Returns GPS "lat lon" string from dict with tags."""
    def ratio_to_float(ratio):
        return float(ratio.num) / ratio.den

    def convert(value):
        d = ratio_to_float(value.values[0])
        m = ratio_to_float(value.values[1])
        s = ratio_to_float(value.values[2])
        return d + (m / 60.0) + (s / 3600.0)

    tags = {key: tags[key] for key in tags.keys() if key.startswith('GPS')}

    lat = tags.get('GPS GPSLatitude')
    lat_ref = tags.get('GPS GPSLatitudeRef')
    lng = tags.get('GPS GPSLongitude')
    lng_ref = tags.get('GPS GPSLongitudeRef')

    if any(v is None for v in [lat, lat_ref, lng, lng_ref]):
        return None

    lat = convert(lat)
    if lat_ref.values and (lat_ref.values[0] != 'N'):
        lat = -lat
    lng = convert(lng)
    if lng_ref.values and (lng_ref.values[0] != 'E'):
        lng = -lng
    return "{}, {}".format(lat, lng)