nt25 0.1.5__py3-none-any.whl → 0.1.6__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.
nt25/data/exif.jpg
ADDED
Binary file
|
nt25/lib/et.py
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
import io
|
2
|
+
from operator import length_hint
|
2
3
|
import time
|
3
4
|
import json
|
4
5
|
import struct
|
@@ -8,6 +9,7 @@ from datetime import UTC, datetime, timedelta, timezone
|
|
8
9
|
from exif import Image, DATETIME_STR_FORMAT
|
9
10
|
|
10
11
|
VERSION = "0.1.2"
|
12
|
+
COMMENT_SEGMENT = b"\xff\xfe"
|
11
13
|
EPOCH = datetime.fromtimestamp(0, UTC)
|
12
14
|
|
13
15
|
|
@@ -43,6 +45,7 @@ def tryGet(img, key, default):
|
|
43
45
|
|
44
46
|
def dumpExif(file):
|
45
47
|
result = {}
|
48
|
+
|
46
49
|
with open(file, 'rb') as f:
|
47
50
|
img = Image(f)
|
48
51
|
for key in img.get_all():
|
@@ -112,18 +115,18 @@ class InvalidImageDataError(ValueError):
|
|
112
115
|
pass
|
113
116
|
|
114
117
|
|
115
|
-
def
|
116
|
-
"""Slices JPEG meta data into a list from JPEG binary data.
|
117
|
-
"""
|
118
|
+
def genSegments(data):
|
118
119
|
if data[0:2] != b"\xff\xd8":
|
119
120
|
raise InvalidImageDataError("Given data isn't JPEG.")
|
120
121
|
|
121
122
|
head = 2
|
122
123
|
segments = [b"\xff\xd8"]
|
124
|
+
|
123
125
|
while 1:
|
124
126
|
if data[head: head + 2] == b"\xff\xda":
|
125
127
|
segments.append(data[head:])
|
126
128
|
break
|
129
|
+
|
127
130
|
else:
|
128
131
|
length = struct.unpack(">H", data[head + 2: head + 4])[0]
|
129
132
|
endPoint = head + length + 2
|
@@ -137,39 +140,34 @@ def split_into_segments(data):
|
|
137
140
|
return segments
|
138
141
|
|
139
142
|
|
140
|
-
def
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
data = f.read(6)
|
143
|
+
def setComment(segments, comment: str, enc='utf-8'):
|
144
|
+
contains = False
|
145
|
+
cb = comment.encode(enc)
|
146
|
+
length = len(cb) + 2
|
145
147
|
|
146
|
-
|
147
|
-
raise InvalidImageDataError("Given data isn't JPEG.")
|
148
|
+
cbSeg = COMMENT_SEGMENT + length.to_bytes(2, byteorder='big') + cb
|
148
149
|
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
else:
|
166
|
-
break
|
150
|
+
for i in range(len(segments)):
|
151
|
+
if segments[i][0:2] == COMMENT_SEGMENT:
|
152
|
+
contains = True
|
153
|
+
segments[i] = cbSeg
|
154
|
+
|
155
|
+
if not contains:
|
156
|
+
length = len(segments)
|
157
|
+
segments.insert(1 if length == 2 else length - 2, cbSeg)
|
158
|
+
|
159
|
+
return segments
|
160
|
+
|
161
|
+
|
162
|
+
def getComment(segments, enc='utf-8'):
|
163
|
+
for seg in segments:
|
164
|
+
if seg[0:2] == COMMENT_SEGMENT:
|
165
|
+
return seg[4:].decode(encoding=enc, errors='replace')
|
167
166
|
|
168
|
-
|
169
|
-
return exif
|
167
|
+
return None
|
170
168
|
|
171
169
|
|
172
|
-
def
|
170
|
+
def getExif(segments):
|
173
171
|
"""Returns Exif from JPEG meta data list
|
174
172
|
"""
|
175
173
|
for seg in segments:
|
@@ -179,7 +177,7 @@ def get_exif_seg(segments):
|
|
179
177
|
return None
|
180
178
|
|
181
179
|
|
182
|
-
def
|
180
|
+
def mergeSegments(segments, exif=b""):
|
183
181
|
"""Merges Exif with APP0 and APP1 manipulations.
|
184
182
|
"""
|
185
183
|
if segments[1][0:2] == b"\xff\xe0" and \
|
@@ -212,14 +210,7 @@ def merge_segments(segments, exif=b""):
|
|
212
210
|
return b"".join(segments)
|
213
211
|
|
214
212
|
|
215
|
-
def
|
216
|
-
"""
|
217
|
-
py:function:: piexif.remove(filename)
|
218
|
-
|
219
|
-
Remove exif from JPEG.
|
220
|
-
|
221
|
-
:param str filename: JPEG
|
222
|
-
"""
|
213
|
+
def removeExif(src, new_file=None):
|
223
214
|
output_is_file = False
|
224
215
|
if src[0:2] == b"\xff\xd8":
|
225
216
|
src_data = src
|
@@ -232,12 +223,13 @@ def remove(src, new_file=None):
|
|
232
223
|
file_type = "jpeg"
|
233
224
|
|
234
225
|
if file_type == "jpeg":
|
235
|
-
segments =
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
226
|
+
segments = genSegments(src_data)
|
227
|
+
segments = list(filter(lambda seg: not (seg[0:2] == b"\xff\xe1"
|
228
|
+
and seg[4:10] == b"Exif\x00\x00"),
|
229
|
+
segments))
|
230
|
+
|
231
|
+
segments = setComment(segments, "nt25.et")
|
232
|
+
new_data = b"".join(segments)
|
241
233
|
|
242
234
|
if isinstance(new_file, io.BytesIO):
|
243
235
|
new_file.write(new_data)
|
@@ -267,8 +259,8 @@ def transplant(exif_src, image, new_file=None):
|
|
267
259
|
with open(exif_src, 'rb') as f:
|
268
260
|
src_data = f.read()
|
269
261
|
|
270
|
-
segments =
|
271
|
-
exif =
|
262
|
+
segments = genSegments(src_data)
|
263
|
+
exif = getExif(segments)
|
272
264
|
|
273
265
|
if exif is None:
|
274
266
|
raise ValueError("not found exif in input")
|
@@ -281,8 +273,9 @@ def transplant(exif_src, image, new_file=None):
|
|
281
273
|
image_data = f.read()
|
282
274
|
output_file = True
|
283
275
|
|
284
|
-
segments =
|
285
|
-
|
276
|
+
segments = genSegments(image_data)
|
277
|
+
segments = setComment(segments, "nt25.et")
|
278
|
+
new_data = mergeSegments(segments, exif)
|
286
279
|
|
287
280
|
if isinstance(new_file, io.BytesIO):
|
288
281
|
new_file.write(new_data)
|
@@ -319,7 +312,7 @@ def main():
|
|
319
312
|
if args.dump:
|
320
313
|
r = dumpExif(args.file)
|
321
314
|
elif args.rm:
|
322
|
-
r =
|
315
|
+
r = removeExif(args.file)
|
323
316
|
elif args.copy:
|
324
317
|
r = transplant(args.copy, args.file)
|
325
318
|
else:
|
@@ -1,13 +1,12 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: nt25
|
3
|
-
Version: 0.1.
|
3
|
+
Version: 0.1.6
|
4
4
|
Summary: Neo's Tools of Python
|
5
5
|
Requires-Python: >=3.10
|
6
6
|
Requires-Dist: exif>=1.6.1
|
7
7
|
Requires-Dist: matplotlib>=3.10.6
|
8
8
|
Requires-Dist: openpyxl>=3.1.5
|
9
9
|
Requires-Dist: pandas>=2.3.2
|
10
|
-
Requires-Dist: piexif>=1.1.3
|
11
10
|
Requires-Dist: pyinstaller>=6.15.0
|
12
11
|
Requires-Dist: scikit-learn>=1.7.1
|
13
12
|
Requires-Dist: sympy>=1.14.0
|
@@ -1,11 +1,12 @@
|
|
1
1
|
nt25/__init__.py,sha256=28wWlyuyScDrZx9ytGM_TxUipk5dg4pOyp_xyj6-NWk,295
|
2
2
|
nt25/demo.py,sha256=W34-7KTYVpBYXg0UrgmkVCRWAdO5RAc1K7zS9pz-BEQ,2179
|
3
|
+
nt25/data/exif.jpg,sha256=Wl9QqZ3UAC_ldd055lJOcZKqvU5swqLEw_HxRBbLYgc,347767
|
3
4
|
nt25/data/test.xlsx,sha256=7C0JDS-TLm_KmjnKtfeajkpwGKSUhcLdr2W2UFUxAgM,10542
|
4
5
|
nt25/lib/calc.py,sha256=3X3k9jisSjRP7OokSdKvoVo4IIOzk2efexW8z1gMo-w,2265
|
5
6
|
nt25/lib/draw.py,sha256=OKTlkkNVUz_LGBA9Gk7fjcnbbbl7e_hT8nWKkcfeg2k,5642
|
6
|
-
nt25/lib/et.py,sha256=
|
7
|
+
nt25/lib/et.py,sha256=b7inPmDy-Vj0v7hdJdpCV-K5c05BgJpVzKAWJe75tfE,7873
|
7
8
|
nt25/lib/fio.py,sha256=WvHpG6QYR1NE19Ss3Sy2FdajTxibX5SVW3PyC5Y5Krk,2525
|
8
|
-
nt25-0.1.
|
9
|
-
nt25-0.1.
|
10
|
-
nt25-0.1.
|
11
|
-
nt25-0.1.
|
9
|
+
nt25-0.1.6.dist-info/METADATA,sha256=LV7UAehxnrZbCOXjbivjfT-xHC9StucF_5xmgb5V4c0,654
|
10
|
+
nt25-0.1.6.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
11
|
+
nt25-0.1.6.dist-info/entry_points.txt,sha256=mtt7YI92CecNLeMvyM3o5IyVzRpYSqqwmUgAzldhFH8,62
|
12
|
+
nt25-0.1.6.dist-info/RECORD,,
|
File without changes
|
File without changes
|