Dalladrain commited on
Commit
d2cad3c
·
verified ·
1 Parent(s): 7f4b241

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +43 -64
app.py CHANGED
@@ -11,89 +11,79 @@ import torch
11
  # =====================================================
12
  pipe = StableDiffusionPipeline.from_pretrained(
13
  "stabilityai/stable-diffusion-2-1-base",
14
- torch_dtype=torch.float16 # use fp16 for GPU
15
  ).to("cuda") # change to "cpu" if GPU not available
16
 
17
  # =====================================================
18
  # Comic Styles & Descriptions
19
  # =====================================================
20
  comic_styles = {
21
- "Superhero comics": "The archetypal American comic style, defined by bold, detailed, and dynamic figures, and vibrant colors. Emphasizes action, drama, and idealism.",
22
- "Alternative comics": "Independent comics outside the mainstream superhero genre. Artwork can range from realistic to highly abstract.",
23
- "Noir": "Uses strong contrasts of light and shadow (chiaroscuro), deep blacks, and gritty details to create a dark and moody atmosphere.",
24
- "Cartooning/Toon style": "Simplified, exaggerated, often caricatured characters. Examples: Betty Boop, modern webcomics.",
25
- "Retro comics/Silver Age": "Homage to comics from the 1950s-1970s. Simpler, energetic designs, vibrant colors.",
26
- "Webcomics": "A medium rather than a style, ranging from simple hand-drawn to polished professional sequential art.",
27
- # Japanese manga
28
- "Shōnen": "For young male audience. Bold lines, dynamic action. Examples: Dragon Ball, Naruto.",
29
- "Shōjo": "For young female readers. Fluid lines, highly detailed eyes, soft and decorative aesthetic.",
30
- "Seinen": "For adult male readers (18–40). More realistic/gritty art, mature themes.",
31
- "Chibi": "Super-deformed, exaggeratedly cute characters with tiny bodies and large heads.",
32
- "Moe": "Cute and innocent-looking characters, appealing to dedicated fanbase.",
33
- "Kodomo": "For young children. Simple, rounded shapes and bright, cheerful artwork.",
34
- # Techniques / hybrid styles
35
- "Line art": "Emphasizes strong, distinct lines without extensive shading or coloring.",
36
- "Slice of life": "Depicts everyday events, can be cartoonish or realistic, focuses on relatability.",
37
  "Celtic art style": "Decorative, stylized, with intricate knotwork and patterns.",
38
- "Ink wash": "Uses diluted ink for varying shades, soft, textured, or painted feel.",
39
- "Pointillism": "Small, distinct dots of color form images, creating interesting textures.",
40
- "Watercolor painting style": "Soft, painterly look with translucent watercolors and delicate gradients.",
41
- "Photorealism": "Attempts photographic accuracy in figures and scenes.",
42
- "Grotesque": "Intentionally distorted/exaggerated to emphasize weird, unsettling, or macabre elements."
43
  }
44
 
45
  # =====================================================
46
  # Comic Generation Functions
47
  # =====================================================
