python(0821-0908)/활용2. GUI(0903-0906)

2. GUI 활용 예제 : 이미지 합치기

나도초딩 2022. 9. 5.

기초 인터페이스 익히는 부분이 역시 가장 지겨웠다. ㅠ html, css 같은거라서 이해하긴 쉽지만, 알아야 하는...

이번 예제는 간단한 예제면서도, 개인 프로그램 용도로는 웬만한건 다 할 수 있을만한 예제같다.

  1. 파일 선택 : filedialog.askopenfilenames(title="", filetypes=(튜플), initialdir=r""
    ** title 유의. (text 아님 )
    선택한 파일을 list_file=Listbox() 에 추가 list_file.insert(END, file)
  2. 선택 삭제 del_file():
    def del_file():
        # Listbox요소삭제: list_file.delete(요소번호) <--- list 요소 숫자 반환함수
        # list_file에서 선택요소(curselection())만 지우기.
        # 역순으로 지워야함 : reversed() 사용. ** reverse 는 요소를 실제로 바꿈.
  3. 저장 경로
    folder_selected = filedialog.askdirectory()
  4. 시작 def start(): 저장경로, 옵션 확인 후 merge_image() 호출
    옵션값, 파일목록, 저장 경로 점검 --> msgbox.showwarning

 

import tkinter.ttk as ttk
import tkinter.messagebox as msgbox
from tkinter import * # __all__
from tkinter import filedialog #askopenfilenames, askdirectory
from PIL import Image #Image.open, new, paste, save


# 파일 추가
def add_file():
    files = filedialog.askopenfilenames(title="이미지 파일을 선택하세요", \
        filetypes=(("PNG 파일", "*.png"), ("모든 파일", "*.*")), \
        initialdir=r"C:\Users\Nadocoding\Desktop\PythonWorkspace\pygame_project\images")
        # 최초에 사용자가 지정한 경로를 보여줌
    
    # 사용자가 선택한 파일 목록
    for file in files:
        list_file.insert(END, file)

# 선택 삭제
def del_file():
    #print(list_file.curselection())
    for index in reversed(list_file.curselection()):
        list_file.delete(index)

# 저장 경로 (폴더)
def browse_dest_path():
    folder_selected = filedialog.askdirectory()
    if folder_selected is None: # 사용자가 취소를 누를 때
        return
    #print(folder_selected)
    txt_dest_path.delete(0, END)
    txt_dest_path.insert(0, folder_selected)

이미지 통합 : merge_image():

from PIL import Image

  1. image = [Image.open(x) for x in list_file.get(0, END)]  --> size[0], size[1]
  2. result_img = Image.new("RGB", (max_width, total_height), (255, 255, 255))
  3. result_img.paste(img, (0, y_offset))
  4. prgoress = (idx+1) / len(images) * 100
  5. result_img.save(os.path.join(txt_dest_path.get(), "파일명")
from PIL import Image

# 이미지 통합
def merge_image():
    #print(list_file.get(0, END)) # 모든 파일 목록을 가지고 오기
    images = [Image.open(x) for x in list_file.get(0, END)]
    # size -> size[0] : width, size[1] : height
    # widths = [x.size[0] for x in images]
    # heights = [x.size[1] for x in images]

    # [(10, 10), (20, 20), (30, 30)]
    widths, heights = zip(*(x.size for x in images))

    # 최대 넓이, 전체 높이 구해옴
    max_width, total_height = max(widths), sum(heights)
    
    # 스케치북 준비
    result_img = Image.new("RGB", (max_width, total_height), (255, 255, 255)) # 배경 흰색
    y_offset = 0 # y 위치
    # for img in images:
    #     result_img.paste(img, (0, y_offset))
    #     y_offset += img.size[1] # height 값 만큼 더해줌

    for idx, img in enumerate(images):
        result_img.paste(img, (0, y_offset))
        y_offset += img.size[1]

        progress = (idx + 1) / len(images) * 100 # 실제 percent 정보를 계산
        p_var.set(progress)
        progress_bar.update()

    dest_path = os.path.join(txt_dest_path.get(), "nado_photo.jpg")
    result_img.save(dest_path)
    msgbox.showinfo("알림", "작업이 완료되었습니다.")

# 시작
def start():
    # 각 옵션들 값을 확인
    print("가로넓이 : ", cmb_width.get())
    print("간격 : ", cmb_space.get())
    print("포맷 : ", cmb_format.get())

    # 파일 목록 확인
    if list_file.size() == 0:
        msgbox.showwarning("경고", "이미지 파일을 추가하세요")
        return

    # 저장 경로 확인
    if len(txt_dest_path.get()) == 0:
        msgbox.showwarning("경고", "저장 경로를 선택하세요")
        return

    # 이미지 통합 작업
    merge_image()

 

댓글