Skip to content

feat(hdr): add phone HDR editing on Mac and iOS - #144

Draft
dancancer wants to merge 3 commits into
developmentfrom
feature/hdr-photo-design
Draft

dancancer wants to merge 3 commits into
developmentfrom
feature/hdr-photo-design

Conversation

@dancancer

@dancancer dancancer commented Oct 28, 2026 •

Copy link
Copy Markdown
Owner

What changes

Mac/iOS can import original iPhone gain-map HEIC/JPEG and Android Ultra HDR JPEG, edit immutable HDR/SDR float32 renditions, monitor HDR presentation and save HDR or explicit SDR output. Basic exposure, relative white balance, tone, saturation and geometry are supported. Unsupported looks and advanced operators remain disabled while their stored values are preserved.

  • Add versioned HDR C ABI, original-container import, source identity/cache ownership, FP16 Metal display with SDR fallback, histograms, reference white and false color. Preserve the existing request v2 layout and RAW/SDR semantics. Display settings stay outside recipes, history and exported pixels.
  • Add HDR state, copy/paste and preset scopes, undo/redo, per-target batch preparation, Edit JSON v6 and negotiated MCP support. Integrate Master Recipe v4 from development.
  • Add HDR JPEG with ISO/XMP gain-map metadata, explicit SDR JPEG/16-bit PNG/rendered DNG, Photos original-resource import/publication, atomic output and source identity/provenance checks.
  • Pin libultrahdr 2.0.2 and its license/dependency closure. Its ARM intrinsics remain disabled because the independent P3 numeric regression exposed incorrect colors; numeric thresholds are unchanged.

The review fixes in 630d55e2 also:

  • Decode SDR editing previews of HDR containers with PREVIEW + long edge on both clients. Preserve original geometry through an additive allocation-free sony2fuji_hdr_geometry_size query; reject preview proxies as FINAL input, and reload the complete original for JPEG/DNG export. SDR-only presentation skips the unused HDR histogram scan.
  • Use sourceDefaultSettings for iOS preset and collection capture when no edit record exists. Initialize iOS collection synchronization with hdrCommon and expose hdrSupported, including relative temperature/tint.
  • Reuse the existing OpenCV CPU worker pool for independent HDR edit/resize pixels on configured builds, with a serial fallback. Preserve per-pixel operation order, source immutability and finite-overflow rejection. GPU Force still reports unsupported for HDR editing.

Validation

Current source: 630d55e2ee5bd921f00784a086095395dfc6c671. Base refreshed and unchanged at d7d5504e905fc325b08589dbf2e40ed96c6d5891. Local hardware: Apple M3 Max, 14 cores, 36 GiB; macOS 27.0.1 and Xcode iOS 27 simulator. Local results are separate from GitHub CI.

Current-source check Actual result
ctest --test-dir lutools/build-macos --output-on-failure 105/105 passed, including HDR numeric/API/render, deterministic parallel/scalar comparison and legacy regressions
bash scripts/ci/apple-models.sh macos and ... ios Both passed: HDR state/transfer and existing edit/reset/persistence/preset/transfer contracts
iOS hdr-history.sh and adjustment-history-model.sh <app> <owned simulator> Passed: fresh HDR preset without record/clipboard/history writes; HDR collection capture; absent-record undo/redo/reload; 54 existing native history assertions
Mac/iOS hdr-sdr-preview.sh with a read-only public 12 MP Ultra HDR original Passed: bounded SDR proxy allocation, native geometry after rotation/crop, proxy rejection for FINAL, full-size fresh FINAL decode; iOS JPEG export reloads the full original rather than its cached proxy
bash lutools/platform/ios/build-framework.sh and framework verification Fresh device + arm64/x86_64 simulator slices built; patched dependency/license/runtime closure passed
RAWLAB_RUM=0 RAWLAB_DUALDN=0 JOBS=4 RAWLAB_APP_PATH=<task output> bash RawLabMac/build.sh App build, packaging, signatures and bundled dependencies passed; no production RUM/AI package claim
iOS arm64 simulator xcodebuild ... build-for-testing App and UI test targets compiled; UI execution is recorded separately below
IOS_SIMULATOR_UDID=<dedicated simulator> bash RawLab/tests/hdr-ui.sh <products> <output> 4/4 executed tests passed, 181.373 s total. Fresh app data verified direct preset save and collection default 7-field scope/preflight (50.057 s); HDR copy/batch inspection and Photos export (44.666 s); landscape (15.622 s); original import, exposure undo/redo, display isolation, HDR/SDR Photos output and mode-conversion undo (71.028 s). Saved preset and relative-WB scope screenshots visually checked
python3 -m unittest discover -s scripts/ci -p 'test_*.py' -v 80 tests, 4 expected skips, passed
Registered CLI encoding/TIFF/single-preview/tool-group checks and localization generation Passed; all 30 localization catalogs are byte-identical
RAWLAB_MCP_CLI=<current CLI> uv run --project tools/mcp --frozen python -m unittest discover -s tools/mcp/tests -v 44/44 passed, including real CLI compatibility checks
git diff --check and public fixture SHA-256 verification Passed; no photo, screenshot, build product or one-PR measurement committed

