geopic-tag-reader 1.7.0__py3-none-any.whl → 1.8.1__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.
Files changed (27) hide show
  1. geopic_tag_reader/__init__.py +1 -1
  2. geopic_tag_reader/camera.py +1 -0
  3. geopic_tag_reader/cameras.csv +8 -0
  4. geopic_tag_reader/reader.py +11 -0
  5. geopic_tag_reader/sequence.py +87 -33
  6. geopic_tag_reader/translations/be/LC_MESSAGES/geopic_tag_reader.mo +0 -0
  7. geopic_tag_reader/translations/be/LC_MESSAGES/geopic_tag_reader.po +216 -0
  8. geopic_tag_reader/translations/de/LC_MESSAGES/geopic_tag_reader.mo +0 -0
  9. geopic_tag_reader/translations/de/LC_MESSAGES/geopic_tag_reader.po +31 -30
  10. geopic_tag_reader/translations/en/LC_MESSAGES/geopic_tag_reader.mo +0 -0
  11. geopic_tag_reader/translations/en/LC_MESSAGES/geopic_tag_reader.po +19 -19
  12. geopic_tag_reader/translations/geopic_tag_reader.pot +16 -16
  13. geopic_tag_reader/translations/nl/LC_MESSAGES/geopic_tag_reader.mo +0 -0
  14. geopic_tag_reader/translations/nl/LC_MESSAGES/geopic_tag_reader.po +3 -3
  15. geopic_tag_reader/translations/pt/LC_MESSAGES/geopic_tag_reader.mo +0 -0
  16. geopic_tag_reader/translations/pt/LC_MESSAGES/geopic_tag_reader.po +222 -0
  17. geopic_tag_reader/translations/pt_BR/LC_MESSAGES/geopic_tag_reader.mo +0 -0
  18. geopic_tag_reader/translations/pt_BR/LC_MESSAGES/geopic_tag_reader.po +223 -0
  19. geopic_tag_reader/translations/tr/LC_MESSAGES/geopic_tag_reader.mo +0 -0
  20. geopic_tag_reader/translations/tr/LC_MESSAGES/geopic_tag_reader.po +216 -0
  21. geopic_tag_reader/translations/uk/LC_MESSAGES/geopic_tag_reader.mo +0 -0
  22. geopic_tag_reader/translations/uk/LC_MESSAGES/geopic_tag_reader.po +220 -0
  23. {geopic_tag_reader-1.7.0.dist-info → geopic_tag_reader-1.8.1.dist-info}/METADATA +2 -1
  24. {geopic_tag_reader-1.7.0.dist-info → geopic_tag_reader-1.8.1.dist-info}/RECORD +27 -17
  25. {geopic_tag_reader-1.7.0.dist-info → geopic_tag_reader-1.8.1.dist-info}/WHEEL +0 -0
  26. {geopic_tag_reader-1.7.0.dist-info → geopic_tag_reader-1.8.1.dist-info}/entry_points.txt +0 -0
  27. {geopic_tag_reader-1.7.0.dist-info → geopic_tag_reader-1.8.1.dist-info}/licenses/LICENSE +0 -0
@@ -2,4 +2,4 @@
2
2
  GeoPicTagReader
