Skip to content

Latest commit

 

History

History
529 lines (456 loc) · 28.5 KB

File metadata and controls

529 lines (456 loc) · 28.5 KB

📋 Project Photon Task List

Phase 0: Infrastructure & Setup [DONE]

  • Test Environment Setup
  • CI/Lint Configuration

Phase 1: The "Real" Image (Core Engine) [DONE]

  • RawEngine Implementation (C++)
  • RawViewport Integration

Phase 2: User Interface (Shadcn/Zinc Theme) [DONE]

  • Theme System
  • Core Components
  • Layout Implementation

Phase 3: Processing Pipeline & Library [DONE]

  • Basic Image Processing (Exposure on CPU - to be optimized)
  • Asynchronous Loading
  • Real Thumbnails (LibRaw extraction + .PhotonData cache)
  • Library Integration (Double-click to open, filmstrip sync)
  • Interactive Viewport (Pan & Zoom)

Phase 4: Advanced Tool Panel & GPU Pipeline [DONE]

  • GPU-Accelerated Edits
    • Move Exposure/Contrast calculation to Fragment Shader.
    • Implement Vibrance/Saturation in shader.
  • Advanced Tool Panel (DevelopView.qml)
    • Implement Collapsible.qml component for accordions.
    • Light Section: Highlights, Shadows, Whites, Blacks sliders.
    • Presence Section: Vibrance, Saturation sliders.
    • Color (HSL) Section: 8-band targeted adjustments.
    • Color Grading Section: Shadows/Midtones/Highlights tinting.
    • Creative Section: Film Grain and Advanced Vignette.
  • Non-Destructive Edit Stack
    • Store edits in JSON sidecar files.
    • Implement persistent Undo/Redo history.

Phase 5: Advanced Features & Refinement [DONE]

  • Histogram Component
    • Compute RGB/Luma distribution in C++ (Async).
    • Render histogram overlay in QML/C++.
  • Technical Polish
    • Implement Dithering for high-precision output.
    • Optimize GPU pipeline performance.

Phase 6: UX Enhancements [DONE]

  • EXIF Metadata
    • Show EXIF metadata.
    • Orient thumbnails using EXIF orientation.
  • Stability & Polish
    • Fix viewport aspect ratio and stretching issues.
    • Synchronize Histogram math with GPU pipeline.

Phase 7: Advanced Edit Management [DONE]

  • Restore to Original
    • Implement global reset logic in C++.
    • Add "Restore" button with Lucide icon to viewport toolbar.
    • Implement "isDefault" check to enable/disable reset action.

Phase 8: Preset Foundations [DONE]

  • Preset System
    • Implement PresetManager (C++) with cross-platform storage.
    • Add applySettings batch logic to RawEngine.
    • Create core PresetPanel.qml logic.

Phase 9: Advanced Sidebar & Tool Selection [DONE]

  • Sidebar Refactoring

    • Implement right-side Section Switcher (Icon-sized navigation).
    • Move Presets to the right sidebar stack.
    • Implement tabbed layout for Metadata, Edit, Crop, Lens, and Presets.
  • Presets Refinement

    • Replace 'x' delete button with trash icon.
    • Implement delete confirmation dialog.
  • Tool Panels

    • Add Export panel placeholder.
  • Develop UI Polish

    • Remove floating top bar in Development view (exclusive to Library/Settings).
    • Add sidebar-based navigation for Library and Settings.

    Phase 11: Advanced Settings & Diagnostics [DONE]

    • GPU Management
      • Detect available Vulkan physical devices in C++.
      • Implement robust GPU selection logic in main.cpp using multiple env vars.
    • Aesthetics & Theme
      • Implement Light/Dark mode toggle.
      • Implement Accent color selection.
      • Synchronize Theme.qml with persistent settings.
    • Cache & Maintenance
      • Implement "Clear Thumbnail Cache" logic.
      • Context-aware enabling/disabling of cache maintenance.
    • Logging System
      • Implement LogManager C++ class with log level filtering.
      • Add log file location selection to UI.
      • Set default log location based on OS standards.

    Phase 12: Hybrid Denoising Pipeline [DONE]

    • Step 1: CPU Algorithm Refinement
      • Refactor Denoiser.cpp to use Luma-only Block Matching.
      • Implement Spatial Tiling (256x256 tiles) for cache locality.
      • Implement fully unrolled 16-point Walsh-Hadamard transform.
    • Step 2: Advanced GPU Preview (NLM)
      • Implement Non-Local Means (NLM) shader in RawViewport.frag.
      • Optimize search radius and patch size for 60fps performance.
  • Step 3: Vulkan-Native Search Offload [DONE]

    • Implement initial Patch Search shaders (3x3 patch SSD).
    • Refactor GpuSearcher to use plain Vulkan (independent compute queue).
    • Implement Vulkan-to-CPU transfer of search indices and SSD values.
    • Integrate search results into the BM3D aggregation phase in Denoiser.cpp.
    • Implement CPU fallback (handled automatically by checking Vulkan availability).
  • Asynchronous Workflow

    • Run heavy denoising in background thread.
    • Implement "Applying denoise..." UI indicator with rotating loader.
    • Implement automatic abort logic when switching photos.
    • Implement dynamic proxy scaling based on viewport size and zoom level.

