top of page
  • Cihan Toraman

Crafting Texture Atlases with Python: Effortlessly Combining Images

Seamless Integration of Assets in Game Development

Texture atlases are a cornerstone of efficient game design, optimizing rendering and minimizing resource usage. Our focus today shifts to a Python script that automates the creation of texture atlases. This utility combines individual images into a single, cohesive texture atlas, a process crucial for game developers aiming to streamline asset management and improve game performance.


Texture Atlas Creatoion with python


Key Components of the Script
  1. Determining the Grid Size: The script starts by calculating the grid dimensions needed to combine the images. The calculate_grid_dimensions function, using the square root and ceiling functions, ensures that the grid is as square as possible, optimizing space and accommodating any number of images.

  2. Combining Images into an Atlas: The combine_images function is the heart of the script. It dynamically reads images from a specified folder, ascertains their dimensions, and then meticulously places them into a new, larger image representing the atlas. This procedure guarantees that each asset is precisely positioned within the grid, maintaining its integrity and quality.

  3. Handling Different Image Counts: An intriguing aspect of this function is its ability to handle scenarios where the number of images doesn't perfectly fit the grid. In such cases, it fills the remaining space with black cells, ensuring the final atlas is always a complete grid.

  4. User-Friendly Interface with Tkinter: Like its counterpart, this script employs Tkinter for its GUI, facilitating ease of use. Users can simply select their source and destination folders and initiate the combining process. This accessibility is crucial in making the tool practical for a wide range of users, from indie developers to large studios.

  5. Execution Flow: The combine_and_save function brings everything together. It triggers the image combination process and informs the user upon completion. This function exemplifies the script’s capacity to automate a task that would otherwise be time-consuming and prone to human error.


texture atlas creator GUI

Script:

import tkinter as tk
from tkinter import filedialog
from PIL import Image
import os
import math

def calculate_grid_dimensions(num_files):
    grid_size = math.ceil(math.sqrt(num_files))
    return grid_size, grid_size

def combine_images(input_folder, output_folder, output_image_name):
    # Find all PNG files in the input folder
    files = sorted([f for f in os.listdir(input_folder) if f.endswith('.png')], key=lambda x: int(x.split('_')[-1].split('.')[0]))
    num_files = len(files)
    grid_width, grid_height = calculate_grid_dimensions(num_files)

    # Open the first image to find out the size of each cell
    with Image.open(os.path.join(input_folder, files[0])) as img:
        cell_width, cell_height = img.width, img.height
        total_width, total_height = cell_width * grid_width, cell_height * grid_height

    # Create a new blank image with the total size
    combined_image = Image.new('RGB', (total_width, total_height))

    # Iterate over the grid and paste each image
    for i in range(grid_height):
        for j in range(grid_width):
            idx = i * grid_width + j
            if idx < num_files:
                with Image.open(os.path.join(input_folder, files[idx])) as img:
                    combined_image.paste(img, (j * cell_width, i * cell_height))
            else:
                # Fill remaining cells with black if there are less images than grid cells
                combined_image.paste(Image.new('RGB', (cell_width, cell_height), (0, 0, 0)), (j * cell_width, i * cell_height))

    # Save the combined image
    combined_image.save(os.path.join(output_folder, output_image_name))

def select_input_folder():
    folder_path = filedialog.askdirectory()
    entry_input_folder.delete(0, tk.END)
    entry_input_folder.insert(0, folder_path)

def select_output_folder():
    folder_path = filedialog.askdirectory()
    entry_output_folder.delete(0, tk.END)
    entry_output_folder.insert(0, folder_path)

def combine_and_save():
    input_folder = entry_input_folder.get()
    output_folder = entry_output_folder.get()
    output_image_name = 'combined_image.png'
    combine_images(input_folder, output_folder, output_image_name)
    label_info.config(text=f"Images combined and saved in '{output_folder}/{output_image_name}'.")

# Set up the GUI
root = tk.Tk()
root.title('Image Combiner')

# Input folder entry
label_input_folder = tk.Label(root, text="Input Folder:")
label_input_folder.grid(row=0, column=0, padx=5, pady=5)

entry_input_folder = tk.Entry(root, width=50)
entry_input_folder.grid(row=0, column=1, padx=5, pady=5)

button_input_folder = tk.Button(root, text="Browse", command=select_input_folder)
button_input_folder.grid(row=0, column=2, padx=5, pady=5)

# Output folder entry
label_output_folder = tk.Label(root, text="Output Folder:")
label_output_folder.grid(row=1, column=0, padx=5, pady=5)

entry_output_folder = tk.Entry(root, width=50)
entry_output_folder.grid(row=1, column=1, padx=5, pady=5)

button_output_folder = tk.Button(root, text="Browse", command=select_output_folder)
button_output_folder.grid(row=1, column=2, padx=5, pady=5)

# Combine and save button
button_combine_save = tk.Button(root, text="Combine and Save", command=combine_and_save)
button_combine_save.grid(row=2, column=1, padx=5, pady=5, sticky='w')

# Info label
label_info = tk.Label(root, text="")
label_info.grid(row=3, column=1, padx=5, pady=5)

# Run the application
root.mainloop()
Summary

This Python-based texture atlas generator is a testament to the power of automation in game design. By efficiently combining individual assets into a single atlas, it significantly enhances the asset management process, leading to more streamlined game development workflows. As the gaming industry continues to evolve, tools like this play a pivotal role in enabling developers to focus more on creative aspects, leaving the technical heavy lifting to automated solutions.


Stay connected for more insights and tools aimed at revolutionizing your approach to game design and development.

Comments


bottom of page