VirtualOasis commited on
Commit
f7e2faa
·
verified ·
1 Parent(s): 30a1cae

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +48 -77
app.py CHANGED
@@ -1,10 +1,10 @@
1
  import os
2
- import tempfile
3
- import base64
4
  import gradio as gr
5
  from PIL import Image, ImageDraw, ImageFont
 
 
6
 
7
- # --- Image Generation Logic (from coverter.py) ---
8
 
9
  def draw_horizontal_lines(draw, width, height, spacing=60, color=(230, 230, 230)):
10
  """Draws horizontal lines on the image."""
@@ -19,39 +19,37 @@ def draw_dot_grid(draw, width, height, spacing=50, color=(220, 220, 220)):
19
 
20
  def draw_lattice_grid(draw, width, height, spacing=100, color=(235, 235, 235)):
21
  """Draws a lattice/graph paper grid on the image."""
22
- # Draw vertical lines
23
  for x in range(0, width, spacing):
24
  draw.line([(x, 0), (x, height)], fill=color, width=2)
25
- # Draw horizontal lines
26
  for y in range(0, height, spacing):
27
  draw.line([(0, y), (width, y)], fill=color, width=2)
28
 
29
 
30
- def text_to_images_generator(text_content, style='lines'):
31
  """
32
- Converts a given string of text into a single combined image and returns the file path.
33
- This is compatible with both UI and MCP.
34
 
35
  Args:
36
  text_content (str): The text to be converted.
37
- style (str): The background style ('plain', 'lines', 'dots', 'grid').
38
 
39
  Returns:
40
- str: Message with the path to the generated combined image file.
41
  """
42
  if not text_content or not text_content.strip():
43
- return "Error: Input text is empty. Please enter some text to generate images."
 
44
 
45
  # --- Configuration ---
46
  IMG_WIDTH = 1080
47
  IMG_HEIGHT = 1080
48
  BACKGROUND_COLOR = (255, 255, 255)
49
  TEXT_COLOR = (10, 10, 10)
50
- STYLE_COLOR = (225, 225, 225) # Color for lines/dots/grid
51
 
52
  PADDING_X = 80
53
  PADDING_Y = 80
54
-
55
  FONT_SIZE = 48
56
  LINE_SPACING = 20
57
 
@@ -73,10 +71,10 @@ def text_to_images_generator(text_content, style='lines'):
73
  if not font:
74
  font = ImageFont.load_default()
75
  except Exception as e:
76
- print(f"An unexpected error occurred during font loading: {e}")
77
  font = ImageFont.load_default()
78
 
79
- # --- Text Wrapping Logic ---
80
  drawable_width = IMG_WIDTH - 2 * PADDING_X
81
  paragraphs = [p.strip() for p in text_content.strip().split('\n') if p.strip()]
82
 
@@ -105,7 +103,11 @@ def text_to_images_generator(text_content, style='lines'):
105
  if i < len(paragraphs) - 1:
106
  all_lines_and_breaks.append(None)
107
 
108
- # --- Image Generation ---
 
 
 
 
109
  try:
110
  line_height = font.getbbox("A")[3] - font.getbbox("A")[1]
111
  except AttributeError:
@@ -113,34 +115,10 @@ def text_to_images_generator(text_content, style='lines'):
113
 
114
  PARAGRAPH_SPACING = line_height
115
 
116
- # Calculate pages and total height needed
117
- pages_content = []
118
- current_page = []
119
- y_text = PADDING_Y
120
-
121
- for item in all_lines_and_breaks:
122
- is_break = item is None
123
- item_height = PARAGRAPH_SPACING if is_break else line_height
124
-
125
- if y_text + item_height > IMG_HEIGHT - PADDING_Y:
126
- pages_content.append(current_page)
127
- current_page = [item]
128
- y_text = PADDING_Y + item_height + (0 if is_break else LINE_SPACING)
129
- else:
130
- current_page.append(item)
131
- y_text += item_height + (0 if is_break else LINE_SPACING)
132
-
133
- if current_page:
134
- pages_content.append(current_page)
135
-
136
- # Create a single combined image with all pages
137
- total_height = len(pages_content) * IMG_HEIGHT
138
- combined_img = Image.new('RGB', (IMG_WIDTH, total_height), color=BACKGROUND_COLOR)
139
-
140
- for page_idx, page_content in enumerate(pages_content):
141
- # Create individual page
142
- page_img = Image.new('RGB', (IMG_WIDTH, IMG_HEIGHT), color=BACKGROUND_COLOR)
143
- draw = ImageDraw.Draw(page_img)
144
 
145
  if style == 'lines':
146
  line_style_spacing = line_height + LINE_SPACING
@@ -151,43 +129,36 @@ def text_to_images_generator(text_content, style='lines'):
151
  draw_lattice_grid(draw, IMG_WIDTH, IMG_HEIGHT, color=STYLE_COLOR)
152
 
153
  current_y = PADDING_Y
154
- for page_item in page_content:
155
  if page_item is not None:
156
  draw.text((PADDING_X, current_y), page_item, font=font, fill=TEXT_COLOR)
157
  current_y += line_height + LINE_SPACING
158
  else:
159
  current_y += PARAGRAPH_SPACING
160
 
161
- # Paste this page onto the combined image
162
- combined_img.paste(page_img, (0, page_idx * IMG_HEIGHT))
163
-
164
- # Save combined image to temporary file and also encode as base64
165
- temp_file = tempfile.NamedTemporaryFile(delete=False, suffix='.png')
166
- combined_img.save(temp_file.name, format='PNG')
167
- temp_file.close()
168
-
169
- # Convert to base64 for inline viewing
170
- import io
171
- img_buffer = io.BytesIO()
172
- combined_img.save(img_buffer, format='PNG')
173
- img_buffer.seek(0)
174
- img_base64 = base64.b64encode(img_buffer.getvalue()).decode('utf-8')
175
-
176
- return f"""Image successfully generated and saved to: {temp_file.name}
177
-
178
- Image details:
179
- - Total pages: {len(pages_content)}
180
- - Image dimensions: {IMG_WIDTH} x {total_height} pixels
181
- - Style: {style}
182
- - Format: PNG
183
 
184
- Base64 encoded image (you can copy this and paste into a base64 image viewer):
185
- data:image/png;base64,{img_base64}
 
 
 
 
 
 
 
 
 
 
 
 
 
186
 
187
- To view the image:
188
- 1. Copy the entire data:image/png;base64,... string above
189
- 2. Paste it into your browser's address bar, or
190
- 3. Use an online base64 image viewer like: https://base64.guru/converter/decode/image"""
191
 
192
  # --- Gradio Interface ---
193
 
@@ -196,14 +167,14 @@ example_text = """In the heart of a bustling city, there lived a clockmaker name
196
  One day, a young girl with eyes as curious as a cat's wandered into his shop. She wasn't interested in the shiny new watches but was drawn to the grandfather clock in the corner. "What's its story?" she asked, her voice soft. Alistair smiled, for he knew he had found the next guardian of the stories. The legacy of the whispering clock would live on."""
197
 
198
  demo = gr.Interface(
199
- fn=text_to_images_generator,
200
  inputs=[
201
  gr.Textbox(lines=15, label="Text Content", placeholder="Paste your long-form text here...", value=example_text),
202
  gr.Radio(['lines', 'dots', 'grid', 'plain'], label="Background Style", value='lines')
203
  ],
204
- outputs=gr.Textbox(label="Result", show_label=True),
205
- title="Text-to-Image Converter",
206
- description="Transforms long-form text into a single combined image with multiple pages. Paste your text, choose a style, and click 'Submit'. The result will show the file path where your image was saved.",
207
  allow_flagging="never"
208
  )
209
 
 
1
  import os
 
 
2
  import gradio as gr
3
  from PIL import Image, ImageDraw, ImageFont
4
+ import base64
5
+ import io
6
 
7
+ # --- Image Generation Logic ---
8
 
9
  def draw_horizontal_lines(draw, width, height, spacing=60, color=(230, 230, 230)):
10
  """Draws horizontal lines on the image."""
 
19
 
20
  def draw_lattice_grid(draw, width, height, spacing=100, color=(235, 235, 235)):
21
  """Draws a lattice/graph paper grid on the image."""
 
22
  for x in range(0, width, spacing):
23
  draw.line([(x, 0), (x, height)], fill=color, width=2)
 
24
  for y in range(0, height, spacing):
25
  draw.line([(0, y), (width, y)], fill=color, width=2)
26
 
27
 
28
+ def text_to_base64_images_generator(text_content, style='lines'):
29
  """
30
+ Converts text into a series of images and returns them as a list
31
+ of base64 encoded strings, suitable for an API/MCP client.
32
 
33
  Args:
34
  text_content (str): The text to be converted.
35
+ style (str, optional): The background style ('plain', 'lines', 'dots', 'grid').
36
 
37
  Returns:
38
+ list: A list of base64 encoded PNG image strings.
39
  """