Phase 13: High-Performance Denoise Control [DONE]

  • Explicit Execution Control
    • Add "Denoise" checkbox to UI.
    • Implement immediate abort logic when unchecking.
  • ROI-Driven Proxy Refinement
    • Update zoom logic to re-render visible crop in high-fidelity first.
    • Apply BM3D only to the high-quality visible region.
  • Lifecycle Management
    • Ensure RawEngine destructor clean-joins all background workers.
    • Prevent segfaults on application close while denoising (Fixed race in ThumbnailProvider and resource cleanup).
  • Viewport Constraints & Polish
    • Lock panning when zoom <= 100% (center image).
    • Constrain pan offset to image boundaries when zoomed in.
    • Implement double-click zoom cycle (100% -> 200% -> 400% -> 100%).
  • Fix pan/zoom interaction bug where double-click zoom triggered during pan.
  • Fix "Zoom Increases" bug during panning (Race condition in ROI calculation).
  • Fix rendering artifacts during zoom/pan with active denoising.

Phase 18: Preview Rendering Optimization [DONE]

  • Property Exposure
    • Expose showingPreview boolean property in RawViewport (C++).
  • Shader Bypass Logic
    • Add float isPreview to uniform block in RawViewport.frag.
    • Implement conditional branch in main() to bypass RAW pipeline when isPreview > 0.5.
  • UI Integration
    • Update ShaderEffect in App.qml to pass rawViewport.showingPreview to the shader.

Phase 19: Basic export functionality [DONE]

  • Export functionality (Save to JPEG/TIFF).

Phase 20: Full Vulkan BM3D Denoising [SUPERSEDED by Phase 24]

  • Architecture & Settings
    • Design VulkanDenoiser class architecture (plain Vulkan, compute shaders).
    • Create compute shader infrastructure (grouping, transform, filter, aggregate).
  • Compute Shader Implementation
    • Implement bm3d_grouping.comp - Block matching and group formation.
    • Implement bm3d_transform.comp - 3D DCT + Walsh-Hadamard transform.
    • Implement bm3d_filter.comp - Hard thresholding (step 1) and Wiener filtering (step 2).
    • Implement bm3d_aggregate.comp - Inverse transform and weighted aggregation.
  • Integration & Fallback
    • Implement wrapper denoise() method in Denoiser class.
    • Rename existing denoise() to denoiseCpu() for CPU-only path.
    • Integrate into RawEngine with async execution via QtConcurrent.
    • Respect previewDenoiseFull setting for high-quality previews.
  • Note: GPU full-denoise was removed due to stability issues. Phase 24 replaced it with an enhanced CPU pipeline (YCbCr + Multi-Scale Guided Filter). GpuSearcher (compute-queue patch matching) is retained.

