193 lines
5.2 KiB
Python
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
|
|
|