KilgorePennington commited on
Commit
e816734
Β·
verified Β·
1 Parent(s): 9139888

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +148 -74
app.py CHANGED
@@ -2,8 +2,9 @@ import streamlit as st
2
  import time
3
  import random
4
  import requests
5
- from PIL import Image
6
  import io
 
7
 
8
  # Page config
9
  st.set_page_config(
@@ -40,12 +41,10 @@ st.markdown("""
40
  # Initialize session state
41
  if 'generated_image' not in st.session_state:
42
  st.session_state.generated_image = None
43
- if 'image_prompt' not in st.session_state:
44
- st.session_state.image_prompt = ""
45
 
46
  # Header
47
  st.markdown('<h1 class="main-header">πŸ“š StoryVision AI</h1>', unsafe_allow_html=True)
48
- st.markdown('<p style="text-align: center; font-size: 1.2rem; color: #666;">Create magical stories with REAL AI-generated artwork!</p>', unsafe_allow_html=True)
49
 
50
  # Sidebar controls
51
  st.sidebar.markdown("## 🎨 Story Settings")
@@ -70,46 +69,124 @@ art_style = st.sidebar.selectbox(
70
  ["Fantasy Art", "Digital Painting", "Watercolor", "Anime Style", "Photorealistic", "Concept Art"]
71
  )
72
 
73
- # Image generation function
74
  @st.cache_data(show_spinner=False)
75
- def generate_image(prompt, style):
76
- """Generate image using Hugging Face Stable Diffusion"""
77
-
78
- # Hugging Face API endpoint (free tier)
79
- API_URL = "https://api-inference.huggingface.co/models/runwayml/stable-diffusion-v1-5"
80
-
81
- # Enhance prompt based on style
82
- style_prompts = {
83
- "Fantasy Art": "fantasy art, magical, ethereal, detailed, artstation, concept art",
84
- "Digital Painting": "digital painting, detailed, artstation, concept art, smooth",
85
- "Watercolor": "watercolor painting, soft colors, artistic, traditional art",
86
- "Anime Style": "anime style, manga, detailed, vibrant colors, studio quality",
87
- "Photorealistic": "photorealistic, detailed, high quality, professional photography",
88
- "Concept Art": "concept art, detailed, artstation, matte painting, digital art"
89
- }
90
-
91
- enhanced_prompt = f"{prompt}, {style_prompts.get(style, 'detailed artwork')}, high quality, masterpiece"
92
-
93
  try:
94
- # Make request to Hugging Face API
95
- headers = {"Content-Type": "application/json"}
96
- payload = {"inputs": enhanced_prompt}
 
 
97
 
98
- response = requests.post(API_URL, headers=headers, json=payload, timeout=30)
99
 
100
  if response.status_code == 200:
101
- # Convert response to image
102
  image = Image.open(io.BytesIO(response.content))
103
- return image, enhanced_prompt
104
  else:
105
- st.warning(f"Image generation failed: {response.status_code}")
106
- return None, enhanced_prompt
107
 
108
  except Exception as e:
109
- st.error(f"Error generating image: {str(e)}")
110
- return None, enhanced_prompt
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
111
 
112
- # Story templates (same as before)
113
  STORY_TEMPLATES = {
114
  "Fantasy": [
115
  "In the mystical realm of {setting}, {protagonist} discovered an ancient artifact that pulsed with magical energy. As whispers of forgotten spells filled the air, they realized their destiny was far greater than they ever imagined. Dragons soared overhead while mystical creatures watched from the shadows, all waiting to see if {protagonist} would embrace their newfound power or be consumed by it.",
@@ -163,17 +240,17 @@ def generate_story(genre, protagonist, setting):
163
  def create_image_prompt(protagonist, setting, genre, art_style):
164
  """Create optimized prompt for image generation"""
165
  prompts = {
166
- "Fantasy": f"{protagonist} in {setting}, magical atmosphere, fantasy character",
167
- "Sci-Fi": f"{protagonist} in {setting}, futuristic, sci-fi environment, technology",
168
- "Mystery": f"{protagonist} in {setting}, mysterious atmosphere, detective scene",
169
- "Romance": f"{protagonist} in {setting}, romantic atmosphere, beautiful lighting",
170
- "Adventure": f"{protagonist} in {setting}, action scene, adventure",
171
- "Horror": f"{setting}, dark atmosphere, horror scene, mysterious figure",
172
- "Comedy": f"{protagonist} in {setting}, lighthearted scene, cheerful"
173
  }
174
 
175
  base_prompt = prompts.get(genre, f"{protagonist} in {setting}")
176
- return base_prompt
177
 
178
  # Main app
179
  col1, col2 = st.columns([1, 1])
@@ -210,17 +287,21 @@ if st.button("✨ Generate Story & Art", type="primary"):
210
  with col2:
211
  st.markdown("### 🎨 AI Generated Artwork")
212
 
213
- # Generate image prompt
214
  image_prompt = create_image_prompt(protagonist, setting, genre, art_style)
215
- st.session_state.image_prompt = image_prompt
216
 
217
- with st.spinner("🎨 Generating AI artwork... (this may take 10-30 seconds)"):
218
- generated_image, full_prompt = generate_image(image_prompt, art_style)
 
 
 
 
 
 
219
  st.session_state.generated_image = generated_image
220
 
221
  if generated_image:
222
  st.markdown('<div class="image-container">', unsafe_allow_html=True)
223
- st.image(generated_image, caption=f"AI Generated: {protagonist} in {setting}", use_column_width=True)
224
  st.markdown('</div>', unsafe_allow_html=True)
225
 
226
  # Image download
@@ -238,11 +319,7 @@ if st.button("✨ Generate Story & Art", type="primary"):
238
  with st.expander("πŸ” Image Details"):
239
  st.markdown(f"**Prompt:** {image_prompt}")
240
  st.markdown(f"**Style:** {art_style}")
241
- st.markdown(f"**Full Prompt:** {full_prompt}")
242
- else:
243
- # Fallback if image generation fails
244
- st.error("🚫 Image generation temporarily unavailable. The Hugging Face API might be overloaded. Try again in a moment!")
245
- st.info("πŸ’‘ **Tip:** The free Hugging Face API can be slow or temporarily unavailable due to high demand.")
246
 
247
  # Show previous image if available
248
  elif st.session_state.generated_image:
@@ -260,50 +337,47 @@ with col3:
260
  st.rerun()
261
 
262
  with col4:
263
- if st.button("🎨 Regenerate Image") and st.session_state.image_prompt:
264
- with st.spinner("🎨 Creating new artwork..."):
265
- generated_image, _ = generate_image(st.session_state.image_prompt, art_style)
266
- if generated_image:
 
 
 
 
267
  st.session_state.generated_image = generated_image
268
- st.success("βœ… New artwork generated!")
269
  st.rerun()
270
 
271
  with col5:
272
  if st.button("🎲 Surprise Me!"):
273
- st.session_state.random_generate = True
274
  st.rerun()
275
 
276
  # Sidebar info
277
  st.sidebar.markdown("---")
278
  st.sidebar.markdown("### πŸš€ About StoryVision AI")
279
  st.sidebar.info("""
280
- 🎯 **What's New:**
281
- - βœ… REAL AI image generation!
282
- - βœ… Powered by Stable Diffusion
 
283
  - βœ… Download stories & images
284
- - βœ… Multiple art styles
285
 
286
  πŸ› οΈ **Tech Stack:**
287
  - Streamlit
288
- - Hugging Face API
289
- - Stable Diffusion
290
  - Python PIL
 
291
 
292
- ⚑ **Note:** Image generation uses free APIs and may be slower during peak times.
 
 
293
  """)
294
 
295
- # Usage stats
296
- st.sidebar.markdown("### πŸ“Š Live Stats")
297
- st.sidebar.metric("πŸ–ΌοΈ Images Generated", f"{random.randint(800, 1200):,}")
298
- st.sidebar.metric("πŸ“š Stories Created", f"{random.randint(1500, 2000):,}")
299
- st.sidebar.metric("πŸ‘₯ Active Users", f"{random.randint(50, 150)}")
300
-
301
  # Footer
302
  st.markdown("---")
303
  st.markdown("""
304
  <div style="text-align: center; color: #666; padding: 2rem;">
305
- <p>🌟 <strong>StoryVision AI</strong> - Now with REAL AI artwork generation!</p>
306
- <p>Made with ❀️ using Streamlit & Stable Diffusion | Perfect for πŸ€— Hugging Face Spaces</p>
307
- <p><small>⚑ Free tier API - Images may take 10-30 seconds to generate</small></p>
308
  </div>
309
  """, unsafe_allow_html=True)
 
2
  import time
3
  import random
4
  import requests
5
+ from PIL import Image, ImageDraw, ImageFont
6
  import io
7
+ import hashlib
8
 
9
  # Page config
10
  st.set_page_config(
 
41
  # Initialize session state
42
  if 'generated_image' not in st.session_state:
43
  st.session_state.generated_image = None
 
 
44
 
45
  # Header
46
  st.markdown('<h1 class="main-header">πŸ“š StoryVision AI</h1>', unsafe_allow_html=True)
47
+ st.markdown('<p style="text-align: center; font-size: 1.2rem; color: #666;">Create magical stories with AI-generated artwork!</p>', unsafe_allow_html=True)
48
 
49
  # Sidebar controls
50
  st.sidebar.markdown("## 🎨 Story Settings")
 
69
  ["Fantasy Art", "Digital Painting", "Watercolor", "Anime Style", "Photorealistic", "Concept Art"]
70
  )
71
 
72
+ # Working image generation using Pollinations AI (No API key needed!)
73
  @st.cache_data(show_spinner=False)
74
+ def generate_image_pollinations(prompt, width=512, height=512):
75
+ """Generate image using Pollinations.ai - completely free, no API key needed"""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76
  try:
77
+ # Clean and encode the prompt
78
+ clean_prompt = prompt.replace(" ", "%20").replace(",", "%2C")
79
+
80
+ # Pollinations.ai API endpoint
81
+ url = f"https://image.pollinations.ai/prompt/{clean_prompt}?width={width}&height={height}&seed={random.randint(1, 10000)}"
82
 
83
+ response = requests.get(url, timeout=30)
84
 
85
  if response.status_code == 200:
 
86
  image = Image.open(io.BytesIO(response.content))
87
+ return image, True
88
  else:
89
+ return None, False
 
90
 
91
  except Exception as e:
92
+ st.error(f"Error: {str(e)}")
93
+ return None, False
94
+
95
+ # Alternative: Generate artistic image using code (always works)
96
+ def generate_procedural_art(prompt, protagonist, setting, genre, style):
97
+ """Generate artistic image using Python - always works offline"""
98
+
99
+ # Create a 512x512 image
100
+ width, height = 512, 512
101
+ image = Image.new('RGB', (width, height))
102
+ draw = ImageDraw.Draw(image)
103
+
104
+ # Color schemes based on genre
105
+ color_schemes = {
106
+ "Fantasy": [(138, 43, 226), (75, 0, 130), (72, 61, 139), (147, 112, 219)],
107
+ "Sci-Fi": [(0, 191, 255), (30, 144, 255), (0, 100, 0), (50, 205, 50)],
108
+ "Mystery": [(25, 25, 112), (72, 61, 139), (105, 105, 105), (128, 128, 128)],
109
+ "Romance": [(255, 182, 193), (255, 105, 180), (219, 112, 147), (199, 21, 133)],
110
+ "Adventure": [(255, 140, 0), (255, 165, 0), (218, 165, 32), (184, 134, 11)],
111
+ "Horror": [(139, 0, 0), (128, 0, 0), (105, 105, 105), (47, 79, 79)],
112
+ "Comedy": [(255, 215, 0), (255, 165, 0), (255, 192, 203), (255, 20, 147)]
113
+ }
114
+
115
+ colors = color_schemes.get(genre, color_schemes["Fantasy"])
116
+
117
+ # Create gradient background
118
+ for y in range(height):
119
+ for x in range(width):
120
+ # Create complex gradient patterns
121
+ color_index = int((x + y + random.randint(-20, 20)) / 100) % len(colors)
122
+ base_color = colors[color_index]
123
+
124
+ # Add some variation
125
+ r = max(0, min(255, base_color[0] + random.randint(-30, 30)))
126
+ g = max(0, min(255, base_color[1] + random.randint(-30, 30)))
127
+ b = max(0, min(255, base_color[2] + random.randint(-30, 30)))
128
+
129
+ draw.point((x, y), (r, g, b))
130
+
131
+ # Add geometric patterns based on genre
132
+ if genre == "Fantasy":
133
+ # Draw magical circles
134
+ for _ in range(5):
135
+ x = random.randint(50, width-50)
136
+ y = random.randint(50, height-50)
137
+ radius = random.randint(20, 80)
138
+ draw.ellipse([x-radius, y-radius, x+radius, y+radius],
139
+ outline=(255, 215, 0), width=3)
140
+
141
+ elif genre == "Sci-Fi":
142
+ # Draw tech patterns
143
+ for _ in range(10):
144
+ x1 = random.randint(0, width)
145
+ y1 = random.randint(0, height)
146
+ x2 = random.randint(0, width)
147
+ y2 = random.randint(0, height)
148
+ draw.line([x1, y1, x2, y2], fill=(0, 255, 255), width=2)
149
+
150
+ # Add title text
151
+ try:
152
+ font_size = 24
153
+ # Try to use a better font, fall back to default
154
+ try:
155
+ font = ImageFont.truetype("arial.ttf", font_size)
156
+ except:
157
+ font = ImageFont.load_default()
158
+
159
+ # Add protagonist name
160
+ text_bbox = draw.textbbox((0, 0), protagonist, font=font)
161
+ text_width = text_bbox[2] - text_bbox[0]
162
+ text_x = (width - text_width) // 2
163
+ text_y = height - 60
164
+
165
+ # Add text with outline
166
+ for dx in [-1, 0, 1]:
167
+ for dy in [-1, 0, 1]:
168
+ if dx != 0 or dy != 0:
169
+ draw.text((text_x + dx, text_y + dy), protagonist, font=font, fill=(0, 0, 0))
170
+ draw.text((text_x, text_y), protagonist, font=font, fill=(255, 255, 255))
171
+
172
+ # Add setting
173
+ setting_bbox = draw.textbbox((0, 0), setting, font=font)
174
+ setting_width = setting_bbox[2] - setting_bbox[0]
175
+ setting_x = (width - setting_width) // 2
176
+ setting_y = 30
177
+
178
+ for dx in [-1, 0, 1]:
179
+ for dy in [-1, 0, 1]:
180
+ if dx != 0 or dy != 0:
181
+ draw.text((setting_x + dx, setting_y + dy), setting, font=font, fill=(0, 0, 0))
182
+ draw.text((setting_x, setting_y), setting, font=font, fill=(255, 255, 255))
183
+
184
+ except:
185
+ pass # Skip text if font issues
186
+
187
+ return image
188
 
189
+ # Story templates (keeping the same as before)
190
  STORY_TEMPLATES = {
191
  "Fantasy": [
192
  "In the mystical realm of {setting}, {protagonist} discovered an ancient artifact that pulsed with magical energy. As whispers of forgotten spells filled the air, they realized their destiny was far greater than they ever imagined. Dragons soared overhead while mystical creatures watched from the shadows, all waiting to see if {protagonist} would embrace their newfound power or be consumed by it.",
 
240
  def create_image_prompt(protagonist, setting, genre, art_style):
241
  """Create optimized prompt for image generation"""
242
  prompts = {
243
+ "Fantasy": f"fantasy art of {protagonist} in {setting}, magical, ethereal, detailed artwork",
244
+ "Sci-Fi": f"sci-fi art of {protagonist} in {setting}, futuristic, technology, space art",
245
+ "Mystery": f"mysterious scene with {protagonist} in {setting}, noir style, detective",
246
+ "Romance": f"romantic art of {protagonist} in {setting}, beautiful, soft lighting",
247
+ "Adventure": f"adventure art of {protagonist} in {setting}, action, dynamic scene",
248
+ "Horror": f"dark art of {setting}, horror atmosphere, mysterious figure, gothic",
249
+ "Comedy": f"cheerful art of {protagonist} in {setting}, bright colors, happy scene"
250
  }
251
 
252
  base_prompt = prompts.get(genre, f"{protagonist} in {setting}")
253
+ return f"{base_prompt}, {art_style.lower()}, high quality, detailed"
254
 
255
  # Main app
256
  col1, col2 = st.columns([1, 1])
 
287
  with col2:
288
  st.markdown("### 🎨 AI Generated Artwork")
289
 
 
290
  image_prompt = create_image_prompt(protagonist, setting, genre, art_style)
 
291
 
292
+ with st.spinner("οΏ½οΏ½οΏ½οΏ½ Generating AI artwork..."):
293
+ # Try Pollinations AI first (free, no API key)
294
+ generated_image, success = generate_image_pollinations(image_prompt)
295
+
296
+ if not success or generated_image is None:
297
+ st.info("🎨 Using procedural art generation...")
298
+ generated_image = generate_procedural_art(image_prompt, protagonist, setting, genre, art_style)
299
+
300
  st.session_state.generated_image = generated_image
301
 
302
  if generated_image:
303
  st.markdown('<div class="image-container">', unsafe_allow_html=True)
304
+ st.image(generated_image, caption=f"Generated: {protagonist} in {setting}", use_column_width=True)
305
  st.markdown('</div>', unsafe_allow_html=True)
306
 
307
  # Image download
 
319
  with st.expander("πŸ” Image Details"):
320
  st.markdown(f"**Prompt:** {image_prompt}")
321
  st.markdown(f"**Style:** {art_style}")
322
+ st.markdown(f"**Method:** {'Pollinations AI' if success else 'Procedural Art'}")
 
 
 
 
323
 
324
  # Show previous image if available
325
  elif st.session_state.generated_image:
 
337
  st.rerun()
338
 
339
  with col4:
340
+ if st.button("🎨 New Artwork"):
341
+ if 'generated_image' in st.session_state:
342
+ # Regenerate with different seed
343
+ image_prompt = create_image_prompt(protagonist, setting, genre, art_style)
344
+ with st.spinner("🎨 Creating new artwork..."):
345
+ generated_image, success = generate_image_pollinations(image_prompt)
346
+ if not success:
347
+ generated_image = generate_procedural_art(image_prompt, protagonist, setting, genre, art_style)
348
  st.session_state.generated_image = generated_image
 
349
  st.rerun()
350
 
351
  with col5:
352
  if st.button("🎲 Surprise Me!"):
 
353
  st.rerun()
354
 
355
  # Sidebar info
356
  st.sidebar.markdown("---")
357
  st.sidebar.markdown("### πŸš€ About StoryVision AI")
358
  st.sidebar.info("""
359
+ 🎯 **Features:**
360
+ - βœ… Real AI image generation
361
+ - βœ… No API keys required
362
+ - βœ… Always works offline backup
363
  - βœ… Download stories & images
 
364
 
365
  πŸ› οΈ **Tech Stack:**
366
  - Streamlit
367
+ - Pollinations.ai (free)
 
368
  - Python PIL
369
+ - Procedural art generation
370
 
371
+ 🎨 **Art Methods:**
372
+ 1. Pollinations AI (primary)
373
+ 2. Procedural art (backup)
374
  """)
375
 
 
 
 
 
 
 
376
  # Footer
377
  st.markdown("---")
378
  st.markdown("""
379
  <div style="text-align: center; color: #666; padding: 2rem;">
380
+ <p>🌟 <strong>StoryVision AI</strong> - Reliable AI artwork generation!</p>
381
+ <p>Made with ❀️ | Always works, no API keys needed</p>
 
382
  </div>
383
  """, unsafe_allow_html=True)