|
|
|
@ -89,20 +89,34 @@ def get_exif_data_fobj(fobj):
|
|
|
|
|
if orien:
|
|
|
|
|
orientationinfo = {0: 0, 8: 1, 3: 2, 6: 3}.get(int(orien), 0)
|
|
|
|
|
|
|
|
|
|
gps = exif.get("GPSInfo")
|
|
|
|
|
if gps and 1 in gps and 2 in gps and 3 in gps and 4 in gps:
|
|
|
|
|
# see https://gis.stackexchange.com/a/273402
|
|
|
|
|
gps_y = round(hms_to_decimal(rational64u_to_hms(gps[2])), 8)
|
|
|
|
|
gps_x = round(hms_to_decimal(rational64u_to_hms(gps[4])), 8)
|
|
|
|
|
if gps[1] == 'S':
|
|
|
|
|
gps_y *= -1
|
|
|
|
|
if gps[3] == 'W':
|
|
|
|
|
gps_x *= -1
|
|
|
|
|
gpsinfo = (gps_y, gps_x)
|
|
|
|
|
gpsinfo = parse_exif_gps(exif.get("GPSInfo"))
|
|
|
|
|
|
|
|
|
|
return dateinfo, gpsinfo, sizeinfo, orientationinfo
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def parse_exif_gps(gps):
|
|
|
|
|
if not gps or 1 not in gps or 2 not in gps or 3 not in gps or 4 not in gps:
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
if gps[1] not in {"N", "S"} or gps[3] not in {"E", "W"}:
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
y_decimal = rational64u_to_hms(gps[2])
|
|
|
|
|
x_decimal = rational64u_to_hms(gps[4])
|
|
|
|
|
except TypeError:
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
# see https://gis.stackexchange.com/a/273402
|
|
|
|
|
gps_y = round(hms_to_decimal(y_decimal), 8)
|
|
|
|
|
gps_x = round(hms_to_decimal(x_decimal), 8)
|
|
|
|
|
if gps[1] == 'S':
|
|
|
|
|
gps_y *= -1
|
|
|
|
|
if gps[3] == 'W':
|
|
|
|
|
gps_x *= -1
|
|
|
|
|
return (gps_y, gps_x)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def rational64u_to_hms(values):
|
|
|
|
|
return [Decimal(values[0].numerator) / Decimal(values[0].denominator),
|
|
|
|
|
Decimal(values[1].numerator) / Decimal(values[1].denominator),
|
|
|
|
@ -125,7 +139,3 @@ def special_magic_fobj(fobj, fname):
|
|
|
|
|
return "application/octet-stream-xmp"
|
|
|
|
|
else:
|
|
|
|
|
return magic.from_buffer(fobj.read(1024), mime=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def main():
|
|
|
|
|
print(get_exif_data("library/2018/9/8/MMwo4hr.jpg"))
|
|
|
|
|