Files
UtilityPole_Info/ExtEXIFData.py
2025-09-23 20:59:17 +09:00

193 lines
5.2 KiB
Python

import os
from PIL import Image
from PIL.ExifTags import TAGS, GPSTAGS
import UtilPack as util
# EXIF 데이터에서 사진이 찍힌 날자와 시간을 가져온다
def GetDateInfo(ImgPath):
img = _imageOpen(ImgPath)
if None == img:
return "", 0.0, 0.0
dataEXIF = _getEXIFData(img)
date = _getDateEXIF(dataEXIF)
dataGPS = _parseGPSInfo(dataEXIF)
lat, lon = _getlatlon(dataGPS)
return date, lat, lon
def ProcessImg(imgAbsPath, fRatio, nQlt = 85, bOrientApy = True):
#
dirSave = "Thumb"
dirpath, filename = os.path.split(imgAbsPath)
parenDir = os.path.dirname(dirpath)
dirThumb = os.path.join(parenDir, dirSave)
finalPath = os.path.join(dirThumb, filename)
# 설정은 상관없이 이전에 리사이즈 해 둔 것이 있으면 경로 반환
if True == os.path.exists(finalPath):
#print(f"[] -> {finalPath}")
return finalPath
img = _imageOpen(imgAbsPath)
if None == img:
return imgAbsPath
nRotate = 0
if True == bOrientApy:
dataEXIF = _getEXIFData(img)
nRotate = _getOrientationEXIF(dataEXIF)
img = _rotateImg(img, nRotate)
img = _resizeImg(img, fRatio)
if False == os.path.exists(dirThumb):
os.makedirs(dirThumb, 0o777)
print(f"Thumb folder Created : {dirThumb}")
img.save(finalPath, optimize=True, quality=nQlt)
#print(f"{imgAbsPath} -> {finalPath}")
return finalPath
def _rotateImg(imgSrc, nRotate):
if None == imgSrc:
return imgSrc
if not isinstance(imgSrc, Image.Image):
#raise TypeError("Input must be a PIL Image object")
print("Type Error")
return imgSrc
if 0 >= nRotate or 360 <= nRotate:
return imgSrc
imgRet = imgSrc.rotate(nRotate, expand=True)
bbox = imgRet.getbbox()
imgRet = imgRet.crop(bbox)
return imgRet
def _resizeImg(imgSrc, fRatio ):
if None == imgSrc:
return imgSrc
if not isinstance(imgSrc, Image.Image):
#raise TypeError("Input must be a PIL Image object")
return imgSrc
if 0 >= fRatio or 1.0 < fRatio:
return imgSrc
imgRet = imgSrc.resize((int(imgSrc.width * fRatio), int(imgSrc.height * fRatio)))
return imgRet
def _imageOpen(ImgPath):
imgRet = None
try:
# 이미지 열기 시도
imgRet = Image.open(ImgPath)
imgRet.load() # 이미지 파일을 실제로 로드하여 확인
util.DbgOut("Image open successful")
# 이미지 처리 코드 추가
except FileNotFoundError:
util.DbgOut(f"can't find Image': {ImgPath}")
except OSError:
util.DbgOut(f"Image broken or unsupported MIME: {ImgPath}")
except Exception as e:
util.DbgOut(f"unexpected error: {e}")
return imgRet
# 이미지에서 EXIF 데이터를 추출하여 딕셔너리 형태로 반환
def _getEXIFData(image):
exif_data = {}
try:
info = image._getexif()
if info:
for tag, value in info.items():
decoded = TAGS.get(tag, tag)
exif_data[decoded] = value
except AttributeError:
pass
return exif_data
def _getDateEXIF(exif_data):
date_taken = exif_data.get('DateTimeOriginal')
return date_taken
# 0 : NoData
# 1: "Landscape (normal) -> 0"
# 3: "Landscape (upside down) -> 180"
# 6: "Portrait (rotated 90° CW) -> 270"
# 8: "Portrait (rotated 90° CCW) -> 90"
def _getOrientationEXIF(exif_data):
if exif_data is None:
return 0
retValue = 0
# EXIF 태그에서 Orientation 추출
for tag, value in exif_data.items():
tag_name = TAGS.get(tag, tag)
if tag_name == 'Orientation':
if value == 3:
retValue = 180
elif value == 6:
retValue = 270
elif value == 8:
retValue = 90
else: # value == 1:
retValue = 0
break
return retValue
# EXIF 데이터에서 GPS 정보를 파싱하여 딕셔너리 형태로 반환
def _parseGPSInfo(exif_data):
gps_info = {}
if 'GPSInfo' in exif_data:
for key in exif_data['GPSInfo'].keys():
decode = GPSTAGS.get(key, key)
gps_info[decode] = exif_data['GPSInfo'][key]
return gps_info
# 도, 분, 초 형식의 GPS 데이터를 도 형식으로 변환
def _convertToDegrees(value):
d = 0.0
if 0 < value[0]:
d = float(value[0])
m = 0.0
if 0 < value[1]:
m = float(value[1]) / 60.0
s = 0.0
if 0 < value[2]:
s = float(value[2]) / 3600.0
return d + m + s
# GPS 정보를 사용하여 위도와 경도를 도 형식으로 반환
def _getlatlon(gps_info):
lat,lon = 0.0, 0.0
if 'GPSLatitude' in gps_info and 'GPSLatitudeRef' in gps_info:
lat = _convertToDegrees(gps_info['GPSLatitude'])
if gps_info['GPSLatitudeRef'] != 'N':
lat = -lat
if 'GPSLongitude' in gps_info and 'GPSLongitudeRef' in gps_info:
lon = _convertToDegrees(gps_info['GPSLongitude'])
if gps_info['GPSLongitudeRef'] != 'E':
lon = -lon
return lat, lon