awacke1 commited on
Commit
aa7ce45
·
verified ·
1 Parent(s): 6dbef36

Update app.py

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