48
- def detect_characters(img: Image.Image):
49
- """Fallback character positions."""
50
- width, height = img.size
51
- return [(width // 4, height // 4), (3 * width // 4, height // 4)]
52
-
53
  def add_speech_bubbles(img: Image.Image, dialogues):
54
- """Draw speech bubbles at placeholder positions."""
55
  draw = ImageDraw.Draw(img)
56
  try:
57
  font = ImageFont.truetype("ComicNeue-Bold.ttf", 20)
58
  except:
59
  font = ImageFont.load_default()
60
-
61
- positions = detect_characters(img)
62
- for i, text in enumerate(dialogues[:len(positions)]):
63
- x, y = positions[i]
64
- bubble_w, bubble_h = 160, 70
65
- rect = [x - bubble_w // 2, y - bubble_h // 2, x + bubble_w // 2, y + bubble_h // 2]
66
  draw.rectangle(rect, fill="white", outline="black", width=3)
67
- draw.text((x - bubble_w // 2 + 10, y - bubble_h // 2 + 10), text, font=font, fill="black")
 
68
  return img
69
 
70
  def generate_panel(prompt):
71
- """Generate a single panel with Stable Diffusion."""
72
- image = pipe(prompt).images[0]
73
- return image
74
 
75
  def generate_comic(title, story, pages, panels, style, dialogues, explicit):
76
- """Generate multi-panel comics."""
77
- generated_images = []
78
  dialogues_list = [d.strip() for d in dialogues.splitlines() if d.strip()]
 
79
 
80
- for p in range(int(pages)):
81
- for n in range(int(panels)):
82
  prompt = f"{style} comic panel ({comic_styles[style]}), theme: {story}"
83
  if explicit:
84
- prompt += " with mature themes, blood and gore, offensive language"
85
  else:
86
  prompt += " safe for all ages"
87
 
88
- panel_img = generate_panel(prompt)
89
 
90
- # Add dialogues if provided
91
  if dialogues_list:
92
- panel_img = add_speech_bubbles(panel_img, dialogues_list)
93
 
94
- generated_images.append(panel_img)
95
 
96
- # Pack into ZIP
97
  buffer = BytesIO()
98
  with zipfile.ZipFile(buffer, "w") as zf:
99
  for i, img in enumerate(generated_images):
@@ -108,10 +98,8 @@ def generate_comic(title, story, pages, panels, style, dialogues, explicit):
108
  # Gradio UI
109
  # =====================================================
110
  with gr.Blocks(theme=gr.themes.Soft()) as demo:
111
- gr.Markdown(
112
- "<h1 style='text-align: center;'>🦸‍♂️ AI Comic Crafter</h1>"
113
- "<p style='text-align: center;'>Generate multi-page, multi-panel comics with AI! 🎨</p>"
114
- )
115
 
116
  with gr.Row():
117
  with gr.Column(scale=1):
@@ -119,8 +107,7 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
119
  story = gr.Textbox(label="Story Setup", placeholder="Describe characters, setting, and plot...")
120
  pages = gr.Slider(1, 5, value=2, step=1, label="Number of Pages")
121
  panels = gr.Slider(1, 6, value=3, step=1, label="Panels Per Page")
122
-
123
- # Style dropdown and description
124
  style_dropdown = gr.Dropdown(
125
  choices=list(comic_styles.keys()),
126
  label="Art Style / Theme",
@@ -138,20 +125,12 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
138
  outputs=style_description
139
  )
140
 
141
- dialogues = gr.Textbox(
142
- label="Custom Dialogues (Optional)",
143
- placeholder="One dialogue per line...",
144
- lines=5
145
- )
146
  explicit = gr.Checkbox(label="Allow Explicit Content (blood/gore, offensive language)", value=False)
147
  generate_btn = gr.Button("⚡ Generate Comic")
148
 
149
  with gr.Column(scale=1):
150
- output_gallery = gr.Gallery(
151
- label="Your Comic Preview",
152
- columns=2,
153
- height="auto"
154
- )
155
  download_file = gr.File(label="Download Complete Comic (.zip)", type="binary")
156
 
157
  generate_btn.click(
 
11
  # =====================================================
12
  pipe = StableDiffusionPipeline.from_pretrained(
13
  "stabilityai/stable-diffusion-2-1-base",
14
+ torch_dtype=torch.float16 # FP16 for GPU
15
  ).to("cuda") # change to "cpu" if GPU not available
16
 
17
  # =====================================================
18
  # Comic Styles & Descriptions
19
  # =====================================================
20
  comic_styles = {
21
+ "Superhero comics": "Bold, dynamic figures and vibrant colors. Emphasizes action, drama, and idealism.",
22
+ "Alternative comics": "Independent comics outside the mainstream genre, from realistic to abstract.",
23
+ "Noir": "High contrast light and shadow, deep blacks, gritty and moody atmosphere.",
24
+ "Cartooning/Toon style": "Simplified, exaggerated, caricatured characters, e.g., Betty Boop.",
25
+ "Retro comics/Silver Age": "1950s1970s style, simpler energetic designs and vibrant colors.",
26
+ "Webcomics": "Digital medium ranging from simple hand-drawn to polished sequential art.",
27
+ "Shōnen": "For young male audience. Bold lines, dynamic action. Examples: Dragon Ball.",
28
+ "Shōjo": "For young female readers. Fluid lines, detailed eyes, decorative aesthetic.",
29
+ "Seinen": "For adult male readers. More realistic/gritty art, mature themes.",
30
+ "Chibi": "Super-deformed cute characters with tiny bodies and oversized heads.",
31
+ "Moe": "Cute, innocent-looking characters, appealing to fans.",
32
+ "Kodomo": "For young children. Simple, rounded shapes, bright artwork.",
33
+ "Line art": "Strong, distinct lines without extensive shading or coloring.",
34
+ "Slice of life": "Depicts everyday events, cartoonish or realistic, relatable.",
 
 
35
  "Celtic art style": "Decorative, stylized, with intricate knotwork and patterns.",
36
+ "Ink wash": "Diluted ink for soft, textured, or painted feel.",
37
+ "Pointillism": "Small dots of color form images, creating textures.",
38
+ "Watercolor painting style": "Soft, painterly look with translucent gradients.",
39
+ "Photorealism": "Attempts photographic accuracy.",
40
+ "Grotesque": "Distorted/exaggerated for weird, unsettling, or macabre effect."
41
  }
42
 
43
  # =====================================================
44
  # Comic Generation Functions
45
  # =====================================================
 
 
 
 
 
46
  def add_speech_bubbles(img: Image.Image, dialogues):
47
+ """Add simple speech bubbles at top-left positions."""
48
  draw = ImageDraw.Draw(img)
49
  try:
50
  font = ImageFont.truetype("ComicNeue-Bold.ttf", 20)
51
  except:
52
  font = ImageFont.load_default()
53
+ x, y = 20, 20
54
+ for text in dialogues:
55
+ bubble_w, bubble_h = 200, 60
56
+ rect = [x, y, x + bubble_w, y + bubble_h]
 
 
57
  draw.rectangle(rect, fill="white", outline="black", width=3)
58
+ draw.text((x + 10, y + 10), text, font=font, fill="black")
59
+ y += bubble_h + 10
60
  return img
61
 
62
  def generate_panel(prompt):
63
+ """Generate a single panel using Stable Diffusion."""
64
+ return pipe(prompt).images[0]
 
65
 
66
  def generate_comic(title, story, pages, panels, style, dialogues, explicit):
67
+ """Generate multi-panel comics and return images + ZIP."""
 
68
  dialogues_list = [d.strip() for d in dialogues.splitlines() if d.strip()]
69
+ generated_images = []
70
 
71
+ for _ in range(int(pages)):
72
+ for _ in range(int(panels)):
73
  prompt = f"{style} comic panel ({comic_styles[style]}), theme: {story}"
74
  if explicit:
75
+ prompt += " with mature themes, blood and offensive language"
76
  else:
77
  prompt += " safe for all ages"
78
 
79
+ img = generate_panel(prompt)
80
 
 
81
  if dialogues_list:
82
+ img = add_speech_bubbles(img, dialogues_list)
83
 
84
+ generated_images.append(img)
85
 
86
+ # Save images to ZIP
87
  buffer = BytesIO()
88
  with zipfile.ZipFile(buffer, "w") as zf:
89
  for i, img in enumerate(generated_images):
 
98
  # Gradio UI
99
  # =====================================================
100
  with gr.Blocks(theme=gr.themes.Soft()) as demo:
101
+ gr.Markdown("<h1 style='text-align:center'>🦸‍♂️ AI Comic Crafter</h1>"
102
+ "<p style='text-align:center'>Generate multi-page, multi-panel comics with AI! 🎨</p>")
 
 
103
 
104
  with gr.Row():
105
  with gr.Column(scale=1):
 
107
  story = gr.Textbox(label="Story Setup", placeholder="Describe characters, setting, and plot...")
108
  pages = gr.Slider(1, 5, value=2, step=1, label="Number of Pages")
109
  panels = gr.Slider(1, 6, value=3, step=1, label="Panels Per Page")
110
+
 
111
  style_dropdown = gr.Dropdown(
112
  choices=list(comic_styles.keys()),
113
  label="Art Style / Theme",
 
125
  outputs=style_description
126
  )
127
 
128
+ dialogues = gr.Textbox(label="Custom Dialogues (Optional)", placeholder="One dialogue per line...", lines=5)
 
 
 
 
129
  explicit = gr.Checkbox(label="Allow Explicit Content (blood/gore, offensive language)", value=False)
130
  generate_btn = gr.Button("⚡ Generate Comic")
131
 
132
  with gr.Column(scale=1):
133
+ output_gallery = gr.Gallery(label="Your Comic Preview", columns=2, height="auto")
 
 
 
 
134
  download_file = gr.File(label="Download Complete Comic (.zip)", type="binary")
135
 
136
  generate_btn.click(