Phase 21: Effects & Slider Refinements [DONE]

  • UI Refinements
    • Map Contrast slider range to [-100, 100] in UI.
    • Implement Effects section sliders: Clarity, Dehaze, Structure, Centrè.
    • Update Sharpening slider in Detail section with range [0, 100].
  • Engine & Shader Implementation
    • Expose new adjustment properties in RawEngine and RawViewport.
    • Implement apply_local_contrast utility in RawViewport.frag.
    • Implement apply_dehaze in RawViewport.frag.
    • Implement apply_centre (radial tonal/color) in RawViewport.frag.
  • Viewport Performance Optimization
    • Implement texture caching in RawViewport to decouple panning from texture uploads.
    • Optimize 16-bit to 8-bit conversion/upload path.
    • Throttled UI updates during pan.

Phase 22: Deployment & Versioning [DONE]

  • Versioning System
    • Create Version.h.in template for CMake.
    • Display version string in Settings footer.
    • Implement tag_release.sh for automated tagging.
    • tag_release.sh now also updates project(Photon VERSION X.Y.Z LANGUAGES CXX) in CMakeLists.txt.
  • CI/CD Infrastructure
    • Create GitHub Actions workflow for cross-platform builds.
    • Configure Nightly builds for develop and Stable for master.
    • Implement automated packaging: Linux AppImage (via linuxdeploy) and Windows MSI (via CPack/WiX).
    • Fix YAML syntax and artifact collection in CI workflow.
    • Resolve QML naming conflicts (renamed Slider to PhotonSlider) to fix AppImage crashes.
  • Cross-Platform Compatibility
    • Make all .PhotonData path handling OS-agnostic using QDir::toNativeSeparators.
    • Update CMake for vcpkg/MSVC compatibility on Windows.
  • Performance Optimization
    • Implement high-performance compiler flags (-O3, LTO, AVX2/FMA) for Release builds.

Phase 23: Adjust basic Tonemapping

Phase 24: Enhanced Denoiser — YCbCr + Multi-Scale Guided Filter [DONE]

  • YCbCr Pipeline Refactor
    • Implement AVX2-optimized RGB↔YCbCr conversion (BT.601 coefficients).
    • Refactor denoiseCpu() to convert to YCbCr, run BM3D on Y only, guided filter on Cb/Cr.
    • Generalize run_bm3d_step_joint() to support arbitrary channel count (1 or 3).
  • SIMD Box Filter
    • Implement O(1) separable box filter (horizontal + vertical running-sum passes).
    • AVX2 vectorized vertical pass (8 columns at a time).
  • Guided Filter Kernel
    • Implement full guided filter math (mean_I, mean_p, var, cov, a, b coefficients).
    • All element-wise operations SIMD-optimized (AVX2/FMA).
  • Multi-Scale Integration
    • Apply guided filter at 3 scales: Fine (r=2, ε=0.01), Medium (r=4, ε=0.04), Coarse (r=8, ε=0.1).
  • GpuDenoiser Cleanup
    • Remove dead denoiseGpu() method and GPU denoise parameters from Denoiser.
    • Remove useGpuDenoise setting from AppStateManager and QML settings toggle.
    • Clean GpuDenoiser references from test CMakeLists.
    • Update SPECIFICATION.md to document new chroma pipeline architecture.

Phase 25: Configurable Denoise Parameters UI [DONE]

  • DenoiseParams Struct
    • Added DenoiseParams struct with searchWindow, groupSize, chromaRadius, chromaDenoise fields.
    • Updated block_matching_joint to use parameterized search window and group size.
    • Updated multiscale_guided_filter to use parameterized radii and epsilon scaling.
  • RawEngine Integration
    • Added 4 new Q_PROPERTY declarations: denoiseSearchWindow, denoiseGroupSize, denoiseChromaRadius, denoiseChromaAmount.
    • Setters with validation, clamping, and denoise result invalidation.
    • JSON serialization/deserialization for .PhotonData edit stacks.
    • Updated resetToDefaults() and isDefault().
    • startAsyncDenoise() constructs DenoiseParams from member variables.
  • ImageDeveloper Integration
    • Export path reads new params from JSON and passes DenoiseParams to Denoiser::denoise().
  • QML UI
    • Added "Advanced" subsection in Detail panel under Noise Reduction.
    • Sliders: Search Window (9-39, step 2), Group Size (4-16, step 4), Chroma Radius (1-16), Chroma Denoise (0-100).
    • Added stepSize property passthrough in ControlGroupPhotonSlider.