The preview regression reproduced the original full 4080×3072 iOS buffer and 50,135,040-byte Mac raster retention before the fix. The 48 MP admission/OOM scenario remains a static call-chain finding, not a reproduced device OOM.

Prior-source evidence at 51893dbd: Mac native UI verified public 12 MP import, +1 EV, undo/redo, display monitoring, histogram, full-size HDR JPEG (re-probed as protocol 4, 4080×3072) and batch float inspection. Runtime headroom was 1. The current Mac native preview regression and build passed; repeating the native UI on the new head is blocked by the locked desktop. Prior Mac Master Recipe/HDR history/batch/Agent and LUT adapter checks remain historical evidence, not newly executed checks.

The unregistered legacy test_interface_copy.py has known baseline failures (previous comparison: current 4 failures / 2 errors, baseline 5 failures / 2 errors). Its HDR format/window checks pass. Unrelated glossary/punctuation checks were left unchanged.

GitHub CI for the current head: Hosted CI #301. Select affected platforms and Contracts and CI policy passed. Platform jobs and the aggregate result job were skipped by the Draft policy. Platform model/build jobs and UI execution are not implied by Draft contract checks.

Performance and hardware acceleration

Synthetic pure HDR edit/resize core, three trials per case, median wall time. The pre-change binary was retained before editing the core; old 14-thread capacity still measured CPU/wall about 1. The new 14-worker runs measured CPU/wall 9.60–10.42, confirming real multi-core execution. Both renditions' full pixel hashes match the serial baseline in every trial.

Canvas Previous serial core Current 14-worker core Speedup
1280×960 97.851 ms 12.739 ms 7.68×
4000×3000 949.720 ms 117.752 ms 8.07×
5656×4242 1787.190 ms 232.796 ms 7.68×
8000×6000 3594.450 ms 467.814 ms 7.68×

These are core measurements, excluding codec, file I/O, Swift packing, UI and physical iPhone execution. Peak resident memory is essentially unchanged: about 558.6 MiB at 12 MP and 2206.6 MiB (2.16 GiB) at 48 MP. The preview fix bounds its allocation; full-resolution dual-rendition editing still needs substantial memory and may be rejected by admission control.

Hardware acceleration is not complete: Metal handles FP16 presentation; HDR edit/resize uses CPU workers. Apple float decoding explicitly selects the software Core Image renderer; JPEG SIMD and libultrahdr ARM intrinsics are disabled in this pinned configuration. Statistics, pixel packing and geometry also contain CPU work. The display retains its existing 30 fps configuration; idle GPU/power profiling and a safe demand-driven display implementation remain follow-up work. Do not enable codec intrinsics or add a GPU backend without the independent P3/negative/over-range/CPU-reference acceptance matrix.

Remaining issues and acceptance gates

This remains Draft and does not close HDR-05. The user approved proceeding with local verification while retaining unavailable device gates.

  • Mac collection synchronization: the equivalent default-scope UI wiring issue was found during the symmetry audit. Its correction is prepared locally and deliberately excluded from this head because the desktop is locked and the required native UI gate cannot run. Apply and verify it after unlock before treating Mac synchronization as complete.
  • Physical iPhone: the current framework performance harness is built/signed/installed for the authorized iPhone 14 Pro Max, but the device locked; no complete current-source physical performance report was obtained. The earlier native phone result used an older ABI/codec combination and is not current-source acceptance. Full editor workflow and measured EDR brightness remain unverified.
  • The earlier iOS 27 final Undo idle wait of about 278 s was not reproduced in the current four-test run (complete workflow 71.028 s). Its root cause is not proven; this is not a general responsiveness/idle-power acceptance claim.
  • Still required: minimum macOS 15 / iOS 18 runtime coverage, physical Intel HDR Mac and HDR iPad, external Apple/Android viewer interoperability, real ISO/HDR-primary phone originals, the full 24/48 MP device memory/failure matrix, and remaining language/accessibility/iCloud/limited-library permission combinations.
  • Android/Windows HDR client UI, advanced HDR operators/looks and additional container families remain outside this first delivery. No merge or release is authorized by this PR.

Design/contracts: docs/design/hdr-photos/technical-design.md, docs/integration/hdr-photos/implementation-plan.md, lutools/docs/hdr-color-contract.md, lutools/docs/edit-json.md. Automatic/manual verification follows docs/process/ci.md.

Preserve native geometry and reload full sources for final output. Use HDR source defaults for first-import presets and collection scopes, and reuse the existing CPU worker pool without changing pixel results.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant