The Renoise Theme-to-Screenshot Preview System
A Pixel-Accurate Theme Preview Engine for Closed-Source Software
Abstract. This document covers a pixel-accurate theme preview system that renders Renoise Digital Audio Workstation (DAW) color themes without requiring a Renoise installation. The system maps every pixel in reference screenshots to semantic UI elements via binary pixel maps, then recolors those pixels using colors extracted from .xrnc theme files. The result is a three-pass rendering pipeline that produces Pattern Editor preview images indistinguishable from native screenshots — at a fraction of the computational and licensing cost.
1. Executive Summary
Renoise is a professional music tracker and Digital Audio Workstation used by electronic musicians worldwide. Like many DAWs, it supports custom color themes via .xrnc XML files containing 70+ color definitions. However, Renoise provides no built-in theme preview mechanism. Music producers who want to evaluate a theme must install it, restart Renoise, and manually inspect every view.
The Renoise Theme-to-Screenshot Preview System solves this by treating theme preview as a pixel recoloring problem rather than a UI rendering problem:
- Map every pixel in a reference screenshot to a semantic UI element
- Parse any
.xrncfile to extract its color definitions - Recolor the mapped pixels using the theme's colors
- Composite text and anti-aliased details using a special black/white text-mask theme
Key innovations:
- Binary pixel maps derived from automated green-probe differential analysis
- A three-pass rendering algorithm that handles anti-aliasing, boundary smoothing, and text compositing
- A headless Xvfb automation pipeline that generates 71 theme variants in ~3 minutes
- A live Theme Creator tool with 70 color pickers ranked by pixel coverage
2. The Problem Space
2.1 What is a Renoise Theme?
A Renoise theme is an XML file with the extension .xrnc (Renoise Color). It defines colors for 70+ UI elements, from the main application background (Main_Back) to the color of automation curve edges (Automation_Line_Edge).
<?xml version="1.0" encoding="UTF-8"?>
<SkinColors doc_version="12">
<Main_Back>30,30,30</Main_Back>
<Main_Font>220,220,220</Main_Font>
<Body_Back>40,40,50</Body_Back>
<!-- ... 70 more elements ... -->
</SkinColors>
These colors control every visible surface of Renoise's interface. Changing Main_Back affects roughly 46% of the screen. Changing VuMeter_Peak affects perhaps 0.01%.
2.2 The Preview Gap
Before this system existed, theme authors and curators faced three problems:
- No built-in preview. Renoise does not generate thumbnails or previews.
- Manual screenshots are inconsistent. Different users run different screen resolutions, window sizes, and song projects.
- Renoise is required. Generating a screenshot means having Renoise installed, licensed, and running.
2.3 Why Not Just Render the UI?
The most obvious solution — parse the theme and draw the UI from scratch — is infeasible. Renoise is closed-source. Its UI contains thousands of custom widgets, proprietary bevel and shading algorithms, and anti-aliased text with unknown font metrics. We needed a different approach.
3. System Architecture
The upload processing pipeline when a .xrnc file is uploaded:
| Stage | Module | What It Does |
|---|---|---|
| 1 | Multer | Handles file upload, sanitizes filename, stores in public/uploads/themes/ |
| 2 | lib/parser.js | Parses XML, extracts colors, assigns semantic roles with weights. Exports elementColorMap — single source of truth for all downstream steps. |
| 3 | lib/categorize.js | Converts colors to HSL, runs weighted analysis to auto-tag themes (dark/light, neon/pastel, etc.) |
| 4 | lib/palette.js | Generates SVG palette strips tiered by MAIN/SECONDARY/UI/ACCENTS bands |
| 5 | lib/preview-renderer.js | Renders PNG previews using the binary pixel map system (see Section 4) |
All stages complete in under 2 seconds for a typical theme.
4. The Pixel Map System (Core Innovation)
4.1 Why Pixel Maps?
Think of it like a paint-by-numbers template. Every pixel has a number, and the theme file provides the color for each number. We never need to understand how Renoise draws its UI — only which element owns which pixel.
4.2 The White-Baseline + Green Probe Method
We generate 71 variant themes and capture them via headless automation:
| Step | Action |
|---|---|
| 1 | Generate 1 baseline (every element = white) and 70 probes (one element = green, rest = white) |
| 2 | Capture each variant screenshot via Renoise inside Xvfb headless display at 1920×1080 |
| 3 | Diff each probe screenshot against the white baseline — green-ish pixels belong to that element |
| 4 | Resolve overlaps: smaller-coverage elements (text, icons) win over larger ones (backgrounds) |
Compared to the original "rainbow voting" method, this approach has zero color collision risk and clean boundary definitions.
4.3 The Three-Pass Rendering Algorithm
Pass 1 — Paint Known Pixels: Iterate every pixel in the map. If the index is not 255 (UNMATCHED), paint with the theme's color using an O(1) lookup array.
Pass 2 — Fill Unmatched Pixels: Fill unpainted pixels by averaging colors of 8-connected neighbors. Critical: reads from the immutable pixel map (not the output buffer) to prevent fill propagation artifacts.
Pass 3 — Composite Text & Icons: Uses a special text-masking theme (all chrome = black, all text/icons = white) as an alpha mask. Rec.601 perceptual luminance converts B/W values to alpha, then blends text color over the existing pixel using standard alpha compositing.
4.4 Text Masking Theme
A special .xrnc theme renders everything black except text/icon pixels (white). Screenshotting with this theme produces an alpha mask. Rec.601 luminance (0.299R + 0.587G + 0.114B) accounts for human visual sensitivity to green. Known non-text elements (scrollbars, sliders, VU meters) are excluded from compositing.
5. The Theme Creator Tool
The creator at /create (login required) presents 70 color pickers ranked by pixel coverage, with live preview:
| Rank | Element | Coverage |
|---|---|---|
| 1 | Main_Back | 46.38% |
| 2 | Body_Back | 31.50% |
| 3 | Button_Back | 6.61% |
| 4 | ValueBox_Back | 4.10% |
| 5 | Pattern_Default_Back | 3.51% |
| 6 | Main_Font | 2.53% |
This ranking is load-bearing: the top 10 elements control 97.9% of the visible screen. A user can create a recognizable theme in under 30 seconds.
6. Headless Automation Pipeline
Generating 71 screenshots is fully automated:
| Tool | Role |
|---|---|
| Xvfb | Virtual X11 display (1920×1080×24) — no physical monitor |
| xdotool | Window detection and geometry verification |
| maim | Screenshot capture by window ID |
| Renoise | The DAW itself, with overridden config |
| Bash + Python | Orchestration, config injection, cleanup |
Key optimization: temp config isolation (never touches user config), fast kill-9 restart cycle (~1 second per variant), plugin rescanning disabled, demo song loaded via CLI argument. Full 71-variant capture completes in ~3 minutes.
7. Results
| Metric | Value |
|---|---|
| Variants captured | 71 (1 baseline + 70 probes) |
| Elements mapped | 37 |
| Matched pixels | 95.0% |
| Unmatched pixels | 5.9% |
The system achieves pixel-perfect color assignment for all mapped elements, with zero Renoise code, assets, or runtime dependency on the server.
8. Future Work
- Map refinement — adjusting probe thresholds for additional UI states
- SVG-based vector renderer — arbitrary resolution scaling using existing
maps/*.svgoutlines - Theme diff & merge tools — perceptual distance between themes, version comparison, blending
9. File Index
Core Libraries
| File | Purpose |
|---|---|
lib/parser.js | Parses .xrnc XML; extracts colors; assigns semantic roles and weights |
lib/categorize.js | HSL conversion; weighted analysis for auto-tagging |
lib/palette.js | Weighted SVG palette strip generation |
lib/preview-renderer.js | Three-pass pixel map renderer: paint → fill → composite |
lib/database.js | SQLite schema, prepared statements, auth |
lib/xrnc-generator.js | Theme Creator .xrnc export |
Automation Tools
| File | Purpose |
|---|---|
tools/generate-white-variants.js | Generates 71 variant themes |
tools/capture-variants.sh | Headless bash pipeline: Xvfb → Renoise → maim |
tools/build-diff-maps.js | Builds pixel maps via green-delta detection |
Map Assets
| File | Purpose |
|---|---|
maps/pattern.bin | Flat Uint8Array — 2,073,600 bytes at 1920×1080 |
maps/pattern.json | Width, height, ordered element name array |
maps/pattern-text.png | Cached text-theme screenshot for Pass 3 |
maps/*.svg | Vector outlines (future SVG renderer) |
The demo song used during automated capture is by Hunz. The Renoise team built an extraordinarily customizable UI; this system exists to make that customization more accessible.
Document version 1.0 · Generated for the Renoise Themes open-source project