콜라주를 만드는 것은 소중한 추억을 보존하고 사진 컬렉션을 전시하는 우아한 수단이 될 수 있습니다. 그러나 온라인 콜라주 생성기는 잠재적인 보안 위험을 초래할 수 있으며, 인터넷과 독립적으로 작동하는 기성 애플리케이션은 사용료를 지불해야 하고 필요한 모든 기능을 제공하지 않을 수 있습니다.

맞춤형 이미지 콜라주 메이커를 만들면 이러한 우려를 덜고 프로세스에 대한 완전한 통제권을 유지할 수 있습니다. 그렇다면 이러한 애플리케이션을 어떻게 구성할 수 있을까요?

Tkinter 및 PIL 모듈

사진 콜라주를 만들기 위한 그래픽 사용자 인터페이스를 구성하려면 Tkinter 라이브러리와 Python 이미징 라이브러리(PIL)를 모두 활용해야 합니다. 전자는 다양한 사용자 친화적인 인터페이스 구성 요소를 제공하여 데스크톱 애플리케이션을 개발할 수 있게 하고, 후자는 디지털 이미지를 원활하게 조작할 수 있게 합니다.

유명한 파이썬 이미징 라이브러리(PIL)의 포크 버전인 Pillow 라이브러리는 고급 이미지 처리 기능을 제공하여 디지털 시각 콘텐츠의 편집, 생성, 형식 변환 및 저장과 같은 작업을 용이하게 합니다.

명령줄 인터페이스를 사용하여 Tkinter와 Pillow를 설정하려면 다음 단계를 따르세요: 1. 컴퓨터에서 터미널 또는 명령 프롬프트를 엽니다. 2. “pip install Tkinter” 명령을 입력하여 Tkinter를 설치합니다. 이렇게 하면 Python으로 GUI 애플리케이션을 만들 수 있습니다. 3. 다음으로 “pip install pillow” 명령을 입력하여 Pillow를 설치합니다. 이 라이브러리는 Python 코드 내에서 이미지를 열고 조작할 수 있도록 지원합니다.

 pip install tk pillow 

GUI 설정 및 이미지 조작

이 프로젝트의 소스 코드는 프로젝트를 성공적으로 실행하는 데 필요한 모든 파일과 문서의 디지털 아카이브 역할을 하는 전용 GitHub 리포지토리에서 확인할 수 있습니다.

Tkinter를 사용하여 Python에서 이미지 콜라주 애플리케이션을 만들려면 먼저 필요한 모듈을 가져옵니다. 그런 다음 ImageCollageApp 클래스를 설정하고 제목과 선호하는 표시 크기를 지정합니다. tkinter의 .create\_window() 메서드를 사용하여 이러한 사양으로 이 앱의 창을 생성합니다. 그런 다음 tkinter의 .create\_canvas() 함수를 사용하여 해당 창 내에 캔버스 위젯을 생성합니다. 부모 요소를 지정된 창으로 지정하고, 캔버스의 원하는 크기와 가로 및 세로 길이를 정의하고, 기본 배경 색조를 지정합니다.

 import tkinter as tk
from tkinter import filedialog, simpledialog, messagebox
from PIL import Image, ImageTk

class ImageCollageApp:
    def __init__(self, root):
        self.root = root
        self.root.title("Image Collage Maker")
        self.images = []
        self.image_refs = []
        self.collage_size = (600, 500)

        self.collage_canvas = tk.Canvas(
            self.root,
            width=self.collage_size[0],
            height=self.collage_size[1],
            bg="white",
        )

        self.collage_canvas.pack()

“이미지 추가” 버튼과 “콜라주 만들기” 버튼 등 지정된 속성을 가진 두 개의 버튼을 만들려면 각각의 부모 요소를 정의하고 CSS를 사용하여 각 버튼에 표시할 텍스트를 지정해야 합니다.이러한 버튼을 클릭할 때 실행될 명령과 시각적 효과를 위해 원하는 글꼴 스타일도 결정해야 합니다. 버튼을 효과적으로 구성하려면 버튼 사이에 적절한 양의 패딩을 추가하는 것이 도움이 될 수 있습니다. 또한 인터페이스 내에서 수행되는 잠재적인 드래그 작업과 관련된 데이터를 쉽게 저장할 수 있도록 “drag\_data”라는 변수를 초기화하는 것이 좋습니다.

이 글도 확인해 보세요:  파이썬을 사용하여 FLAMES 게임 플레이하기