Phase 26: GPU Chroma Filter & Sharpness Fix [DONE]

  • GPU-Accelerated Guided Filter (GpuChromaFilter)
    • Created box_filter.comp — separable horizontal/vertical box filter with coalesced memory access.
    • Created guided_ops.comp — element-wise operations: multiply, compute a/b coefficients, final output.
    • Created GpuChromaFilter class following GpuSearcher Vulkan compute pattern.
    • Single command buffer records all 51 dispatches (3 passes × 17 ops) with pipeline barriers.
    • Automatic CPU SIMD fallback when Vulkan is unavailable.
    • Integrated into Denoiser::denoiseCpu() — GPU path tried first for Cb and Cr channels.
  • Sharpness Slider Fix
    • Widened fragment shader blur kernel from 5-tap (1.5 texel radius) to 13-tap dual-radius (1.5 + 3.0–4.0 texels).
    • Effective unsharp mask now works on BM3D-denoised images.
  • Build & Infrastructure
    • Added box_filter.comp and guided_ops.comp to CMakeLists compute_shaders target.
    • Added GpuChromaFilter.cpp/.h to main and test CMakeLists.
    • Added CmdPipelineBarrier to VulkanFunctions struct and loader.
  • Documentation
    • Updated SPECIFICATION.md denoising pipeline section.

Phase 27: Edge-Selective Sharpening Mask [DONE]

  • Scharr Edge Detection in Fragment Shader
    • Implemented compute_edge_mask() using 3×3 Scharr kernels (Gx/Gy) on luminance.
    • Threshold/gain curve controlled by sharpenMask parameter (0–100).
    • Smooth Hermite interpolation for natural mask transitions.
    • Sharpening applied selectively: mix(preSharp, sharpened, finalMask).
  • Mask Feather (Option 1)
    • Spatial smoothing by averaging mask at 4 cardinal neighbors (radius 1–6 texels).
    • maskFeather parameter (0–100) controls blur radius.
  • Focus Detection (Option 2)
    • Local-contrast gating via |color − blurred| from existing unsharp mask blur (zero extra samples).
    • focusDetect parameter (0–100) restricts sharpening to in-focus areas.
    • Combined mask: finalMask = edgeMask × focusGate.
  • Alt+Drag Mask Preview
    • showSharpenMask uniform renders combined mask as grayscale overlay.
    • Created KeyTracker C++ singleton with global QEvent filter for reliable Alt key detection.
    • Connections in App.qml resets preview on Alt release.
  • Q_PROPERTY Chain
    • sharpenMask, maskFeather, focusDetect: RawEngine → RawViewport → QML ShaderEffect (persisted).
    • showSharpenMask: RawViewport → QML ShaderEffect (transient, not persisted).
    • JSON serialization, resetToDefaults(), isDefault() for all three parameters.
  • UI — DevelopView
    • "Masking", "Feather", "Focus" sliders (0–100) in Detail section.
    • Alt+drag activates grayscale combined mask preview on all three sliders.
  • Slider Reset Fix
    • Fixed ControlGroup slider not resetting visually on photo switch (broken QML binding after user drag).
  • Documentation
    • Updated SPECIFICATION.md with feather and focus detection details.
    • Updated TASKS.md.

