Color/contrast/dithering sliders + before/after render preview
Advanced configuration gains three sliders (PIL ImageEnhance factors for color/contrast, 0-2, 1=unchanged; a 0-1 dithering strength) applied to every photo this frame renders. Confirmed the parameter conventions against a similar project (jwchen119/EPF: ImageEnhance.Color/Contrast, 1.0 baseline) before implementing; dithering strength isn't natively exposed by PIL's quantize(), so it's implemented by blending the source toward its own flat/undithered quantization before running Floyd- Steinberg on the blend -- at 0 there's no quantization error left to diffuse (exactly the flat result), at 1 it's the original unmodified behavior, with a smooth continuum between rather than dithering being an on/off toggle. image_pipeline.py split into composition (_compose), enhancement (_enhance), quantization (_quantize), and transpose+pack stages so render_frame (device bytes) and the new render_preview_png (a normal viewable PNG, upright logical orientation) share the same pipeline instead of duplicating it. Named-face overlay label math (face_labels.py) was already routed through the shared _placement_transform, so it needed no changes for the new params. Also added the requested before/after comparison: the Configuration tab's new Preview card shows the current photo's untouched Immich preview next to that same photo run through the frame's actual saved rendering pipeline (two new GET endpoints, /preview/original and /preview/rendered) -- immediate visual feedback for tuning the palette and these new sliders. "Refresh preview" re-fetches after saving. Schema migration v6 adds color_boost/contrast_boost/dither_strength, defaulting to 1.0/1.0/1.0 -- reproduces the exact previous rendering until a frame's Configuration tab changes one. Verified against the live-shaped test database: the migration, sliders persisting and clamping out-of-range input, both preview endpoints (real JPEG passthrough / real PNG at correct logical size+orientation), confirmed dither_strength=0 actually changes the rendered bytes vs. default, and the standing legacy-device curl suite.
This commit is contained in:
+17
-7
@@ -147,16 +147,26 @@ Pages: `/` (routing hub), `/setup`, `/login`, `/claim`, `/settings`,
|
||||
- `GET .../albums` -- the owner's Immich albums.
|
||||
- `POST .../config` -- **partial** update: only provided fields change
|
||||
(`name`, `album_id` -- resets queue/history on change --, `order`,
|
||||
`refresh_interval_s`, `smart_crop_faces`, `queue_target_len`,
|
||||
`orientation` (composed logically then rotated server-side; the
|
||||
on-device manage overlay still renders native, a known limitation),
|
||||
`quiet_hours_*` + `timezone` (a pure server-side decision shaping
|
||||
what `refresh_interval_s` gets handed to the device),
|
||||
`firmware_update_repo_url`, `firmware_auto_update`,
|
||||
`refresh_interval_s`, `display_mode` (`crop_fill`/`crop_faces`/
|
||||
`stretch_fill`/`letterbox`, see `image_pipeline.DISPLAY_MODES`),
|
||||
`queue_target_len`, `orientation` (composed logically then rotated
|
||||
server-side; the on-device manage overlay still renders native, a
|
||||
known limitation), `quiet_hours_*` + `timezone` (a pure server-side
|
||||
decision shaping what `refresh_interval_s` gets handed to the
|
||||
device), `firmware_update_repo_url`, `firmware_auto_update`,
|
||||
`battery_alert_threshold_pct` -- percent, or `-1`/blank to disable --,
|
||||
`palette` -- exactly 6 `#rrggbb` values in black/white/yellow/red/
|
||||
blue/green order --, `palette_reset` -- `true` clears back to the
|
||||
default palette).
|
||||
default palette --, `color_boost`/`contrast_boost` -- PIL
|
||||
`ImageEnhance` factors, 0-2, 1 = unchanged --, `dither_strength` --
|
||||
0-1, blends toward a flat/undithered quantization before running
|
||||
Floyd-Steinberg, so 0 = no dithering texture and 1 = full strength).
|
||||
- `GET .../preview/original`, `GET .../preview/rendered` -- the
|
||||
before/after comparison on the Configuration tab: the current
|
||||
photo's Immich preview untouched (JPEG), and that same photo run
|
||||
through this frame's actual saved rendering pipeline (PNG, upright
|
||||
logical orientation, not packed device bytes) -- reflects saved
|
||||
settings, not unsaved slider positions.
|
||||
- `POST .../take-control` -- always succeeds for a linked user.
|
||||
- `GET .../stats`, `GET .../battery-log`, `GET .../thumbnail/{asset_id}`.
|
||||
- `POST .../firmware` (manual .bin upload, esp_app_desc_t-validated),
|
||||
|
||||
Reference in New Issue
Block a user