Palette Companion
A local-first desktop utility for turning reference images into drawing-ready palettes for Clip Studio Paint and Krita.
Motivation
I first built palette extraction as part of my Krita reference-board extension. It was useful enough that I wanted it outside one host application: a small tool I could open beside either Clip Studio Paint or Krita, feed a reference image, and close when the drawing session was over. Palette Companion turns that feature into a standalone macOS and Windows workflow without trying to automate either drawing app.
A Deliberately Explicit Workflow
An image can come from the clipboard, a local file, or a supported browser drag. I choose a target between 2 and 100 colors and press Generate. Keeping generation explicit matters for large references and makes the moment of computation predictable.
After the first result, changing the count preserves the current palette until I press Generate again. That next extraction reuses the histogram already built by the worker instead of decoding and sampling the source again. Loading another image clears that cached state and invalidates pending results.
Deterministic Extraction Off the UI Thread
The extraction pipeline samples at most 65,536 pixels on a deterministic grid. It folds identical RGB values into an alpha-weighted histogram, ignores fully transparent pixels, and lets partially transparent pixels contribute proportionally.
A weighted median-cut pass repeatedly chooses the bucket with the strongest combination of population and channel range, splits it near half of its cumulative weight, and computes a weighted average for each result. Duplicate results are removed, then the palette is ordered from dark to light with stable RGB tie-breakers. The requested count is a ceiling: an image with fewer useful colors may return fewer swatches.
This work runs in a Web Worker, away from the renderer UI. Generation identifiers prevent an older request from replacing a newer one, while the cached histogram makes count changes a quantization step rather than a second sampling pass.
Outputs for Drawing Tools
The primary output is a transparent PNG palette copied to the system clipboard, designed to paste into Clip Studio Paint or Krita as a normal image layer. Clipboard copying and PNG export share the same rendered image; separate Adobe Color Swatch (.aco) and GIMP/Krita Palette (.gpl) exporters preserve the extracted RGB values. A full 100-color result becomes a 10-by-10 swatch grid.
A Narrow Desktop Security Boundary
Electron owns the native clipboard, file dialogs, saving, and remote image transport. The sandboxed renderer receives only a small typed preload bridge and has no direct Node access. Browser input is treated as untrusted data: dragged HTML is parsed rather than executed, remote fetches accept direct HTTP(S) images without browser cookies, and byte, pixel, metadata, redirect, and timeout limits bound the work.
Source artwork stays in memory for the session. Palette Companion does not automatically write it to disk, keep an image history, or send it to a service.
Distribution
Palette Companion 1.0.0 is published for macOS and Windows, with downloads, checksums, platform notes, and current validation limitations kept in the public product documentation. The release records owner-accepted deferred native checks instead of presenting them as passed; an earlier build’s reported Krita copy/paste and palette import result does not establish every platform, browser, or Clip Studio Paint workflow.
Lessons Learned
Moving a feature out of a plugin clarified which parts were truly portable. The extraction and rendering logic could remain deterministic and testable, while native privileges became a deliberately small edge around it. That separation made the tool useful across drawing applications without making private artwork or host automation part of the architecture.