#7 전자액자 프로젝트 - 소스보기 2/2

2022. 3. 26. 01:09IT

이번 파일은 PhotoFile.py로

 - createFileList

 - getRandomPhoto

 - getPhotoData

의 세 개의 함수로 이루어져 있다. 

 

우선 createFileList는 주어진 경로의 하위를 훑어가면서 jpg 파일만을 골라서 경로와 파일명을 모두 파일에 순차적으로 저장을 하는 것이다. Database에 넣는 것도 고려해 봤으나 크게 속도차이도 없었기 때문에 text 파일로 저장을 했다. 이 소스에서 @eaDir이라는 폴더를 제외하는 if문이 나오는데 이 폴더는 시놀로지라는 NAS 서버에서 만드는 썸네일 파일을 담아 놓는 디렉토리이고 그 안에 작은 jpg 파일이 들어 있다. 이 작은 파일까지 보여줄 필요가 없기 때문에 제외하도록 코딩을 했다. 

 

getRandomPhoto는 함수 이름 그대로 사진 파일이 있는 파일에서 무작위로 파일을 읽는 함수이다. 여기에는 파일이 존재하는지 확인하는 루틴이 들어가 있다. 왜냐하면 정리되지 않은 사진이 있는 폴더들이 있기 때문에 나중에 사진을 지우면 에러가 날 수 있기 때문이다. 사실은 지금도 사진을 정리하고 있다. 사진이 잘 정리가 되어 있다면 없어도 될 루틴이다. 참고로 파일 리스트는 프로그램이 실행될 때 다시 파일 리스트를 만든다. 따라서 전원을 내렸다가 올리면 자동으로 파일 리스트는 새로이 생성된다.

 

마지막은 getPhotoData이다. 사진에서 Exif 정보를 읽어오는 루틴이다. 여기서는 현재의 시스템이 windows인지 linux인지 확인하는 루틴이 나온다. 파이썬은 같은 코드를 가지고 컴파일만 새로하면 어느 os에서든 돌아가게 되어 있다고 자랑을 한다. 하지만 라이브러리에 따라서 동작하는 os가 있고 동작하지 않는 곳이 있게 마련이다. 

안타깝게도 PIL(Python Image Library)는 linux에서 exif 값을 읽어오지 못하게 되어 있어 별도의 라이브러리를 썼다. 

 

import os
import sys
import random
from PIL import Image, ExifTags
import exifread

class Photo():
    def __init__(self, fname, path):
        self.filename = fname
        self.path = path
        self.cnt = 40000

    def createFileList(self):
        cnt = 0
        f = open(self.filename, 'a')
        for root, dirs, files in os.walk(self.path):
            for file in files:
                if file.endswith(".JPG") or file.endswith(".jpg"):
                    txt = os.path.join(root, file)
                    if "@eaDir" in txt:
                        ...
                    else:
                        print(os.path.join(root, file))
                        f.write(os.path.join(root, file) + '\n')
                        cnt += 1
        f.close()
        print(f"File count = {cnt}")
        self.cnt = cnt
        return cnt

    def getRandomPhoto(self):
        cnt = 0
        while(1):
            cnt += 1
            index = random.randint(1, self.cnt)
            print(f"random index number = {index}")
            with open(self.filename) as f:
                data = f.readlines()[index]
            length = len(data)
            if os.path.exists(data[0:length-1]):
                image = Image.open(data[0:length-1])
                if image.width > image.height:
                    print(data[0:length-1])
                    photo_date = self.getPhotoDate(data[0:length-1])
                    return image, data[0:length-1], photo_date
            #if cnt > 100: break

        return None, 0, "없음"


    def getPhotoDate(self, fname):
        if sys.platform.startswith('win'):
            image = Image.open(fname)
            photo_date = "없음"
            img_exif = image.getexif()
            if img_exif is None:
                print('Sorry, image has no exif data.')
            else:
                for key, val in img_exif.items():
                    if key == 0x0132:
                        return val

            return "No date"
        elif sys.platform.startswith('linux'): # or sys.platform.startswith('cygwin'):
            print(sys.platform.title)
            with open(fname, "rb") as f:
                tags = exifread.process_file(f)
                #print(tags)
            ret = tags.get("EXIF DateTimeDigitized")
            if ret: return tags["EXIF DateTimeDigitized"]
            else : return "No date"
        else:
            return "No date"
반응형