Update app.py from anycoder
Browse files
app.py
CHANGED
|
@@ -1,10 +1,24 @@
|
|
| 1 |
import gradio as gr
|
| 2 |
import numpy as np
|
| 3 |
-
from PIL import Image
|
| 4 |
import io
|
| 5 |
import time
|
| 6 |
import random
|
|
|
|
| 7 |
from typing import List, Dict, Any
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 8 |
|
| 9 |
# Configuration
|
| 10 |
CONFIG = {
|
|
@@ -21,6 +35,7 @@ class ImageSequenceGenerator:
|
|
| 21 |
self.playback_interval: Any = None
|
| 22 |
self.is_generating: bool = False
|
| 23 |
|
|
|
|
| 24 |
def generate_random_image(self, prompt: str) -> str:
|
| 25 |
"""Generate a random colorful image with the prompt text"""
|
| 26 |
width, height = CONFIG["image_size"]
|
|
@@ -107,23 +122,27 @@ class ImageSequenceGenerator:
|
|
| 107 |
img_str = f"data:image/png;base64,{base64.b64encode(buffered.getvalue()).decode()}"
|
| 108 |
return img_str
|
| 109 |
|
|
|
|
| 110 |
def add_image_to_buffer(self, image_data: str):
|
| 111 |
"""Add image to buffer"""
|
| 112 |
self.images.append(image_data)
|
| 113 |
return self.get_state()
|
| 114 |
|
|
|
|
| 115 |
def remove_image_from_buffer(self, index: int):
|
| 116 |
"""Remove image from buffer"""
|
| 117 |
if 0 <= index < len(self.images):
|
| 118 |
self.images.pop(index)
|
| 119 |
return self.get_state()
|
| 120 |
|
|
|
|
| 121 |
def clear_buffer(self):
|
| 122 |
"""Clear the entire buffer"""
|
| 123 |
self.images = []
|
| 124 |
self.stop_sequence()
|
| 125 |
return self.get_state()
|
| 126 |
|
|
|
|
| 127 |
def play_sequence(self):
|
| 128 |
"""Start playing the sequence"""
|
| 129 |
if self.is_playing or len(self.images) < CONFIG["required_images"]:
|
|
@@ -133,6 +152,7 @@ class ImageSequenceGenerator:
|
|
| 133 |
self.current_frame = 0
|
| 134 |
return self.get_state()
|
| 135 |
|
|
|
|
| 136 |
def stop_sequence(self):
|
| 137 |
"""Stop playing the sequence"""
|
| 138 |
if not self.is_playing:
|
|
@@ -142,6 +162,7 @@ class ImageSequenceGenerator:
|
|
| 142 |
self.current_frame = 0
|
| 143 |
return self.get_state()
|
| 144 |
|
|
|
|
| 145 |
def get_current_frame(self):
|
| 146 |
"""Get the current frame for display"""
|
| 147 |
if not self.is_playing or not self.images:
|
|
@@ -151,6 +172,7 @@ class ImageSequenceGenerator:
|
|
| 151 |
self.current_frame = (self.current_frame + 1) % len(self.images)
|
| 152 |
return frame_data
|
| 153 |
|
|
|
|
| 154 |
def get_state(self) -> Dict[str, Any]:
|
| 155 |
"""Get current state for UI updates"""
|
| 156 |
return {
|
|
@@ -161,6 +183,7 @@ class ImageSequenceGenerator:
|
|
| 161 |
"images": self.images
|
| 162 |
}
|
| 163 |
|
|
|
|
| 164 |
def generate_image(self, prompt: str, negative_prompt: str, steps: int, guidance_scale: float, seed: int, batch_size: int):
|
| 165 |
"""Generate a new image"""
|
| 166 |
if self.is_generating:
|
|
@@ -335,7 +358,7 @@ def create_gradio_app():
|
|
| 335 |
}
|
| 336 |
"""
|
| 337 |
|
| 338 |
-
with gr.Blocks(
|
| 339 |
gr.Markdown("""
|
| 340 |
<div style="text-align: center; margin-bottom: 2rem;">
|
| 341 |
<h1 style="color: #6c5ce7; font-size: 2.5rem; margin-bottom: 0.5rem;">
|
|
@@ -540,16 +563,12 @@ def create_gradio_app():
|
|
| 540 |
# Timer for playback
|
| 541 |
timer = gr.Timer(1.0 / CONFIG["playback_fps"])
|
| 542 |
|
|
|
|
| 543 |
def update_player_display():
|
| 544 |
if generator.is_playing and generator.images:
|
| 545 |
frame_data = generator.get_current_frame()
|
| 546 |
if frame_data:
|
| 547 |
# Convert base64 to PIL Image
|
| 548 |
-
from PIL import Image
|
| 549 |
-
import io
|
| 550 |
-
import base64
|
| 551 |
-
|
| 552 |
-
# Extract base64 data
|
| 553 |
header, encoded = frame_data.split(",", 1)
|
| 554 |
binary_data = base64.b64decode(encoded)
|
| 555 |
image = Image.open(io.BytesIO(binary_data))
|
|
|
|
| 1 |
import gradio as gr
|
| 2 |
import numpy as np
|
| 3 |
+
from PIL import Image, ImageDraw, ImageFont
|
| 4 |
import io
|
| 5 |
import time
|
| 6 |
import random
|
| 7 |
+
import base64
|
| 8 |
from typing import List, Dict, Any
|
| 9 |
+
from functools import wraps
|
| 10 |
+
|
| 11 |
+
# ZeroGPU decorator
|
| 12 |
+
def zero_gpu(func):
|
| 13 |
+
"""
|
| 14 |
+
Decorator to indicate that this function can run on CPU-only environments.
|
| 15 |
+
This is useful for deployment on platforms without GPU access.
|
| 16 |
+
"""
|
| 17 |
+
@wraps(func)
|
| 18 |
+
def wrapper(*args, **kwargs):
|
| 19 |
+
return func(*args, **kwargs)
|
| 20 |
+
wrapper.zero_gpu = True
|
| 21 |
+
return wrapper
|
| 22 |
|
| 23 |
# Configuration
|
| 24 |
CONFIG = {
|
|
|
|
| 35 |
self.playback_interval: Any = None
|
| 36 |
self.is_generating: bool = False
|
| 37 |
|
| 38 |
+
@zero_gpu
|
| 39 |
def generate_random_image(self, prompt: str) -> str:
|
| 40 |
"""Generate a random colorful image with the prompt text"""
|
| 41 |
width, height = CONFIG["image_size"]
|
|
|
|
| 122 |
img_str = f"data:image/png;base64,{base64.b64encode(buffered.getvalue()).decode()}"
|
| 123 |
return img_str
|
| 124 |
|
| 125 |
+
@zero_gpu
|
| 126 |
def add_image_to_buffer(self, image_data: str):
|
| 127 |
"""Add image to buffer"""
|
| 128 |
self.images.append(image_data)
|
| 129 |
return self.get_state()
|
| 130 |
|
| 131 |
+
@zero_gpu
|
| 132 |
def remove_image_from_buffer(self, index: int):
|
| 133 |
"""Remove image from buffer"""
|
| 134 |
if 0 <= index < len(self.images):
|
| 135 |
self.images.pop(index)
|
| 136 |
return self.get_state()
|
| 137 |
|
| 138 |
+
@zero_gpu
|
| 139 |
def clear_buffer(self):
|
| 140 |
"""Clear the entire buffer"""
|
| 141 |
self.images = []
|
| 142 |
self.stop_sequence()
|
| 143 |
return self.get_state()
|
| 144 |
|
| 145 |
+
@zero_gpu
|
| 146 |
def play_sequence(self):
|
| 147 |
"""Start playing the sequence"""
|
| 148 |
if self.is_playing or len(self.images) < CONFIG["required_images"]:
|
|
|
|
| 152 |
self.current_frame = 0
|
| 153 |
return self.get_state()
|
| 154 |
|
| 155 |
+
@zero_gpu
|
| 156 |
def stop_sequence(self):
|
| 157 |
"""Stop playing the sequence"""
|
| 158 |
if not self.is_playing:
|
|
|
|
| 162 |
self.current_frame = 0
|
| 163 |
return self.get_state()
|
| 164 |
|
| 165 |
+
@zero_gpu
|
| 166 |
def get_current_frame(self):
|
| 167 |
"""Get the current frame for display"""
|
| 168 |
if not self.is_playing or not self.images:
|
|
|
|
| 172 |
self.current_frame = (self.current_frame + 1) % len(self.images)
|
| 173 |
return frame_data
|
| 174 |
|
| 175 |
+
@zero_gpu
|
| 176 |
def get_state(self) -> Dict[str, Any]:
|
| 177 |
"""Get current state for UI updates"""
|
| 178 |
return {
|
|
|
|
| 183 |
"images": self.images
|
| 184 |
}
|
| 185 |
|
| 186 |
+
@zero_gpu
|
| 187 |
def generate_image(self, prompt: str, negative_prompt: str, steps: int, guidance_scale: float, seed: int, batch_size: int):
|
| 188 |
"""Generate a new image"""
|
| 189 |
if self.is_generating:
|
|
|
|
| 358 |
}
|
| 359 |
"""
|
| 360 |
|
| 361 |
+
with gr.Blocks() as demo:
|
| 362 |
gr.Markdown("""
|
| 363 |
<div style="text-align: center; margin-bottom: 2rem;">
|
| 364 |
<h1 style="color: #6c5ce7; font-size: 2.5rem; margin-bottom: 0.5rem;">
|
|
|
|
| 563 |
# Timer for playback
|
| 564 |
timer = gr.Timer(1.0 / CONFIG["playback_fps"])
|
| 565 |
|
| 566 |
+
@zero_gpu
|
| 567 |
def update_player_display():
|
| 568 |
if generator.is_playing and generator.images:
|
| 569 |
frame_data = generator.get_current_frame()
|
| 570 |
if frame_data:
|
| 571 |
# Convert base64 to PIL Image
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 572 |
header, encoded = frame_data.split(",", 1)
|
| 573 |
binary_data = base64.b64decode(encoded)
|
| 574 |
image = Image.open(io.BytesIO(binary_data))
|