-
-
Notifications
You must be signed in to change notification settings - Fork 6
/
getters.py
143 lines (111 loc) · 3.23 KB
/
getters.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
import datetime
from enum import Enum
from typing import Any, Callable, Dict, Optional
from choicesenum import ChoicesEnum
from .exceptions import ExifError
ExifType = Dict[str, Dict[str, Any]]
class Orientation(ChoicesEnum, Enum): # NOTE inherits from `Enum` to make `mypy` happy
LANDSCAPE = 'landscape'
PORTRAIT = 'portrait'
class Mode(ChoicesEnum, Enum): # NOTE inherits from `Enum` to make `mypy` happy
TIMELAPSE = 'timelapse'
BURST = 'burst'
BRACKETING = 'bracketing'
SINGLE = 'single'
def exifgetter(field: str) -> Callable[[ExifType], Any]:
"""
Return the unmodified value.
"""
def inner(exif: ExifType) -> Any:
return exif[field]['val']
inner.__name__ = f'exifgetter("{field}")'
return inner
def exifgetter_num(field: str) -> Callable[[ExifType], Any]:
"""
Return the unmodified value.
"""
def inner(exif: ExifType) -> Any:
return exif[field]['num']
inner.__name__ = f'exifgetter_num("{field}")'
return inner
def get_gps_latitude(exif: ExifType) -> str:
"""
Return the latitude (decimal) where the file was taken.
"""
try:
return exif['GPSLatitude']['num']
except KeyError:
return 0
def get_gps_longitude(exif: ExifType) -> str:
"""
Return the latitude (decimal) where the file was taken.
"""
try:
return exif['GPSLongitude']['num']
except KeyError:
return 0
def get_type(exif: ExifType) -> str:
"""
Return type of file, e.g. image.
"""
return exif['MIMEType']['val'].split('/')[0]
def get_datetaken(exif: ExifType) -> Optional[datetime.datetime]:
"""
Return when the file was created.
"""
for key in ['DateTimeOriginal', 'GPSDateTime']:
try:
datetime_str = exif[key]['val']
except KeyError:
continue
try:
return datetime.datetime.strptime(
datetime_str,
'%Y:%m:%d %H:%M:%S',
)
except ValueError as e:
raise ExifError(f'Could not parse {datetime_str}') from e
raise ExifError('Could not find date')
def get_orientation(exif: ExifType) -> Orientation:
"""
Return orientation of the file.
"""
orientation = exif['Orientation']['num']
width, height = exif['ImageWidth']['val'], exif['ImageHeight']['val']
if orientation > 4:
# image rotated image by 90 degrees
width, height = height, width
if width < height:
return Orientation.PORTRAIT
return Orientation.LANDSCAPE
def get_sequencetype(exif) -> Mode:
"""
Return the recoding mode.
"""
# burst or bracketing
try:
mode = exif['BurstMode']['num']
except KeyError:
pass
else:
if mode == 1:
return Mode.BURST
if mode == 2:
return Mode.BRACKETING
# time lapse
try:
mode = exif['TimerRecording']['num']
except KeyError:
pass
else:
if mode == 1:
return Mode.TIMELAPSE
return Mode.SINGLE
def get_sequencenumber(exif) -> int:
"""
Return position of image within the recoding sequence.
"""
try:
return exif['SequenceNumber']['num']
except KeyError:
return 0