Fix gamma correction, frame interpolation flicker, and target card redraws
- Fix inverted gamma formula: use (i/255)^gamma instead of (i/255)^(1/gamma) so gamma>1 correctly darkens midtones (standard LED gamma correction) - Fix frame interpolation flicker: move interp buffer update after temporal smoothing so idle-tick output is consistent with new-frame output - Fix target card hover/animation reset: use stable placeholder values in card HTML for volatile metrics (data-tm attributes), patch real values in-place after reconcile instead of replacing entire card DOM element Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -20,7 +20,7 @@ class GammaFilter(PostprocessingFilter):
|
||||
super().__init__(options)
|
||||
value = self.options["value"]
|
||||
lut = np.arange(256, dtype=np.float32) / 255.0
|
||||
np.power(lut, 1.0 / value, out=lut)
|
||||
np.power(lut, value, out=lut)
|
||||
self._lut = np.clip(lut * 255.0, 0, 255).astype(np.uint8)
|
||||
|
||||
@classmethod
|
||||
|
||||
@@ -64,13 +64,13 @@ def _build_gamma_lut(gamma: float) -> np.ndarray:
|
||||
"""Build a 256-entry uint8 LUT for gamma correction.
|
||||
|
||||
gamma=1.0: identity (no correction)
|
||||
gamma<1.0: brighter midtones
|
||||
gamma>1.0: darker midtones
|
||||
gamma<1.0: brighter midtones (gamma < 1 lifts shadows)
|
||||
gamma>1.0: darker midtones (standard LED gamma, e.g. 2.2–2.8)
|
||||
"""
|
||||
if gamma == 1.0:
|
||||
return np.arange(256, dtype=np.uint8)
|
||||
lut = np.array(
|
||||
[min(255, int(((i / 255.0) ** (1.0 / gamma)) * 255 + 0.5)) for i in range(256)],
|
||||
[min(255, int(((i / 255.0) ** gamma) * 255 + 0.5)) for i in range(256)],
|
||||
dtype=np.uint8,
|
||||
)
|
||||
return lut
|
||||
@@ -407,13 +407,6 @@ class PictureColorStripStream(ColorStripStream):
|
||||
frame_buf[:] = led_colors
|
||||
led_colors = frame_buf
|
||||
|
||||
# Update interpolation buffers (raw colors, before corrections)
|
||||
if self._frame_interpolation:
|
||||
self._interp_from = self._interp_to
|
||||
self._interp_to = led_colors.copy()
|
||||
self._interp_start = loop_start
|
||||
self._interp_duration = max(interval, 0.001)
|
||||
|
||||
# Temporal smoothing (pre-allocated uint16 scratch)
|
||||
smoothing = self._smoothing
|
||||
if (
|
||||
@@ -426,6 +419,15 @@ class PictureColorStripStream(ColorStripStream):
|
||||
int(smoothing * 256), led_colors)
|
||||
t3 = time.perf_counter()
|
||||
|
||||
# Update interpolation buffers (smoothed colors, before corrections)
|
||||
# Must be AFTER smoothing so idle-tick interpolation produces
|
||||
# output consistent with new-frame ticks (both smoothed).
|
||||
if self._frame_interpolation:
|
||||
self._interp_from = self._interp_to
|
||||
self._interp_to = led_colors.copy()
|
||||
self._interp_start = loop_start
|
||||
self._interp_duration = max(interval, 0.001)
|
||||
|
||||
# Saturation (pre-allocated int32 scratch)
|
||||
saturation = self._saturation
|
||||
if saturation != 1.0:
|
||||
|
||||
Reference in New Issue
Block a user