-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathAddMetaData.py
More file actions
109 lines (87 loc) · 4.15 KB
/
Copy pathAddMetaData.py
File metadata and controls
109 lines (87 loc) · 4.15 KB
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
# Jacob Morris :: 7/25/2025
#Python version: 3.12.7
# Ensure piexif is installed!
# On windows python ver-3.12: 'pip install Pillow piexif'
# Takes files and sub-folders in folder named: "input_images" and will
# tag them with date, time, and location in bottom right
# of screen. Outputs into folder named: "output_images".
# Works with JPG's only for now
from PIL import Image, ImageDraw, ImageFont, ImageOps
import piexif
import os
# Helper function to convert GPS to degrees, minutes, seconds (DMS)
def convert_gps_to_dms(gps_tuple, ref):
try:
deg = gps_tuple[0][0] / gps_tuple[0][1]
minute = gps_tuple[1][0] / gps_tuple[1][1]
sec = gps_tuple[2][0] / gps_tuple[2][1]
decimal = deg + (minute / 60.0) + (sec / 3600.0)
direction = ref.decode() if isinstance(ref, bytes) else ref
if direction in ['S', 'W']:
decimal = -decimal
return f"{decimal:.6f}° {direction}"
except Exception as e:
print("GPS Conversion Error:", e)
return "Invalid GPS"
# Folder paths
input_folder = "./input_images"
output_root = "./output_images"
os.makedirs(output_root, exist_ok=True)
# Font setup
font_path = "arial.ttf" # Replace with actual path if needed
#font_size = max(20, int(img.height * 0.1))
#font = ImageFont.truetype(font_path, font_size)
# Walk through all files and subdirectories
for root, dirs, files in os.walk(input_folder):
for filename in files:
if not filename.lower().endswith((".jpg", ".jpeg", ".JPG")):
continue
input_path = os.path.join(root, filename)
# Get relative path from input root
rel_path = os.path.relpath(root, input_folder)
tagged_subfolder = os.path.join(output_root, rel_path + "-tagged")
os.makedirs(tagged_subfolder, exist_ok=True)
# Output path
output_filename = filename.rsplit(".", 1)[0] + "-tagged.jpg"
output_path = os.path.join(tagged_subfolder, output_filename)
try:
img = Image.open(input_path)
img = ImageOps.exif_transpose(img)
exif_dict = piexif.load(img.info["exif"])
# Get datetime
datetime_str = exif_dict["0th"][piexif.ImageIFD.DateTime].decode()
date_part, time_part = datetime_str.split()
# Get GPS
gps = exif_dict.get("GPS", {})
lat = lon = None
if piexif.GPSIFD.GPSLatitude in gps and piexif.GPSIFD.GPSLongitude in gps:
lat = convert_gps_to_dms(gps[piexif.GPSIFD.GPSLatitude], gps[piexif.GPSIFD.GPSLatitudeRef])
lon = convert_gps_to_dms(gps[piexif.GPSIFD.GPSLongitude], gps[piexif.GPSIFD.GPSLongitudeRef])
# Compose label
label = f"Date: {date_part} Time: {time_part}"
if lat and lon:
label += f"\nCoords: {lat}, {lon}"
else:
print("[WARNING] Location not found")
label += f"\nCoords: , NOT FOUND"
#text
font_size = max(20, int(img.height * 0.04))
font = ImageFont.truetype(font_path, font_size)
edge_margin = max(20, int(min(img.size) * 0.02)) # distance from the image edges
inner_pad = max(10, int(font_size * 0.35))
# Draw overlay
draw = ImageDraw.Draw(img)
text_bbox = draw.multiline_textbbox((0, 0), label, font=font, align="right")
text_w = text_bbox[2] - text_bbox[0]
text_h = text_bbox[3] - text_bbox[1]
x = img.width - text_w - edge_margin
y = img.height - text_h - edge_margin
# Draw background rectangle
draw.rectangle((x - inner_pad, y - inner_pad, x + text_w + inner_pad, y + text_h + inner_pad), fill=(0, 0, 0, 180))
# Draw text
draw.multiline_text((x, y), label, fill="white", font=font, align="right")
# Save tagged image
img.save(output_path, "JPEG")
print(f"[OK] Processed: {input_path}")
except Exception as e:
print(f"[Error] Failed to process {input_path}: {e}")