Phase 28: Tone Curve, Library Improvements & Auto-Scan [DONE]

  • Histogram Fix
    • Changed normalization from global max to P99 percentile (skip bins 0/255).
    • Prevents single dominant bin from compressing entire histogram.
  • Library Sorting
    • Sort dropdown (Date/Name/Rating) with ascending/descending toggle.
    • Smart refreshFiles(): filter → sort → append pipeline.
    • Home button to return to Welcome view (Lucide house icon).
  • Auto-Scan
    • scanIntervalSeconds Q_PROPERTY on AppStateManager with QSettings persistence.
    • QTimer in LibraryView: periodic scan, smart diff (append-only, no flicker).
    • "Library" settings section in SettingView with interval spinner.
  • Tone Curve
    • ToneCurve.qml Canvas component: 4 channels (L/R/G/B), tab selector.
    • Click to add points, drag to move, double-click to remove interior points.
    • Endpoints draggable vertically only, interior points constrained between neighbors.
    • Monotonic cubic Hermite spline (Fritsch-Carlson) for smooth curves.
    • 4 × QVariantList Q_PROPERTYs: toneCurveLuma/Red/Green/Blue.
    • C++ spline→256-entry LUT computation in RawEngine::rebuildToneLut() (later superseded by Phase 34 full 65536 precision).
    • 256×4 QImage LUT texture (one row per channel) via ToneLutProvider image provider (later superseded by Phase 34 packed 16-bit LUT texture).
    • sampler2D toneLUT in fragment shader, applied after tonemapping.
    • Luma curve applied as ratio to preserve color relationships.
    • Per-channel (R/G/B) curves applied independently.
    • JSON serialization of control points, resetToDefaults(), isDefault().
    • Collapsible "Tone Curve" section after "Light" in DevelopView.
  • Documentation
    • Updated SPECIFICATION.md and TASKS.md.
  • Before/after view + keybind to \
  • Return to WelcomeView to change workspace

Phase 29: Stability Fixes & Filmstrip Sort Sync [DONE]

  • Preview Task Serialization
    • Prevent overlapping refreshPreview() tasks in PreviewManager (guards: m_refreshRunning / m_pendingRefreshPath).
    • Fixes segfault caused by concurrent develop() + denoise() pipelines competing for global thread pool.
  • Histogram Buffer Safety
    • clearProcessedImage() waits for in-flight histogram QtConcurrent::run future before freeing m_processedImage.
  • Spline LUT Hardening
    • evalMonotonicSpline / evalMonotonicSplineLut sort control points by X and deduplicate before evaluation.
    • Prevents NaN/inf from unsorted or duplicate-X points in malformed JSON.
  • Filmstrip Sort Sync
    • Sort properties (sortProperty, sortAscending) moved to shared window root object.
    • Library and filmstrip both read/write the same properties; sort order stays in sync.
    • App.qml refreshFiles() applies identical sort logic (Name/Date/Rating, asc/desc).

Phase 30: Crop & Geometry [DONE]

  • Backend Q_PROPERTYs
    • cropRect (QRectF), cropAspectRatio (float), straightenAngle (float ±45°), orientationSteps (int 0–3), flipHorizontal/flipVertical (bool) on RawEngine → RawViewport.
    • Added to stateToJson(), applyJsonToState(), resetToDefaults().
  • CropPanel.qml
    • Aspect ratio preset grid (Free, Original, 1:1, 5:4, 4:3, 3:2, 16:9, 21:9, 65:24).
    • Landscape/portrait toggle (click active preset).
    • Straighten slider ±45° with reset button.
    • Straighten tool (ruler icon) — draw reference line to auto-level.
    • Rotate Left/Right (90° steps), Flip Horizontal/Vertical toggles.
    • Reset all crop/geometry button.
    • Commit-on-Enter: changes saved to engine only on Enter; ESC discards.
  • CropOverlay.qml
    • Semi-transparent dark mask outside crop rect (50% in crop mode, 100% otherwise).
    • Rule of Thirds grid lines.
    • 8 drag handles (corners + edges) for resize with aspect ratio lock.
    • Center drag to move crop rect.
    • Straighten tool Canvas overlay with dashed reference line.
  • Visual Transforms
    • QML Rotation + Scale transforms on ShaderEffect for orientationSteps, straighten, flip.
  • Export Integration
    • ImageDeveloper::develop() applies orientation steps → flip → straighten → crop rect on rotated frame.
  • Icons
    • Lucide SVGs: rotate-cw, flip-horizontal, flip-vertical, ruler.
  • isDefault() & resetToDefaults()
    • Crop and geometry properties included in both.
  • Documentation
    • Updated SPECIFICATION.md and TASKS.md.