40
  if not text_content or not text_content.strip():
41
+ gr.Warning("Input text is empty. Please enter some text to generate images.")
42
+ return []
43
 
44
  # --- Configuration ---
45
  IMG_WIDTH = 1080
46
  IMG_HEIGHT = 1080
47
  BACKGROUND_COLOR = (255, 255, 255)
48
  TEXT_COLOR = (10, 10, 10)
49
+ STYLE_COLOR = (225, 225, 225)
50
 
51
  PADDING_X = 80
52
  PADDING_Y = 80
 
53
  FONT_SIZE = 48
54
  LINE_SPACING = 20
55
 
 
71
  if not font:
72
  font = ImageFont.load_default()
73
  except Exception as e:
74
+ print(f"Font loading error: {e}")
75
  font = ImageFont.load_default()
76
 
77
+ # --- Text Wrapping ---
78
  drawable_width = IMG_WIDTH - 2 * PADDING_X
79
  paragraphs = [p.strip() for p in text_content.strip().split('\n') if p.strip()]
80
 
 
103
  if i < len(paragraphs) - 1:
104
  all_lines_and_breaks.append(None)
105
 
106
+ # --- Image Generation & Encoding ---
107
+ generated_base64_list = []
108
+ page_content = []
109
+ y_text = PADDING_Y
110
+
111
  try:
112
  line_height = font.getbbox("A")[3] - font.getbbox("A")[1]
113
  except AttributeError:
 
115
 
116
  PARAGRAPH_SPACING = line_height
117
 
118
+ def create_and_encode_page(content):
119
+ """Helper to create a PIL image, draw text, and encode to base64."""
120
+ img = Image.new('RGB', (IMG_WIDTH, IMG_HEIGHT), color=BACKGROUND_COLOR)
121
+ draw = ImageDraw.Draw(img)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
122
 
123
  if style == 'lines':
124
  line_style_spacing = line_height + LINE_SPACING
 
129
  draw_lattice_grid(draw, IMG_WIDTH, IMG_HEIGHT, color=STYLE_COLOR)
130
 
131
  current_y = PADDING_Y
132
+ for page_item in content:
133
  if page_item is not None:
134
  draw.text((PADDING_X, current_y), page_item, font=font, fill=TEXT_COLOR)
135
  current_y += line_height + LINE_SPACING
136
  else:
137
  current_y += PARAGRAPH_SPACING
138
 
139
+ # Encode image to base64 string
140
+ buffered = io.BytesIO()
141
+ img.save(buffered, format="PNG")
142
+ img_base64 = base64.b64encode(buffered.getvalue()).decode("utf-8")
143
+ generated_base64_list.append(img_base64)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
144
 
145
+ # --- Page Creation Loop ---
146
+ for item in all_lines_and_breaks:
147
+ is_break = item is None
148
+ item_height = PARAGRAPH_SPACING if is_break else line_height
149
+
150
+ if y_text + item_height > IMG_HEIGHT - PADDING_Y:
151
+ create_and_encode_page(page_content)
152
+ page_content = [item]
153
+ y_text = PADDING_Y + item_height + (0 if is_break else LINE_SPACING)
154
+ else:
155
+ page_content.append(item)
156
+ y_text += item_height + (0 if is_break else LINE_SPACING)
157
+
158
+ if page_content:
159
+ create_and_encode_page(page_content)
160
 
161
+ return generated_base64_list
 
 
 
162
 
163
  # --- Gradio Interface ---
164
 
 
167
  One day, a young girl with eyes as curious as a cat's wandered into his shop. She wasn't interested in the shiny new watches but was drawn to the grandfather clock in the corner. "What's its story?" she asked, her voice soft. Alistair smiled, for he knew he had found the next guardian of the stories. The legacy of the whispering clock would live on."""
168
 
169
  demo = gr.Interface(
170
+ fn=text_to_base64_images_generator,
171
  inputs=[
172
  gr.Textbox(lines=15, label="Text Content", placeholder="Paste your long-form text here...", value=example_text),
173
  gr.Radio(['lines', 'dots', 'grid', 'plain'], label="Background Style", value='lines')
174
  ],
175
+ outputs=gr.JSON(label="Base64 Encoded Images"),
176
+ title="Text-to-Image API Server",
177
+ description="Transforms long-form text into a series of images and returns a JSON list of base64-encoded strings.",
178
  allow_flagging="never"
179
  )
180