Rearranging already-rendered ascii characters (the old text-transpose
rotation) ignores non-square character cells and read as visibly
distorted. Instead, crop the raw camera frame to roughly the right
aspect ratio, rotate it (only for PRINTER_A4) with OpenCV, and only
then convert to ascii - so ascii-image-converter picks shading
characters for correctly-oriented pixel data instead of us hacking
around after the fact.
The live curses viewfinder is now a separate, always-upright,
aspect-corrected preview independent of PRINTER_A4; the rotated/resized
version used for printing is computed fresh from the raw frame only at
capture time.
txt2printr.sh gains ALREADY_ROTATED, set automatically by photobooth.py
so it doesn't redundantly apply its own text-rotation on top of the
image-level one. The bash pipeline (webcam2ascii.sh/exec-cycle.sh),
which can't rotate images itself, still falls back to that text
rotation unchanged.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Real-world testing (pagetest.sh) showed the printer's actual per-page
line/column capacity didn't match what the A4-geometry math predicted,
and the redundant blank second page was traced to the printer
auto-advancing to a new page once content hits the bottom margin,
with our own unconditional trailing form-feed then ejecting that
already-started blank page on top of it.
Replace PRINTER_CPI/PRINTER_LPI with directly-measured
PRINTER_MAX_LINES/PRINTER_MAX_COLS in printer.conf (read via
pagetest.sh), and have txt2printr.sh skip the trailing form-feed
whenever the print job already reaches that line capacity.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Dot-matrix printers have no hardware page-rotation, so when PRINTER_A4
is enabled in the new printer.conf, txt2printr.sh rotates the ascii art
90 degrees in software before sending it, and photobooth.py caps its
live-preview viewfinder to an A4-landscape character grid (sized from
configurable PRINTER_CPI/PRINTER_LPI) instead of just filling the
terminal, so the preview matches what actually gets printed.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Missing '!' meant the kernel couldn't recognize the interpreter
directive, causing ENOEXEC (errno 8) when executed directly, e.g.
via subprocess.run() from photobooth.py.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
-f only matches regular files, so it never matched the /dev/lp0 or
/dev/usb/lp0 character device nodes, leaving dev unset and always
failing. Use -e existence checks in proper if/elif priority order
(lp0 > usb/lp0 > stdout), with PRINTER_DEV as an unconditional override.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
writes raw bytes to /dev/lp0 (overridable via PRINTER_DEV): resets the
printer with ESC @, converts LF to CRLF to avoid staircasing on raw
device writes, then form-feeds to eject the page.
replaced the guvcview+keypress capture flow with a continuous
capture/convert/display loop so the terminal shows a live ascii
preview; pressing c saves the frame and triggers the new
txt2printr.sh hook (currently a blank template).