Commit Graph
5 Commits
Author SHA1 Message Date
insideTheFluxandClaude Opus 5.5 0b610c8307 LR-PREF-DISPLAY: an unreadable Windows advanced-colour state leaves previews sRGB
When the display configuration, the window's display path or its advanced-colour state can't be
read, `monitor_color` answered with the monitor's profile as if Windows weren't colour-managing the
desktop. If it was (HDR, Auto Color Management), previews were converted twice. It now answers
`Unknown`, as the crate's other failures do, so previews stay sRGB (Windows 10 before 1709 and
drivers that don't report the state included).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GfjNkJiMUagz3DN3zoV2rV
2026-10-25 22:05:23 -07:00
Claude 423d209d16 LR-PREF-DISPLAY: Windows previews follow the monitor's colour profile
While no monitor profile is chosen in Settings > Display, Windows now shows
previews through the profile Windows Color System assigns to the monitor
showing the window (per-user or system), as macOS and Linux already do. It is
read about once a second, so moving the window to another monitor and changing
the profile in Windows are followed without a restart. While Windows
colour-manages the desktop itself (HDR, Auto Color Management), previews stay
sRGB.

The Win32 calls live in a new L0 helper crate, crates/wincolor, the second
crate allowed `unsafe` after crates/sysmem (SAFETY comments on every block,
safe API, Unknown on any failure); CLAUDE.md and AGENTS.md name it. GDI's
GetICMProfileW keeps the profile a process first saw, so WCS is read directly
and GetICMProfileW is only a fallback.

The profile-file loader moves from the Linux-only colord.rs to a shared
profile_file.rs (unchanged), with a cache that re-reads a file only when it
changes.

Verified on Windows 11 by setting and clearing a Display P3 profile and
toggling HDR while the app ran.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K93HTyCiwYvbRGaAkjPvXn
2026-10-20 22:24:20 -07:00
Andrew FrahnandClaude Opus 5.5 8695c3391f LR-PREF-DISPLAY: on Linux, previews use the display profile from colord
While no monitor profile is chosen, the Linux app reads the profile the
desktop assigns to the display in colord (org.freedesktop.ColorManager,
system bus, via zbus) on a background thread every 3 s, and shows
previews through it. With several displays it is used only when they all
share one profile; without colord the view stays sRGB. Windows' WCS
needs FFI and stays manual. Also satisfies clippy 1.99's
chunks_exact_to_as_chunks in spots.rs.

Sources: the colord D-Bus API documentation; own design.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-12 04:42:12 +11:00
lloydandClaude Opus 5.5 d7eb6b2ab4 LR-PREF-DISPLAY: macOS previews follow the screen's profile, so they match exports (#787)
Previews looked more saturated than the exported files on Mac screens. The
pixels are the same: preview and export match to within one level on the CPU
and GPU paths, and exports embed a correct sRGB profile. But wgpu leaves the
window's Metal layer without a colour space for sRGB surfaces, and Core
Animation shows such a layer without colour matching ("If nil, no
colormatching occurs", CAMetalLayer.h). On a P3 screen the sRGB previews
were therefore shown too saturated, while Preview and Photos convert the
exports properly.

While no monitor profile is chosen in Settings > Display, the desktop app now
shows previews through the profile of the screen the window is on
(NSWindow.screen.colorSpace.ICCProfileData, safe objc2 calls), through the
existing display-profile path. It is read again about once a second, so
moving the window to another screen is followed. A chosen profile still wins;
"Use Screen Profile" goes back to it. app.displayProfile reports it as
path: null, screen: true. Other platforms and headless sessions are
unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 19:51:01 +02:00
kelannaandClaude Opus 5.5 3bcc265bf6 LR-PREF-DISPLAY: monitor ICC profiles (display colour management)
Previews were always sRGB, which wide-gamut monitors show oversaturated.
Settings > Display > Choose Profile... (and the UI command
app.displayProfile) now shows photos through the monitor's ICC profile,
matrix/TRC or LUT-based.

- codecs: DisplayProfile (moxcms): the display's primaries (colorant tags,
  or measured through the A2B tables of a LUT-only profile), the proxy ->
  device correction (per-channel curve tables for matrix/TRC profiles, a
  CMS transform for LUT profiles) and sRGB <-> display transforms.
- pipeline: DisplaySpace / RenderRequest::display: the per-pixel stage
  renders into the display's primaries and gamut maps into its gamut
  (CPU and GPU: only to_out / out_luma change). Soft proofing's display
  gamut warning uses the display's gamut.
- engine: RenderJob::with_display; display::present converts sRGB
  results (thumbnails, cached previews, embedded JPEGs). Histograms and
  the preview caches stay sRGB; exports are unchanged.
- ui: the loupe, Before, Compare, hover and second window render for the
  display; everything else is converted on the render workers. Settings >
  Display tab, ui.json setting, file picker opening in the system's ICC
  folder.

Tests: profile parsing and transforms (sRGB, P3, gamma 2.2, a synthetic
LUT-only profile, corrupted files), display renders equal 8-bit renders
into the matching output space, sampled histograms, and a headless UI test
of the whole flow. docs/display-profiles.md describes the design.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WEuxxPyG8t6KcADbZSEAUj
2026-10-09 11:21:09 -07:00