Skip to content

Infinite color engine

Awawa edited this page Oct 6, 2025 · 1 revision

What is the Infinite Color Engine?

In short, it marks a clean break from the old 24-bit color space, moving to floating-point precision while still maintaining performance.

You might ask: Why bother, if most sources don’t provide more than 24-bit color, except perhaps the P010 format?

Well, here’s the thing:
such sources have always been available—even with something as basic as a cheap MS2109 grabber or flatbuffers external source.
In our application, when averaging colors for each LED, we’ve always had access to a high-precision theoretical color space.
Until now, that precision was being brutally truncated to 24-bit.

Another hidden “source” of precision has long been smoothing, which interpolates intermediate colors.
This entire subsystem has now been rewritten to handle floating-point numbers at both input and output.


What Does This Mean in Practice?

  • The obvious: using the possibilities of lamps that offer support for an extended color palette
  • Reduced banding, noise, and flicker
  • More stable color transitions across frames
  • Smoother post-processing corrections

Previously, when the final averaged color happened to fall on the boundary between two integers, even tiny changes in the source could trigger sudden jumps between frames.
By switching to floating-point, this issue has been drastically minimized.


Hardware Support

Extended color support is now available in drivers for:

  • All Philips Hue lamps using the Entertainment API (v1 & v2)
  • HD108

This covers a wide range of popular devices.
On my own Philips Hue lamps, the first noticeable improvement was much smoother transitions
where before there were obvious “steps” in color changes, now the shift feels more continuous.


Why “Infinite”?

The name isn’t just marketing.
The Infinite Color Engine works with a color palette of 1.24 × 10²⁷ possible values.
For comparison:

  • Old 24-bit color: 1.67 × 10⁷ values
  • New floating-point engine: 1.24 × 10²⁷ values

The difference is, quite literally, astronomical. 🌌


New smoothing algorithms

In addition to the transition to floating-point numbers, the focus was on adding parameters that control the abruptness of color changes (brightness limiter or averaging with the previous frame) and adding the ability to work in the YUV space, not just RGB.

Title Description
Linear Interpolator The Linear Interpolator is an adaptation of a legacy algorithm from previous HyperHDR versions, rewritten to use floating-point arithmetic for higher precision. It works by linearly interpolating the current color towards a target color, ensuring the transition completes over a defined duration regardless of the frame rate. Its key characteristic is the ability to smoothly retarget mid-animation, initiating a new, full-duration transition from its current state toward the new goal.
RGB Infinite Interpolator This algorithm smoothly animates RGB colors over a set duration, offering two distinct modes for the transition. The first is a direct linear interpolation for a straight path between colors, while the second is a smoothed mode where the current color gracefully 'chases'' the target to create an ease-in/ease-out effect. A key feature is its ability to intelligently rescale an animation's duration when interrupted, ensuring a perceptually constant speed of change.
YUV Infinite Interpolator This algorithm smoothly interpolates colors by operating in the YUV color space for more perceptually uniform transitions. Its main feature is limiting the rate of luminance change in each step, preventing sudden, jarring flashes of brightness. This ensures a visually pleasing effect, even if it extends the animation beyond its initially set duration to maintain that smoothness.
Hybrid Physics Infinite Interpolator This algorithm smoothly transitions between colors using a hybrid physical model. A linear 'pacer' defines the direct path and timing to the target color, while the actual output color follows this pacer like an object attached to a damped spring. This two-part approach creates fluid, natural-looking animations with customizable inertia and overshoot, all while operating in the perceptually-uniform YUV color space.
Exponential Infinite Interpolator Classic exponential implementation of smoothing updates LED colors toward a target, reacting quickly to large differences and slowing as they approach the target, producing smooth, natural ambient lighting transitions.

Processing Pipeline (Before → Now)

⬇️ 1. Video Frame Area Averaging for LED

  • Before: color (float) truncated to 24-bit at output
  • Now: output remains as float

⬇️ 2. Post-Processing

  • Before: received, processed in pipeline, and output 24-bit color. some functions, such as changing luminance or saturation, could use float, but they still received and output 24-bit color
  • Now: both processing and input/output work on float colors

⬇️ 3. Smoothing

  • Before: input/output in 24-bit color, internal processing on float
  • Now: input, processing, and output all on float colors

⬇️ 4. LED Drivers

  • Before: always received and rendered 24-bit color
  • Now: if the device supports it (Philips Hue, HD108) → rendering at higher precision;
    otherwise → fallback to 24-bit rendering

The post-processing Pipeline (Before → Now)

Old approach (24-bit pipeline)

  • Operated directly on 8-bit nonlinear sRGB values.
  • Every transformation (brightness, per-channel gamma, calibration, temperature, backlight) worked on already quantized integers → rounding/precision loss at every step.
  • Per-channel gamma correction was not equivalent to standard gamma adjustment, and could distort hues 😬.
  • Input being nonlinear made operations like calibration and saturation adjustment less accurate (they are meant to be done in linear space).

New approach (float3 pipeline)

  • Operates first in linear sRGB space with float precision → avoids cumulative rounding errors.
  • Color temperature applied first: tinting works best before calibration so that calibration LUT/matrix can correct consistently.
  • Calibration in colorspace applied in linear domain → mathematically correct, ensures LUT/matrix is used as designed.
  • Scale color output (user parameter)
  • Convert back to nonlinear sRGB only once: avoids repeated conversions and precision loss.
  • Global user gamma correction applied consistently on all channels → perceptually uniform adjustment ✅.
  • Brightness and saturation after calibration: adjusting perceptual properties after ensuring primaries are correct.
  • Minimal backlight last: guarantees final safety floor regardless of prior adjustments.
  • Limit power output: scale down only if the power limit (user parameter) is exceeded

👉 Overall: the new pipeline is much more accurate, perceptually consistent, and scientifically correct. The old one was simpler but mathematically flawed.

Old approach (24-bit) New approach (float3)
Input: sRGB nonlinear 😬 (24-bit).
All further steps already lose accuracy due to rounding 😬
Input: sRGB linear (float3).
Correct starting point for calibration & math ✅
Steps:
1. Apply Brightness & Saturation
2. Apply User Gamma per channel 😬
3. Calibrate in Colorspace (on nonlinear data 😬)
4. Apply Color Temperature
5. Apply Minimal Backlight
Steps:
1. Apply Color Temperature (before calibration ✅)
2. Calibrate in Colorspace (linear domain ✅)
3. Scale color output (user parameter ✅)
4. Convert to nonlinear sRGB (only once ✅)
5. Apply User Gamma (global, consistent ✅)
6. Apply Brightness & Saturation (perceptual ops ✅)
7. Apply Minimal Backlight (final floor ✅)
8. Limit power output (scale down only if the power limit is exceeded ✅)
Output: sRGB nonlinear (24-bit). Output: sRGB nonlinear (float3 → quantized later).
Clone this wiki locally