Dithering - but with constraints inspired by the Commodore 64 https://git.lewismoten.com/tiny-pockets-press/dither-c64-lib/raw/branch/main/index.html
  • JavaScript 91.2%
  • CSS 5.6%
  • HTML 3.2%
Find a file
2026-06-22 11:23:30 -04:00
c64-blocks show bayer prepass 2026-06-21 02:18:34 -04:00
c64-charset-shifted-business show bayer prepass 2026-06-21 02:18:34 -04:00
c64-charset-unshifted show bayer prepass 2026-06-21 02:18:34 -04:00
c64-custom-charset show bayer prepass 2026-06-21 02:18:34 -04:00
c64-hires-bitmap show bayer prepass 2026-06-21 02:18:34 -04:00
c64-multicolor-bitmap show bayer prepass 2026-06-21 02:18:34 -04:00
scripts show bayer prepass 2026-06-21 02:18:34 -04:00
.gitignore Initial commit 2026-06-21 04:45:40 +00:00
c64-support.js reuse unshifted chars 2026-06-21 10:12:10 -04:00
index.css glyph phantom lines and panning 2026-06-22 11:23:30 -04:00
index.html glyph phantom lines and panning 2026-06-22 11:23:30 -04:00
index.js glyph phantom lines and panning 2026-06-22 11:23:30 -04:00
library.js setup bitmap modes 2026-06-21 01:30:07 -04:00
package-lock.json move c64 files over and setup project 2026-06-21 00:49:58 -04:00
package.json move c64 files over and setup project 2026-06-21 00:49:58 -04:00
README.md add c64 disclaimer 2026-06-21 09:57:05 -04:00
source-sample.svg work with 320x200 images 2026-06-21 02:04:46 -04:00

C64 Dither Library

This folder contains C64-specific dithers and helper APIs for browser-based image export.

It is intended to work as a separate library from the basic dithers so C64 features can carry their own helper surface under window.C64.dither.

Disclaimer

This project is not affiliated with or endorsed by Commodore. Commodore and Commodore 64 are trademarks of their respective owner(s). This library uses those names descriptively to refer to historical display constraints and compatible visual styles.

What It Provides

The entry point is library.js. When loaded in a page that already exposes window.TPP.registerDitherLibrary, it registers the C64 dither catalog without eagerly loading every implementation.

The individual C64 plug-ins then lazy-load c64-support.js, which sets up:

window.C64.dither;

That API exposes shared C64 helper methods, glyph catalogs, and export helpers used by the C64 dithers.

Included dithers:

  • c64-blocks as C64 Blocks
  • c64-hires-bitmap as C64 Standard / High-Res Bitmap Mode
  • c64-multicolor-bitmap as C64 Multicolor Bitmap Mode
  • c64-charset-unshifted as C64 Default Charset
  • c64-charset-shifted-business as C64 Shifted Business Charset
  • c64-custom-charset as C64 Custom Charset

To regenerate the gallery samples after changing any plug-in:

npm run dither

Demo Page

Open index.html in a browser served from this folder to try the library interactively. The page:

  • uploads an image and displays it on a canvas
  • loads library.js and the selected plug-in through window.TPP
  • applies the standard C64 16-color palette used by palette-lib
  • resizes every loaded source image to the Commodore 64 screen size of 320x200 before previewing and dithering
  • can apply an optional Bayer 4x4 ordered pre-dither before the C64 reduction step
  • exposes a Threshold slider for C64 Custom Charset, where it acts as a bias between glyph variety and per-cell accuracy
  • shows the selected global background color for modes that use one
  • previews either the generated custom charset or the glyphs used by the active character mode in a 128x128 sheet
  • renders the processed result to a second canvas

The gallery shows the original source image and the same image reduced through each bundled C64 dither using the standard C64 16-color palette. These are not generic mono dithers; they are C64-style reductions intended to feel at home in bitmap and character-based export workflows. Each example also shows how the same mode looks when a Bayer 4x4 ordered pre-dither is applied before the C64 reduction step.

C64 Blocks

Original C64 Blocks C64 Blocks + Bayer 4x4 Prepass
Original sample C64 Blocks sample C64 Blocks Bayer prepass sample

This mode leans on PETSCII-style block and quarter-block glyphs, so it reads quickly and keeps a very recognizable character-screen aesthetic. It is useful when you want the result to feel obviously text-mode and icon-like rather than strictly bitmap-based.

C64 Standard / High-Res Bitmap Mode

Original C64 Standard / High-Res Bitmap Mode C64 Standard / High-Res Bitmap Mode + Bayer 4x4 Prepass
Original sample C64 Standard / High-Res Bitmap Mode sample C64 Standard / High-Res Bitmap Mode Bayer prepass sample

This mode fits each 8x8 cell to two colors from the standard C64 palette. That matches the machine's high-resolution bitmap rules closely, so it is the better choice when you want crisp line work, tighter silhouettes, and individually addressable pixels instead of wide multicolor blocks.

C64 Multicolor Bitmap Mode

