sdata 1.5.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- sdata/__init__.py +140 -0
- sdata/base.py +684 -0
- sdata/contrib/__init__.py +0 -0
- sdata/contrib/piexif/__init__.py +12 -0
- sdata/contrib/piexif/_common.py +94 -0
- sdata/contrib/piexif/_dump.py +346 -0
- sdata/contrib/piexif/_exceptions.py +2 -0
- sdata/contrib/piexif/_exif.py +638 -0
- sdata/contrib/piexif/_insert.py +60 -0
- sdata/contrib/piexif/_load.py +270 -0
- sdata/contrib/piexif/_remove.py +56 -0
- sdata/contrib/piexif/_transplant.py +45 -0
- sdata/contrib/piexif/_webp.py +240 -0
- sdata/contrib/piexif/helper.py +66 -0
- sdata/contrib/ranger/__init__.py +8 -0
- sdata/contrib/ranger/collections/__init__.py +0 -0
- sdata/contrib/ranger/collections/rangebucketmap.py +346 -0
- sdata/contrib/ranger/collections/rangemap.py +396 -0
- sdata/contrib/ranger/collections/rangeset.py +483 -0
- sdata/contrib/ranger/range/__init__.py +0 -0
- sdata/contrib/ranger/range/cut.py +285 -0
- sdata/contrib/ranger/range/range.py +644 -0
- sdata/contrib/sobol_seq.py +394 -0
- sdata/contrib/sortedcontainers/LICENSE +13 -0
- sdata/contrib/sortedcontainers/__init__.py +74 -0
- sdata/contrib/sortedcontainers/sorteddict.py +789 -0
- sdata/contrib/sortedcontainers/sortedlist.py +2646 -0
- sdata/contrib/sortedcontainers/sortedset.py +733 -0
- sdata/contrib/sqlitedict.py +598 -0
- sdata/contrib/timeflake/__init__.py +40 -0
- sdata/contrib/timeflake/flake.py +69 -0
- sdata/contrib/timeflake/utils.py +47 -0
- sdata/deprecated/__init__.py +10 -0
- sdata/deprecated/data.py +1503 -0
- sdata/did/__init__.py +129 -0
- sdata/did/_http.py +67 -0
- sdata/did/base58btc.py +49 -0
- sdata/did/did_github.py +152 -0
- sdata/did/did_peer4.py +155 -0
- sdata/did/did_web.py +222 -0
- sdata/did/diddoc.py +75 -0
- sdata/did/ed25519.py +225 -0
- sdata/did/eddsa.py +107 -0
- sdata/did/errors.py +40 -0
- sdata/did/issue_vc.py +193 -0
- sdata/did/jose.py +126 -0
- sdata/did/keys.py +104 -0
- sdata/did/utils_didkey.py +161 -0
- sdata/did/verify_vp.py +158 -0
- sdata/doe.py +101 -0
- sdata/dtypes.py +510 -0
- sdata/experiments/__init__.py +331 -0
- sdata/experiments/blob0.py +131 -0
- sdata/experiments/file.py +42 -0
- sdata/experiments/filegroup.py +144 -0
- sdata/experiments/image_old.py +313 -0
- sdata/experiments/ks2.py +15 -0
- sdata/experiments/lapshear.py +8 -0
- sdata/experiments/material.py +7 -0
- sdata/experiments/parameters_deprecated.py +394 -0
- sdata/experiments/workbook.py +226 -0
- sdata/format.py +125 -0
- sdata/imagemeta.py +533 -0
- sdata/interactive.py +118 -0
- sdata/iolib/__init__.py +51 -0
- sdata/iolib/hashtree.py +264 -0
- sdata/iolib/json1sqlitestore.py +554 -0
- sdata/iolib/jsonsqlitestore.py +704 -0
- sdata/iolib/pud.py +242 -0
- sdata/iolib/reader.py +262 -0
- sdata/iolib/writer.py +419 -0
- sdata/metadata.py +882 -0
- sdata/parameter.py +414 -0
- sdata/schema.py +273 -0
- sdata/sclass/__init__.py +111 -0
- sdata/sclass/bfo_classes.py +362 -0
- sdata/sclass/blob.py +362 -0
- sdata/sclass/content.py +87 -0
- sdata/sclass/dataframe.py +1251 -0
- sdata/sclass/dataframegroup.py +187 -0
- sdata/sclass/dependency_graph.py +85 -0
- sdata/sclass/filereference.py +124 -0
- sdata/sclass/image.py +218 -0
- sdata/sclass/lazy_namespace.py +155 -0
- sdata/sclass/process.py +383 -0
- sdata/sclass/process_graph.py +221 -0
- sdata/sclass/zipfile.py +135 -0
- sdata/semantic.py +346 -0
- sdata/suuid.py +136 -0
- sdata/timestamp.py +336 -0
- sdata/tools.py +14 -0
- sdata/units.py +602 -0
- sdata/vocab.py +149 -0
- sdata-1.5.0.dist-info/METADATA +264 -0
- sdata-1.5.0.dist-info/RECORD +98 -0
- sdata-1.5.0.dist-info/WHEEL +5 -0
- sdata-1.5.0.dist-info/licenses/LICENSE-MIT +21 -0
- sdata-1.5.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import struct
|
|
2
|
+
|
|
3
|
+
from ._exceptions import InvalidImageDataError
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def split_into_segments(data):
|
|
7
|
+
"""Slices JPEG meta data into a list from JPEG binary data.
|
|
8
|
+
"""
|
|
9
|
+
if data[0:2] != b"\xff\xd8":
|
|
10
|
+
raise InvalidImageDataError("Given data isn't JPEG.")
|
|
11
|
+
|
|
12
|
+
head = 2
|
|
13
|
+
segments = [b"\xff\xd8"]
|
|
14
|
+
while 1:
|
|
15
|
+
if data[head: head + 2] == b"\xff\xda":
|
|
16
|
+
segments.append(data[head:])
|
|
17
|
+
break
|
|
18
|
+
else:
|
|
19
|
+
length = struct.unpack(">H", data[head + 2: head + 4])[0]
|
|
20
|
+
endPoint = head + length + 2
|
|
21
|
+
seg = data[head: endPoint]
|
|
22
|
+
segments.append(seg)
|
|
23
|
+
head = endPoint
|
|
24
|
+
|
|
25
|
+
if (head >= len(data)):
|
|
26
|
+
raise InvalidImageDataError("Wrong JPEG data.")
|
|
27
|
+
return segments
|
|
28
|
+
|
|
29
|
+
def read_exif_from_file(filename):
|
|
30
|
+
"""Slices JPEG meta data into a list from JPEG binary data.
|
|
31
|
+
"""
|
|
32
|
+
f = open(filename, "rb")
|
|
33
|
+
data = f.read(6)
|
|
34
|
+
|
|
35
|
+
if data[0:2] != b"\xff\xd8":
|
|
36
|
+
raise InvalidImageDataError("Given data isn't JPEG.")
|
|
37
|
+
|
|
38
|
+
head = data[2:6]
|
|
39
|
+
HEAD_LENGTH = 4
|
|
40
|
+
exif = None
|
|
41
|
+
while len(head) == HEAD_LENGTH:
|
|
42
|
+
length = struct.unpack(">H", head[2: 4])[0]
|
|
43
|
+
|
|
44
|
+
if head[:2] == b"\xff\xe1":
|
|
45
|
+
segment_data = f.read(length - 2)
|
|
46
|
+
if segment_data[:4] != b'Exif':
|
|
47
|
+
head = f.read(HEAD_LENGTH)
|
|
48
|
+
continue
|
|
49
|
+
exif = head + segment_data
|
|
50
|
+
break
|
|
51
|
+
elif head[0:1] == b"\xff":
|
|
52
|
+
f.read(length - 2)
|
|
53
|
+
head = f.read(HEAD_LENGTH)
|
|
54
|
+
else:
|
|
55
|
+
break
|
|
56
|
+
|
|
57
|
+
f.close()
|
|
58
|
+
return exif
|
|
59
|
+
|
|
60
|
+
def get_exif_seg(segments):
|
|
61
|
+
"""Returns Exif from JPEG meta data list
|
|
62
|
+
"""
|
|
63
|
+
for seg in segments:
|
|
64
|
+
if seg[0:2] == b"\xff\xe1" and seg[4:10] == b"Exif\x00\x00":
|
|
65
|
+
return seg
|
|
66
|
+
return None
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def merge_segments(segments, exif=b""):
|
|
70
|
+
"""Merges Exif with APP0 and APP1 manipulations.
|
|
71
|
+
"""
|
|
72
|
+
if segments[1][0:2] == b"\xff\xe0" and \
|
|
73
|
+
segments[2][0:2] == b"\xff\xe1" and \
|
|
74
|
+
segments[2][4:10] == b"Exif\x00\x00":
|
|
75
|
+
if exif:
|
|
76
|
+
segments[2] = exif
|
|
77
|
+
segments.pop(1)
|
|
78
|
+
elif exif is None:
|
|
79
|
+
segments.pop(2)
|
|
80
|
+
else:
|
|
81
|
+
segments.pop(1)
|
|
82
|
+
elif segments[1][0:2] == b"\xff\xe0":
|
|
83
|
+
if exif:
|
|
84
|
+
segments[1] = exif
|
|
85
|
+
elif segments[1][0:2] == b"\xff\xe1" and \
|
|
86
|
+
segments[1][4:10] == b"Exif\x00\x00":
|
|
87
|
+
if exif:
|
|
88
|
+
segments[1] = exif
|
|
89
|
+
elif exif is None:
|
|
90
|
+
segments.pop(1)
|
|
91
|
+
else:
|
|
92
|
+
if exif:
|
|
93
|
+
segments.insert(1, exif)
|
|
94
|
+
return b"".join(segments)
|
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
import copy
|
|
2
|
+
import numbers
|
|
3
|
+
import struct
|
|
4
|
+
|
|
5
|
+
from ._common import *
|
|
6
|
+
from ._exif import *
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
TIFF_HEADER_LENGTH = 8
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def dump(exif_dict_original):
|
|
13
|
+
"""
|
|
14
|
+
py:function:: piexif.load(data)
|
|
15
|
+
|
|
16
|
+
Return exif as bytes.
|
|
17
|
+
|
|
18
|
+
:param dict exif: Exif data({"0th":dict, "Exif":dict, "GPS":dict, "Interop":dict, "1st":dict, "thumbnail":bytes})
|
|
19
|
+
:return: Exif
|
|
20
|
+
:rtype: bytes
|
|
21
|
+
"""
|
|
22
|
+
exif_dict = copy.deepcopy(exif_dict_original)
|
|
23
|
+
header = b"Exif\x00\x00\x4d\x4d\x00\x2a\x00\x00\x00\x08"
|
|
24
|
+
exif_is = False
|
|
25
|
+
gps_is = False
|
|
26
|
+
interop_is = False
|
|
27
|
+
first_is = False
|
|
28
|
+
|
|
29
|
+
if "0th" in exif_dict:
|
|
30
|
+
zeroth_ifd = exif_dict["0th"]
|
|
31
|
+
else:
|
|
32
|
+
zeroth_ifd = {}
|
|
33
|
+
|
|
34
|
+
if (("Exif" in exif_dict) and len(exif_dict["Exif"]) or
|
|
35
|
+
("Interop" in exif_dict) and len(exif_dict["Interop"]) ):
|
|
36
|
+
zeroth_ifd[ImageIFD.ExifTag] = 1
|
|
37
|
+
exif_is = True
|
|
38
|
+
exif_ifd = exif_dict["Exif"]
|
|
39
|
+
if ("Interop" in exif_dict) and len(exif_dict["Interop"]):
|
|
40
|
+
exif_ifd[ExifIFD. InteroperabilityTag] = 1
|
|
41
|
+
interop_is = True
|
|
42
|
+
interop_ifd = exif_dict["Interop"]
|
|
43
|
+
elif ExifIFD. InteroperabilityTag in exif_ifd:
|
|
44
|
+
exif_ifd.pop(ExifIFD.InteroperabilityTag)
|
|
45
|
+
elif ImageIFD.ExifTag in zeroth_ifd:
|
|
46
|
+
zeroth_ifd.pop(ImageIFD.ExifTag)
|
|
47
|
+
|
|
48
|
+
if ("GPS" in exif_dict) and len(exif_dict["GPS"]):
|
|
49
|
+
zeroth_ifd[ImageIFD.GPSTag] = 1
|
|
50
|
+
gps_is = True
|
|
51
|
+
gps_ifd = exif_dict["GPS"]
|
|
52
|
+
elif ImageIFD.GPSTag in zeroth_ifd:
|
|
53
|
+
zeroth_ifd.pop(ImageIFD.GPSTag)
|
|
54
|
+
|
|
55
|
+
if (("1st" in exif_dict) and
|
|
56
|
+
("thumbnail" in exif_dict) and
|
|
57
|
+
(exif_dict["thumbnail"] is not None)):
|
|
58
|
+
first_is = True
|
|
59
|
+
exif_dict["1st"][ImageIFD.JPEGInterchangeFormat] = 1
|
|
60
|
+
exif_dict["1st"][ImageIFD.JPEGInterchangeFormatLength] = 1
|
|
61
|
+
first_ifd = exif_dict["1st"]
|
|
62
|
+
|
|
63
|
+
zeroth_set = _dict_to_bytes(zeroth_ifd, "0th", 0)
|
|
64
|
+
zeroth_length = (len(zeroth_set[0]) + exif_is * 12 + gps_is * 12 + 4 +
|
|
65
|
+
len(zeroth_set[1]))
|
|
66
|
+
|
|
67
|
+
if exif_is:
|
|
68
|
+
exif_set = _dict_to_bytes(exif_ifd, "Exif", zeroth_length)
|
|
69
|
+
exif_length = len(exif_set[0]) + interop_is * 12 + len(exif_set[1])
|
|
70
|
+
else:
|
|
71
|
+
exif_bytes = b""
|
|
72
|
+
exif_length = 0
|
|
73
|
+
if gps_is:
|
|
74
|
+
gps_set = _dict_to_bytes(gps_ifd, "GPS", zeroth_length + exif_length)
|
|
75
|
+
gps_bytes = b"".join(gps_set)
|
|
76
|
+
gps_length = len(gps_bytes)
|
|
77
|
+
else:
|
|
78
|
+
gps_bytes = b""
|
|
79
|
+
gps_length = 0
|
|
80
|
+
if interop_is:
|
|
81
|
+
offset = zeroth_length + exif_length + gps_length
|
|
82
|
+
interop_set = _dict_to_bytes(interop_ifd, "Interop", offset)
|
|
83
|
+
interop_bytes = b"".join(interop_set)
|
|
84
|
+
interop_length = len(interop_bytes)
|
|
85
|
+
else:
|
|
86
|
+
interop_bytes = b""
|
|
87
|
+
interop_length = 0
|
|
88
|
+
if first_is:
|
|
89
|
+
offset = zeroth_length + exif_length + gps_length + interop_length
|
|
90
|
+
first_set = _dict_to_bytes(first_ifd, "1st", offset)
|
|
91
|
+
thumbnail = _get_thumbnail(exif_dict["thumbnail"])
|
|
92
|
+
thumbnail_max_size = 64000
|
|
93
|
+
if len(thumbnail) > thumbnail_max_size:
|
|
94
|
+
raise ValueError("Given thumbnail is too large. max 64kB")
|
|
95
|
+
else:
|
|
96
|
+
first_bytes = b""
|
|
97
|
+
if exif_is:
|
|
98
|
+
pointer_value = TIFF_HEADER_LENGTH + zeroth_length
|
|
99
|
+
pointer_str = struct.pack(">I", pointer_value)
|
|
100
|
+
key = ImageIFD.ExifTag
|
|
101
|
+
key_str = struct.pack(">H", key)
|
|
102
|
+
type_str = struct.pack(">H", TYPES.Long)
|
|
103
|
+
length_str = struct.pack(">I", 1)
|
|
104
|
+
exif_pointer = key_str + type_str + length_str + pointer_str
|
|
105
|
+
else:
|
|
106
|
+
exif_pointer = b""
|
|
107
|
+
if gps_is:
|
|
108
|
+
pointer_value = TIFF_HEADER_LENGTH + zeroth_length + exif_length
|
|
109
|
+
pointer_str = struct.pack(">I", pointer_value)
|
|
110
|
+
key = ImageIFD.GPSTag
|
|
111
|
+
key_str = struct.pack(">H", key)
|
|
112
|
+
type_str = struct.pack(">H", TYPES.Long)
|
|
113
|
+
length_str = struct.pack(">I", 1)
|
|
114
|
+
gps_pointer = key_str + type_str + length_str + pointer_str
|
|
115
|
+
else:
|
|
116
|
+
gps_pointer = b""
|
|
117
|
+
if interop_is:
|
|
118
|
+
pointer_value = (TIFF_HEADER_LENGTH +
|
|
119
|
+
zeroth_length + exif_length + gps_length)
|
|
120
|
+
pointer_str = struct.pack(">I", pointer_value)
|
|
121
|
+
key = ExifIFD.InteroperabilityTag
|
|
122
|
+
key_str = struct.pack(">H", key)
|
|
123
|
+
type_str = struct.pack(">H", TYPES.Long)
|
|
124
|
+
length_str = struct.pack(">I", 1)
|
|
125
|
+
interop_pointer = key_str + type_str + length_str + pointer_str
|
|
126
|
+
else:
|
|
127
|
+
interop_pointer = b""
|
|
128
|
+
if first_is:
|
|
129
|
+
pointer_value = (TIFF_HEADER_LENGTH + zeroth_length +
|
|
130
|
+
exif_length + gps_length + interop_length)
|
|
131
|
+
first_ifd_pointer = struct.pack(">L", pointer_value)
|
|
132
|
+
thumbnail_pointer = (pointer_value + len(first_set[0]) + 24 +
|
|
133
|
+
4 + len(first_set[1]))
|
|
134
|
+
thumbnail_p_bytes = (b"\x02\x01\x00\x04\x00\x00\x00\x01" +
|
|
135
|
+
struct.pack(">L", thumbnail_pointer))
|
|
136
|
+
thumbnail_length_bytes = (b"\x02\x02\x00\x04\x00\x00\x00\x01" +
|
|
137
|
+
struct.pack(">L", len(thumbnail)))
|
|
138
|
+
first_bytes = (first_set[0] + thumbnail_p_bytes +
|
|
139
|
+
thumbnail_length_bytes + b"\x00\x00\x00\x00" +
|
|
140
|
+
first_set[1] + thumbnail)
|
|
141
|
+
else:
|
|
142
|
+
first_ifd_pointer = b"\x00\x00\x00\x00"
|
|
143
|
+
|
|
144
|
+
zeroth_bytes = (zeroth_set[0] + exif_pointer + gps_pointer +
|
|
145
|
+
first_ifd_pointer + zeroth_set[1])
|
|
146
|
+
if exif_is:
|
|
147
|
+
exif_bytes = exif_set[0] + interop_pointer + exif_set[1]
|
|
148
|
+
|
|
149
|
+
return (header + zeroth_bytes + exif_bytes + gps_bytes +
|
|
150
|
+
interop_bytes + first_bytes)
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def _get_thumbnail(jpeg):
|
|
154
|
+
segments = split_into_segments(jpeg)
|
|
155
|
+
while (b"\xff\xe0" <= segments[1][0:2] <= b"\xff\xef"):
|
|
156
|
+
segments.pop(1)
|
|
157
|
+
thumbnail = b"".join(segments)
|
|
158
|
+
return thumbnail
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def _pack_byte(*args):
|
|
162
|
+
return struct.pack("B" * len(args), *args)
|
|
163
|
+
|
|
164
|
+
def _pack_signed_byte(*args):
|
|
165
|
+
return struct.pack("b" * len(args), *args)
|
|
166
|
+
|
|
167
|
+
def _pack_short(*args):
|
|
168
|
+
return struct.pack(">" + "H" * len(args), *args)
|
|
169
|
+
|
|
170
|
+
def _pack_signed_short(*args):
|
|
171
|
+
return struct.pack(">" + "h" * len(args), *args)
|
|
172
|
+
|
|
173
|
+
def _pack_long(*args):
|
|
174
|
+
return struct.pack(">" + "L" * len(args), *args)
|
|
175
|
+
|
|
176
|
+
def _pack_slong(*args):
|
|
177
|
+
return struct.pack(">" + "l" * len(args), *args)
|
|
178
|
+
|
|
179
|
+
def _pack_float(*args):
|
|
180
|
+
return struct.pack(">" + "f" * len(args), *args)
|
|
181
|
+
|
|
182
|
+
def _pack_double(*args):
|
|
183
|
+
return struct.pack(">" + "d" * len(args), *args)
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
def _value_to_bytes(raw_value, value_type, offset):
|
|
187
|
+
four_bytes_over = b""
|
|
188
|
+
value_str = b""
|
|
189
|
+
|
|
190
|
+
if value_type == TYPES.Byte:
|
|
191
|
+
length = len(raw_value)
|
|
192
|
+
if length <= 4:
|
|
193
|
+
value_str = (_pack_byte(*raw_value) +
|
|
194
|
+
b"\x00" * (4 - length))
|
|
195
|
+
else:
|
|
196
|
+
value_str = struct.pack(">I", offset)
|
|
197
|
+
four_bytes_over = _pack_byte(*raw_value)
|
|
198
|
+
elif value_type == TYPES.Short:
|
|
199
|
+
length = len(raw_value)
|
|
200
|
+
if length <= 2:
|
|
201
|
+
value_str = (_pack_short(*raw_value) +
|
|
202
|
+
b"\x00\x00" * (2 - length))
|
|
203
|
+
else:
|
|
204
|
+
value_str = struct.pack(">I", offset)
|
|
205
|
+
four_bytes_over = _pack_short(*raw_value)
|
|
206
|
+
elif value_type == TYPES.Long:
|
|
207
|
+
length = len(raw_value)
|
|
208
|
+
if length <= 1:
|
|
209
|
+
value_str = _pack_long(*raw_value)
|
|
210
|
+
else:
|
|
211
|
+
value_str = struct.pack(">I", offset)
|
|
212
|
+
four_bytes_over = _pack_long(*raw_value)
|
|
213
|
+
elif value_type == TYPES.SLong:
|
|
214
|
+
length = len(raw_value)
|
|
215
|
+
if length <= 1:
|
|
216
|
+
value_str = _pack_slong(*raw_value)
|
|
217
|
+
else:
|
|
218
|
+
value_str = struct.pack(">I", offset)
|
|
219
|
+
four_bytes_over = _pack_slong(*raw_value)
|
|
220
|
+
elif value_type == TYPES.Ascii:
|
|
221
|
+
try:
|
|
222
|
+
new_value = raw_value.encode("latin1") + b"\x00"
|
|
223
|
+
except:
|
|
224
|
+
try:
|
|
225
|
+
new_value = raw_value + b"\x00"
|
|
226
|
+
except TypeError:
|
|
227
|
+
raise ValueError("Got invalid type to convert.")
|
|
228
|
+
length = len(new_value)
|
|
229
|
+
if length > 4:
|
|
230
|
+
value_str = struct.pack(">I", offset)
|
|
231
|
+
four_bytes_over = new_value
|
|
232
|
+
else:
|
|
233
|
+
value_str = new_value + b"\x00" * (4 - length)
|
|
234
|
+
elif value_type == TYPES.Rational:
|
|
235
|
+
if isinstance(raw_value[0], numbers.Integral):
|
|
236
|
+
length = 1
|
|
237
|
+
num, den = raw_value
|
|
238
|
+
new_value = struct.pack(">L", num) + struct.pack(">L", den)
|
|
239
|
+
elif isinstance(raw_value[0], tuple):
|
|
240
|
+
length = len(raw_value)
|
|
241
|
+
new_value = b""
|
|
242
|
+
for n, val in enumerate(raw_value):
|
|
243
|
+
num, den = val
|
|
244
|
+
new_value += (struct.pack(">L", num) +
|
|
245
|
+
struct.pack(">L", den))
|
|
246
|
+
value_str = struct.pack(">I", offset)
|
|
247
|
+
four_bytes_over = new_value
|
|
248
|
+
elif value_type == TYPES.SRational:
|
|
249
|
+
if isinstance(raw_value[0], numbers.Integral):
|
|
250
|
+
length = 1
|
|
251
|
+
num, den = raw_value
|
|
252
|
+
new_value = struct.pack(">l", num) + struct.pack(">l", den)
|
|
253
|
+
elif isinstance(raw_value[0], tuple):
|
|
254
|
+
length = len(raw_value)
|
|
255
|
+
new_value = b""
|
|
256
|
+
for n, val in enumerate(raw_value):
|
|
257
|
+
num, den = val
|
|
258
|
+
new_value += (struct.pack(">l", num) +
|
|
259
|
+
struct.pack(">l", den))
|
|
260
|
+
value_str = struct.pack(">I", offset)
|
|
261
|
+
four_bytes_over = new_value
|
|
262
|
+
elif value_type == TYPES.Undefined:
|
|
263
|
+
length = len(raw_value)
|
|
264
|
+
if length > 4:
|
|
265
|
+
value_str = struct.pack(">I", offset)
|
|
266
|
+
try:
|
|
267
|
+
four_bytes_over = b"" + raw_value
|
|
268
|
+
except TypeError:
|
|
269
|
+
raise ValueError("Got invalid type to convert.")
|
|
270
|
+
else:
|
|
271
|
+
try:
|
|
272
|
+
value_str = raw_value + b"\x00" * (4 - length)
|
|
273
|
+
except TypeError:
|
|
274
|
+
raise ValueError("Got invalid type to convert.")
|
|
275
|
+
elif value_type == TYPES.SByte: # Signed Byte
|
|
276
|
+
length = len(raw_value)
|
|
277
|
+
if length <= 4:
|
|
278
|
+
value_str = (_pack_signed_byte(*raw_value) +
|
|
279
|
+
b"\x00" * (4 - length))
|
|
280
|
+
else:
|
|
281
|
+
value_str = struct.pack(">I", offset)
|
|
282
|
+
four_bytes_over = _pack_signed_byte(*raw_value)
|
|
283
|
+
elif value_type == TYPES.SShort: # Signed Short
|
|
284
|
+
length = len(raw_value)
|
|
285
|
+
if length <= 2:
|
|
286
|
+
value_str = (_pack_signed_short(*raw_value) +
|
|
287
|
+
b"\x00\x00" * (2 - length))
|
|
288
|
+
else:
|
|
289
|
+
value_str = struct.pack(">I", offset)
|
|
290
|
+
four_bytes_over = _pack_signed_short(*raw_value)
|
|
291
|
+
elif value_type == TYPES.Float:
|
|
292
|
+
length = len(raw_value)
|
|
293
|
+
if length <= 1:
|
|
294
|
+
value_str = _pack_float(*raw_value)
|
|
295
|
+
else:
|
|
296
|
+
value_str = struct.pack(">I", offset)
|
|
297
|
+
four_bytes_over = _pack_float(*raw_value)
|
|
298
|
+
elif value_type == TYPES.DFloat: # Double
|
|
299
|
+
length = len(raw_value)
|
|
300
|
+
value_str = struct.pack(">I", offset)
|
|
301
|
+
four_bytes_over = _pack_double(*raw_value)
|
|
302
|
+
|
|
303
|
+
length_str = struct.pack(">I", length)
|
|
304
|
+
return length_str, value_str, four_bytes_over
|
|
305
|
+
|
|
306
|
+
def _dict_to_bytes(ifd_dict, ifd, ifd_offset):
|
|
307
|
+
tag_count = len(ifd_dict)
|
|
308
|
+
entry_header = struct.pack(">H", tag_count)
|
|
309
|
+
if ifd in ("0th", "1st"):
|
|
310
|
+
entries_length = 2 + tag_count * 12 + 4
|
|
311
|
+
else:
|
|
312
|
+
entries_length = 2 + tag_count * 12
|
|
313
|
+
entries = b""
|
|
314
|
+
values = b""
|
|
315
|
+
|
|
316
|
+
for n, key in enumerate(sorted(ifd_dict)):
|
|
317
|
+
if (ifd == "0th") and (key in (ImageIFD.ExifTag, ImageIFD.GPSTag)):
|
|
318
|
+
continue
|
|
319
|
+
elif (ifd == "Exif") and (key == ExifIFD.InteroperabilityTag):
|
|
320
|
+
continue
|
|
321
|
+
elif (ifd == "1st") and (key in (ImageIFD.JPEGInterchangeFormat, ImageIFD.JPEGInterchangeFormatLength)):
|
|
322
|
+
continue
|
|
323
|
+
|
|
324
|
+
raw_value = ifd_dict[key]
|
|
325
|
+
key_str = struct.pack(">H", key)
|
|
326
|
+
value_type = TAGS[ifd][key]["type"]
|
|
327
|
+
type_str = struct.pack(">H", value_type)
|
|
328
|
+
four_bytes_over = b""
|
|
329
|
+
|
|
330
|
+
if isinstance(raw_value, numbers.Integral) or isinstance(raw_value, float):
|
|
331
|
+
raw_value = (raw_value,)
|
|
332
|
+
offset = TIFF_HEADER_LENGTH + entries_length + ifd_offset + len(values)
|
|
333
|
+
|
|
334
|
+
try:
|
|
335
|
+
length_str, value_str, four_bytes_over = _value_to_bytes(raw_value,
|
|
336
|
+
value_type,
|
|
337
|
+
offset)
|
|
338
|
+
except ValueError:
|
|
339
|
+
raise ValueError(
|
|
340
|
+
'"dump" got wrong type of exif value.\n' +
|
|
341
|
+
'{} in {} IFD. Got as {}.'.format(key, ifd, type(ifd_dict[key]))
|
|
342
|
+
)
|
|
343
|
+
|
|
344
|
+
entries += key_str + type_str + length_str + value_str
|
|
345
|
+
values += four_bytes_over
|
|
346
|
+
return (entry_header + entries, values)
|