파일 이름을 이용해 사진 찍은 날짜 저장하기

컴순이·2022년 10월 20일
0
post-thumbnail

(2022-10-20 211315.jpg 파일 이름에는 날짜가 써 있을 때 .. !)

파일 이름에 촬영 일시가 포함되어 있는 사진에 대해 사진의 메타 데이터에 저장할 수 있도록 자동화 시키자.

구글 포토나 네이버 마이박스와 같은 클라우드 서비스에 사진을 저장하면 사진을 촬영한 날짜 별로 정렬하여 구경할 수 있다. 그런데 사진을 카톡으로 주고 받거나, 기본 카메라가 아닌 특정 어플로 촬영하였을 때 종종 사진의 "찍은 날짜" 속성이 없어지기도 한다.

만든 날짜, 수정한 날짜가 있어도 파일에 찍은 날짜가 없으면 마이박스에 업로드했을 때 촬영일시: 날짜 정보 없음이라고 나오면서 업로드한 날짜의 사진으로 분류가 된다.

클라우드에 사진이 날짜 별로 정리되어 구경하는 데 희열을 느끼는 나는 Bulk File Changer라는 프로그램으로 하나 하나 날짜를 바꾸다가, 파일 이름을 이용하여 자동으로 찍은 날짜를 설정하는 코드를 짜기로 하였다.

시행 착오

OS.stat

OS의 stat을 이용하여 time 관련된 변수를 바꿔 보았지만 파일의 "수정한 날짜" 속성만 바뀌고 사진을 "찍은 날짜" 속성은 바뀌지 않았다.

import time
import os
filename = "beauty_20200307210649 - 복사본.jpg"

mytime = "20200307210649"
mytime = time.mktime(time.strptime(mytime, '%Y%m%d%H%M%S'))
# 시간은 OS에서 쓰는 초단위?로 바꿔야 한다

statinfo = os.stat(filename)
print(statinfo)
# 출력🐻
# os.stat_result(st_mode=33206, st_ino=10977524092276104, st_dev=570579415, st_nlink=1, st_uid=0, st_gid=0, st_size=820773, st_atime=1666169606, st_mtime=1276171619, st_ctime=1666169606)

os.utime(filename, (statinfo.st_atime, mytime))
os.utime(filename, (statinfo.st_mtime, mytime))
os.utime(filename, (statinfo.st_ctime, mytime))

PIL (Python Imaging Library)

Pycharm에서 package 검색으로는 설치할 수 없고,
pip install image로 PIL을 이어 받은 Pillow가 설치됐다.

from PIL import Image

img1 = Image.open("beauty_20200307210649 - 복사본.jpg")
img2 = Image.open("20220704_185644.jpg")
meta_data1 = img1._getexif()
meta_data2 = img2._getexif()

