Khalil09 commited on
Commit
cba3926
ยท
verified ยท
1 Parent(s): 404a9b7

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +215 -0
app.py ADDED
@@ -0,0 +1,215 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import torch
3
+ from diffusers import StableDiffusionPipeline, DPMSolverMultistepScheduler
4
+ from PIL import Image
5
+ import io
6
+
7
+ # โ”€โ”€ Page Config โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
8
+ st.set_page_config(
9
+ page_title="Text to Image Generator",
10
+ page_icon="๐ŸŽจ",
11
+ layout="wide",
12
+ )
13
+
14
+ # โ”€โ”€ Custom CSS โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
15
+ st.markdown("""
16
+ <style>
17
+ .main { background-color: #0f0f1a; }
18
+ .stApp { background: linear-gradient(135deg, #0f0f1a 0%, #1a1a2e 100%); }
19
+ h1 { color: #c084fc !important; font-size: 2.5rem !important; }
20
+ h3 { color: #a78bfa !important; }
21
+ .stButton > button {
22
+ background: linear-gradient(90deg, #7c3aed, #a855f7);
23
+ color: white;
24
+ border: none;
25
+ border-radius: 10px;
26
+ padding: 0.6rem 2rem;
27
+ font-size: 1rem;
28
+ font-weight: 600;
29
+ width: 100%;
30
+ transition: opacity 0.2s;
31
+ }
32
+ .stButton > button:hover { opacity: 0.85; }
33
+ .stTextArea textarea, .stTextInput input {
34
+ background-color: #1e1e3a !important;
35
+ color: #e2e8f0 !important;
36
+ border: 1px solid #4c1d95 !important;
37
+ border-radius: 8px !important;
38
+ }
39
+ .stSlider > div > div { color: #c084fc; }
40
+ label { color: #c4b5fd !important; font-weight: 500; }
41
+ .stImage img {
42
+ border-radius: 12px;
43
+ border: 1px solid #4c1d95;
44
+ box-shadow: 0 0 20px rgba(168, 85, 247, 0.2);
45
+ }
46
+ .info-box {
47
+ background: #1e1e3a;
48
+ border-left: 4px solid #7c3aed;
49
+ border-radius: 8px;
50
+ padding: 12px 16px;
51
+ margin-bottom: 16px;
52
+ color: #c4b5fd;
53
+ font-size: 0.9rem;
54
+ }
55
+ .stExpander { border: 1px solid #4c1d95 !important; border-radius: 8px !important; }
56
+ .stDownloadButton > button {
57
+ background: #1e1e3a !important;
58
+ color: #c084fc !important;
59
+ border: 1px solid #7c3aed !important;
60
+ border-radius: 8px;
61
+ width: 100%;
62
+ }
63
+ </style>
64
+ """, unsafe_allow_html=True)
65
+
66
+
67
+ # โ”€โ”€ Model Loader (cached) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
68
+ @st.cache_resource(show_spinner=False)
69
+ def load_pipeline():
70
+ model_id = "runwayml/stable-diffusion-v1-5"
71
+ pipe = StableDiffusionPipeline.from_pretrained(
72
+ model_id,
73
+ torch_dtype=torch.float16 if torch.cuda.is_available() else torch.float32,
74
+ safety_checker=None,
75
+ requires_safety_checker=False,
76
+ )
77
+ pipe.scheduler = DPMSolverMultistepScheduler.from_config(pipe.scheduler.config)
78
+ device = "cuda" if torch.cuda.is_available() else "cpu"
79
+ pipe = pipe.to(device)
80
+ if torch.cuda.is_available():
81
+ pipe.enable_attention_slicing()
82
+ return pipe
83
+
84
+
85
+ # โ”€โ”€ Helper: PIL โ†’ bytes โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
86
+ def image_to_bytes(img: Image.Image) -> bytes:
87
+ buf = io.BytesIO()
88
+ img.save(buf, format="PNG")
89
+ return buf.getvalue()
90
+
91
+
92
+ # โ”€โ”€ UI โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
93
+ st.title("๐ŸŽจ Text to Image Generator")
94
+ st.markdown("**Powered by Stable Diffusion v1.5** โ€” Transform your words into stunning visuals.")
95
+
96
+ col_left, col_right = st.columns([1, 1], gap="large")
97
+
98
+ with col_left:
99
+ st.markdown("### โœ๏ธ Describe your image")
100
+
101
+ prompt = st.text_area(
102
+ "Prompt",
103
+ placeholder="a futuristic city at sunset, cyberpunk style, ultra detailed, 4k...",
104
+ height=110,
105
+ label_visibility="collapsed",
106
+ )
107
+
108
+ negative_prompt = st.text_area(
109
+ "Negative Prompt",
110
+ value="blurry, ugly, distorted, low quality, watermark, text, signature",
111
+ height=75,
112
+ help="Describe what you DON'T want in the image.",
113
+ )
114
+
115
+ with st.expander("โš™๏ธ Advanced Settings"):
116
+ col_w, col_h = st.columns(2)
117
+ with col_w:
118
+ width = st.select_slider("Width", options=[256, 320, 384, 448, 512, 576, 640, 704, 768], value=512)
119
+ with col_h:
120
+ height = st.select_slider("Height", options=[256, 320, 384, 448, 512, 576, 640, 704, 768], value=512)
121
+
122
+ steps = st.slider("Inference Steps", min_value=10, max_value=50, value=25, step=1,
123
+ help="More steps = better quality but slower.")
124
+ guidance = st.slider("Guidance Scale", min_value=1.0, max_value=15.0, value=7.5, step=0.5,
125
+ help="Higher = more literal to your prompt.")
126
+ num_images = st.slider("Number of Images", min_value=1, max_value=4, value=1, step=1)
127
+ seed = st.number_input("Seed (-1 = random)", value=-1, step=1,
128
+ help="Same seed + same prompt = same image every time.")
129
+
130
+ st.markdown("### ๐Ÿ’ก Example Prompts")
131
+ examples = [
132
+ "portrait of a samurai warrior, cinematic lighting, 4k",
133
+ "dragon flying over snow-capped mountains, fantasy art",
134
+ "astronaut riding a horse on Mars, photorealistic",
135
+ "cute cartoon cat in sunglasses, vibrant illustration",
136
+ ]
137
+ for ex in examples:
138
+ if st.button(f"๐Ÿ“ {ex[:45]}...", key=ex):
139
+ st.session_state["example_prompt"] = ex
140
+
141
+ if "example_prompt" in st.session_state:
142
+ st.info(f"Copied: *{st.session_state['example_prompt']}* โ€” paste it in the prompt box above.")
143
+
144
+ generate_btn = st.button("โœจ Generate Image")
145
+
146
+
147
+ with col_right:
148
+ st.markdown("### ๐Ÿ–ผ๏ธ Output")
149
+
150
+ if generate_btn:
151
+ if not prompt.strip():
152
+ st.error("Please enter a prompt first!")
153
+ else:
154
+ with st.spinner("๐Ÿ”ฎ Loading model (first run takes ~2 min)..."):
155
+ pipe = load_pipeline()
156
+
157
+ with st.spinner(f"๐ŸŽจ Generating {num_images} image(s)... (~{steps * 2}s)"):
158
+ try:
159
+ generator = None
160
+ if seed != -1:
161
+ device = "cuda" if torch.cuda.is_available() else "cpu"
162
+ generator = torch.Generator(device).manual_seed(int(seed))
163
+
164
+ result = pipe(
165
+ prompt=prompt,
166
+ negative_prompt=negative_prompt if negative_prompt.strip() else None,
167
+ num_inference_steps=steps,
168
+ guidance_scale=guidance,
169
+ width=width,
170
+ height=height,
171
+ generator=generator,
172
+ num_images_per_prompt=num_images,
173
+ )
174
+
175
+ images = result.images
176
+ st.session_state["images"] = images
177
+ st.session_state["last_prompt"] = prompt
178
+ st.success(f"โœ… Generated {len(images)} image(s)!")
179
+
180
+ except Exception as e:
181
+ st.error(f"Generation failed: {e}")
182
+
183
+ if "images" in st.session_state:
184
+ images = st.session_state["images"]
185
+ cols = st.columns(2 if len(images) > 1 else 1)
186
+ for i, img in enumerate(images):
187
+ with cols[i % len(cols)]:
188
+ st.image(img, use_column_width=True)
189
+ st.download_button(
190
+ label=f"โฌ‡๏ธ Download image {i + 1}",
191
+ data=image_to_bytes(img),
192
+ file_name=f"generated_{i + 1}.png",
193
+ mime="image/png",
194
+ key=f"dl_{i}",
195
+ )
196
+
197
+ else:
198
+ st.markdown("""
199
+ <div class="info-box">
200
+ ๐Ÿ‘ˆ Fill in your prompt on the left and hit <strong>Generate Image</strong> to get started.<br><br>
201
+ ๐Ÿš€ <strong>Tips:</strong><br>
202
+ โ€ข Add style words: <em>cinematic, 4k, oil painting, photorealistic</em><br>
203
+ โ€ข Use negative prompts to remove unwanted elements<br>
204
+ โ€ข Guidance scale 7โ€“9 gives the best balance
205
+ </div>
206
+ """, unsafe_allow_html=True)
207
+
208
+ # โ”€โ”€ Footer โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
209
+ st.divider()
210
+ st.markdown(
211
+ "<p style='text-align:center; color:#6b7280; font-size:0.85rem;'>"
212
+ "Built with Streamlit ยท Stable Diffusion v1.5 ยท Deployed on Hugging Face Spaces"
213
+ "</p>",
214
+ unsafe_allow_html=True,
215
+ )