인터페이스에서 시각적 위치를 유지하기 위해 `image_positions`라는 데이터 구조를 초기화합니다. 그림의 선택, 이동, 해제에 반응하는 세 가지 이벤트 처리 함수를 구현합니다.

         self.btn_add_image = tk.Button(
            self.root,
            text="Add Image",
            command=self.add_images,
            font=("Arial", 12, "bold"),
        )

        self.btn_add_image.pack(pady=10)

        self.btn_create_collage = tk.Button(
            self.root,
            text="Create Collage",
            command=self.create_collage,
            font=("Arial", 12, "bold"),
        )

        self.btn_create_collage.pack(pady=5)
        self.drag_data = {"x": 0, "y": 0, "item": None}
        self.image_positions = []
        self.collage_canvas.bind("<ButtonPress-1>", self.on_press)
        self.collage_canvas.bind("<B1-Motion>", self.on_drag)
        self.collage_canvas.bind("<ButtonRelease-1>", self.on_release)

`on_press` 함수는 사용자가 마우스를 클릭한 지점에서 가장 가까운 캔버스 항목을 검색하도록 정의되어 있습니다. 이 항목은 “item” 키와 함께 `drag_data` 사전에 저장됩니다. 또한 드래그하는 동안 변위를 계산하기 위해 마우스 클릭의 x 및 y 좌표가 저장됩니다.

     def on_press(self, event):
        self.drag_data["item"] = self.collage_canvas.find_closest(event.x, event.y)[0]
        self.drag_data["x"] = event.x
        self.drag_data["y"] = event.y

