geopic-tag-reader 1.0.4__tar.gz → 1.0.6__tar.gz
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.
- {geopic_tag_reader-1.0.4 → geopic_tag_reader-1.0.6}/CHANGELOG.md +39 -14
- {geopic_tag_reader-1.0.4 → geopic_tag_reader-1.0.6}/Makefile +1 -1
- {geopic_tag_reader-1.0.4 → geopic_tag_reader-1.0.6}/PKG-INFO +7 -8
- {geopic_tag_reader-1.0.4 → geopic_tag_reader-1.0.6}/docs/API_USAGE.md +2 -2
- {geopic_tag_reader-1.0.4 → geopic_tag_reader-1.0.6}/docs/Install.md +1 -1
- {geopic_tag_reader-1.0.4 → geopic_tag_reader-1.0.6}/docs/camera.md +11 -4
- {geopic_tag_reader-1.0.4 → geopic_tag_reader-1.0.6}/docs/model.md +1 -3
- {geopic_tag_reader-1.0.4 → geopic_tag_reader-1.0.6}/geopic_tag_reader/__init__.py +2 -1
- {geopic_tag_reader-1.0.4 → geopic_tag_reader-1.0.6}/geopic_tag_reader/camera.py +11 -5
- {geopic_tag_reader-1.0.4 → geopic_tag_reader-1.0.6}/geopic_tag_reader/reader.py +2 -2
- {geopic_tag_reader-1.0.4 → geopic_tag_reader-1.0.6}/pyproject.toml +6 -8
- geopic_tag_reader-1.0.6/tests/fixtures/gopromax_flat.jpg +0 -0
- geopic_tag_reader-1.0.6/tests/fixtures/gps_date_slash.jpg +0 -0
- {geopic_tag_reader-1.0.4 → geopic_tag_reader-1.0.6}/tests/test_reader.py +46 -2
- {geopic_tag_reader-1.0.4 → geopic_tag_reader-1.0.6}/.gitignore +0 -0
- {geopic_tag_reader-1.0.4 → geopic_tag_reader-1.0.6}/.gitlab-ci.yml +0 -0
- {geopic_tag_reader-1.0.4 → geopic_tag_reader-1.0.6}/.pre-commit-config.yaml +0 -0
- {geopic_tag_reader-1.0.4 → geopic_tag_reader-1.0.6}/CODE_OF_CONDUCT.md +0 -0
- {geopic_tag_reader-1.0.4 → geopic_tag_reader-1.0.6}/LICENSE +0 -0
- {geopic_tag_reader-1.0.4 → geopic_tag_reader-1.0.6}/README.md +0 -0
- {geopic_tag_reader-1.0.4 → geopic_tag_reader-1.0.6}/docs/.pages +0 -0
- {geopic_tag_reader-1.0.4 → geopic_tag_reader-1.0.6}/docs/CLI_USAGE.md +0 -0
- {geopic_tag_reader-1.0.4 → geopic_tag_reader-1.0.6}/docs/Develop.md +0 -0
- {geopic_tag_reader-1.0.4 → geopic_tag_reader-1.0.6}/docs/reader.md +0 -0
- {geopic_tag_reader-1.0.4 → geopic_tag_reader-1.0.6}/docs/writer.md +0 -0
- {geopic_tag_reader-1.0.4 → geopic_tag_reader-1.0.6}/geopic_tag_reader/main.py +0 -0
- {geopic_tag_reader-1.0.4 → geopic_tag_reader-1.0.6}/geopic_tag_reader/model.py +0 -0
- {geopic_tag_reader-1.0.4 → geopic_tag_reader-1.0.6}/geopic_tag_reader/py.typed +0 -0
- {geopic_tag_reader-1.0.4 → geopic_tag_reader-1.0.6}/geopic_tag_reader/writer.py +0 -0
- {geopic_tag_reader-1.0.4 → geopic_tag_reader-1.0.6}/pytest.ini +0 -0
- {geopic_tag_reader-1.0.4 → geopic_tag_reader-1.0.6}/tests/__init__.py +0 -0
- {geopic_tag_reader-1.0.4 → geopic_tag_reader-1.0.6}/tests/conftest.py +0 -0
- {geopic_tag_reader-1.0.4 → geopic_tag_reader-1.0.6}/tests/fixtures/1.jpg +0 -0
- {geopic_tag_reader-1.0.4 → geopic_tag_reader-1.0.6}/tests/fixtures/IMG_20210720_144918.jpg +0 -0
- {geopic_tag_reader-1.0.4 → geopic_tag_reader-1.0.6}/tests/fixtures/IMG_20210720_161352.jpg +0 -0
- {geopic_tag_reader-1.0.4 → geopic_tag_reader-1.0.6}/tests/fixtures/a1.jpg +0 -0
- {geopic_tag_reader-1.0.4 → geopic_tag_reader-1.0.6}/tests/fixtures/b1.jpg +0 -0
- {geopic_tag_reader-1.0.4 → geopic_tag_reader-1.0.6}/tests/fixtures/broken_makernotes.jpg +0 -0
- {geopic_tag_reader-1.0.4 → geopic_tag_reader-1.0.6}/tests/fixtures/c1.jpg +0 -0
- {geopic_tag_reader-1.0.4 → geopic_tag_reader-1.0.6}/tests/fixtures/cropped.jpg +0 -0
- {geopic_tag_reader-1.0.4 → geopic_tag_reader-1.0.6}/tests/fixtures/d1.jpg +0 -0
- {geopic_tag_reader-1.0.4 → geopic_tag_reader-1.0.6}/tests/fixtures/datetime_ms_float.jpg +0 -0
- {geopic_tag_reader-1.0.4 → geopic_tag_reader-1.0.6}/tests/fixtures/datetime_offset.jpg +0 -0
- {geopic_tag_reader-1.0.4 → geopic_tag_reader-1.0.6}/tests/fixtures/e1.jpg +0 -0
- {geopic_tag_reader-1.0.4 → geopic_tag_reader-1.0.6}/tests/fixtures/flat.jpg +0 -0
- {geopic_tag_reader-1.0.4 → geopic_tag_reader-1.0.6}/tests/fixtures/gps_date_time_stamp.jpg +0 -0
- {geopic_tag_reader-1.0.4 → geopic_tag_reader-1.0.6}/tests/fixtures/img_Ricoh_Theta.jpg +0 -0
- {geopic_tag_reader-1.0.4 → geopic_tag_reader-1.0.6}/tests/fixtures/img_V4MPack.jpg +0 -0
- {geopic_tag_reader-1.0.4 → geopic_tag_reader-1.0.6}/tests/fixtures/img_categorisee.jpg +0 -0
- {geopic_tag_reader-1.0.4 → geopic_tag_reader-1.0.6}/tests/fixtures/img_datetimeoriginal.jpg +0 -0
- {geopic_tag_reader-1.0.4 → geopic_tag_reader-1.0.6}/tests/fixtures/img_gps_date_string.jpg +0 -0
- {geopic_tag_reader-1.0.4 → geopic_tag_reader-1.0.6}/tests/fixtures/img_gps_datestamp.jpg +0 -0
- {geopic_tag_reader-1.0.4 → geopic_tag_reader-1.0.6}/tests/fixtures/img_gps_sotm.jpg +0 -0
- {geopic_tag_reader-1.0.4 → geopic_tag_reader-1.0.6}/tests/fixtures/img_invalid_gps_date.jpg +0 -0
- {geopic_tag_reader-1.0.4 → geopic_tag_reader-1.0.6}/tests/fixtures/img_without_coord.jpg +0 -0
- {geopic_tag_reader-1.0.4 → geopic_tag_reader-1.0.6}/tests/fixtures/img_without_dt.jpg +0 -0
- {geopic_tag_reader-1.0.4 → geopic_tag_reader-1.0.6}/tests/fixtures/img_without_exif_tags.jpg +0 -0
- {geopic_tag_reader-1.0.4 → geopic_tag_reader-1.0.6}/tests/fixtures/insta360_date.jpg +0 -0
- {geopic_tag_reader-1.0.4 → geopic_tag_reader-1.0.6}/tests/fixtures/int_long_tag.jpg +0 -0
- {geopic_tag_reader-1.0.4 → geopic_tag_reader-1.0.6}/tests/fixtures/out_of_bounds_lat.jpg +0 -0
- {geopic_tag_reader-1.0.4 → geopic_tag_reader-1.0.6}/tests/fixtures/out_of_bounds_lon.jpg +0 -0
- {geopic_tag_reader-1.0.4 → geopic_tag_reader-1.0.6}/tests/fixtures/pic_with_float_lat.jpg +0 -0
- {geopic_tag_reader-1.0.4 → geopic_tag_reader-1.0.6}/tests/fixtures/ricoh_theta_no_projection.jpg +0 -0
- {geopic_tag_reader-1.0.4 → geopic_tag_reader-1.0.6}/tests/test_main.py +0 -0
- {geopic_tag_reader-1.0.4 → geopic_tag_reader-1.0.6}/tests/test_writer.py +0 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# Changelog
|
|
2
|
+
|
|
2
3
|
All notable changes to this project will be documented in this file.
|
|
3
4
|
|
|
4
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
@@ -6,130 +7,154 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
6
7
|
|
|
7
8
|
## [Unreleased]
|
|
8
9
|
|
|
10
|
+
## [1.0.6] - 2024-04-02
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- Bump some dependencies, the most important one being [typer](https://typer.tiangolo.com/) since it removes the need for typer-cli.
|
|
15
|
+
|
|
16
|
+
## [1.0.5] - 2024-03-06
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
|
|
20
|
+
- Automatic detection of 360° pictures based on make and model also checks for image dimensions (to avoid false positive, when 360° camera can also take flat pictures).
|
|
21
|
+
- Slash character in GPS date stamp was not correctly interpreted.
|
|
9
22
|
|
|
10
23
|
## [1.0.4] - 2024-02-12
|
|
11
24
|
|
|
12
25
|
### Changed
|
|
13
|
-
- When using date/time not coming from GPS, offset time EXIF field are also read (`Exif.Photo.OffsetTimeOriginal` or `Exif.Photo.OffsetTime` depending on used date/time EXIF tag).
|
|
14
26
|
|
|
27
|
+
- When using date/time not coming from GPS, offset time EXIF field are also read (`Exif.Photo.OffsetTimeOriginal` or `Exif.Photo.OffsetTime` depending on used date/time EXIF tag).
|
|
15
28
|
|
|
16
29
|
## [1.0.3] - 2023-12-18
|
|
17
30
|
|
|
18
31
|
### Added
|
|
32
|
+
|
|
19
33
|
- Support reading date from EXIF fields `Exif.Image.DateTime` and `Xmp.GPano.SourceImageCreateTime`.
|
|
20
34
|
- Auto-detect if a picture is 360° based on make and model.
|
|
21
35
|
|
|
22
36
|
### Fixed
|
|
23
|
-
- Avoid failures for pictures with invalid offset for maker notes (due to PyExiv2 log level).
|
|
24
37
|
|
|
38
|
+
- Avoid failures for pictures with invalid offset for maker notes (due to PyExiv2 log level).
|
|
25
39
|
|
|
26
40
|
## [1.0.2] - 2023-11-20
|
|
27
41
|
|
|
28
42
|
### Added
|
|
43
|
+
|
|
29
44
|
- A warning is thrown when microseconds values between decimal seconds and sub-second time fields are not matching.
|
|
30
45
|
|
|
31
46
|
### Changed
|
|
32
|
-
- Fraction values for date, time and GPS coordinates are supported.
|
|
33
47
|
|
|
48
|
+
- Fraction values for date, time and GPS coordinates are supported.
|
|
34
49
|
|
|
35
50
|
## [1.0.1] - 2023-11-17
|
|
36
51
|
|
|
37
52
|
### Fixed
|
|
38
|
-
- `DateTimeOriginal` field wasn't correctly read when seconds value was decimal.
|
|
39
53
|
|
|
54
|
+
- `DateTimeOriginal` field wasn't correctly read when seconds value was decimal.
|
|
40
55
|
|
|
41
56
|
## [1.0.0] - 2023-10-18
|
|
42
57
|
|
|
43
58
|
### Added
|
|
59
|
+
|
|
44
60
|
- Add subseconds to written metadata
|
|
45
61
|
- Read altitude in metadata
|
|
46
62
|
- Write direction and altitude metadata
|
|
47
63
|
- Add `additional_exif` tags in `writePictureMetadata`
|
|
48
64
|
|
|
49
65
|
### Changed
|
|
50
|
-
- EXIF list of tags now uses the [Exiv2](https://exiv2.org/metadata.html) notation (example `Exif.Image.Artist`) in returned data. To do this, pyexiv2 dependency is always necessary, and Pillow dependency has been removed. As a consequence, `readPictureMetadata` function __now takes in input `bytes`__ read from picture file instead of Pillow image. This is a breaking change.
|
|
51
|
-
- Use overriden metadata is available to localize overriden capture_time
|
|
52
66
|
|
|
67
|
+
- EXIF list of tags now uses the [Exiv2](https://exiv2.org/metadata.html) notation (example `Exif.Image.Artist`) in returned data. To do this, pyexiv2 dependency is always necessary, and Pillow dependency has been removed. As a consequence, `readPictureMetadata` function **now takes in input `bytes`** read from picture file instead of Pillow image. This is a breaking change.
|
|
68
|
+
- Use overriden metadata is available to localize overriden capture_time
|
|
53
69
|
|
|
54
70
|
## [0.4.1] - 2023-09-08
|
|
55
71
|
|
|
56
72
|
### Added
|
|
57
|
-
- Latitude and longitude values are checked to verify they fit into WGS84 projection bounds (-180, -90, 180, 90).
|
|
58
73
|
|
|
74
|
+
- Latitude and longitude values are checked to verify they fit into WGS84 projection bounds (-180, -90, 180, 90).
|
|
59
75
|
|
|
60
76
|
## [0.4.0] - 2023-09-01
|
|
61
77
|
|
|
62
78
|
### Added
|
|
79
|
+
|
|
63
80
|
- When a picture does not contain a mandatory exif tag (coordinates or datetime), a `PartialExifException` is thrown containing some information about what has been parsed and what is missing.
|
|
64
81
|
|
|
65
82
|
## [0.3.1] - 2023-07-31
|
|
66
83
|
|
|
67
84
|
### Added
|
|
85
|
+
|
|
68
86
|
- A way to write exif lon/lat and type tags.
|
|
69
87
|
|
|
70
88
|
## [0.3.0] - 2023-07-31
|
|
71
89
|
|
|
72
90
|
### Added
|
|
91
|
+
|
|
73
92
|
- Support of any date/time separator for EXIF tag `DateTimeOriginal`
|
|
74
93
|
- A way to write exif tags. To use this, you need to install this library with the extra `[write-exif]`.
|
|
75
94
|
|
|
76
|
-
|
|
77
95
|
## [0.2.0] - 2023-07-13
|
|
78
96
|
|
|
79
97
|
### Added
|
|
98
|
+
|
|
80
99
|
- Support of cropped equirectangular panoramas
|
|
81
100
|
|
|
82
101
|
### Changed
|
|
102
|
+
|
|
83
103
|
- Support python 3.8
|
|
84
104
|
|
|
85
105
|
## [0.1.3]
|
|
86
106
|
|
|
87
107
|
### Changed
|
|
108
|
+
|
|
88
109
|
- Bump [Typer](typer.tiangolo.com/) version, and use fork of [Typer-cli](https://gitlab.com/geovisio/infra/typer-cli)
|
|
89
110
|
|
|
90
111
|
## [0.1.2]
|
|
91
112
|
|
|
92
113
|
### Added
|
|
93
|
-
- Full typing support ([PEP 484](https://peps.python.org/pep-0484/) and [PEP 561](https://peps.python.org/pep-0561/))
|
|
94
114
|
|
|
115
|
+
- Full typing support ([PEP 484](https://peps.python.org/pep-0484/) and [PEP 561](https://peps.python.org/pep-0561/))
|
|
95
116
|
|
|
96
117
|
## [0.1.1]
|
|
97
118
|
|
|
98
119
|
### Added
|
|
99
|
-
- Support of Mapillary tags stored in EXIF tag `ImageDescription`
|
|
100
120
|
|
|
121
|
+
- Support of Mapillary tags stored in EXIF tag `ImageDescription`
|
|
101
122
|
|
|
102
123
|
## [0.1.0]
|
|
103
124
|
|
|
104
125
|
### Added
|
|
126
|
+
|
|
105
127
|
- If GPS Date or time can't be read, fallbacks to Original Date EXIF tag associated with a reader warning
|
|
106
128
|
- New EXIF tags are supported: `GPSDateTime`
|
|
107
129
|
|
|
108
130
|
### Changed
|
|
131
|
+
|
|
109
132
|
- `tag_reader:warning` property has been moved from EXIF, and is now available as a direct property named `tagreader_warnings` of `GeoPicTags` class
|
|
110
133
|
- Reader now supports `GPSLatitude` and `GPSLongitude` stored as decimal values instead of tuple
|
|
111
134
|
- Reader now supports reading `FocalLength` written in `NUMBER/NUMBER` format
|
|
112
135
|
- If EXIF tags for heading `PoseHeadingDegrees` and `GPSImgDirection` have contradicting values, we use by default `GPSImgDirection` value and issue a warning, instead of raising an error
|
|
113
136
|
|
|
114
137
|
### Fixed
|
|
115
|
-
- EXIF tag `SubsecTimeOriginal` was not correctly read due to a typo
|
|
116
138
|
|
|
139
|
+
- EXIF tag `SubsecTimeOriginal` was not correctly read due to a typo
|
|
117
140
|
|
|
118
141
|
## [0.0.2] - 2023-05-10
|
|
119
142
|
|
|
120
143
|
### Added
|
|
144
|
+
|
|
121
145
|
- EXIF tag `UserComment` is now read and available in raw `exif` tags
|
|
122
146
|
- If not set, `GPSLatitudeRef` defaults to North and `GPSLongitudeRef` defaults to East
|
|
123
147
|
- A new `tag_reader:warning` property lists non-blocking warnings raised while reading EXIF tags
|
|
124
148
|
|
|
125
|
-
|
|
126
149
|
## [0.0.1] - 2023-03-31
|
|
127
150
|
|
|
128
151
|
### Added
|
|
129
|
-
- EXIF tag reading methods extracted from [GeoVisio API](https://gitlab.com/geovisio/api)
|
|
130
152
|
|
|
153
|
+
- EXIF tag reading methods extracted from [GeoVisio API](https://gitlab.com/geovisio/api)
|
|
131
154
|
|
|
132
|
-
[Unreleased]: https://gitlab.com/geovisio/geo-picture-tag-reader/-/compare/1.0.
|
|
155
|
+
[Unreleased]: https://gitlab.com/geovisio/geo-picture-tag-reader/-/compare/1.0.6...main
|
|
156
|
+
[1.0.6]: https://gitlab.com/geovisio/geo-picture-tag-reader/-/compare/1.0.5...1.0.6
|
|
157
|
+
[1.0.5]: https://gitlab.com/geovisio/geo-picture-tag-reader/-/compare/1.0.4...1.0.5
|
|
133
158
|
[1.0.4]: https://gitlab.com/geovisio/geo-picture-tag-reader/-/compare/1.0.3...1.0.4
|
|
134
159
|
[1.0.3]: https://gitlab.com/geovisio/geo-picture-tag-reader/-/compare/1.0.2...1.0.3
|
|
135
160
|
[1.0.2]: https://gitlab.com/geovisio/geo-picture-tag-reader/-/compare/1.0.1...1.0.2
|
|
@@ -14,7 +14,7 @@ fmt: ## Format code
|
|
|
14
14
|
ci: type-check fmt test ## Run all check like the ci
|
|
15
15
|
|
|
16
16
|
docs: ## Generates documentation from Typer embedded docs
|
|
17
|
-
python -m
|
|
17
|
+
python -m typer ./geopic_tag_reader/main.py utils docs --name geopic-tag-reader --output docs/CLI_USAGE.md
|
|
18
18
|
lazydocs --overview-file API_USAGE.md --ignored-modules main --output-path docs/ geopic_tag_reader/
|
|
19
19
|
|
|
20
20
|
help: ## Print this help message
|
|
@@ -1,22 +1,21 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: geopic-tag-reader
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.6
|
|
4
4
|
Summary: GeoPicTagReader
|
|
5
5
|
Author-email: Adrien PAVIE <panieravide@riseup.net>
|
|
6
6
|
Requires-Python: >=3.8
|
|
7
7
|
Description-Content-Type: text/markdown
|
|
8
8
|
Classifier: License :: OSI Approved :: MIT License
|
|
9
|
-
Requires-Dist: typer ~= 0.
|
|
10
|
-
Requires-Dist: xmltodict ~= 0.13
|
|
9
|
+
Requires-Dist: typer ~= 0.12
|
|
10
|
+
Requires-Dist: xmltodict ~= 0.13
|
|
11
11
|
Requires-Dist: pyexiv2 == 2.8.3
|
|
12
12
|
Requires-Dist: flit ~= 3.8.0 ; extra == "build"
|
|
13
|
-
Requires-Dist: black ~=
|
|
14
|
-
Requires-Dist: mypy ~= 1.
|
|
13
|
+
Requires-Dist: black ~= 24.3 ; extra == "dev"
|
|
14
|
+
Requires-Dist: mypy ~= 1.9 ; extra == "dev"
|
|
15
15
|
Requires-Dist: pytest ~= 7.2.0 ; extra == "dev"
|
|
16
|
-
Requires-Dist: pytest-datafiles ~=
|
|
17
|
-
Requires-Dist: typer-cli-forked ~= 0.0.14 ; extra == "dev"
|
|
16
|
+
Requires-Dist: pytest-datafiles ~= 3.0 ; extra == "dev"
|
|
18
17
|
Requires-Dist: lazydocs ~= 0.4.8 ; extra == "dev"
|
|
19
|
-
Requires-Dist: types-xmltodict ~= 0.13
|
|
18
|
+
Requires-Dist: types-xmltodict ~= 0.13 ; extra == "dev"
|
|
20
19
|
Requires-Dist: pre-commit ~= 3.3.3 ; extra == "dev"
|
|
21
20
|
Requires-Dist: timezonefinder == 6.2.0 ; extra == "write-exif"
|
|
22
21
|
Requires-Dist: pytz ~= 2023.3 ; extra == "write-exif"
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
|
|
12
12
|
## Classes
|
|
13
13
|
|
|
14
|
-
- [`model.PictureType`](./model.md#class-picturetype)
|
|
14
|
+
- [`model.PictureType`](./model.md#class-picturetype): An enumeration.
|
|
15
15
|
- [`reader.CropValues`](./reader.md#class-cropvalues): Cropped equirectangular pictures metadata
|
|
16
16
|
- [`reader.GeoPicTags`](./reader.md#class-geopictags): Tags associated to a geolocated picture
|
|
17
17
|
- [`reader.InvalidExifException`](./reader.md#class-invalidexifexception): Exception for invalid EXIF information from image
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
|
|
25
25
|
## Functions
|
|
26
26
|
|
|
27
|
-
- [`camera.is_360`](./camera.md#function-is_360): Checks if given camera is equirectangular (360°) based on its make and
|
|
27
|
+
- [`camera.is_360`](./camera.md#function-is_360): Checks if given camera is equirectangular (360°) based on its make, model and dimensions (width, height).
|
|
28
28
|
- [`reader.decodeDateTimeOriginal`](./reader.md#function-decodedatetimeoriginal)
|
|
29
29
|
- [`reader.decodeGPSDateTime`](./reader.md#function-decodegpsdatetime)
|
|
30
30
|
- [`reader.decodeLatLon`](./reader.md#function-decodelatlon): Reads GPS info from given group to get latitude/longitude as float coordinates
|
|
@@ -5,7 +5,7 @@ GeoPicTagReader can be installed using two methods:
|
|
|
5
5
|
- From [PyPI](https://pypi.org/project/geopic-tag-reader/), the Python central package repository
|
|
6
6
|
- Using this [Git repository](https://gitlab.com/geovisio/geo-picture-tag-reader)
|
|
7
7
|
|
|
8
|
-
GeoPicTagReader is compatible with all python version >= 3.8.
|
|
8
|
+
GeoPicTagReader is compatible with all python version >= 3.8. Note that, due to [Pyexiv2 dependency on a recent GLIBC version](https://github.com/LeoHsiao1/pyexiv2/issues/120), you have to make sure to run on a recent, up-to-date operating system.
|
|
9
9
|
|
|
10
10
|
## From PyPI
|
|
11
11
|
|
|
@@ -18,15 +18,22 @@
|
|
|
18
18
|
## <kbd>function</kbd> `is_360`
|
|
19
19
|
|
|
20
20
|
```python
|
|
21
|
-
is_360(
|
|
21
|
+
is_360(
|
|
22
|
+
make: Optional[str] = None,
|
|
23
|
+
model: Optional[str] = None,
|
|
24
|
+
width: Optional[str] = None,
|
|
25
|
+
height: Optional[str] = None
|
|
26
|
+
) → bool
|
|
22
27
|
```
|
|
23
28
|
|
|
24
|
-
Checks if given camera is equirectangular (360°) based on its make and
|
|
29
|
+
Checks if given camera is equirectangular (360°) based on its make, model and dimensions (width, height).
|
|
25
30
|
|
|
26
|
-
``` is_360(
|
|
31
|
+
``` is_360()```
|
|
27
32
|
False
|
|
28
|
-
``` is_360("GoPro"
|
|
33
|
+
``` is_360("GoPro")``` False ``` is_360("GoPro", "Max 360")```
|
|
29
34
|
True
|
|
35
|
+
``` is_360("GoPro", "Max 360", "2048", "1024")``` True ``` is_360("GoPro", "Max 360", "1024", "768")```
|
|
36
|
+
False
|
|
30
37
|
|
|
31
38
|
|
|
32
39
|
|
|
@@ -25,19 +25,25 @@ EQUIRECTANGULAR_MODELS: Dict[str, List[str]] = {
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
|
|
28
|
-
def is_360(make: Optional[str], model: Optional[str]) -> bool:
|
|
28
|
+
def is_360(make: Optional[str] = None, model: Optional[str] = None, width: Optional[str] = None, height: Optional[str] = None) -> bool:
|
|
29
29
|
"""
|
|
30
|
-
Checks if given camera is equirectangular (360°) based on its make and
|
|
30
|
+
Checks if given camera is equirectangular (360°) based on its make, model and dimensions (width, height).
|
|
31
31
|
|
|
32
|
-
>>> is_360(
|
|
32
|
+
>>> is_360()
|
|
33
33
|
False
|
|
34
|
-
>>> is_360("GoPro"
|
|
34
|
+
>>> is_360("GoPro")
|
|
35
35
|
False
|
|
36
36
|
>>> is_360("GoPro", "Max 360")
|
|
37
37
|
True
|
|
38
|
+
>>> is_360("GoPro", "Max 360", "2048", "1024")
|
|
39
|
+
True
|
|
40
|
+
>>> is_360("GoPro", "Max 360", "1024", "768")
|
|
41
|
+
False
|
|
38
42
|
"""
|
|
39
43
|
|
|
40
44
|
if not make or not model:
|
|
41
45
|
return False
|
|
42
46
|
|
|
43
|
-
return any(model.startswith(potentialModel) for potentialModel in EQUIRECTANGULAR_MODELS.get(make, []))
|
|
47
|
+
return any(model.startswith(potentialModel) for potentialModel in EQUIRECTANGULAR_MODELS.get(make, [])) and (
|
|
48
|
+
(width is None or height is None) or int(width) == 2 * int(height)
|
|
49
|
+
)
|
|
@@ -281,7 +281,7 @@ def readPictureMetadata(picture: bytes) -> GeoPicTags:
|
|
|
281
281
|
if isExifTagUsable(data, "Xmp.GPano.ProjectionType"):
|
|
282
282
|
pic_type = data["Xmp.GPano.ProjectionType"]
|
|
283
283
|
# 360° based on known models
|
|
284
|
-
elif camera.is_360(make, model):
|
|
284
|
+
elif camera.is_360(make, model, data.get("Exif.Photo.PixelXDimension"), data.get("Exif.Photo.PixelYDimension")):
|
|
285
285
|
pic_type = "equirectangular"
|
|
286
286
|
# Flat by default
|
|
287
287
|
else:
|
|
@@ -473,7 +473,7 @@ def decodeGPSDateTime(data: dict, group: str) -> Tuple[Optional[datetime.datetim
|
|
|
473
473
|
|
|
474
474
|
if d is None and isExifTagUsable(data, f"{group}.GPSDateStamp"):
|
|
475
475
|
try:
|
|
476
|
-
dateRaw = data[f"{group}.GPSDateStamp"].replace(":", "-").replace("\x00", "")
|
|
476
|
+
dateRaw = data[f"{group}.GPSDateStamp"].replace(":", "-").replace("\x00", "").replace("/", "-")
|
|
477
477
|
|
|
478
478
|
# Time
|
|
479
479
|
if isExifTagUsable(data, f"{group}.GPSTimeStamp", List[Fraction]):
|
|
@@ -8,8 +8,8 @@ license = {file = "LICENSE"}
|
|
|
8
8
|
classifiers = ["License :: OSI Approved :: MIT License"]
|
|
9
9
|
dynamic = ["version", "description"]
|
|
10
10
|
dependencies = [
|
|
11
|
-
"typer ~= 0.
|
|
12
|
-
"xmltodict ~= 0.13
|
|
11
|
+
"typer ~= 0.12",
|
|
12
|
+
"xmltodict ~= 0.13",
|
|
13
13
|
"pyexiv2 == 2.8.3",
|
|
14
14
|
]
|
|
15
15
|
requires-python = ">=3.8"
|
|
@@ -22,14 +22,12 @@ geopic-tag-reader="geopic_tag_reader.main:app"
|
|
|
22
22
|
|
|
23
23
|
[project.optional-dependencies]
|
|
24
24
|
dev = [
|
|
25
|
-
"black ~=
|
|
26
|
-
"mypy ~= 1.
|
|
25
|
+
"black ~= 24.3",
|
|
26
|
+
"mypy ~= 1.9",
|
|
27
27
|
"pytest ~= 7.2.0",
|
|
28
|
-
"pytest-datafiles ~=
|
|
29
|
-
"typer-cli-forked ~= 0.0.14", # fork dependency needed until https://github.com/tiangolo/typer-cli/pull/120 is merged.
|
|
30
|
-
#"typer-cli ~= 0.0.13",
|
|
28
|
+
"pytest-datafiles ~= 3.0",
|
|
31
29
|
"lazydocs ~= 0.4.8",
|
|
32
|
-
"types-xmltodict ~= 0.13
|
|
30
|
+
"types-xmltodict ~= 0.13",
|
|
33
31
|
"pre-commit ~= 3.3.3",
|
|
34
32
|
]
|
|
35
33
|
build = ["flit ~= 3.8.0"]
|
|
Binary file
|
|
Binary file
|
|
@@ -143,7 +143,7 @@ def test_readPictureMetadata_noHeading(datafiles):
|
|
|
143
143
|
|
|
144
144
|
@pytest.mark.datafiles(os.path.join(FIXTURE_DIR, "img_Ricoh_Theta.jpg"))
|
|
145
145
|
def test_readPictureMetadata_ricoh_theta(datafiles):
|
|
146
|
-
for f in datafiles.
|
|
146
|
+
for f in datafiles.iterdir():
|
|
147
147
|
result = reader.readPictureMetadata(openImg(str(f)))
|
|
148
148
|
assertGeoPicTagsEquals(
|
|
149
149
|
result,
|
|
@@ -162,7 +162,7 @@ def test_readPictureMetadata_ricoh_theta(datafiles):
|
|
|
162
162
|
|
|
163
163
|
@pytest.mark.datafiles(os.path.join(FIXTURE_DIR, "img_V4MPack.jpg"))
|
|
164
164
|
def test_readPictureMetadata_v4mpack(datafiles):
|
|
165
|
-
for f in datafiles.
|
|
165
|
+
for f in datafiles.iterdir():
|
|
166
166
|
result = reader.readPictureMetadata(openImg(str(f)))
|
|
167
167
|
assertGeoPicTagsEquals(
|
|
168
168
|
result,
|
|
@@ -540,6 +540,26 @@ def test_readPictureMetadata_ricoh_noproj(datafiles):
|
|
|
540
540
|
)
|
|
541
541
|
|
|
542
542
|
|
|
543
|
+
@pytest.mark.datafiles(os.path.join(FIXTURE_DIR, "gopromax_flat.jpg"))
|
|
544
|
+
def test_readPictureMetadata_gopromax_flat(datafiles):
|
|
545
|
+
result = reader.readPictureMetadata(openImg(str(datafiles) + "/gopromax_flat.jpg"))
|
|
546
|
+
|
|
547
|
+
assertGeoPicTagsEquals(
|
|
548
|
+
result,
|
|
549
|
+
{
|
|
550
|
+
"lat": 47.22555109997222,
|
|
551
|
+
"lon": -1.5631604999722222,
|
|
552
|
+
"ts": 1708173992.0,
|
|
553
|
+
"heading": None,
|
|
554
|
+
"type": "flat",
|
|
555
|
+
"make": "GoPro",
|
|
556
|
+
"model": "Max",
|
|
557
|
+
"focal_length": 3,
|
|
558
|
+
"altitude": 78,
|
|
559
|
+
},
|
|
560
|
+
)
|
|
561
|
+
|
|
562
|
+
|
|
543
563
|
@pytest.mark.datafiles(os.path.join(FIXTURE_DIR, "broken_makernotes.jpg"))
|
|
544
564
|
def test_readPictureMetadata_broken_makernotes(datafiles):
|
|
545
565
|
result = reader.readPictureMetadata(openImg(str(datafiles) + "/broken_makernotes.jpg"))
|
|
@@ -579,3 +599,27 @@ def test_readPictureMetadata_datetime_offset(datafiles):
|
|
|
579
599
|
"altitude": 79,
|
|
580
600
|
},
|
|
581
601
|
)
|
|
602
|
+
|
|
603
|
+
|
|
604
|
+
@pytest.mark.datafiles(os.path.join(FIXTURE_DIR, "gps_date_slash.jpg"))
|
|
605
|
+
def test_readPictureMetadata_gps_date_slash(datafiles):
|
|
606
|
+
result = reader.readPictureMetadata(openImg(str(datafiles) + "/gps_date_slash.jpg"))
|
|
607
|
+
|
|
608
|
+
assertGeoPicTagsEquals(
|
|
609
|
+
result,
|
|
610
|
+
{
|
|
611
|
+
"lat": 43.42541569992266,
|
|
612
|
+
"lon": 1.3766216000638112,
|
|
613
|
+
"ts": 1686640500.0,
|
|
614
|
+
"heading": None,
|
|
615
|
+
"type": "flat",
|
|
616
|
+
"make": None,
|
|
617
|
+
"model": None,
|
|
618
|
+
"focal_length": None,
|
|
619
|
+
"altitude": None,
|
|
620
|
+
"tagreader_warnings": [
|
|
621
|
+
"GPSLatitudeRef not found, assuming GPSLatitudeRef is North",
|
|
622
|
+
"GPSLongitudeRef not found, assuming GPSLongitudeRef is East",
|
|
623
|
+
],
|
|
624
|
+
},
|
|
625
|
+
)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{geopic_tag_reader-1.0.4 → geopic_tag_reader-1.0.6}/tests/fixtures/img_without_exif_tags.jpg
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{geopic_tag_reader-1.0.4 → geopic_tag_reader-1.0.6}/tests/fixtures/ricoh_theta_no_projection.jpg
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|