add roll printer support via PRINTER_MAX_LINES=0

A continuous-feed printer has no fixed page length, so photobooth.py
now sizes captures to the carriage width (PRINTER_MAX_COLS) and lets
height follow the image's own aspect ratio instead of cropping to a
row count, and txt2printr.sh always feeds the paper out at the end of
a print since there's no page to auto-advance past.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
master
Amir Alexander Abdelbaki 2026-07-14 12:21:29 +02:00
parent 96194f6d77
commit c1d5c7d9cb
3 changed files with 29 additions and 6 deletions

View File

@ -110,8 +110,12 @@ class Config:
def convert_to_ascii(jpg_bytes, width, height, flags): def convert_to_ascii(jpg_bytes, width, height, flags):
# height=None means "roll printer": only the width is fixed, so let the
# converter derive height from the image's own aspect ratio instead of
# forcing both dimensions and distorting or cropping the art.
dim_flags = ["-W", str(width)] if height is None else ["-d", f"{width},{height}"]
proc = subprocess.run( proc = subprocess.run(
["ascii-image-converter", "-", "-d", f"{width},{height}", *flags], ["ascii-image-converter", "-", *dim_flags, *flags],
input=jpg_bytes, input=jpg_bytes,
stdout=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
@ -206,7 +210,16 @@ def prepare_print_frame(frame, cfg, inner_cols, inner_rows):
first and mangling already-rendered ascii text, which doesn't account first and mangling already-rendered ascii text, which doesn't account
for non-square character cells and reads as visibly distorted. for non-square character cells and reads as visibly distorted.
""" """
if cfg.printer_max_lines == 0:
# Roll printer: paper feeds continuously, so there's no page height
# to crop to - only the carriage width (PRINTER_MAX_COLS) limits the
# print. Leave the frame uncropped and pass rows=None downstream so
# ascii-image-converter derives height from the image's own aspect
# ratio instead of forcing a row count.
cols, rows = cfg.printer_max_cols, None
if cfg.printer_a4: if cfg.printer_a4:
frame = cv2.rotate(frame, cv2.ROTATE_90_CLOCKWISE)
elif cfg.printer_a4:
cols, rows = cfg.printer_max_cols, cfg.printer_max_lines cols, rows = cfg.printer_max_cols, cfg.printer_max_lines
# Cropping happens before the 90-degree rotation below, which swaps # Cropping happens before the 90-degree rotation below, which swaps
# width and height, so crop to the inverse of the final aspect ratio. # width and height, so crop to the inverse of the final aspect ratio.
@ -338,7 +351,7 @@ def main(stdscr):
) )
print_jpg_bytes = print_buf.tobytes() print_jpg_bytes = print_buf.tobytes()
print_width = cfg.width or str(print_cols) print_width = cfg.width or str(print_cols)
print_height = cfg.height or str(print_rows) print_height = cfg.height or (str(print_rows) if print_rows is not None else None)
print_ascii_lines = convert_to_ascii( print_ascii_lines = convert_to_ascii(
print_jpg_bytes, print_width, print_height, conv_flags print_jpg_bytes, print_width, print_height, conv_flags
) )

View File

@ -21,5 +21,12 @@ PRINTER_A4=false
# then read off the last line number on page 1 (-> PRINTER_MAX_LINES) and # then read off the last line number on page 1 (-> PRINTER_MAX_LINES) and
# how many characters of the 64-wide test lines actually printed before # how many characters of the 64-wide test lines actually printed before
# being cut off (-> PRINTER_MAX_COLS). # being cut off (-> PRINTER_MAX_COLS).
#
# Set PRINTER_MAX_LINES=0 for a roll/continuous-feed printer that has no
# fixed page length. In that mode photobooth.py sizes captures to fill
# PRINTER_MAX_COLS width and lets height follow the image's own aspect
# ratio instead of cropping to a row count, and txt2printr.sh always feeds
# the paper out at the end of a print instead of skipping the feed when a
# page is already full (there's no page to fill).
PRINTER_MAX_LINES=64 PRINTER_MAX_LINES=64
PRINTER_MAX_COLS=54 PRINTER_MAX_COLS=54

View File

@ -9,7 +9,8 @@
# converting it to ascii (photobooth.py does this # converting it to ascii (photobooth.py does this
# for better quality; set by it automatically) # for better quality; set by it automatically)
# Reads printer.conf for PRINTER_A4 (landscape rotation) and PRINTER_MAX_LINES # Reads printer.conf for PRINTER_A4 (landscape rotation) and PRINTER_MAX_LINES
# (per-page line capacity, measured with pagetest.sh). # (per-page line capacity, measured with pagetest.sh; 0 means a roll/
# continuous-feed printer with no fixed page length).
dir="$(dirname "$0")" dir="$(dirname "$0")"
[ -f "$dir/printer.conf" ] && source "$dir/printer.conf" [ -f "$dir/printer.conf" ] && source "$dir/printer.conf"
@ -84,7 +85,9 @@ line_count=$(body | wc -l)
# Skip the form feed once the page is already full: printers commonly # Skip the form feed once the page is already full: printers commonly
# auto-advance to a new page as soon as content hits the bottom margin, # auto-advance to a new page as soon as content hits the bottom margin,
# so an explicit form feed on top of that just ejects a blank extra page. # so an explicit form feed on top of that just ejects a blank extra page.
if [ "$line_count" -lt "$PRINTER_MAX_LINES" ]; then # A roll printer (PRINTER_MAX_LINES=0) has no page to fill or auto-advance
printf '\x0c' # form feed - eject the page # past, so always feed the paper out to clear the printed art for tear-off.
if [ "$PRINTER_MAX_LINES" -eq 0 ] || [ "$line_count" -lt "$PRINTER_MAX_LINES" ]; then
printf '\x0c' # form feed - eject the page / advance the roll
fi fi
} > "$dev" } > "$dev"