Added image upload, new binary
This commit is contained in:
parent
5367624808
commit
9f61f7f447
42
app.py
42
app.py
@ -5,6 +5,7 @@ import requests
|
|||||||
from flask import Flask, render_template_string, request, send_from_directory
|
from flask import Flask, render_template_string, request, send_from_directory
|
||||||
from PIL import Image, ImageDraw, ImageFont
|
from PIL import Image, ImageDraw, ImageFont
|
||||||
import re
|
import re
|
||||||
|
import argparse
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
app.secret_key = 'TpfxYMxUJxJMtCCTraBSg1rbd6NLz38JTmIfpBLsotcI47EqXU'
|
app.secret_key = 'TpfxYMxUJxJMtCCTraBSg1rbd6NLz38JTmIfpBLsotcI47EqXU'
|
||||||
@ -254,6 +255,7 @@ HTML_FORM = '''
|
|||||||
</center>
|
</center>
|
||||||
<form method=post enctype=multipart/form-data>
|
<form method=post enctype=multipart/form-data>
|
||||||
<textarea name=md placeholder="Ingrese Markdown aquí...">{{ default_md }}</textarea><br>
|
<textarea name=md placeholder="Ingrese Markdown aquí...">{{ default_md }}</textarea><br>
|
||||||
|
<input type="file" name="userimg" accept="image/png, image/jpeg" style="margin: 0 0.25em 1.5em 0.25em"><br>
|
||||||
<div class="buttons">
|
<div class="buttons">
|
||||||
<button type=submit name="generate">📷 Generar</button>
|
<button type=submit name="generate">📷 Generar</button>
|
||||||
<button type=submit name="print">🖨️ Imprimir</button>
|
<button type=submit name="print">🖨️ Imprimir</button>
|
||||||
@ -289,6 +291,7 @@ HTML_FORM = '''
|
|||||||
<li><b>Lista numerada:</b> <code>1. Elemento</code></li>
|
<li><b>Lista numerada:</b> <code>1. Elemento</code></li>
|
||||||
<li><b>Imágen:</b> <code></code></li>
|
<li><b>Imágen:</b> <code></code></li>
|
||||||
<li><b>Salto de línea:</b> Deje una línea vacía</li>
|
<li><b>Salto de línea:</b> Deje una línea vacía</li>
|
||||||
|
<li><b>Imagen subida:</b> <code>!(img)</code> (usa la imagen cargada abajo)</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -309,7 +312,22 @@ def bleh_image_from_url(url):
|
|||||||
img = img.resize((IMAGE_WIDTH, img.height), Image.LANCZOS)
|
img = img.resize((IMAGE_WIDTH, img.height), Image.LANCZOS)
|
||||||
return img
|
return img
|
||||||
|
|
||||||
|
def bleh_image_from_bytes(image_bytes):
|
||||||
|
bleh = subprocess.Popen(
|
||||||
|
["./bleh", "-o", "-", "-mode", "1bpp", "-d", "floyd", "-"],
|
||||||
|
stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE
|
||||||
|
)
|
||||||
|
out, err = bleh.communicate(image_bytes)
|
||||||
|
if bleh.returncode != 0:
|
||||||
|
raise RuntimeError(f"Driver failed: {err.decode()}")
|
||||||
|
img = Image.open(io.BytesIO(out)).convert("L")
|
||||||
|
if img.width != IMAGE_WIDTH:
|
||||||
|
img = img.resize((IMAGE_WIDTH, img.height), Image.LANCZOS)
|
||||||
|
return img
|
||||||
|
|
||||||
def parse_line(line):
|
def parse_line(line):
|
||||||
|
if re.match(r"!\(img\)", line) or re.match(r"!\[.*\]\(img\)", line):
|
||||||
|
return ('userimage', None)
|
||||||
image_match = re.match(r"^!\[(.*?)\]\((.+?)\)", line)
|
image_match = re.match(r"^!\[(.*?)\]\((.+?)\)", line)
|
||||||
if image_match:
|
if image_match:
|
||||||
alt = image_match.group(1)
|
alt = image_match.group(1)
|
||||||
@ -406,7 +424,7 @@ def wrap_segments(segments, font, font_bold, font_italic, font_bolditalic, max_w
|
|||||||
if line:
|
if line:
|
||||||
yield line
|
yield line
|
||||||
|
|
||||||
def render(md):
|
def render(md, uploaded_img_bytes=None):
|
||||||
font = ImageFont.truetype(FONT_PATH, FONT_SIZE)
|
font = ImageFont.truetype(FONT_PATH, FONT_SIZE)
|
||||||
font_bold = ImageFont.truetype(FONT_PATH_BOLD, FONT_SIZE)
|
font_bold = ImageFont.truetype(FONT_PATH_BOLD, FONT_SIZE)
|
||||||
font_italic = ImageFont.truetype(FONT_PATH_OBLIQUE, FONT_SIZE)
|
font_italic = ImageFont.truetype(FONT_PATH_OBLIQUE, FONT_SIZE)
|
||||||
@ -422,13 +440,22 @@ def render(md):
|
|||||||
if src_line.strip() == '':
|
if src_line.strip() == '':
|
||||||
lines_out.append(('blank', []))
|
lines_out.append(('blank', []))
|
||||||
continue
|
continue
|
||||||
tag = parse_line(src_line)
|
tag = parse_line(src_line)
|
||||||
if tag[0] == 'image':
|
if tag[0] == 'image':
|
||||||
try:
|
try:
|
||||||
image = bleh_image_from_url(tag[1])
|
image = bleh_image_from_url(tag[1])
|
||||||
lines_out.append(('image', image))
|
lines_out.append(('image', image))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
lines_out.append(('text', [('text', f"[Imagen inválida: {e}]")], font, FONT_SIZE))
|
lines_out.append(('text', [('text', f"[Imagen inválida: {e}]")], font, FONT_SIZE))
|
||||||
|
elif tag[0] == 'userimage':
|
||||||
|
if uploaded_img_bytes:
|
||||||
|
try:
|
||||||
|
image = bleh_image_from_bytes(uploaded_img_bytes)
|
||||||
|
lines_out.append(('image', image))
|
||||||
|
except Exception as e:
|
||||||
|
lines_out.append(('text', [('text', f"[Error al procesar imágen subida: {e}]")], font, FONT_SIZE))
|
||||||
|
else:
|
||||||
|
lines_out.append(('text', [('text', "[No se subió una imagen]")], font, FONT_SIZE))
|
||||||
elif tag[0] == 'hr':
|
elif tag[0] == 'hr':
|
||||||
lines_out.append(('hr',))
|
lines_out.append(('hr',))
|
||||||
elif tag[0] == 'header':
|
elif tag[0] == 'header':
|
||||||
@ -549,8 +576,12 @@ def index():
|
|||||||
printed = False
|
printed = False
|
||||||
error = None
|
error = None
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
|
userimg = request.files.get("userimg")
|
||||||
|
uploaded_img_bytes = None
|
||||||
|
if userimg and userimg.filename:
|
||||||
|
uploaded_img_bytes = userimg.read()
|
||||||
md = request.form["md"]
|
md = request.form["md"]
|
||||||
image = render(md)
|
image = render(md, uploaded_img_bytes)
|
||||||
buf = io.BytesIO()
|
buf = io.BytesIO()
|
||||||
image.save(buf, format="PNG")
|
image.save(buf, format="PNG")
|
||||||
buf.seek(0)
|
buf.seek(0)
|
||||||
@ -593,4 +624,7 @@ def icon_rounded():
|
|||||||
return send_from_directory('static', 'icon512_rounded.png')
|
return send_from_directory('static', 'icon512_rounded.png')
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
app.run(host="0.0.0.0")
|
parser = argparse.ArgumentParser(description='CatNote: Server for Markdown to MXW01 Cat Printer')
|
||||||
|
parser.add_argument('-p', '--port', type=int, default=5000, help='Port to run the server on (default: 5000)')
|
||||||
|
args = parser.parse_args()
|
||||||
|
app.run(host='0.0.0.0', port=args.port)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user