rickveloper commited on
Commit
032d725
·
verified ·
1 Parent(s): 93ad549

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +22 -45
app.py CHANGED
@@ -24,7 +24,6 @@ def draw_text_block(draw, text, img_w, y, font, fill, stroke_fill, stroke_width,
24
  bbox = draw.textbbox((0, 0), line, font=font, stroke_width=stroke_width)
25
  line_heights.append(bbox[3] - bbox[1])
26
 
27
- total_h = sum(line_heights) + (len(lines) - 1) * int(font.size * 0.25)
28
  curr_y = y
29
  for i, line in enumerate(lines):
30
  w = draw.textlength(line, font=font, stroke_width=stroke_width)
@@ -37,7 +36,7 @@ def draw_text_block(draw, text, img_w, y, font, fill, stroke_fill, stroke_width,
37
  draw.text((x, curr_y), line, font=font, fill=fill,
38
  stroke_width=stroke_width, stroke_fill=stroke_fill)
39
  curr_y += line_heights[i] + int(font.size * 0.25)
40
- return curr_y, total_h
41
 
42
  def make_meme(
43
  image, top_text, bottom_text,
@@ -62,24 +61,19 @@ def make_meme(
62
  fill=text_color, stroke_fill=outline_color, stroke_width=stroke, align=align
63
  )
64
 
65
- # Measure bottom block
66
- tmp = Image.new("RGBA", img.size, (0, 0, 0, 0))
67
- mdraw = ImageDraw.Draw(tmp)
68
- lines = []
69
- max_chars = max(12, min(30, w // 30))
70
- for paragraph in (bottom_text or "").split("\n"):
71
- wrapped = textwrap.wrap(paragraph, width=max_chars)
72
- lines.extend(wrapped if wrapped else [""])
73
- line_heights = [mdraw.textbbox((0, 0), line, font=font, stroke_width=stroke)[3] for line in lines]
74
  total_bottom_h = sum(line_heights) + (len(lines) - 1) * int(font.size * 0.25)
75
-
76
  bottom_y_start = int(h - total_bottom_h - h * 0.03) - int(bottom_nudge)
 
77
  draw_text_block(
78
  draw=draw, text=(bottom_text or "").strip(), img_w=w, y=bottom_y_start, font=font,
79
  fill=text_color, stroke_fill=outline_color, stroke_width=stroke, align=align
80
  )
81
  return img
82
 
 
83
  THEME = gr.themes.Soft(
84
  primary_hue="indigo",
85
  secondary_hue="violet",
@@ -88,7 +82,6 @@ THEME = gr.themes.Soft(
88
  button_border_width="0px",
89
  button_large_padding="14px",
90
  button_large_radius="14px",
91
- radius_md="14px",
92
  body_background_fill_dark="linear-gradient(180deg, #0b0f17 0%, #0a0920 100%)",
93
  block_shadow="none",
94
  )
@@ -98,49 +91,33 @@ CUSTOM_CSS = """
98
  * { -webkit-tap-highlight-color: transparent; }
99
  .gradio-container { padding: 10px; max-width: 820px; margin: 0 auto; }
100
  h2, p { text-align:center }
101
- #stickybar { position: sticky; bottom: 0; z-index: 50; backdrop-filter: blur(8px); }
102
- #stickybar .gr-button { width: 100%; font-weight: 700; }
103
- @media (max-width: 640px){
104
- .gradio-container { padding: 8px; }
105
- .compact .gr-form{ gap:8px }
106
- }
107
  """
108
 
109
- with gr.Blocks(theme=THEME, css=CUSTOM_CSS, fill_height=True, analytics_enabled=False) as demo:
110
  gr.Markdown("<h2>📱 Mobile Meme Maker</h2><p>Upload → Type → Download. Built on iPhone, for iPhone.</p>")
111
 
112
- with gr.Row(equal_height=False, elem_classes="compact"):
113
- with gr.Column(scale=1):
114
  in_img = gr.Image(type="pil", label="Upload photo", height=320)
115
-
116
- with gr.Accordion("Text & Style", open=True):
117
- top_text = gr.Textbox(label="Top text", value="WHEN THE WIFI JUST WORKS", autofocus=True)
118
- bottom_text = gr.Textbox(label="Bottom text", value="CHEF'S KISS")
119
- align = gr.Radio(choices=["left", "center", "right"], value="center", label="Alignment", inline=True)
120
- font_size = gr.Slider(8, 22, value=12, step=1, label="Font size (% of width)")
121
- stroke_width = gr.Slider(0, 14, value=4, step=1, label="Outline thickness")
122
- with gr.Row():
123
- text_color = gr.ColorPicker(value="#FFFFFF", label="Text")
124
- outline_color = gr.ColorPicker(value="#000000", label="Outline")
125
-
126
- with gr.Accordion("Position Nudges", open=False):
127
- top_nudge = gr.Slider(-300, 300, value=0, step=1, label="Top text nudge (px)")
128
- bottom_nudge = gr.Slider(-300, 300, value=0, step=1, label="Bottom text nudge (px)")
129
-
130
- with gr.Column(scale=1):
131
  out = gr.Image(type="pil", label="Preview / Download", height=440, show_download_button=True)
132
  generate = gr.Button("✨ Generate", size="lg")
133
- gr.Markdown(
134
- "<div id='stickybar'>"
135
- "<div class='container' style='display:flex; gap:10px; margin-top:8px;'>"
136
- "</div></div>"
137
- )
138
 
139
- # Generate action
140
  inputs = [in_img, top_text, bottom_text, font_size, stroke_width, text_color, outline_color, align, top_nudge, bottom_nudge]
141
  generate.click(fn=make_meme, inputs=inputs, outputs=out)
142
 
143
- # Live preview as you change things
144
  for comp in inputs:
145
  comp.change(fn=make_meme, inputs=inputs, outputs=out, show_progress=False)
146
 
 
24
  bbox = draw.textbbox((0, 0), line, font=font, stroke_width=stroke_width)
25
  line_heights.append(bbox[3] - bbox[1])
26
 
 
27
  curr_y = y
28
  for i, line in enumerate(lines):
29
  w = draw.textlength(line, font=font, stroke_width=stroke_width)
 
36
  draw.text((x, curr_y), line, font=font, fill=fill,
37
  stroke_width=stroke_width, stroke_fill=stroke_fill)
38
  curr_y += line_heights[i] + int(font.size * 0.25)
39
+ return curr_y
40
 
41
  def make_meme(
42
  image, top_text, bottom_text,
 
61
  fill=text_color, stroke_fill=outline_color, stroke_width=stroke, align=align
62
  )
63
 
64
+ # Bottom
65
+ lines = textwrap.wrap(bottom_text or "", width=max(20, w // 30))
66
+ line_heights = [draw.textbbox((0,0), l, font=font, stroke_width=stroke)[3] for l in lines]
 
 
 
 
 
 
67
  total_bottom_h = sum(line_heights) + (len(lines) - 1) * int(font.size * 0.25)
 
68
  bottom_y_start = int(h - total_bottom_h - h * 0.03) - int(bottom_nudge)
69
+
70
  draw_text_block(
71
  draw=draw, text=(bottom_text or "").strip(), img_w=w, y=bottom_y_start, font=font,
72
  fill=text_color, stroke_fill=outline_color, stroke_width=stroke, align=align
73
  )
74
  return img
75
 
76
+ # Theme (compatible version)
77
  THEME = gr.themes.Soft(
78
  primary_hue="indigo",
79
  secondary_hue="violet",
 
82
  button_border_width="0px",
83
  button_large_padding="14px",
84
  button_large_radius="14px",
 
85
  body_background_fill_dark="linear-gradient(180deg, #0b0f17 0%, #0a0920 100%)",
86
  block_shadow="none",
87
  )
 
91
  * { -webkit-tap-highlight-color: transparent; }
92
  .gradio-container { padding: 10px; max-width: 820px; margin: 0 auto; }
93
  h2, p { text-align:center }
 
 
 
 
 
 
94
  """
95
 
96
+ with gr.Blocks(theme=THEME, css=CUSTOM_CSS) as demo:
97
  gr.Markdown("<h2>📱 Mobile Meme Maker</h2><p>Upload → Type → Download. Built on iPhone, for iPhone.</p>")
98
 
99
+ with gr.Row():
100
+ with gr.Column():
101
  in_img = gr.Image(type="pil", label="Upload photo", height=320)
102
+ top_text = gr.Textbox(label="Top text", value="WHEN THE WIFI JUST WORKS")
103
+ bottom_text = gr.Textbox(label="Bottom text", value="CHEF'S KISS")
104
+ align = gr.Radio(choices=["left", "center", "right"], value="center", label="Alignment", inline=True)
105
+ font_size = gr.Slider(8, 22, value=12, step=1, label="Font size (% of width)")
106
+ stroke_width = gr.Slider(0, 14, value=4, step=1, label="Outline thickness")
107
+ with gr.Row():
108
+ text_color = gr.ColorPicker(value="#FFFFFF", label="Text")
109
+ outline_color = gr.ColorPicker(value="#000000", label="Outline")
110
+ with gr.Row():
111
+ top_nudge = gr.Slider(-300, 300, value=0, step=1, label="Top nudge (px)")
112
+ bottom_nudge = gr.Slider(-300, 300, value=0, step=1, label="Bottom nudge (px)")
113
+
114
+ with gr.Column():
 
 
 
115
  out = gr.Image(type="pil", label="Preview / Download", height=440, show_download_button=True)
116
  generate = gr.Button("✨ Generate", size="lg")
 
 
 
 
 
117
 
 
118
  inputs = [in_img, top_text, bottom_text, font_size, stroke_width, text_color, outline_color, align, top_nudge, bottom_nudge]
119
  generate.click(fn=make_meme, inputs=inputs, outputs=out)
120
 
 
121
  for comp in inputs:
122
  comp.change(fn=make_meme, inputs=inputs, outputs=out, show_progress=False)
123