summaryrefslogtreecommitdiffstats
path: root/photomap/pmap.py
blob: 055b7350eb8eaff89a69f83dc391ebc9605cb7c8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import os
import folium
from pathlib import Path
from PIL import Image, ExifTags
from itertools import chain

"""To do 
- create gpx file for adding in to existing GPSprune maps
- omit all the thumbs
- include *.jpeg
- can we also do other formats than JPG ?
- we want popup that hotlinks to URL of the photo of course
"""

def get_coordinates(photo_path):
    """Extracting EXIF data from jpg files requires an external package because the EXIF standard
    is interpreted differently by the many different implementations of the JPG file format
    """
    try:
        # Read EXIF data from photo
        img = Image.open(photo_path)
        exif_data = img._getexif()

        # Extract latitude and longitude from EXIF data
        gps_info = exif_data.get(34853) #'GPSInfo is a dict
        # This does not mean that all the GPS fields are populated. 
        
        lat = gps_info.get(2, None)
        lon = gps_info.get(4, None)
        isn = gps_info.get(1, None)
        ise = gps_info.get(3, None)
        if isn and isn != "N":
            print(f"{photo_path} WRONG hemisphere N/S {isn}")
        if ise and ise != "E":
            print(f"{photo_path} WRONG hemisphere E/W")
        point = gps_info.get(17, None) # direction the camera is point towards
        pointref = gps_info.get(16, None) # "M" for magnetic
        taken = gps_info.get(29, None) #  GPS datestamp 
    except:
        #print(f"{photo_path} - lat/lon exception")
        # for key, value in gps_info.items():
            # print(key, value, value.type())
        return None, None
        
        # Convert coordinates to decimal format
    if lat and lon:
        # lat and lon are tuples e.g.  (47.0, 35.0, 5.77)
        latitude = float(lat[0] + lat[1] / 60 + lat[2] / 3600)
        longitude = float(lon[0] + lon[1] / 60 + lon[2] / 3600)

        # Reverse geocode coordinates to get address
        #address = geolocator.reverse((latitude, longitude))
        return latitude, longitude
    else:
        # print(f"{photo_path} - lat/lon conversion exception {lat=} {lon=}")
        # for key, value in gps_info.items():
            # print(key, value, type(value))
        return None, None


# Specify the folder containing the photos
#photo_folder = Path("../../expoweb")
photo_folder = Path("/mnt/d/EXPO/PHOTOS")
#photo_folder = Path("/mnt/d/EXPO/PHOTOS/2019")
#photo_folder = Path("/mnt/d/EXPO/PHOTOS/2022/JonoL") # jpeg
save_gpx = "photos_jpg.gpx"

# these are generators, not lists
photosjpg = photo_folder.rglob("*.jpg") 
photosjpeg = photo_folder.rglob("*.jpeg") 
photos = chain(photosjpg, photosjpeg)


# Initialize a Folium map centered at an initial location
map = folium.Map(location=[47.691036, 13.821314], zoom_start=13)

photoset = []
# Iterate through photos in the folder
for photo_path in photos: 
    if photo_path.stem.startswith("slide_"):
        #print(f" - abort slide")
        continue
    if photo_path.stem.startswith("thumb_"):
        #print(f" - abort thumb")
        continue    

    # Extract latitude, longitude, and address from photo
    latitude, longitude = get_coordinates(photo_path)

    if latitude and longitude:
        print(f"{photo_path} {latitude:.6f} {longitude:.6f}")
        # Create a marker for each photo with its location and address
        folium.Marker(
            location=[latitude, longitude],
            popup=f"{photo_path}",
            icon=folium.Icon(color="red", icon="camera"),
        ).add_to(map)
        photoset.append((photo_path, latitude, longitude))
        
# Save the folium map as an HTML file
map.save("photo_map.html")
print(f"Found {len(photoset)} GPS located photos in '{photo_folder}' and subdirectories.")

header = """<?xml version="1.0" encoding="windows-1252"?>
<gpx version="1.0" creator="troggle pmap" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns="http://www.topografix.com/GPX/1/0"
xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd">
	<name>pmap photo GPS</name>
	<desc>Troggle photos archive</desc>
"""
with open(save_gpx, "w") as f:
    f.write(header)
    for p in photoset:
        photo_path, latitude, longitude = p
        # add ele=
        f.write(f'<wpt lat="{latitude:.6f}" lon="{longitude:.6f}"> <name>[{photo_path.stem}]</name><type>photo</type><desc>{str(photo_path).replace(str(photo_folder),"")}</desc></wpt>\n')
    f.write(f'</gpx>\n')