예! 다음은 객체를 드래그하는 동안 마우스의 움직임에 따라 수평 및 수직 방향의 변화를 계산하고, 이러한 변화에 따라 객체의 위치를 업데이트하며, 객체의 새로운 위치를 `drag_data` 사전의 ‘x’ 및 ‘y’ 키 아래에 저장하는 `on_drag` 함수에 대한 Python 구현 예제입니다: “`파이썬 def on_drag(event): # 이벤트에서 현재 데이터를 가져옵니다. data = event.data # 이벤트 데이터에 키가 존재하는지 확인합니다. “x”가 데이터에 없거나 “y”가 데이터에 없는 경우: 반환 # 이벤트 데이터에서 이전 위치와 새 위치를 추출합니다. old_x = data[“x”]

     def on_drag(self, event):
        delta_x = event.x - self.drag_data["x"]
        delta_y = event.y - self.drag_data["y"]
        self.collage_canvas.move(self.drag_data["item"], delta_x, delta_y)
        self.drag_data["x"] = event.x
        self.drag_data["y"] = event.y

좌표와 함께 드래그된 이미지가 제대로 해제되도록 하려면 코드에 “on\_release”라는 메서드를 정의할 수 있습니다. 이 메서드는 이전에 사용자가 드래그했던 이미지에 대한 참조를 모두 지워야 합니다. 또한 사용자가 이미지를 드래그했다가 놓으면 캔버스에 있는 모든 이미지의 위치를 업데이트하기 위해 “update\_image\_positions” 함수를 호출하는 것이 적절할 수 있습니다.

     def on_release(self, event):
        self.drag_data["item"] = None
        self.drag_data["x"] = 0
        self.drag_data["y"] = 0
        self.update_image_positions()

캔버스에서 이미지의 위치를 효율적으로 관리하기 위해 ‘update_image_positions’라는 알고리즘 솔루션을 고안했습니다. 이 방법은 캔버스에 존재하는 모든 개별 요소에 대한 포괄적인 스캔을 진행하기 전에 ‘image_positions’ 목록 내의 기존 데이터를 먼저 지움으로써 프로세스를 간소화하도록 설계되었습니다. 이 검사 과정에서 각 항목과 관련된 정확한 x-y 좌표 쌍을 찾은 다음 필요에 따라 추가 참조 또는 조작을 위해 이 값을 업데이트된 `image_positions` 배열에 추가합니다.

     def update_image_positions(self):
        self.image_positions.clear()

        for item in self.collage_canvas.find_all():
            x, y = self.collage_canvas.coords(item)
            self.image_positions.append((x, y))

다음 단계를 통합하여 Python 및 PIL 라이브러리(Pillow)를 사용하여 “add\_images” 함수를 생성합니다: 1. “add\_images”라는 새 함수를 정의합니다. 2. 그래픽 사용자 인터페이스(GUI) 대화 상자를 통해 콜라주에 포함할 이미지 수를 입력하라는 메시지를 사용자에게 표시합니다. 3. 입력한 값이 숫자인지, 콜라주에 필요한 이미지 수에 적합한 범위 내에 있는지 확인합니다. 4. 다른 GUI 대화 상자를 사용하여 사용자가 로컬 스토리지 시스템에서 특정 이미지 파일을 찾아보고 선택할 수 있도록 합니다. 이 프로세스를 통해 사용자는 최종 제품에 포함될 이미지를 선택할 수 있습니다. 5. 선택한 이미지 파일을 반복하여 Pillow의 Image.open()

이 글도 확인해 보세요:  어수선한 카메라 롤을 정리하는 방법: 검증된 7가지 방법

`resize_image` 함수를 사용하여 지정된 이미지의 크기를 조정하고, `PhotoImage` 객체로 변환하여 Tkinter GUI와 호환되는지 확인합니다. 그런 다음 `update_canvas` 메서드를 호출하기 전에 이 크기 조정된 이미지를 `image_refs` 목록에 추가하여 업데이트된 이미지를 GUI에 표시합니다.

     def add_images(self):
        num_images = simpledialog.askinteger(
            "Number of Images", "Enter the number of images:"
        )

        if num_images is not None:
            file_paths = filedialog.askopenfilenames(
                filetypes=[("Image files", "*.png;*.jpg;*.jpeg;*.gif")]
            )

            if file_paths:
                for i in range(min(num_images, len(file_paths))):
                    file_path = file_paths[i]
                    image = Image.open(file_path)
                    resized_image = self.resize_image(image)
                    self.images.append(resized_image)
                    self.image_refs.append(ImageTk.PhotoImage(resized_image))

                self.update_canvas()

Resize\_Image는 지정된 레이아웃에 맞도록 이미지의 크기를 조정하는 메서드입니다. 먼저 이미지의 너비와 높이를 결정하여 이미지의 현재 가로 세로 비율을 계산합니다. 그런 다음 가로 세로 비율을 1과 비교하여 1보다 크면 원래 가로 세로 비율을 그대로 유지하면서 새 너비를 콜라주 너비의 절반과 같게 설정합니다. 이렇게 하면 높이도 그에 따라 계산되어 비례적으로 변경됩니다.

콜라주의 종횡비가 1보다 작은 경우 새 높이를 전체 높이의 절반으로 설정하고 그에 따라 해당 너비를 계산하여 크기를 조정할 수 있습니다. 이를 위해 파이썬 라이브러리 Pillow의 `resize` 함수를 사용하여 가로 세로 비율을 유지하면서 지정된 치수로 원본 이미지의 확대 버전을 생성합니다.

     def resize_image(self, image):
        img_width, img_height = image.size
        aspect_ratio = img_width / img_height

        if aspect_ratio > 1:
            new_width = self.collage_size[0] // 2
            new_height = int(new_width / aspect_ratio)
        else:
            new_height = self.collage_size[1] // 2
            new_width = int(new_height * aspect_ratio)

        return image.resize((new_width, new_height))

`update_canvas` 함수는 캔버스에서 이미지 배열의 시각적 표현을 새로 고치는 역할을 합니다. 이 프로세스에는 캔버스 내의 모든 기존 요소를 지운 다음 파일 대화 인터페이스를 통해 사용자가 원하는 아트웍의 치수를 입력하라는 메시지가 표시됩니다. 그런 다음 콜라주의 너비와 높이가 지정된 크기의 절반으로 설정됩니다. 또한 이미지 위치 목록에서 이전 이미지 배치 기록이 모두 지워집니다. 행과 열 배열 추적을 시작하기 위해 x 오프셋과 y 오프셋 변수가 모두 초기화됩니다.

     def update_canvas(self):
        self.collage_canvas.delete("all")
        rows = simpledialog.askinteger("Number of Rows", "Enter the number of rows:")

        cols = simpledialog.askinteger(
            "Number of Columns", "Enter the number of columns:"
        )

        collage_width = self.collage_size[0] * cols // 2
        collage_height = self.collage_size[1] * rows // 2
        self.collage_canvas.config(width=collage_width, height=collage_height)
        self.image_positions.clear()
        x_offset, y_offset = 0, 0

이미지\_refs 목록을 반복하고 제공된 오프셋을 활용하여 스케치패드에 항목의 시각적 표현을 생성합니다.앵커를 북서쪽으로 설정하여 배치의 원점이 왼쪽 상단 모서리에 위치하도록 합니다. 또한 이미지\_포지션 목록에 특정 x 및 y 좌표를 추가합니다.

후속 이미지의 올바른 위치를 고려하여 콜라주 전체 너비의 절반을 추가하여 x\_오프셋의 값을 수정합니다. 또한 현재 같은 행에 표시되는 이미지 수가 미리 정의된 열 수를 충족하는 경우 x\_offset 값을 0으로 재설정하면 새 행이 시작됩니다. 마지막으로 y\_좌표를 콜라주 높이의 절반만큼 증가시켜 다음 행의 시작점을 설정합니다.

         for i, image_ref in enumerate(self.image_refs):
            self.collage_canvas.create_image(
                x_offset, y_offset, anchor=tk.NW, image=image_ref
            )

            self.image_positions.append((x_offset, y_offset))
            x_offset += self.collage_size[0] // 2

            if (i + 1) % cols == 0:
                x_offset = 0
                y_offset += self.collage_size[1] // 2

콜라주 생성 및 저장

디지털 사진의 예술적인 구성을 생성하기 위해 ‘create_collage’라는 함수를 설정합니다. 이 함수는 콜라주 내에 이미지가 없는 경우 시각적 표시를 제공합니다. 그 후 폭과 높이를 확인하여 결과물의 치수를 결정합니다. 그 다음에는 균일한 흰색 배경의 파이썬 이미징 라이브러리(PIL)를 사용하여 빈 캔버스를 구성합니다. 마지막으로, 사진 컬렉션을 반복하여 이 기초 위에 지정된 위치에 겹쳐서 배치합니다.

이 글도 확인해 보세요:  JES를 활용한 흥미로운 사운드 처리 기법 3가지

합성 이미지를 보존하고 표준 그래픽 뷰어를 사용하여 표시합니다.

     def create_collage(self):
        if len(self.images) == 0:
            messagebox.showwarning("Warning", "Please add images first!")
            return

        collage_width = self.collage_canvas.winfo_width()
        collage_height = self.collage_canvas.winfo_height()
        background = Image.new("RGB", (collage_width, collage_height), "white")

        for idx, image in enumerate(self.images):
            x_offset, y_offset = self.image_positions[idx]
            x_offset, y_offset = int(x_offset), int(y_offset)

            paste_box = (
                x_offset,
                y_offset,
                x_offset + image.width,
                y_offset + image.height,
            )

            background.paste(image, paste_box)

        background.save("collage_with_white_background.jpg")
        background.show()

이 프로세스에는 프로그램 GUI 내에서 기본 루프 작업을 시작하는 역할을 하는 Tkinter 및 ImageCollage Application 클래스의 인스턴스화가 포함됩니다. 이 이벤트 루프는 그래픽 인터페이스가 닫힐 때까지 파이썬이 사용자 상호작용에 대한 경계를 유지하도록 합니다.

 if __name__ == "__main__":
    root = tk.Tk()
    app = ImageCollageApp(root)
    root.mainloop()

이미지 콜라주 메이커의 다양한 기능 테스트

“이미지 추가” 및 “콜라주 만들기”. 이미지 추가를 선택하면 별도의 창에서 몽타주에 포함할 시각적 요소의 총 개수를 지정하라는 메시지가 표시됩니다. 원하는 이미지 5개를 선택하고 이 값을 입력하면 이러한 구성 요소의 가로 및 세로 배열에 관한 정보를 요청하는 추가 대화 상자가 표시됩니다.

각각 3개의 행과 4개의 요소로 구성된 두 세트의 비주얼을 삽입하면 그래픽 사용자 인터페이스가 배열과 같은 레이아웃으로 정렬합니다.

미리보기 기능을 사용하면 원하는 대로 이미지의 위치를 변경하여 이미지를 조작할 수 있습니다. “콜라주 만들기” 버튼을 클릭하면 소프트웨어가 최종 이미지를 저장합니다.

출력물의 시각적 표현을 살펴보면 소프트웨어가 프로그램에서 의도한 대로 합성 이미지를 효과적으로 생성했음을 알 수 있습니다.

이미지 콜라주 메이커의 기능 향상

사용자는 테이블 기반 구조를 활용하는 대신 자신의 선호도에 맞는 다양한 사전 정의된 디자인 테마 중에서 선택할 수 있습니다. 또한 이 기능은 배경 색조 조정, 텍스트 요소 통합, 이미지 향상 적용, 온라인에서 얻은 가상 스티커 통합과 같은 사용자 정의 옵션을 제공합니다.

이러한 기능을 통합하여 실행 취소/다시 실행 기능을 포함하여 편리하게 수정할 수 있는 간단한 편집 인터페이스를 사용할 수 있습니다. 사용자가 원하는 대로 이미지 자르기, 크기 조정, 회전 등의 방법으로 배열을 조작할 수 있도록 허용합니다. 또한 이미지를 선택한 파일 형식으로 보존하는 기능을 통합하세요.

By 최은지

윈도우(Windows)와 웹 서비스에 대한 전문 지식을 갖춘 노련한 UX 디자이너인 최은지님은 효율적이고 매력적인 디지털 경험을 개발하는 데 탁월한 능력을 발휘합니다. 사용자의 입장에서 생각하며 누구나 쉽게 접근하고 즐길 수 있는 콘텐츠를 개발하는 데 주력하고 있습니다. 사용자 경험을 향상시키기 위해 연구를 거듭하는 은지님은 All Things N 팀의 핵심 구성원으로 활약하고 있습니다.