Spaces:
Sleeping
Sleeping
File size: 4,987 Bytes
6dbef36 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 |
import streamlit as st
import os
from PIL import Image
import random
from io import BytesIO
import datetime
import base64
# Adjust Streamlit layout to wide mode
st.set_page_config(layout="wide")
# Function to arrange images dynamically
def arrange_images(image_files, canvas_size=(3000, 3000)):
if not image_files:
return None
positions = [] # Keeps track of image positions (x1, y1, x2, y2)
canvas = Image.new("RGBA", canvas_size, "white")
def get_center(pos):
"""Calculate center of a bounding box (x1, y1, x2, y2)."""
return ((pos[0] + pos[2]) // 2, (pos[1] + pos[3]) // 2)
def does_overlap(new_box, existing_boxes):
"""Check if a new bounding box overlaps any existing boxes."""
for box in existing_boxes:
if (
new_box[0] < box[2]
and new_box[2] > box[0]
and new_box[1] < box[3]
and new_box[3] > box[1]
):
return True
return False
# Place the first image at the center of the canvas
first_img_path = os.path.join(map_dir, image_files[0])
with Image.open(first_img_path) as img:
width, height = img.size
x1 = (canvas_size[0] - width) // 2
y1 = (canvas_size[1] - height) // 2
x2, y2 = x1 + width, y1 + height
positions.append((x1, y1, x2, y2))
canvas.paste(img, (x1, y1))
# Place remaining images
for img_file in image_files[1:]:
placed = False
img_path = os.path.join(map_dir, img_file)
with Image.open(img_path) as img:
width, height = img.size
while not placed:
target_box = random.choice(positions)
target_center = get_center(target_box)
side = random.choice(["top", "bottom", "left", "right"])
if side == "top":
x1 = target_center[0] - width // 2
y1 = target_box[1] - height
elif side == "bottom":
x1 = target_center[0] - width // 2
y1 = target_box[3]
elif side == "left":
x1 = target_box[0] - width
y1 = target_center[1] - height // 2
elif side == "right":
x1 = target_box[2]
y1 = target_center[1] - height // 2
x2, y2 = x1 + width, y1 + height
if not does_overlap((x1, y1, x2, y2), positions):
positions.append((x1, y1, x2, y2))
canvas.paste(img, (x1, y1))
placed = True
buffer = BytesIO()
canvas.save(buffer, format="PNG")
buffer.seek(0)
return buffer, canvas
# Function to create a base64 download link
def create_download_link(image_bytes, filename):
b64 = base64.b64encode(image_bytes.getvalue()).decode()
href = f'<a href="data:image/png;base64,{b64}" download="{filename}">📥 Download {filename}</a>'
return href
# Streamlit App
st.title("Dynamic Dungeon Map Generator")
# Directory for images
map_dir = "."
canvas_size = 3000
# Initialize session state
if "layout_image" not in st.session_state:
st.session_state["layout_image"] = None
if "canvas" not in st.session_state:
st.session_state["canvas"] = None
# Generate map if layout_image is empty
if st.session_state["layout_image"] is None:
image_files = [f for f in os.listdir(map_dir) if f.endswith(".png")]
if image_files:
layout_image, canvas = arrange_images(image_files, canvas_size=(canvas_size, canvas_size))
st.session_state["layout_image"] = layout_image
st.session_state["canvas"] = canvas
# Display map with scroll and zoom controls
if st.session_state["layout_image"] is not None:
st.image(
st.session_state["layout_image"],
caption="Generated Dungeon Map Layout",
use_container_width=True,
output_format="PNG",
clamp=True,
)
# Sidebar Controls
st.sidebar.title("Map Controls")
if st.sidebar.button("💾 Save Map"):
now = datetime.datetime.now()
filename = f"dungeon_map_{now.strftime('%Y%m%d_%H%M%S')}.png"
st.session_state["canvas"].save(filename)
st.sidebar.success(f"Map saved as {filename}")
if st.sidebar.button("🗺️ Regenerate Map"):
image_files = [f for f in os.listdir(map_dir) if f.endswith(".png")]
if image_files:
layout_image, canvas = arrange_images(image_files, canvas_size=(canvas_size, canvas_size))
st.session_state["layout_image"] = layout_image
st.session_state["canvas"] = canvas
st.rerun()
# Zoom controls
st.sidebar.title("Zoom")
zoom_level = st.sidebar.slider("Zoom Level", min_value=0.5, max_value=2.0, value=1.0, step=0.1)
st.image(
st.session_state["layout_image"],
caption="Zoomed Dungeon Map Layout",
use_container_width=False,
output_format="PNG",
clamp=True,
width=int(canvas_size * zoom_level),
)
|