import
tkinter as tk
from tkinter
import
filedialog, messagebox
from tkinterdnd2
import
TkinterDnD, DND_FILES # 使用 tkinterdnd2 支持拖放
from PIL
import
Image
from PIL.ExifTags
import
TAGS, GPSTAGS
def get_exif_data(image_path):
""
"获取图片的EXIF数据"
""
try:
with Image.open(image_path) as img:
exif_data = img._getexif()
if
not
exif_data:
return
None
return {TAGS.get(tag, tag): value
for
tag, value
in
exif_data.items()}
except Exception as e:
return
None
def get_gps_info(exif_data):
""
"从EXIF数据中提取GPS信息"
""
gps_info = {}
if
"GPSInfo"
in
exif_data:
for
key, value
in
exif_data[
"GPSInfo"
].items():
gps_info[GPSTAGS.get(key, key)] = value
return gps_info
return
None
def convert_to_degrees(value):
""
"将GPS坐标转换为十进制度数"
""
d, m, s = value
return d + (m / 60.0) + (s / 3600.0)
def get_lat_lon(gps_info):
""
"从GPS信息中提取经纬度"
""
latitude = longitude =
None
if
"GPSLatitude"
in
gps_info
and
"GPSLatitudeRef"
in
gps_info:
latitude = convert_to_degrees(gps_info[
"GPSLatitude"
])
if
gps_info[
"GPSLatitudeRef"
] !=
"N"
:
latitude = -latitude
if
"GPSLongitude"
in
gps_info
and
"GPSLongitudeRef"
in
gps_info:
longitude = convert_to_degrees(gps_info[
"GPSLongitude"
])
if
gps_info[
"GPSLongitudeRef"
] !=
"E"
:
longitude = -longitude
return latitude, longitude
def on_drop(event):
""
"处理拖放事件"
""
# 获取拖放的文件路径
image_path = event
.data
.strip(
'{}'
) # 去掉可能的花括号
process_image(image_path)
def process_image(image_path):
""
"处理图片并显示经纬度"
""
exif_data = get_exif_data(image_path)
if
not
exif_data:
messagebox.showwarning(
"警告"
,
"该图片没有EXIF信息"
)
return
gps_info = get_gps_info(exif_data)
if
not
gps_info:
messagebox.showwarning(
"警告"
,
"未找到GPS信息"
)
return
latitude, longitude = get_lat_lon(gps_info)
if
latitude is
None
or
longitude is
None
:
messagebox.showwarning(
"警告"
,
"无法解析经纬度信息"
)
return
# 更新文本框内容
lon_entry.delete(0, tk.
END
) # 先清空经度文本框
lat_entry.delete(0, tk.
END
) # 再清空纬度文本框
lon_entry.insert(0,
str
(longitude)) # 插入经度
lat_entry.insert(0,
str
(latitude)) # 插入纬度
# 创建主窗口(使用 TkinterDnD.Tk)
root = TkinterDnD.Tk()
root.
title
(
"图片经纬度提取工具"
)
# 设置窗口大小
root.geometry(
"500x400"
)
# 创建一个容器用于放置经度和纬度的输入框
frame_coords = tk.Frame(root)
frame_coords.pack(pady=10)
# 经度标签和文本框(调整到前面)
tk.
Label
(frame_coords, text=
"经度:"
).pack(side=tk.LEFT, padx=5)
lon_entry = tk.Entry(frame_coords,
width
=20)
lon_entry.pack(side=tk.LEFT, padx=5)
# 纬度标签和文本框(调整到后面)
tk.
Label
(frame_coords, text=
"纬度:"
).pack(side=tk.LEFT, padx=5)
lat_entry = tk.Entry(frame_coords,
width
=20)
lat_entry.pack(side=tk.LEFT, padx=5)
# 拖放区域(加大尺寸)
drop_label = tk.
Label
(root, text=
"将图片拖放到此处"
, relief=
"raised"
,
width
=40, height=15, font=(
"Arial"
, 18))
drop_label.pack(pady=1)
# 绑定拖放事件
drop_label.drop_target_register(DND_FILES) # 注册拖放目标
drop_label.dnd_bind(
"<<Drop>>"
, on_drop) # 绑定拖放事件
# 运行主循环
root.mainloop()