8bitlenser/README.md
2026-06-14 17:43:12 -07:00

125 lines
5.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# c64view
Convert a modern image (PNG/JPG/GIF/BMP/WEBP) into a **Commodore 64 disk image**
(`.d64` / `.d71` / `.d81`) containing a self-contained viewer that displays the
picture on a real C64 or in an emulator. The converter works hard to preserve
quality within the VIC-II's tight colour and resolution limits.
![c64view GUI](docs/gui.png)
## Highlights
- **Five display modes** (auto-selectable):
- **Hires** — 320×200, 2 colours per 8×8 cell. Best for sharp line art.
- **Multicolor** — 160×200, 1 shared background + 3 colours per 4×8 cell
(the classic "Koala" format). Best general-purpose photo mode.
- **FLI** — re-points the video matrix every scanline for per-line (4×1) colour.
- **Interlace** — two multicolor frames blended at 50 Hz for ~136 apparent colours.
- **Mono** — highest-resolution path: 320×200 matched by *luminance* to a colour
ramp, so detail is carried by intense dithering. Greyscale by default, or pick
any palette colour as the base for a tinted monochrome (black → blue → light
blue → white, etc.).
- **Perceptual conversion.** All colour decisions are made in CIELAB. Each screen
cell's colour set is chosen by an exhaustive, vectorised search that minimises
reproduction error; an *Intensive* mode additionally searches the global
background colour.
- **Selectable dithering** — ordered Bayer (default, artifact-free), FloydSteinberg,
Atkinson, and the larger Stucki / Jarvis error-diffusion kernels (smoothest
gradients, ideal for mono), or none — all constrained so a cell never shows a
colour it can't.
- **Explore variations.** One click renders every Mode × Palette × Dither
combination as a contact sheet (parallelised across CPU cores); pick the best,
then fine-tune brightness/contrast/saturation/gamma on that choice.
- **PAL / NTSC.** Choose the target video standard. Static and interlace viewers
work on both (interlace flips per frame, so it flickers at the standard's field
rate automatically); FLI ships a separately-timed viewer for each.
- **Run in VICE.** One click builds the disk and launches it in VICE in the chosen
standard (warp mode, except interlace which needs real-time for its flicker): it
lists the directory, then `LOAD"*",8,1` + `RUN` to show the picture.
- **On-disk info program.** When there's room, a colourful BASIC program is added
that prints the original name, dimensions, format, colour depth, oldest EXIF date,
file date, EXIF comment, when the C64 version was made, the host platform, and the
Linux distribution/version.
- **Self-contained viewers.** Each disk's first program embeds the picture and loads
in a single pass, so `LOAD"*",8,1` then `RUN` just works — no second disk access,
no emulator-config surprises.
- **Standard interchange files.** Multicolor exports also drop a `PICTURE.KOA`
(Koala) and hires a `PICTURE.ART` (OCP Art Studio) file for use in other C64 tools.
- **GUI and CLI.**
## Requirements
- Python 3.9+, with `numpy` and `Pillow`.
- `PyQt5` (GUI only).
- [`xa`](https://www.floodgap.com/retrotech/xa/) (xa65) — assembles the 6502 viewers.
- [VICE](https://vice-emu.sourceforge.io/)'s `c1541` — builds the disk images.
On Debian/Ubuntu:
```sh
sudo apt install python3-numpy python3-pil python3-pyqt5 xa65 vice
```
## Usage
### GUI
```sh
python -m c64view.gui # or: c64view
```
Open an image, pick a mode / disk format / dithering, watch the live C64 preview,
then **Export**.
### Command line
```sh
# Multicolor picture onto a .d64, plus a preview PNG of how it will look:
python -m c64view.cli photo.jpg -m multicolor -o photo.d64 --preview photo.png
# Let the tool pick the best standard mode, write a .d81:
python -m c64view.cli photo.jpg -m auto -o photo.d81
# Best quality (slower) FLI with error-diffusion dithering:
python -m c64view.cli photo.jpg -m fli -d floyd --intensive -o photo.d64
# High-res greyscale with smooth Stucki dithering:
python -m c64view.cli photo.jpg -m mono -d stucki -o photo.d64
# ...or tinted monochrome in blue:
python -m c64view.cli photo.jpg -m mono --mono-base blue -d jarvis -o photo.d64
```
Options: `-m/--mode {auto,hires,multicolor,fli,interlace,mono}`,
`-f/--format {d64,d71,d81}`, `-p/--palette {colodore,pepto}`,
`-d/--dither {bayer,floyd,atkinson,stucki,jarvis,none}`,
`--mono-base {grayscale,<colour name>}`, `--video {pal,ntsc}`,
`-a/--aspect {fit,fill,stretch}`, `--intensive`,
`--brightness/--contrast/--saturation/--gamma`, `--preview`.
### On the C64 / in an emulator
Attach the disk to drive 8 and:
```
LOAD"*",8,1
RUN
```
Press any key to return to BASIC (hires/multicolor). For FLI/interlace, reset to exit.
## Notes on the advanced modes
- **FLI** is timing-critical: the viewer runs a cycle-stable raster loop. Expect a
small settling artifact in the top rows (a well-known FLI characteristic) and the
leftmost few pixels reserved by the hardware "FLI bug".
- **Interlace** flickers at 25 Hz on a CRT; it looks best in an emulator or on an LCD.
- Multicolor and Hires are the universally safe, flicker-free choices.
## How conversion works
`c64view/convert/` holds one encoder per mode on top of a shared core
(`convert/base.py` + `dither.py`). The pipeline: prepare & resize the image to the
mode's pixel grid (`imageprep.py`), convert to CIELAB (`palette.py`), choose each
cell's legal colour set by exhaustive search, dither within those sets, then pack the
VIC-II bytes. `viewer/*.s` are the 6502 viewers (assembled by `xa`), combined with the
picture data and written to a disk image by `diskimage.py` / `exporter.py`.