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 split_into_segments(data):
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 read_exif_from_file(filename):
141
- """Slices JPEG meta data into a list from JPEG binary data.
142
- """
143
- f = open(filename, "rb")
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
- if data[0:2] != b"\xff\xd8":
147
- raise InvalidImageDataError("Given data isn't JPEG.")
148
+ cbSeg = COMMENT_SEGMENT + length.to_bytes(2, byteorder='big') + cb
148
149
 
149
- head = data[2:6]
150
- HEAD_LENGTH = 4
151
- exif = None
152
- while len(head) == HEAD_LENGTH:
153
- length = struct.unpack(">H", head[2: 4])[0]
154
-
155
- if head[:2] == b"\xff\xe1":
156
- segment_data = f.read(length - 2)
157
- if segment_data[:4] != b'Exif':
158
- head = f.read(HEAD_LENGTH)
159
- continue
160
- exif = head + segment_data
161
- break
162
- elif head[0:1] == b"\xff":
163
- f.read(length - 2)
164
- head = f.read(HEAD_LENGTH)
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
- f.close()
169
- return exif
167
+ return None
170
168
 
171
169
 
172
- def get_exif_seg(segments):
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 merge_segments(segments, exif=b""):
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 remove(src, new_file=None):
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 = split_into_segments(src_data)
236
- exif = get_exif_seg(segments)
237
- if exif:
238
- new_data = src_data.replace(exif, b"")
239
- else:
240
- new_data = src_data
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 = split_into_segments(src_data)
271
- exif = get_exif_seg(segments)
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 = split_into_segments(image_data)
285
- new_data = merge_segments(segments, exif)
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 = remove(args.file)
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.5
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=BWg4dl1EuDA6pKQbWqxSY_OE5ya7l8vvGsMb7SGDpaM,7933
7
+ nt25/lib/et.py,sha256=b7inPmDy-Vj0v7hdJdpCV-K5c05BgJpVzKAWJe75tfE,7873
7
8
  nt25/lib/fio.py,sha256=WvHpG6QYR1NE19Ss3Sy2FdajTxibX5SVW3PyC5Y5Krk,2525
8
- nt25-0.1.5.dist-info/METADATA,sha256=NbRanYnyhkstfCxQIS-nxf2f1E4VdI_QZJhd0TBmmeM,683
9
- nt25-0.1.5.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
10
- nt25-0.1.5.dist-info/entry_points.txt,sha256=mtt7YI92CecNLeMvyM3o5IyVzRpYSqqwmUgAzldhFH8,62
11
- nt25-0.1.5.dist-info/RECORD,,
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