3
3
  """
4
4
 
5
- __version__ = "1.7.0"
5
+ __version__ = "1.8.1"
@@ -20,6 +20,7 @@ GPS_ACCURACY_MAKE = {
20
20
  "tectectec": 4,
21
21
  "arashi vision": 4,
22
22
  "qoocam": 4,
23
+ "dji": 4,
23
24
  # Smartphone GPS
24
25
  "samsung": 5,
25
26
  "xiaomi": 5,
@@ -1094,7 +1094,14 @@
1094
1094
  "Fujifilm";"X-M1";"23.6";;
1095
1095
  "Fujifilm";"X-Pro1";"23.6";;
1096
1096
  "Fujifilm";"X-S1";"8.8";;
1097
+ "Fujifilm";"X-S10";"23.5";;
1098
+ "Fujifilm";"X-S20";"23.5";;
1097
1099
  "Fujifilm";"X-T1";"23.6";;
1100
+ "Fujifilm";"X-T2";"23.5";;
1101
+ "Fujifilm";"X-T3";"23.5";;
1102
+ "Fujifilm";"X-T30";"23.5";;
1103
+ "Fujifilm";"X-T4";"23.5";;
1104
+ "Fujifilm";"X-T5";"23.5";;
1098
1105
  "Fujifilm";"X10";"8.8";;
1099
1106
  "Fujifilm";"X100S";"23.6";;
1100
1107
  "Fujifilm";"X100T";"23.6";;
@@ -2298,6 +2305,7 @@
2298
2305
  "oneplu";"A000";"4.8";;
2299
2306
  "OnePlus";"A3003";"6.4";;
2300
2307
  "OnePlus";"A5000";"5.22";;
2308
+ "OnePlus";"EB2103";"6.51";;
2301
2309
  "Panasonic";"Lumix DMC-LZ20";"6.08";;
2302
2310
  "Panasonic";"D-snap SV-AS10";"4.5";;
2303
2311
  "Panasonic";"D-snap SV-AS3";"4.5";;
@@ -385,6 +385,17 @@ def getPictureMetadata(data: dict, width: int, height: int, lang_code: str = "en
385
385
  if fw > w or fh > h:
386
386
  crop = CropValues(fw, fh, w, h, l, t)
387
387
 
388
+ # Skip images where crop width/height equals full width/length
389
+ elif (
390
+ isExifTagUsable(data, "Xmp.GPano.CroppedAreaImageWidthPixels", int)
391
+ and isExifTagUsable(data, "Xmp.GPano.CroppedAreaImageHeightPixels", int)
392
+ and isExifTagUsable(data, "Xmp.GPano.FullPanoWidthPixels", int)
393
+ and isExifTagUsable(data, "Xmp.GPano.FullPanoHeightPixels", int)
394
+ and int(data["Xmp.GPano.FullPanoHeightPixels"]) == int(data["Xmp.GPano.CroppedAreaImageHeightPixels"])
395
+ and int(data["Xmp.GPano.FullPanoWidthPixels"]) == int(data["Xmp.GPano.CroppedAreaImageWidthPixels"])
396
+ ):
397
+ pass
398
+
388
399
  elif (
389
400
  isExifTagUsable(data, "Xmp.GPano.CroppedAreaImageWidthPixels", int)
390
401
  or isExifTagUsable(data, "Xmp.GPano.CroppedAreaImageHeightPixels", int)
@@ -1,9 +1,10 @@
1
- from dataclasses import dataclass
1
+ from dataclasses import dataclass, field
2
2
  from enum import Enum
3
3
  from typing import Optional, List, Tuple
4
4
  from pathlib import PurePath
5
5
  from geopic_tag_reader.reader import GeoPicTags
6
6
  import datetime
7
+ from rtree import index
7
8
  import math
8
9
 
9
10
 
@@ -37,6 +38,7 @@ class SplitParams:
37
38
  class Picture:
38
39
  filename: str
39
40
  metadata: GeoPicTags
41
+ heading_computed: bool = False
40
42
 
41
43
  def distance_to(self, other) -> float:
42
44
  """Computes distance in meters based on Haversine formula"""
@@ -50,7 +52,7 @@ class Picture:
50
52
  distance = R * c
51
53
  return distance
52
54
 
53
- def rotation_angle(self, other) -> Optional[float]:
55
+ def rotation_angle(self, other) -> Optional[int]:
54
56
  return rotation_angle(self.metadata.heading, other.metadata.heading)
55
57
 
56
58
 
@@ -116,11 +118,19 @@ class Sequence:
116
118
  return (otherSeq.from_ts() - self.to_ts(), otherSeq.pictures[0].distance_to(self.pictures[-1])) # type: ignore
117
119
 
118
120
 
121
+ @dataclass
122
+ class Duplicate:
123
+ picture: Picture
124
+ duplicate_of: Picture
125
+ distance: float
126
+ angle: Optional[int]
127
+
128
+
119
129
  @dataclass
120
130
  class DispatchReport:
121
131
  sequences: List[Sequence]
122
- duplicate_pictures: Optional[List[Picture]] = None
123
- sequences_splits: Optional[List[Split]] = None
132
+ duplicate_pictures: List[Duplicate] = field(default_factory=list)
133
+ sequences_splits: List[Split] = field(default_factory=list)
124
134
 
125
135
 
126
136
  def sort_pictures(pictures: List[Picture], method: Optional[SortMethod] = SortMethod.time_asc) -> List[Picture]:
@@ -202,7 +212,38 @@ def sort_pictures(pictures: List[Picture], method: Optional[SortMethod] = SortMe
202
212
  return pictures
203
213
 
204
214
 
205
- def find_duplicates(pictures: List[Picture], params: Optional[MergeParams] = None) -> Tuple[List[Picture], List[Picture]]:
215
+ def are_duplicates(a: Picture, b: Picture, params: MergeParams) -> Optional[Tuple[float, Optional[int]]]:
216
+ """
217
+ Check if 2 pictures are too similar and should be considered duplicates
218
+
219
+ They are duplicates if they are close to each other, and for non 360 pictures, if they are roughly in the same direction.
220
+
221
+ Note that we only consider the direction (also called heading) if it is provided by the camera (and not computed with the sequences geometries)
222
+ since GPS can drift a bit resulting in erratic direction when waiting at a traffic light cf https://gitlab.com/panoramax/server/api/-/issues/231#note_2329723526
223
+
224
+ Return None if not duplicates, or the distance/angle if they are
225
+ """
226
+ dist = a.distance_to(b)
227
+
228
+ if params.maxDistance is None or dist > params.maxDistance:
229
+ return None
230
+
231
+ # Compare angle (if available on both images)
232
+ angle = a.rotation_angle(b)
233
+ # if one of the heading has been computed, we cannot rely on this angle being correct, so we don't consider it for the deduplication
234
+ # it's especially important when stopped and the GPS drift a bit, cf https://gitlab.com/panoramax/server/api/-/issues/231#note_2329723526
235
+ angle_computed = b.heading_computed or a.heading_computed
236
+ if angle is None or angle_computed or params.maxRotationAngle is None:
237
+ return (dist, None)
238
+ if angle <= params.maxRotationAngle:
239
+ return (dist, angle)
240
+ return None
241
+
242
+
243
+ APPROX_DEGREE_TO_METER = 0.00001 # this is roughly 1m
244
+
245
+
246
+ def find_duplicates(pictures: List[Picture], params: Optional[MergeParams] = None) -> Tuple[List[Picture], List[Duplicate]]:
206
247
  """