Original C64 Multicolor Bitmap Mode C64 Multicolor Bitmap Mode + Bayer 4x4 Prepass
Original sample C64 Multicolor Bitmap Mode sample C64 Multicolor Bitmap Mode Bayer prepass sample

This mode uses one global background color across the whole image and then allows three additional colors inside each 8x8 cell. Horizontally, pixels are paired, so each cell behaves like a 4x8 pattern stretched to 8x8. That wide pixel structure is a defining part of the classic C64 multicolor bitmap look.

C64 Default Charset

Original C64 Default Charset C64 Default Charset + Bayer 4x4 Prepass
Original sample C64 Default Charset sample C64 Default Charset Bayer prepass sample

This uses the standard unshifted character ROM shapes. It tends to feel the most like a normal C64 text screen because the glyph vocabulary is the one most people associate with stock machine output.

C64 Shifted Business Charset

Original C64 Shifted Business Charset C64 Shifted Business Charset + Bayer 4x4 Prepass
Original sample C64 Shifted Business Charset sample C64 Shifted Business Charset Bayer prepass sample

This variant swaps in the shifted business-mode character set. It can produce a different texture than the default ROM because the glyph pool includes more office-oriented letters and symbols and fewer of the more playful default screen shapes.

C64 Custom Charset

Original C64 Custom Charset C64 Custom Charset + Bayer 4x4 Prepass
Original sample C64 Custom Charset sample C64 Custom Charset Bayer prepass sample

This mode is the most flexible because it derives a custom glyph set from the image itself. That usually gives it the highest fidelity of the four, at the cost of being less tied to the stock built-in C64 ROM feel. In the demo, its Threshold slider controls the selection bias used while reducing the glyph set: lower values favor closer per-cell matches, while higher values preserve a wider variety of distinct glyph shapes.

How To Host It

Host this folder structure as-is so the relative paths remain valid. For example:

https://git.lewismoten.com/tiny-pockets-press/dither-c64-lib/raw/branch/main/library.js
https://git.lewismoten.com/tiny-pockets-press/dither-c64-lib/raw/branch/main/c64-support.js
https://git.lewismoten.com/tiny-pockets-press/dither-c64-lib/raw/branch/main/c64-blocks/plugin.js
https://git.lewismoten.com/tiny-pockets-press/dither-c64-lib/raw/branch/main/c64-charset-unshifted/plugin.js

The library file references sibling and parent-relative plug-in paths, so preserving structure matters.

How To Use It

Your application should provide:

  • window.TPP.registerDitherLibrary(library)
  • window.TPP.registerDither(dither)

Then load the C64 library:

<script src="https://git.lewismoten.com/tiny-pockets-press/dither-c64-lib/raw/branch/main/library.js"></script>

That registers the available C64 dithers. Later, when your app loads one of the individual plug-ins, that plug-in will load c64-support.js on demand and use window.C64.dither.

Using Outside TPP

The plug-ins are not tied to Tiny Pockets Press specifically. The TPP hooks are just a lightweight registration mechanism. Any application can load a plug-in, capture the registered object, and call its palette handler directly.

The C64 plug-ins in this library are palette-oriented and typically expose:

  • applyPaletteAsync(data, width, height, palette, options)

The palette value should be an array of [r, g, b] swatches. In the bundled demo and sample generator, this is the same standard C64 palette defined in palette-lib as c64. The options object is used for rendering behavior such as progress reporting in long-running browser operations.

The window.C64.dither API

After a C64 plug-in loads its support file, these helpers become available:

  • window.C64.dither.applyPaletteHiresBitmapAsync(...)
  • window.C64.dither.applyPaletteMulticolorBitmapAsync(...)
  • window.C64.dither.applyPalettePetsciiAsync(...)
  • window.C64.dither.applyPaletteCustomCharsetAsync(...)
  • window.C64.dither.buildImageExportCustomCharsetSheet(...)
  • window.C64.dither.buildC64CustomCharsetLayout(...)
  • window.C64.dither.petsciiGlyphs
  • window.C64.dither.c64CharsetUnshiftedGlyphs
  • window.C64.dither.c64CharsetShiftedBusinessGlyphs

This API is meant for browser use and for reuse by related C64 plug-ins.

Plug-in Behavior

Each C64 dither plug-in:

  • registers itself through window.TPP.registerDither(...)
  • loads c64-support.js only when the dither is actually needed
  • reads helper methods and, when needed, glyph catalogs from window.C64.dither
  • mutates the provided RGBA pixel buffer in place

That keeps the C64 library lazy-loaded while still exposing a reusable public helper API.

Notes

  • The default and shifted-business charsets use hard-coded glyph catalogs extracted from the source C64 sheets already included with this project.
  • The lower reverse-video half of those sheets is not duplicated in the baked glyph list because the top half provides the unique glyph shapes needed for dithering.
  • The bundled demo and sample generator use the same standard C64 palette that is defined in palette-lib as c64.
  • If registration or helper loading fails, errors are written to console.error.
  • This project is not affiliated with or endorsed by Commodore. Commodore and Commodore 64 are trademarks of their respective owner(s).