Compare commits

..

No commits in common. "55d3e69320ca9c1fdd2db4a046543e91602e50d3" and "c3269bcbf2e3e8debce3fcb5d78f765b44dd66bc" have entirely different histories.

3 changed files with 24 additions and 64 deletions

88
app.py
View File

@ -1,7 +1,6 @@
import io import io
import tempfile import tempfile
import subprocess import subprocess
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
@ -287,48 +286,27 @@ HTML_FORM = '''
<li><b>Encabezado chico:</b> <code>### Título</code></li> <li><b>Encabezado chico:</b> <code>### Título</code></li>
<li><b>Lista con viñetas:</b> <code>- Elemento</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>Lista numerada:</b> <code>1. Elemento</code></li>
<li><b>Imágen:</b> <code>![Texto alternativo](Enlace a imágen)</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>
</ul> </ul>
</div> </div>
</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): def parse_line(line):
image_match = re.match(r"^!\[(.*?)\]\((.+?)\)", line) if re.match(r'^\s*---\s*$', line):
if image_match: return ('hr', [])
alt = image_match.group(1) header_match = re.match(r"^(#{1,3}) +(.*)", line)
url = image_match.group(2) if header_match:
return ('image', url, alt) header_level = len(header_match.group(1))
if re.match(r'^\s*---\s*$', line): line = header_match.group(2)
return ('hr', []) return ('header', header_level, parse_segments(line))
header_match = re.match(r"^(#{1,3}) +(.*)", line) bullet_match = re.match(r"^\s*([-*\u2022]) +(.*)", line)
if header_match: if bullet_match:
header_level = len(header_match.group(1)) return ('bullet', parse_segments(bullet_match.group(2)))
line = header_match.group(2) ordered_match = re.match(r"^\s*(\d+)\. +(.*)", line)
return ('header', header_level, parse_segments(line)) if ordered_match:
bullet_match = re.match(r"^\s*([-*\u2022]) +(.*)", line) return ('ordered', int(ordered_match.group(1)), parse_segments(ordered_match.group(2)))
if bullet_match: return ('text', parse_segments(line))
return ('bullet', parse_segments(bullet_match.group(2)))
ordered_match = re.match(r"^\s*(\d+)\. +(.*)", line)
if ordered_match:
return ('ordered', int(ordered_match.group(1)), parse_segments(ordered_match.group(2)))
return ('text', parse_segments(line))
def parse_segments(line): def parse_segments(line):
# Handle escaped asterisks: replace them with a placeholder # Handle escaped asterisks: replace them with a placeholder
@ -423,13 +401,7 @@ def render(md):
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] == 'hr':
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',)) lines_out.append(('hr',))
elif tag[0] == 'header': elif tag[0] == 'header':
header_level = tag[1] header_level = tag[1]
@ -471,18 +443,12 @@ def render(md):
for wrapped in wrap_segments(segments, font, font_bold, font_italic, font_bolditalic, IMAGE_WIDTH): for wrapped in wrap_segments(segments, font, font_bold, font_italic, font_bolditalic, IMAGE_WIDTH):
lines_out.append(('text', wrapped, font, FONT_SIZE)) lines_out.append(('text', wrapped, font, FONT_SIZE))
# Compute total height, including images height = sum(
height = 10 # Top margin item[3] if item[0] in ('header', 'text', 'bullet', 'ordered') else
for item in lines_out: 10 if item[0] == 'hr' else
if item[0] in ('header', 'text', 'bullet', 'ordered'): FONT_SIZE
height += item[3] for item in lines_out
elif item[0] == 'hr': ) + 10
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) image = Image.new("L", (IMAGE_WIDTH, height), 255)
draw = ImageDraw.Draw(image) draw = ImageDraw.Draw(image)
@ -534,12 +500,6 @@ def render(md):
draw.text((x, y), text, font=f, fill=0) draw.text((x, y), text, font=f, fill=0)
x += f.getbbox(text)[2] - f.getbbox(text)[0] x += f.getbbox(text)[2] - f.getbbox(text)[0]
y += sz 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 return image
@app.route("/", methods=["GET", "POST"]) @app.route("/", methods=["GET", "POST"])
@ -556,17 +516,17 @@ def index():
buf.seek(0) buf.seek(0)
import base64 import base64
img_data = base64.b64encode(buf.getvalue()).decode() img_data = base64.b64encode(buf.getvalue()).decode()
# If print button pressed, send to driver # If print button pressed, send to catprinter-ble
if "print" in request.form: if "print" in request.form:
try: try:
with tempfile.NamedTemporaryFile(suffix=".png", delete=True) as tmpfile: with tempfile.NamedTemporaryFile(suffix=".png", delete=True) as tmpfile:
image.save(tmpfile, format="PNG") image.save(tmpfile, format="PNG")
tmpfile.flush() tmpfile.flush()
# Run the bleh command # Run the catprinter-ble command
# You can set dither method here if desired # You can set dither method here if desired
result = subprocess.run([ result = subprocess.run([
"sudo", "sudo",
"./bleh", "./catprinter-ble",
"-mode", "1bpp", "-mode", "1bpp",
"-intensity", "100", "-intensity", "100",
tmpfile.name tmpfile.name

BIN
bleh

Binary file not shown.

BIN
catprinter-ble Executable file

Binary file not shown.