Phase 31: Baked Geometry Pipeline [DONE]

  • Engine Infrastructure
    • Add m_geometryBuffer, m_geometryWidth, m_geometryHeight, m_geometryBaked, m_inCropMode state to RawEngine.
    • Add Q_PROPERTY(bool geometryBaked) exposed to QML.
    • Add QFutureWatcher<void> m_geometryLoadWatcher for async geometry baking.
  • applyGeometryTransforms() Static Utility
    • Reusable QImage transform: orientation (N×90°) → flip → straighten → crop on rotated frame.
    • Transform order matches ImageDeveloper::develop().
  • reloadWithGeometry()
    • Async re-decode RAW from disk → apply geometry → store in m_geometryBuffer.
    • Sets geometryBaked = true, emits imageLoaded.
  • enterCropMode() / exitCropMode()
    • Enter: clears geometry bake, re-processes original image for live QML preview.
    • Exit (ESC): re-bakes geometry if non-default; returns to develop panel.
  • getProcessedData() Integration
    • Returns m_geometryBuffer when geometry is baked, otherwise existing pipeline.
  • RawViewport Bridge
    • geometryBaked Q_PROPERTY, geometryBakedChanged signal.
    • Q_INVOKABLE reloadWithGeometry(), enterCropMode(), exitCropMode().
    • updatePaintNode() syncs m_imageWidth/m_imageHeight when buffer dimensions change.
  • QML Integration
    • ShaderEffect transforms conditional on !geometryBaked (neutral when baked).
    • Enter → commitEdit() + reloadWithGeometry() + switch to Edit panel.
    • ESC → discardCrop() + exitCropMode().
    • Sidebar button clicks call enterCropMode()/exitCropMode() appropriately.
  • Undo/Redo & Reset
    • Undo/redo outside crop mode re-bakes geometry when properties changed.
    • resetToOriginal() clears geometry bake.
  • Documentation
    • Updated SPECIFICATION.md with baked geometry pipeline details.
    • Updated TASKS.md with Phase 31.

Phase 32: Crop Coordinate Parity & Domain Clamp [DONE]

  • Domain-Safe Crop Interaction
    • Enforced crop validity against rotated image quadrilateral domain (not only [0,1] bounds).
    • Incremental drag updates with projection from last valid rect to avoid border skips/jumps.
  • Preview Behavior Refinement
    • Crop mode resets zoom/pan and auto-fits transformed bounds for full-domain visibility.
    • Disabled extra non-active crop mask when geometry is already baked (avoid double-crop visual mismatch).
  • Bake/Export Coordinate Parity
    • Unified deterministic normalized→pixel crop mapping in engine/export:
      • left=floor(x*W), top=floor(y*H), right=ceil((x+w)*W), bottom=ceil((y+h)*H) (clamped).
    • Verified parity between RawEngine::applyGeometryTransforms() and ImageDeveloper::develop().
  • Diagnostics & Verification
    • Added temporary crop debug traces in QML/C++ for preview vs bake reconciliation.
    • Build + tests pass; user-validated that crop overlay domain movement and preview/bake match.

Phase 33: Post-Crop Quality & Stability [DONE]

  • Denoise + Zoom Aspect Fix
    • Fixed X-axis stretch when enabling denoise while zoomed in.
    • RawViewport::updatePaintNode() keeps logical image dimensions stable when using partial denoise ROI textures.
  • Tone/HSL Engine-Only Quality Pass (No UI Changes)
    • Added smoother tonal masks and safer luma-target remap for Whites/Blacks/Highlights/Shadows.
    • Broadened/normalized HSL hue influence and added low-chroma protection to reduce harsh transitions/artifacts.
    • Applied parity updates across shader (RawViewport.frag), CPU export (ImageDeveloper.cpp), and histogram simulation (RawEngine.cpp).
    • Fixed positive-slider whiteout regression by applying brightening shoulder compression only when target luma exceeds 1.0.
  • Research & Documentation
    • Added comparative analysis against darktable in tones_report.md (tone transitions, HSL behavior, tone-curve banding, denoise softness).
    • Captured implementation touchpoints for follow-up engine changes.