print("image 1:", meta_data1)
print("image 2:", meta_data2)
출력🐻
image 1: {256: 1080, 257: 1080, 274: 1, 34665: 62, 37384: 0}
image 2: {256: 3024, 257: 3024, 296: 2, 34665: 225, 271: 'samsung', 272: 'SM-N960N', 305: 'N960NKSU3FVE1', 274: 6, 531: 1, 306: '2022:07:04 18:56:44', 282: 72.0, 283: 72.0, 36864: b'0220', 37377: 5.32, 37378: 2.52, 36867: '2022:07:04 18:56:44', 36868: '2022:07:04 18:56:44', 37379: 0.97, 37380: 0.0, 37381: 1.16, 37383: 2, 37385: 0, 40960: b'0100', 37386: 4.3, 37510: b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', 40961: 1, 37121: b'\x01\x02\x03\x00', 40962: 3024, 37520: '0469', 37521: '0469', 37522: '0469', 40963: 3024, 33434: 0.025, 40965: 815, 33437: 2.4, 41729: b'\x01\x00\x00\x00', 42016: 'J12LLKL00SM', 34850: 2, 41985: 0, 34855: 320, 41986: 0, 41987: 0, 41988: nan, 41989: 26, 41990: 0, 41992: 0, 41993: 0, 41994: 0}

image2에는 촬영한 기기의 OS와 같은 별의별 TMI까지 다 나오지만, 내가 작업하고 싶은 image1과 같은 파일에는 사진의 Imagewidth(256), length(257)를 비롯한 몇 가지 정보 밖에 저장되어있지 않다. 각 숫자 태그가 무슨 값을 의미하는 지 확인하려면 PIL.TiffTags를 import한 후 TiffTags.lookup(숫자)를 이용하여 개별적으로 확인하거나 Pillow TiffTags 문서에서 태그들을 확인할 수 있다.
나는 사진을 찍은 날짜인 36867: "DateTimeOriginal" 태그만 이용할 것이다.
하지만 PIL 라이브러리를 이용하여 exif 정보를 얻기만 할 수 있을 뿐 write은 안 되는 것 같다.

PiExif

새로운 EXIF 정보를 추가하고 이미지에 dump한 후 저장하면 간단하게 "찍은 날짜"를 입력할 수 있었다.

 from PIL import Image
import piexif

filename = "beauty_20200307210649 - 복사본.jpg"
img = Image.open(filename)
exif_dict = piexif.load(img.info['exif'])
exif_dict['Exif'][piexif.ExifIFD.DateTimeOriginal] = b'2020:03:07 21:06:49'

exif_bytes = piexif.dump(exif_dict)
img.save('%s' % filename, "jpeg", exif=exif_bytes)

exif_dict를 찍어보면 DateTimeOriginal(위와 같은 36867)은 요롷게 보인다. 요 형식으로 저장하면 될 것 같다.

{'0th': {256: 1080, 257: 1080, 34665: 62, 274: 1}, 'Exif': {37384: 0, 36867: b'2020:03:07 21:06:49'}, 'GPS': {}, 'Interop': {}, '1st': {}, 'thumbnail': None}

아니 그런데!! 이렇게 이미지를 새로 저장하니 사진 파일의 용량이 급감했다. 새로 저장하며 사진의 품질이 안 좋아진 것이다. 이 방식에 상처를 받아 exif를 수정이 아닌 살포시 삽입하는 방식을 찾았다.

img.save 대신 piexif.insert(exif_bytes, filename)을 입력하면 사진 용량도 같고 (아마도 품질 저하 없음) 찍은 날짜도 성공적으로 업데이트할 수 있다🥰

짜잔~ jpg에만 적용이 된다고 한다.


전체 코드

디렉토리만 설정해 놓으면 이 폴더 내의 파일 이름에 날짜 및 시간이 있는 사진에 대하여 찍은 날짜를 설정할 수 있도록 하자.
2000년 대 사진에는 전부 '20'이 들어가니까 일단 20으로 필터를 했다. 나는 연도 별로 폴더가 정리가 되어 있어서 2020으로 필터링해도 상관 없긴 하다.

 import piexif
import os
from re import sub

src = "C:/Users/~/Google 포토/Photos from 2020"
files = os.listdir(src)
files = list(filter(lambda x: x.endswith('jpg') and '20' in x, files))

for i, filename in enumerate(files):
    print(i, filename, end='\t')
    if i % 4 == 3:
        print()

c = int(input())
while c > 0:
    files[c] = ''
    c = int(input())

for filename in files:
    numbers = sub(r'[^0-9]', '', filename)
    if numbers.startswith('20'):
        exif_dict = piexif.load(src + '/' + filename)
        time = numbers[:4] + ':' + numbers[4:6] + ':' + numbers[6:8] + ' ' + numbers[8:10] + ':' \
               + numbers[10:12] + ':' + numbers[12:14]
        exif_dict['Exif'][piexif.ExifIFD.DateTimeOriginal] = time.encode('utf-8')
        exif_bytes = piexif.dump(exif_dict)
        piexif.insert(exif_bytes, src + '/' + filename)
        print(filename + " > " + time)
        if os.path.exists(src + '/' + filename + '.json'):
            os.remove(src + '/' + filename + '.json')

'20'을 포함한 JPG 파일을 확인하고 날짜를 바꿔 버리면 안 되는 파일을 c에 입력을 받아 제외할 수 있도록 했다. (-1을 입력하면 종료) 파일의 이름을 따서 날짜를 저장한 후, 마지막줄은 구글 포토에서 사진을 일괄 다운로드 받을 때 생성된 json 파일을 삭제한다.


이럿케 찍은 날짜가 없던 파일에 !!

파일 이름에 맞추어 찍은 날짜가 생겼다 ㅎㅎ 두둥~ 한 폴더에 몇 백 개 씩 있는 날짜 없는 사진들의 찍은 날짜를 한 번에 살릴 수 있다 ><

profile
음음

0개의 댓글