125 lines
5.5 KiB
Markdown
125 lines
5.5 KiB
Markdown
# 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.
|
||
|
||

|
||
|
||
## 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), Floyd–Steinberg,
|
||
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`.
|