Phase 34: 65536 Tone Curve LUT Precision [DONE]

  • Upgraded tone-curve LUT precision from 256 to 65536 entries per channel.
  • Reworked LUT texture contract to 256×1024 with 4 stacked 256×256 planes (Luma/R/G/B), packing 16-bit values in RG bytes.
  • Updated shader tone-curve sampling to decode packed 16-bit LUT values from centered texture samples.
  • Updated CPU export path (ImageDeveloper) to use matching 65536-entry LUT indexing and 16-bit identity detection.
  • Updated QML tone LUT source texture sizing to Qt.size(256, 1024).
  • Reduced black-point aggressiveness by attenuating positive low-luma tone-curve lift (shader + CPU parity).
  • Updated SPECIFICATION.md and TASKS.md to reflect the new precision contract and completed work.

Phase 35: Selective Preset Save Workflow [DONE]

  • Added reusable SettingsSelectionDialog.qml component for settings-key selection (designed for preset save now, copy/paste reuse later).
  • Implemented hierarchical checkbox groups with cascading parent behavior (parent check/uncheck applies to all children).
  • Added sectioned key coverage for Light, Presence, Color, HSL, Color Grading, Effects, Creative, Detail, Denoise, Tone Curve, and Geometry.
  • Simplified preset selection granularity to match workflow expectations:
    • HSL grouped into single Color Correction checkbox.
    • Tone curve channels grouped into single Tone Curve checkbox.
  • Improved selection dialog usability:
    • Increased dialog width and switched to plain section layout with column wrapping by visible height.
    • Kept rounded dialog corners consistent (including top corners).
  • Updated preset save flow in PresetPanel.qml:
    • Save button opens selection dialog first.
    • After selection, user names preset.
    • Only selected keys are saved to preset JSON.
  • Preset apply behavior remains partial-safe (RawEngine::applyJsonToState only applies keys present in the preset map).
  • Registered the new component in QML module files (qmldir, CMakeLists.txt).
  • Updated SPECIFICATION.md and TASKS.md.

Phase 36: Reusable Right-Click Edit Context Menu [DONE]

  • Added reusable PhotoContextMenu.qml component for thumbnail/viewport contextual actions.
  • Wired right-click activation in:
    • Library grid thumbnails (LibraryView.qml)
    • Filmstrip thumbnails (App.qml)
    • Develop viewport (App.qml)
  • Implemented contextual actions:
    • Copy settings (opens reusable SettingsSelectionDialog, stores filtered keys only).
    • Paste settings (dynamic text: "Paste settings to N photos" when multi-selection is active).
    • Rating actions (No rating + 1★..5★) for selected photos.
    • Filter actions (criteria cycle + star threshold) synchronized with library filter state.
    • Rotate right/left and flip horizontal/vertical actions.
  • Extended AppStateManager with batch sidecar edit operations for selected photos:
    • loadSettingsForImage(...)
    • applySettingsForSelected(...)
    • rotateSelectedRight/Left(...)
    • flipSelectedHorizontal/Vertical(...)
    • editsUpdated() signal for UI refresh.
  • Added missing Lucide-style icon assets (copy, clipboard-paste, star, filter) and registered resources.
  • Polished context-menu UX:
    • Fixed menu icon contrast via dedicated high-contrast menu icon assets.
    • Restored rating/filter submenu structure.
    • Kept filter criteria cycling in active context-menu flow for faster iteration.
  • Build + tests + offscreen runtime smoke validated after integration.

Taking back control of the codebase

Phase 37: Old session Not Found and log rotation

  • Pop up error when continue session folder is not found, then reset it and return to WelcomeView
  • Auto log cleanup

Phase 38: Panorama and other improvements

  • Panorama Stitching
    • OpenCV integration
    • Stitching
  • Dng export
    • Implement a DNG-like export
    • Move the implementation to ExportManager
  • New tone processing pipeline
    • Implement new pipeline
    • Port it to ImageDeveloper
    • Tune tone targeting

Backlog / Future

  • Perspective Correction
    • Keystone/perspective transform controls.
  • Lens Correction
    • Integrate lensfun for automatic distortion/vignette removal.
  • Let the use decide whether to use auto brightness or not (and threshold)