Added image support
This commit is contained in:
parent
f1ef93798e
commit
5367624808
54
app.py
54
app.py
@ -1,6 +1,7 @@
|
||||
import io
|
||||
import tempfile
|
||||
import subprocess
|
||||
import requests
|
||||
from flask import Flask, render_template_string, request, send_from_directory
|
||||
from PIL import Image, ImageDraw, ImageFont
|
||||
import re
|
||||
@ -286,13 +287,34 @@ HTML_FORM = '''
|
||||
<li><b>Encabezado chico:</b> <code>### Título</code></li>
|
||||
<li><b>Lista con viñetas:</b> <code>- Elemento</code></li>
|
||||
<li><b>Lista numerada:</b> <code>1. Elemento</code></li>
|
||||
<li><b>Imágen:</b> <code></code></li>
|
||||
<li><b>Salto de línea:</b> Deje una línea vacía</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
'''
|
||||
|
||||
def bleh_image_from_url(url):
|
||||
resp = requests.get(url, stream=True)
|
||||
resp.raise_for_status()
|
||||
bleh = subprocess.Popen(
|
||||
["./bleh", "-o", "-", "-mode", "1bpp", "-d", "floyd", "-"],
|
||||
stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
out, err = bleh.communicate(resp.content)
|
||||
if bleh.returncode != 0:
|
||||
raise RuntimeError(f"Driver failed: {err.decode()}")
|
||||
img = Image.open(io.BytesIO(out)).convert("L")
|
||||
# Optionally check width, pad/resize if needed
|
||||
if img.width != IMAGE_WIDTH:
|
||||
img = img.resize((IMAGE_WIDTH, img.height), Image.LANCZOS)
|
||||
return img
|
||||
|
||||
def parse_line(line):
|
||||
image_match = re.match(r"^!\[(.*?)\]\((.+?)\)", line)
|
||||
if image_match:
|
||||
alt = image_match.group(1)
|
||||
url = image_match.group(2)
|
||||
return ('image', url, alt)
|
||||
if re.match(r'^\s*---\s*$', line):
|
||||
return ('hr', [])
|
||||
header_match = re.match(r"^(#{1,3}) +(.*)", line)
|
||||
@ -401,7 +423,13 @@ def render(md):
|
||||
lines_out.append(('blank', []))
|
||||
continue
|
||||
tag = parse_line(src_line)
|
||||
if tag[0] == 'hr':
|
||||
if tag[0] == 'image':
|
||||
try:
|
||||
image = bleh_image_from_url(tag[1])
|
||||
lines_out.append(('image', image))
|
||||
except Exception as e:
|
||||
lines_out.append(('text', [('text', f"[Imagen inválida: {e}]")], font, FONT_SIZE))
|
||||
elif tag[0] == 'hr':
|
||||
lines_out.append(('hr',))
|
||||
elif tag[0] == 'header':
|
||||
header_level = tag[1]
|
||||
@ -443,12 +471,18 @@ def render(md):
|
||||
for wrapped in wrap_segments(segments, font, font_bold, font_italic, font_bolditalic, IMAGE_WIDTH):
|
||||
lines_out.append(('text', wrapped, font, FONT_SIZE))
|
||||
|
||||
height = sum(
|
||||
item[3] if item[0] in ('header', 'text', 'bullet', 'ordered') else
|
||||
10 if item[0] == 'hr' else
|
||||
FONT_SIZE
|
||||
for item in lines_out
|
||||
) + 10
|
||||
# Compute total height, including images
|
||||
height = 10 # Top margin
|
||||
for item in lines_out:
|
||||
if item[0] in ('header', 'text', 'bullet', 'ordered'):
|
||||
height += item[3]
|
||||
elif item[0] == 'hr':
|
||||
height += 10
|
||||
elif item[0] == 'blank':
|
||||
height += FONT_SIZE
|
||||
elif item[0] == 'image':
|
||||
img = item[1]
|
||||
height += img.height + 10 # add margin below image
|
||||
|
||||
image = Image.new("L", (IMAGE_WIDTH, height), 255)
|
||||
draw = ImageDraw.Draw(image)
|
||||
@ -500,6 +534,12 @@ def render(md):
|
||||
draw.text((x, y), text, font=f, fill=0)
|
||||
x += f.getbbox(text)[2] - f.getbbox(text)[0]
|
||||
y += sz
|
||||
elif item[0] == 'image':
|
||||
img = item[1]
|
||||
# Center image horizontally if narrower
|
||||
img_x = (IMAGE_WIDTH - img.width) // 2 if img.width < IMAGE_WIDTH else 0
|
||||
image.paste(img, (img_x, y))
|
||||
y += img.height + 10 # vertical margin after image
|
||||
return image
|
||||
|
||||
@app.route("/", methods=["GET", "POST"])
|
||||
|
||||
Loading…
Reference in New Issue
Block a user