Spaces:
Sleeping
Sleeping
import streamlit as st | |
import os | |
from PIL import Image, ImageDraw | |
import random | |
# Function to calculate aspect ratio | |
def calculate_aspect_ratio(image_path): | |
with Image.open(image_path) as img: | |
width, height = img.size | |
gcd = lambda a, b: a if not b else gcd(b, a % b) | |
divisor = gcd(width, height) | |
return width // divisor, height // divisor | |
# Function to randomly position images while ensuring no overlap | |
def arrange_images(image_files, output_path="dungeon_layout.png"): | |
if not image_files: | |
return None | |
# Initialize variables for layout | |
positions = [] # Keeps track of image positions | |
canvas_size = (3000, 3000) # Adjust based on your needs | |
canvas = Image.new("RGBA", canvas_size, "white") | |
draw = ImageDraw.Draw(canvas) | |
for img_file in image_files: | |
img_path = os.path.join(map_dir, img_file) | |
with Image.open(img_path) as img: | |
width, height = img.size | |
# Randomly decide horizontal or vertical placement | |
if random.choice(["horizontal", "vertical"]) == "horizontal": | |
x_center = random.randint(width // 2, canvas_size[0] - width // 2) | |
y_center = canvas_size[1] // 2 | |
else: | |
x_center = canvas_size[0] // 2 | |
y_center = random.randint(height // 2, canvas_size[1] - height // 2) | |
# Calculate position | |
x1 = x_center - width // 2 | |
y1 = y_center - height // 2 | |
x2 = x1 + width | |
y2 = y1 + height | |
# Ensure no overlap with existing images | |
overlap = any( | |
x1 < pos[2] and x2 > pos[0] and y1 < pos[3] and y2 > pos[1] | |
for pos in positions | |
) | |
if not overlap: | |
positions.append((x1, y1, x2, y2)) | |
canvas.paste(img, (x1, y1)) | |
# Draw connection line | |
if len(positions) > 1: | |
prev_x, prev_y = (positions[-2][0] + positions[-2][2]) // 2, (positions[-2][1] + positions[-2][3]) // 2 | |
curr_x, curr_y = (x1 + x2) // 2, (y1 + y2) // 2 | |
draw.line([(prev_x, prev_y), (curr_x, curr_y)], fill="black", width=5) | |
canvas.save(output_path) | |
return output_path | |
# Streamlit App | |
st.title("Dynamic Dungeon Map Generator") | |
st.write("Automatically generates dungeon maps by analyzing PNG images in a top-level directory.") | |
# Directory for images | |
map_dir = "." # Top-level directory | |
# Scan the directory for .png files | |
image_files = [f for f in os.listdir(map_dir) if f.endswith(".png")] | |
if image_files: | |
# Add "Create Map" button | |
if st.button("🗺️ Create Map"): | |
layout_image = arrange_images(image_files) | |
if layout_image: | |
st.image(layout_image, caption="Generated Dungeon Map Layout") | |
else: | |
st.write("Failed to generate a map. Please check the images in the directory.") | |
else: | |
st.write("No PNG files found in the top-level directory.") | |
# Sidebar for file upload | |
st.sidebar.title("Options") | |
uploaded_file = st.sidebar.file_uploader("Upload a PNG file", type="png") | |
if uploaded_file: | |
# Save uploaded file to the directory | |
with open(os.path.join(map_dir, uploaded_file.name), "wb") as f: | |
f.write(uploaded_file.getbuffer()) | |
st.sidebar.success("File uploaded successfully! Refresh the app to include it in the dungeon map.") | |