207
248
  Finds too similar pictures.
208
249
  Note that input list should be properly sorted.
@@ -217,42 +258,51 @@ def find_duplicates(pictures: List[Picture], params: Optional[MergeParams] = Non
217
258
  (Non-duplicates pictures, Duplicates pictures)
218
259
  """
219
260
 
220
- if params is None or not params.is_merge_needed():
261
+ if params is None or not params.is_merge_needed() or not pictures:
221
262
  return (pictures, [])
263
+ assert params.maxDistance is not None
222
264
 
223
265
  nonDups: List[Picture] = []
224
- dups: List[Picture] = []
225
- lastNonDuplicatedPicId = 0
266
+ duplicates = []
267
+ duplicates_idx = set()
226
268
 
227
- for i, currentPic in enumerate(pictures):
228
- if i == 0:
229
- nonDups.append(currentPic)
230
- continue
269
+ rtree_index = index.Index(((i, (p.metadata.lon, p.metadata.lat, p.metadata.lon, p.metadata.lat), None) for i, p in enumerate(pictures)))
231
270
 
232
- prevPic = pictures[lastNonDuplicatedPicId]
271
+ # the rtree will give us all the neighbors in an approximated bounding box,
272
+ # and will check, for all those pictures if some pictures are really closed, using a real haversine distance
273
+ # we do a rough conversion between the maxDistance (in m) to degree, since it's only for the initial bounding box
274
+ # and we use a bbox bigger than necessary (could be half by direction) to not miss duplicates due to the degree to meter approximation
233
275
 
234
- if prevPic.metadata is None or currentPic.metadata is None:
235
- nonDups.append(currentPic)
276
+ bounding_box_tolerance_approx = params.maxDistance * APPROX_DEGREE_TO_METER
277
+ for i, currentPic in enumerate(pictures):
278
+ if i in duplicates_idx:
279
+ # the picture has already been flagged as duplicate by one of its neighbor, we can skip it
236
280
  continue
237
281
 
238
- is_duplicate = False
282
+ bounding_box = (
283
+ currentPic.metadata.lon - bounding_box_tolerance_approx,
284
+ currentPic.metadata.lat - bounding_box_tolerance_approx,
285
+ currentPic.metadata.lon + bounding_box_tolerance_approx,
286
+ currentPic.metadata.lat + bounding_box_tolerance_approx,
287
+ )
239
288
 
240
- # Compare distance
241
- dist = prevPic.distance_to(currentPic)
289
+ near_pics_idx = rtree_index.nearest(bounding_box, num_results=100, objects=False)
242
290
 
243
- if params.maxDistance is not None and dist <= params.maxDistance:
244
- # Compare angle (if available on both images)
245
- angle = prevPic.rotation_angle(currentPic)
246
- if angle is None or params.maxRotationAngle is None or angle <= params.maxRotationAngle:
247
- is_duplicate = True
291
+ for neighbor_idx in near_pics_idx:
292
+ if neighbor_idx == i:
293
+ continue
294
+ if neighbor_idx in duplicates_idx:
295
+ continue
296
+ neighbor = pictures[neighbor_idx]
297
+ duplicate_details = are_duplicates(currentPic, neighbor, params)
298
+ if duplicate_details:
299
+ distance, angle = duplicate_details
300
+ duplicates_idx.add(neighbor_idx)
301
+ duplicates.append(Duplicate(picture=neighbor, duplicate_of=currentPic, distance=round(distance, 2), angle=angle))
248
302
 
249
- if is_duplicate:
250
- dups.append(currentPic)
251
- else:
252
- lastNonDuplicatedPicId = i
253
- nonDups.append(currentPic)
303
+ nonDups.append(currentPic)
254
304
 
255
- return (nonDups, dups)
305
+ return (nonDups, duplicates)
256
306
 
257
307
 
258
308
  def split_in_sequences(pictures: List[Picture], splitParams: Optional[SplitParams] = SplitParams()) -> Tuple[List[Sequence], List[Split]]:
@@ -354,10 +404,14 @@ def dispatch_pictures(
354
404
  # Sort
355
405
  myPics = sort_pictures(pictures, sortMethod)
356
406
 
357
- # De-duplicate
358
- (myPics, dupsPics) = find_duplicates(myPics, mergeParams)
359
-
360
407
  # Split in sequences
361
408
  (mySeqs, splits) = split_in_sequences(myPics, splitParams)
362
409
 
363
- return DispatchReport(mySeqs, dupsPics if len(dupsPics) > 0 else None, splits if len(splits) > 0 else None)
410
+ # De-duplicate inside each sequences
411
+ dups_pics = []
412
+ for s in mySeqs:
413
+ (myPics, dups) = find_duplicates(s.pictures, mergeParams)
414
+ s.pictures = myPics
415
+ dups_pics.extend(dups)
416
+
417
+ return DispatchReport(sequences=mySeqs, duplicate_pictures=dups_pics, sequences_splits=splits)
@@ -0,0 +1,216 @@
1
+ # SOME DESCRIPTIVE TITLE.
2
+ # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
3
+ # This file is distributed under the same license as the PACKAGE package.
4
+ # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
5
+ #
6
+ msgid ""
7
+ msgstr ""
8
+ "Project-Id-Version: PACKAGE VERSION\n"
9
+ "Report-Msgid-Bugs-To: \n"
10
+ "POT-Creation-Date: 2025-08-25 15:35+0200\n"
11
+ "PO-Revision-Date: 2025-11-04 18:45+0000\n"
12
+ "Last-Translator: Jordjio Minchane <bigopenmac@gmail.com>\n"
13
+ "Language-Team: Belarusian <http://weblate.panoramax.xyz/projects/panoramax/"
14
+ "tag-reader/be/>\n"
15
+ "Language: be\n"
16
+ "MIME-Version: 1.0\n"
17
+ "Content-Type: text/plain; charset=UTF-8\n"
18
+ "Content-Transfer-Encoding: 8bit\n"
19
+ "Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
20
+ "n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
21
+ "X-Generator: Weblate 5.4.3\n"
22
+
23
+ #: geopic_tag_reader/main.py:26
24
+ msgid "Latitude:"
25
+ msgstr "Шырата:"
26
+
27
+ #: geopic_tag_reader/main.py:27
28
+ msgid "Longitude:"
29
+ msgstr "Даўгата:"
30
+
31
+ #: geopic_tag_reader/main.py:28
32
+ msgid "GPS accuracy:"
33
+ msgstr "Дакладнасць GPS:"
34
+
35
+ #: geopic_tag_reader/main.py:28 geopic_tag_reader/main.py:31
36
+ #: geopic_tag_reader/main.py:32
37
+ msgid "not set"
38
+ msgstr "не зададзена"
39
+
40
+ #: geopic_tag_reader/main.py:29
41
+ msgid "Timestamp:"
42
+ msgstr "Метка часу:"
43
+
44
+ #: geopic_tag_reader/main.py:31
45
+ msgid "(GPS)"
46
+ msgstr "(GPS)"
47
+
48
+ #: geopic_tag_reader/main.py:32
49
+ msgid "(Camera)"
50
+ msgstr "(Фотакамера)"
51
+
52
+ #: geopic_tag_reader/main.py:33
53
+ msgid "Heading:"
54
+ msgstr "Напрамак:"
55
+
56
+ #: geopic_tag_reader/main.py:34
57
+ msgid "Type:"
58
+ msgstr "Тып:"
59
+
60
+ #: geopic_tag_reader/main.py:35
61
+ msgid "Make:"
62
+ msgstr "Вытворца:"
63
+
64
+ #: geopic_tag_reader/main.py:36
65
+ msgid "Model:"
66
+ msgstr "Мадэль:"
67
+
68
+ #: geopic_tag_reader/main.py:37
69
+ msgid "Focal length:"
70
+ msgstr "Факусная адлегласць:"
71
+
72
+ #: geopic_tag_reader/main.py:38
73
+ msgid "Field of view:"
74
+ msgstr "Поле зроку:"
75
+
76
+ #: geopic_tag_reader/main.py:39
77
+ msgid "Sensor width:"
78
+ msgstr "Шырыня сэнсара:"
79
+
80
+ #: geopic_tag_reader/main.py:40
81
+ msgid "Crop parameters:"
82
+ msgstr "Параметры абрэзкі:"
83
+
84
+ #: geopic_tag_reader/main.py:41
85
+ msgid "Pitch:"
86
+ msgstr "Нахіл:"
87
+
88
+ #: geopic_tag_reader/main.py:42
89
+ msgid "Roll:"
90
+ msgstr "Крэн:"
91
+
92
+ #: geopic_tag_reader/main.py:43
93
+ msgid "Yaw:"
94
+ msgstr "Адхіленне:"
95
+
96
+ #: geopic_tag_reader/main.py:46
97
+ msgid "Warnings raised by reader:"
98
+ msgstr "Папярэджанні чытальніка:"
99
+
100
+ #: geopic_tag_reader/reader.py:246
101
+ msgid "Read latitude is out of WGS84 bounds (should be in [-90, 90])"
102
+ msgstr "Шырата па-за межамі WGS84 (павінна быць у дыяпазоне [-90, 90])"
103
+
104
+ #: geopic_tag_reader/reader.py:248
105
+ msgid "Read longitude is out of WGS84 bounds (should be in [-180, 180])"
106
+ msgstr "Даўгата па-за межамі WGS84 (павінна быць у дыяпазоне [-180, 180])"
107
+
108
+ #: geopic_tag_reader/reader.py:276
109
+ #, python-brace-format
110
+ msgid "Skipping Mapillary date/time as it was not recognized: {v}"
111
+ msgstr "Прапускаем дату/час Mapillary, бо яны не распазнаны: {v}"
112
+
113
+ #: geopic_tag_reader/reader.py:306
114
+ msgid "No heading value was found, this reduces usability of picture"
115
+ msgstr "Значэнне напрамку не знойдзена, гэта пагаршае выкарыстальнасць выявы"
116
+
117
+ #: geopic_tag_reader/reader.py:349
118
+ msgid ""
119
+ "No make and model value found, no assumption on focal length or GPS "
120
+ "precision can be made"
121
+ msgstr ""
122
+ "Не знойдзены вытворца і мадэль, немагчыма зрабіць здагадкі пра факусную "
123
+ "адлегласць або дакладнасць GPS"
124
+
125
+ #: geopic_tag_reader/reader.py:418
126
+ msgid ""
127
+ "No focal length value was found, this prevents calculating field of view"
128
+ msgstr ""
129
+ "Значэнне факуснай адлегласці не знойдзена, гэта перашкаджае разліку поля "
130
+ "зроку"
131
+
132
+ #: geopic_tag_reader/reader.py:470
133
+ msgid "No GPS accuracy value found, this prevents computing a quality score"
134
+ msgstr ""
135
+ "Значэнне дакладнасці GPS не знойдзена, гэта перашкаджае разліку адзнакі "
136
+ "якасці"
137
+
138
+ #: geopic_tag_reader/reader.py:472
139
+ msgid ""
140
+ "No GPS horizontal positioning error value found, GPS accuracy can only be "
141
+ "estimated"
142
+ msgstr ""
143
+ "Значэнне памылкі гарызантальнага пазіцыянавання GPS не знойдзена, "
144
+ "дакладнасць GPS можна толькі ацаніць"
145
+
146
+ #: geopic_tag_reader/reader.py:479
147
+ msgid "No GPS coordinates or broken coordinates in picture EXIF tags"
148
+ msgstr "Адсутнічаюць GPS-каардынаты або яны пашкоджаныя ў EXIF тэгах выявы"
149
+
150
+ #: geopic_tag_reader/reader.py:485
151
+ msgid "No valid date in picture EXIF tags"
152
+ msgstr "У EXIF тэгах выявы адсутнічае сапраўдная дата"
153
+
154
+ #: geopic_tag_reader/reader.py:490
155
+ msgid "The picture is missing mandatory metadata:"
156
+ msgstr "Выяве не хапае абавязковых метаданых:"
157
+
158
+ #: geopic_tag_reader/reader.py:604 geopic_tag_reader/reader.py:633
159
+ msgid "GPSLatitudeRef not found, assuming GPSLatitudeRef is North"
160
+ msgstr "GPSLatitudeRef не знойдзены, мяркуем што GPSLatitudeRef - Поўнач"
161
+
162
+ #: geopic_tag_reader/reader.py:612
163
+ msgid "Broken GPS coordinates in picture EXIF tags"
164
+ msgstr "Пашкоджаныя GPS каардынаты ў EXIF тэгах выявы"
165
+
166
+ #: geopic_tag_reader/reader.py:615 geopic_tag_reader/reader.py:639
167
+ msgid "GPSLongitudeRef not found, assuming GPSLongitudeRef is East"
168
+ msgstr "GPSLongitudeRef не знойдзены, мяркуем што GPSLongitudeRef - Усход"
169
+
170
+ #: geopic_tag_reader/reader.py:700
171
+ msgid "Precise timezone information not found, fallback to UTC"
172
+ msgstr "Дакладная інфармацыя пра часавы пояс не знойдзена, пераходзім на UTC"
173
+
174
+ #: geopic_tag_reader/reader.py:705
175
+ msgid ""
176
+ "Precise timezone information not found (and no GPS coordinates to help), "
177
+ "fallback to UTC"
178
+ msgstr ""
179
+ "Дакладная інфармацыя пра часавы пояс не знойдзена (і няма GPS-каардынат для "
180
+ "дапамогі), пераходзім на UTC"
181
+
182
+ #: geopic_tag_reader/reader.py:709
183
+ #, python-brace-format
184
+ msgid ""
185
+ "Skipping original date/time (from {datefield}) as it was not recognized: {v}"
186
+ msgstr ""
187
+ "Прапускаем арыгінальную дату/час (з {datefield}), бо яны не распазнаны: {v}"
188
+
189
+ #: geopic_tag_reader/reader.py:741
190
+ #, python-brace-format
191
+ msgid ""
192
+ "GPSTimeStamp and GPSDateTime don't contain supported time format (in {group} "
193
+ "group)"
194
+ msgstr ""
195
+ "GPSTimeStamp і GPSDateTime не ўтрымліваюць падтрыманы фармат часу (у групе "
196
+ "{group})"
197
+
198
+ #: geopic_tag_reader/reader.py:772
199
+ #, python-brace-format
200
+ msgid "Skipping GPS date/time ({group} group) as it was not recognized: {v}"
201
+ msgstr "Прапускаем GPS дату/час (група {group}), бо яны не распазнаны: {v}"
202
+
203
+ #: geopic_tag_reader/reader.py:798
204
+ #, python-brace-format
205
+ msgid ""
206
+ "Microseconds read from decimal seconds value ({microsecondsFromSeconds}) is "
207
+ "not matching value from EXIF field ({microseconds}). Max value will be kept."
208
+ msgstr ""
209
+ "Мікрасекунды, прачытаныя з дзесятковага значэння секунд "
210
+ "({microsecondsFromSeconds}), не супадаюць са значэннем з поля EXIF "
211
+ "({microseconds}). Будзе захавана максімальнае значэнне."
212
+
213
+ #: geopic_tag_reader/writer.py:132
214
+ #, python-brace-format
215
+ msgid "Unsupported key in additional tags ({k})"
216
+ msgstr "Непадтрыманы ключ у дадатковых тэгах ({k})"
@@ -8,9 +8,9 @@ msgstr ""
8
8
  "Project-Id-Version: PACKAGE VERSION\n"
9
9
  "Report-Msgid-Bugs-To: \n"
10
10
  "POT-Creation-Date: 2024-07-10 13:05+0200\n"
11
- "PO-Revision-Date: 2025-07-31 16:22+0000\n"
12
- "Last-Translator: osmmapper222 <osmmapper222@users.noreply.weblate.panoramax."
13
- "xyz>\n"
11
+ "PO-Revision-Date: 2025-10-17 17:31+0000\n"
12
+ "Last-Translator: \"F. Bausch\" <fbausch@users.noreply.weblate.panoramax.xyz>"
13
+ "\n"
14
14
  "Language-Team: German <http://weblate.panoramax.xyz/projects/panoramax/"
15
15
  "tag-reader/de/>\n"
16
16
  "Language: de\n"
@@ -30,7 +30,7 @@ msgstr "Längengrad:"
30
30
 
31
31
  #: geopic_tag_reader/main.py:28
32
32
  msgid "Timestamp:"
33
- msgstr "Zeitpunkt:"
33
+ msgstr "Zeitstempel:"
34
34
 
35
35
  #: geopic_tag_reader/main.py:29
36
36
  msgid "Heading:"
@@ -66,25 +66,25 @@ msgstr "Rollwinkel:"
66
66
 
67
67
  #: geopic_tag_reader/main.py:39
68
68
  msgid "Warnings raised by reader:"
69
- msgstr "Warnungen vom Leser erhoben:"
69
+ msgstr "Vom Leser gemeldete Warnungen:"
70
70
 
71
71
  #: geopic_tag_reader/reader.py:183
72
72
  msgid "Read latitude is out of WGS84 bounds (should be in [-90, 90])"
73
73
  msgstr ""
74
- "Ausgelesener Breitengrad liegt außerhalb der WGS84-Grenzen (sollte in "
75
- "[-90,90] liegen)"
74
+ "Ausgelesener Breitengrad liegt außerhalb der WGS84-Grenzen (muss in [-90,90] "
75
+ "liegen)"
76
76
 
77
77
  #: geopic_tag_reader/reader.py:185
78
78
  msgid "Read longitude is out of WGS84 bounds (should be in [-180, 180])"
79
79
  msgstr ""
80
- "Ausgelesener Längengrad liegt außerhalb der WGS84-Grenzen (sollte in "
81
- "[-180,180] liegen)"
80
+ "Ausgelesener Längengrad liegt außerhalb der WGS84-Grenzen (muss in [-180,180]"
81
+ " liegen)"
82
82
 
83
83
  #: geopic_tag_reader/reader.py:227
84
84
  #, python-brace-format
85
85
  msgid "Skipping Mapillary date/time as it was not recognized: {v}"
86
86
  msgstr ""
87
- "Mapillary Datum/Uhrzeit wurde übersprungen weil sie nicht erkannt wurden: {v}"
87
+ "Überspringe Datum/Uhrzeit von Mapillary, weil sie nicht erkannt wurden: {v}"
88
88
 
89
89
  #: geopic_tag_reader/reader.py:240
90
90
  msgid "Contradicting heading values found, GPSImgDirection value is used"
@@ -93,23 +93,23 @@ msgstr ""
93
93
 
94
94
  #: geopic_tag_reader/reader.py:351
95
95
  msgid "No GPS coordinates or broken coordinates in picture EXIF tags"
96
- msgstr "Keine oder invalide GPS-Koordinaten in den EXIF-Daten des Fotos"
96
+ msgstr "Keine oder ungültige GPS-Koordinaten in den EXIF-Daten des Fotos"
97
97
 
98
98
  #: geopic_tag_reader/reader.py:357
99
99
  msgid "No valid date in picture EXIF tags"
100
- msgstr "Kein valides Datum in den EXIF-Daten des Fotos"
100
+ msgstr "Kein gültiges Datum in den EXIF-Daten des Fotos"
101
101
 
102
102
  #: geopic_tag_reader/reader.py:362
103
103
  msgid "The picture is missing mandatory metadata:"
104
- msgstr "Dem Foto fehlen obligatorische Metadaten:"
104
+ msgstr "Dem Foto fehlen erforderliche Metadaten:"
105
105
 
106
106
  #: geopic_tag_reader/reader.py:449 geopic_tag_reader/reader.py:478
107
107
  msgid "GPSLatitudeRef not found, assuming GPSLatitudeRef is North"
108
- msgstr "GPSLatitudeRef nicht gefunden, nutze Norden als GPSLatitudeRef"
108
+ msgstr "GPSLatitudeRef nicht gefunden. Nutze Norden als GPSLatitudeRef"
109
109
 
110
110
  #: geopic_tag_reader/reader.py:457
111
111
  msgid "Broken GPS coordinates in picture EXIF tags"
112
- msgstr "Invalide GPS-Koordinaten in den EXIF-Daten des Fotos"
112
+ msgstr "Ungültige GPS-Koordinaten in den EXIF-Daten des Fotos"
113
113
 
114
114
  #: geopic_tag_reader/reader.py:460 geopic_tag_reader/reader.py:484
115
115
  msgid "GPSLongitudeRef not found, assuming GPSLongitudeRef is East"
@@ -117,22 +117,22 @@ msgstr "GPSLongitudeRef nicht gefunden, nutze Osten als GPSLongitudeRef"
117
117
 
118
118
  #: geopic_tag_reader/reader.py:537
119
119
  msgid "Precise timezone information not found, fallback to UTC"
120
- msgstr "Genaue Zeitzonen-Information nicht gefunden, falle auf UTC zurück"
120
+ msgstr "Genaue Zeitzonen-Information nicht gefunden, Rückgriff auf UTC"
121
121
 
122
122
  #: geopic_tag_reader/reader.py:542
123
123
  msgid ""
124
124
  "Precise timezone information not found (and no GPS coordinates to help), "
125
125
  "fallback to UTC"
126
126
  msgstr ""
127
- "Genaue Zeitzonen-Information nicht gefunden (und keine GPS-Koordinaten um zu "
128
- "helfen), falle auf UTC zurück"
127
+ "Genaue Zeitzonen-Information nicht gefunden (und keine GPS-Koordinaten zum "
128
+ "Erkennen einer möglichen Zeitzone vorhanden). Rückgriff auf UTC"
129
129
 
130
130
  #: geopic_tag_reader/reader.py:546
131
131
  #, python-brace-format
132
132
  msgid ""
133
133
  "Skipping original date/time (from {datefield}) as it was not recognized: {v}"
134
134
  msgstr ""
135
- "Überspringe originales Datum/Zeit (aus {datefield}) weil es nicht erkannt "
135
+ "Überspringe originales Datum/Zeit (aus {datefield}), weil es nicht erkannt "
136
136
  "wurde: {v}"
137
137
 
138
138
  #: geopic_tag_reader/reader.py:580
@@ -142,13 +142,13 @@ msgid ""
142
142
  "group)"
143
143
  msgstr ""
144
144
  "GPSTimeStamp und GPSDateTime enthalten kein unterstütztes Zeitformat (in "
145
- "{group} Gruppe)"
145
+ "Gruppe {group})"
146
146
 
147
147
  #: geopic_tag_reader/reader.py:611
148
148
  #, python-brace-format
149
149
  msgid "Skipping GPS date/time ({group} group) as it was not recognized: {v}"
150
150
  msgstr ""
151
- "Überspringe GPS Datum/Zeit ({group} Gruppe) da es nicht erkannt wurde: {v}"
151
+ "Überspringe GPS Datum/Zeit (Gruppe {group}), da es nicht erkannt wurde: {v}"
152
152
 
153
153
  #: geopic_tag_reader/reader.py:637
154
154
  #, python-brace-format
@@ -156,8 +156,8 @@ msgid ""
156
156
  "Microseconds read from decimal seconds value ({microsecondsFromSeconds}) is "
157
157
  "not matching value from EXIF field ({microseconds}). Max value will be kept."
158
158
  msgstr ""
159
- "Die Mikrosekunden die aus den Dezimalwerten der Sekunden gelesen wurden "
160
- "({microsecondsFromSeconds}) stimmen nicht mit den Werten aus den EXIF-Daten "
159
+ "Die Mikrosekunden, die aus den Dezimalwerten der Sekunden gelesen wurden "
160
+ "({microsecondsFromSeconds}), stimmen nicht mit den Werten aus den EXIF-Daten "
161
161
  "({microseconds}) überein. Maximaler Wert wird beibehalten."
162
162
 
163
163
  #: geopic_tag_reader/writer.py:132
@@ -184,24 +184,25 @@ msgstr "nicht gesetzt"
184
184
  #: geopic_tag_reader/reader.py:330
185
185
  msgid ""
186
186
  "No focal length value was found, this prevents calculating field of view"
187
- msgstr "Keine Brennweite gefunden, dies verhindert den Blickwinkel zu berechnen"
187
+ msgstr ""
188
+ "Keine Brennweite gefunden. Dies verhindert die Berechnung des Blickwinkels"
188
189
 
189
190
  #: geopic_tag_reader/reader.py:388
190
191
  msgid ""
191
192
  "No GPS horizontal positioning error value found, GPS accuracy can only be "
192
193
  "estimated"
193
194
  msgstr ""
194
- "Kein horizontaler GPS-Positionierungsfehlerwert gefunden, GPS-Genauigkeit "
195
- "kann nur geschätzt werden"
195
+ "Keinen Fehlerwert für horizontale GPS-Positionierung gefunden. Die GPS-"
196
+ "Genauigkeit kann nur geschätzt werden"
196
197
 
197
198
  #: geopic_tag_reader/reader.py:278
198
199
  msgid "No heading value was found, this reduces usability of picture"
199
- msgstr "Kein Kompasskurs gefunden, dies reduziert die Nutzbarkeit des Fotos"
200
+ msgstr "Keinen Kompasskurs gefunden. Dies reduziert die Nutzbarkeit des Fotos"
200
201
 
201
202
  #: geopic_tag_reader/reader.py:386
202
203
  msgid "No GPS accuracy value found, this prevents computing a quality score"
203
204
  msgstr ""
204
- "Keine GPS-Genauigkeit gefunden, dies verhindert das Berechnen eines "
205
+ "Keine GPS-Genauigkeit gefunden. Dies verhindert das Berechnen eines "
205
206
  "Qualitätswerts"
206
207
 
207
208
  #: geopic_tag_reader/reader.py:321
@@ -209,8 +210,8 @@ msgid ""
209
210
  "No make and model value found, no assumption on focal length or GPS "
210
211
  "precision can be made"
211
212
  msgstr ""
212
- "Kein Hersteller und Modell gefunden, keine Annahmen zu Brennweite oder GPS-"
213
- "Genauigkeit können angestellt werden"
213
+ "Keinen Hersteller und Modell gefunden. Annahmen zu Brennweite oder GPS-"
214
+ "Genauigkeit können nicht getroffen werden"
214
215
 
215
216
  #: geopic_tag_reader/main.py:28
216
217
  msgid "GPS accuracy:"