개발/Python

[IOS 미디어 컨버터] Heic to jpg / Mov to mp4

비트-바이트 2024. 4. 25. 01:45
반응형

 

아이폰 사용자들이 가장 불편한 점.

사진을 PC로 옮기면 heic 포맷

동영상을 옮기면 mov 포맷

 

활용하기가 불편하긴 하다.

 

사용방법은 파일을 옮겨둔 폴더 통째로 하얀색 필드로 드래그 앤 드롭하면

폴더 안의 heic, mov 파일들이 자동으로 추가된다.

 

이후 

추출 폴더는 동일 폴더의 "output" 폴더에 저장된다.

 

자 이제, 편하게 사진을 활용해 봅시다.

 

[다운로드]

 

IOS미디어컨버터.exe

 

drive.google.com

 

참고 : https://github.com/welcomechoi/heicTojpg_python_tkinter

 

GitHub - welcomechoi/heicTojpg_python_tkinter

Contribute to welcomechoi/heicTojpg_python_tkinter development by creating an account on GitHub.

github.com

 

from tkinterdnd2 import DND_FILES, TkinterDnD
from PIL import Image
import pillow_heif
import tkinter as tk
from tkinter import messagebox
import os
import subprocess

pillow_heif.register_heif_opener()  # HEIF 파일을 열 수 있게 등록

def drop(event):
    drop_items = root.tk.splitlist(event.data)
    for item in drop_items:
        if os.path.isdir(item):
            global sourceDirectory
            sourceDirectory = item
            sourceDirectoryLabel.config(text=f"원본 디렉토리: {sourceDirectory}")
            updateFileList()

def updateFileList():
    fileListbox.delete(0, tk.END)
    media_files = [f for f in os.listdir(sourceDirectory) if f.endswith(('.heic', '.HEIC', '.mov', '.MOV'))]
    for file in media_files:
        fileListbox.insert(tk.END, file)
    fileListbox.select_set(0, tk.END)

def createOutputDirectory():
    output_dir = os.path.join(sourceDirectory, "output")
    if not os.path.exists(output_dir):
        os.makedirs(output_dir)
    return output_dir

def convertMedia():
    if not sourceDirectory:
        messagebox.showwarning("알림", "원본 디렉토리를 선택해 주세요.")
        return

    outputDirectory = createOutputDirectory()
    selectedFiles = fileListbox.curselection()
    if not selectedFiles:
        messagebox.showwarning("알림", "변환할 파일을 선택해 주세요.")
        return

    for index, i in enumerate(selectedFiles):
        file = fileListbox.get(i)
        filePath = os.path.join(sourceDirectory, file)
        outputFilePath = os.path.join(outputDirectory, os.path.splitext(file)[0])

        if file.lower().endswith(('.heic', '.HEIC')):
            outputFilePath += ".jpg"
        elif file.lower().endswith(('.mov', '.MOV')):
            outputFilePath += ".mp4"

        # 파일 덮어쓰기 확인
        if os.path.exists(outputFilePath):
            response = messagebox.askyesno("Confirm Overwrite", f"File {os.path.basename(outputFilePath)} already exists. Overwrite?")
            if not response:
                continue  # 사용자가 'No'를 선택한 경우, 덮어쓰기하지 않고 다음 파일로 넘어갑니다.

        # 파일 처리
        try:
            if file.lower().endswith(('.heic', '.HEIC')):
                processImageFile(filePath, outputFilePath)
            elif file.lower().endswith(('.mov', '.MOV')):
                subprocess.run(['ffmpeg', '-y', '-i', filePath, '-codec', 'copy', outputFilePath], check=True)
        except Exception as e:
            messagebox.showerror("Error", f"Failed to convert {file}. Error: {str(e)}")
            continue

        # 파일 이름 업데이트
        fileListbox.delete(index)
        fileListbox.insert(index, f"{file} (완료)")

    messagebox.showinfo("알림", "변환 완료")

def processImageFile(input_path, output_path):
    with Image.open(input_path) as image:
        iccProfile = image.info.get("icc_profile")
        exif = image.getexif()
        image.save(output_path, "JPEG", exif=exif, icc_profile=iccProfile)

root = TkinterDnD.Tk()
root.title("IOS 미디어 컨버터")
root.resizable(False, False)

mainFrame = tk.Frame(root, padx=10, pady=10)
mainFrame.pack(fill="both", expand=True)

sourceDirectoryFrame = tk.Frame(mainFrame)
sourceDirectoryFrame.pack(pady=10, fill="x")
sourceDirectoryLabel = tk.Label(sourceDirectoryFrame, text="원본 디렉토리: ")
sourceDirectoryLabel.pack(side="left", padx=10)

fileListbox = tk.Listbox(mainFrame, width=50, height=15, selectmode=tk.MULTIPLE)
fileListbox.pack(pady=10)

convertButton = tk.Button(mainFrame, text="변환 시작", command=convertMedia)
convertButton.pack(pady=10)

root.drop_target_register(DND_FILES)
root.dnd_bind('<<Drop>>', drop)

root.mainloop()
반응형