# ASCII Photobooth A Linux webcam photobooth that converts live frames to ASCII art in the terminal, and can optionally send captures to a parallel-port needle/dot-matrix printer. There are two front ends: - **`photobooth.py`** — a curses TUI. Grabs frames directly via OpenCV/v4l2 (no per-frame process spawn), converts them with the `ascii-image-converter` binary, and supports live brightness/exposure adjustment. This is the actively developed front end. - **`exec-cycle.sh` / `webcam2ascii.sh`** — a simpler bash implementation of the same live-preview loop, built around `fswebcam` and `ascii-image-converter`. Both read the same `webcam.conf` / `ascii.conf` / `keybinds.conf` / `printer.conf` files, so you only need to configure your hardware once. ## Requirements - `fswebcam`, `ascii-image-converter`, `v4l-utils` - `python-opencv` (for `photobooth.py`) - A V4L2-compatible webcam - Optionally, a parallel-port printer wired up via `parport`/`parport_pc`/`lp` kernel modules, for hardcopy prints Install everything with the script for your distro: ```sh ./install_deps_arch.sh # Arch Linux / other pacman+AUR distros ./install_deps_debian.sh # Debian, Ubuntu, and other apt-based distros ./install_deps_fedora.sh # Fedora and other dnf-based distros ``` `install_deps_arch.sh` installs [`yay`](https://aur.archlinux.org/packages/yay) if needed and pulls `ascii-image-converter` from the AUR. The Debian/Fedora scripts build `ascii-image-converter` with `go install` instead, since it isn't packaged for `apt`/`dnf`. All three install the required packages, add your user to the `lp` group (needed to write to `/dev/lp0`), and load the parallel-port kernel modules. ## Usage Run the TUI (recommended): ```sh ./photobooth.py ``` Or the bash live-preview loop: ```sh ./exec-cycle.sh ``` ### Controls Configurable in `keybinds.conf`; defaults shown below. | Key | Action | | --- | --- | | `space` | Capture a photo | | `+` / `-` | Adjust brightness | | `.` / `,` | Adjust exposure | | `r` | Reset brightness/exposure to defaults | | `q` | Quit (`photobooth.py` only; `exec-cycle.sh` quits on Ctrl+C) | Captures are saved as `photo-.jpg` and `ascii-img-.txt`, and are automatically sent to the printer via `txt2printr.sh` if one is configured. ## Configuration | File | Purpose | | --- | --- | | `webcam.conf` | Capture device, resolution, JPEG quality, default brightness/exposure, and the v4l2 control names/IDs used to adjust them | | `ascii.conf` | `ascii-image-converter` options: output size, character map/complexity, grayscale, negative, flips, and whether the live-preview viewfinder mirrors the print output's aspect ratio (`REAL_VIEWFINDER`) | | `keybinds.conf` | Single-character key bindings for capture/brightness/exposure/reset/quit | | `printer.conf` | Printer device, A4 landscape rotation (`PRINTER_A4`), and per-page capacity (`PRINTER_MAX_LINES`/`PRINTER_MAX_COLS`) | ### Printing `txt2printr.sh` sends an ASCII art text file to a parallel-port printer (`/dev/lp0` by default, override with `PRINTER_DEV`). Needle/dot-matrix printers have no hardware landscape mode, so setting `PRINTER_A4=true` in `printer.conf` rotates the art in software before printing (turn the printed page 90° to read it); `photobooth.py` instead rotates the source image before ASCII conversion for better quality, and sets `PRINTER_MAX_LINES=0` to signal a roll/continuous-feed printer with no fixed page length. Printer page capacity varies by hardware and isn't reliably predictable from paper geometry — measure it with `pagetest.sh`: ```sh ./pagetest.sh # numbered lines, to find lines-per-page ./pagetest.sh ruler # a column ruler, to find chars-per-line PRINTER_A4=false ./txt2printr.sh pagetest.txt ``` Read the last line/column that printed on page 1 and set `PRINTER_MAX_LINES`/`PRINTER_MAX_COLS` in `printer.conf` accordingly. `printer.conf.hpold.bak` and `printer.conf.rollpaper.bak` are example configs for a couple of previously-tested printers. ## Other scripts - `yay-installer.sh` — installs the `yay` AUR helper (used by `install_deps_arch.sh`) script (LUKS2/btrfs/FIDO2), unrelated to the photobooth itself, was origin