- Test Environment Setup
- CI/Lint Configuration
- RawEngine Implementation (C++)
- RawViewport Integration
- Theme System
- Core Components
- Layout Implementation
- 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)
- GPU-Accelerated Edits
- Move Exposure/Contrast calculation to Fragment Shader.
- Implement Vibrance/Saturation in shader.
- Advanced Tool Panel (DevelopView.qml)
- Implement
Collapsible.qmlcomponent 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.
- Implement
- Non-Destructive Edit Stack
- Store edits in JSON sidecar files.
- Implement persistent Undo/Redo history.
- 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.
- 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.
- 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.
- Preset System
- Implement
PresetManager(C++) with cross-platform storage. - Add
applySettingsbatch logic toRawEngine. - Create core
PresetPanel.qmllogic.
- Implement
-
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.
- GPU Management
- Detect available Vulkan physical devices in C++.
- Implement robust GPU selection logic in
main.cppusing multiple env vars.
- Aesthetics & Theme
- Implement Light/Dark mode toggle.
- Implement Accent color selection.
- Synchronize
Theme.qmlwith persistent settings.
- Cache & Maintenance
- Implement "Clear Thumbnail Cache" logic.
- Context-aware enabling/disabling of cache maintenance.
- Logging System
- Implement
LogManagerC++ class with log level filtering. - Add log file location selection to UI.
- Set default log location based on OS standards.
- Implement
- Step 1: CPU Algorithm Refinement
- Refactor
Denoiser.cppto use Luma-only Block Matching. - Implement Spatial Tiling (256x256 tiles) for cache locality.
- Implement fully unrolled 16-point Walsh-Hadamard transform.
- Refactor
- Step 2: Advanced GPU Preview (NLM)
- Implement Non-Local Means (NLM) shader in
RawViewport.frag. - Optimize search radius and patch size for 60fps performance.
- Implement Non-Local Means (NLM) shader in
-
Step 3: Vulkan-Native Search Offload [DONE]
- Implement initial Patch Search shaders (3x3 patch SSD).
- Refactor
GpuSearcherto 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.
- 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
RawEnginedestructor clean-joins all background workers. - Prevent segfaults on application close while denoising (Fixed race in
ThumbnailProviderand resource cleanup).
- Ensure
- 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.
- Property Exposure
- Expose
showingPreviewboolean property inRawViewport(C++).
- Expose
- Shader Bypass Logic
- Add
float isPreviewto uniform block inRawViewport.frag. - Implement conditional branch in
main()to bypass RAW pipeline whenisPreview > 0.5.
- Add
- UI Integration
- Update
ShaderEffectinApp.qmlto passrawViewport.showingPreviewto the shader.
- Update
- Export functionality (Save to JPEG/TIFF).
- Architecture & Settings
- Design
VulkanDenoiserclass architecture (plain Vulkan, compute shaders). - Create compute shader infrastructure (grouping, transform, filter, aggregate).
- Design
- 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.
- Implement
- Integration & Fallback
- Implement wrapper
denoise()method inDenoiserclass. - Rename existing
denoise()todenoiseCpu()for CPU-only path. - Integrate into
RawEnginewith async execution viaQtConcurrent. - Respect
previewDenoiseFullsetting for high-quality previews.
- Implement wrapper
- 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.
- 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
RawEngineandRawViewport. - Implement
apply_local_contrastutility inRawViewport.frag. - Implement
apply_dehazeinRawViewport.frag. - Implement
apply_centre(radial tonal/color) inRawViewport.frag.
- Expose new adjustment properties in
- Viewport Performance Optimization
- Implement texture caching in
RawViewportto decouple panning from texture uploads. - Optimize 16-bit to 8-bit conversion/upload path.
- Throttled UI updates during pan.
- Implement texture caching in
- Versioning System
- Create
Version.h.intemplate for CMake. - Display version string in Settings footer.
- Implement
tag_release.shfor automated tagging. -
tag_release.shnow also updatesproject(Photon VERSION X.Y.Z LANGUAGES CXX)inCMakeLists.txt.
- Create
- CI/CD Infrastructure
- Create GitHub Actions workflow for cross-platform builds.
- Configure Nightly builds for
developand Stable formaster. - 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
.PhotonDatapath handling OS-agnostic usingQDir::toNativeSeparators. - Update CMake for vcpkg/MSVC compatibility on Windows.
- Make all
- Performance Optimization
- Implement high-performance compiler flags (-O3, LTO, AVX2/FMA) for Release builds.
- 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 fromDenoiser. - Remove
useGpuDenoisesetting fromAppStateManagerand QML settings toggle. - Clean GpuDenoiser references from test CMakeLists.
- Update SPECIFICATION.md to document new chroma pipeline architecture.
- Remove dead
- DenoiseParams Struct
- Added
DenoiseParamsstruct withsearchWindow,groupSize,chromaRadius,chromaDenoisefields. - Updated
block_matching_jointto use parameterized search window and group size. - Updated
multiscale_guided_filterto use parameterized radii and epsilon scaling.
- Added
- RawEngine Integration
- Added 4 new Q_PROPERTY declarations:
denoiseSearchWindow,denoiseGroupSize,denoiseChromaRadius,denoiseChromaAmount. - Setters with validation, clamping, and denoise result invalidation.
- JSON serialization/deserialization for
.PhotonDataedit stacks. - Updated
resetToDefaults()andisDefault(). -
startAsyncDenoise()constructsDenoiseParamsfrom member variables.
- Added 4 new Q_PROPERTY declarations:
- ImageDeveloper Integration
- Export path reads new params from JSON and passes
DenoiseParamstoDenoiser::denoise().
- Export path reads new params from JSON and passes
- 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
stepSizeproperty passthrough inControlGroup→PhotonSlider.
- 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
GpuChromaFilterclass followingGpuSearcherVulkan 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.
- Created
- 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.compandguided_ops.compto CMakeLists compute_shaders target. - Added
GpuChromaFilter.cpp/.hto main and test CMakeLists. - Added
CmdPipelineBarriertoVulkanFunctionsstruct and loader.
- Added
- Documentation
- Updated SPECIFICATION.md denoising pipeline section.
- Scharr Edge Detection in Fragment Shader
- Implemented
compute_edge_mask()using 3×3 Scharr kernels (Gx/Gy) on luminance. - Threshold/gain curve controlled by
sharpenMaskparameter (0–100). - Smooth Hermite interpolation for natural mask transitions.
- Sharpening applied selectively:
mix(preSharp, sharpened, finalMask).
- Implemented
- Mask Feather (Option 1)
- Spatial smoothing by averaging mask at 4 cardinal neighbors (radius 1–6 texels).
-
maskFeatherparameter (0–100) controls blur radius.
- Focus Detection (Option 2)
- Local-contrast gating via
|color − blurred|from existing unsharp mask blur (zero extra samples). -
focusDetectparameter (0–100) restricts sharpening to in-focus areas. - Combined mask:
finalMask = edgeMask × focusGate.
- Local-contrast gating via
- Alt+Drag Mask Preview
-
showSharpenMaskuniform renders combined mask as grayscale overlay. - Created
KeyTrackerC++ singleton with globalQEventfilter for reliable Alt key detection. -
Connectionsin 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.
- 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
-
scanIntervalSecondsQ_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.qmlCanvas 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
QImageLUT texture (one row per channel) viaToneLutProviderimage provider (later superseded by Phase 34 packed 16-bit LUT texture). -
sampler2D toneLUTin 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
- 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.
- Prevent overlapping
- Histogram Buffer Safety
-
clearProcessedImage()waits for in-flight histogramQtConcurrent::runfuture before freeingm_processedImage.
-
- Spline LUT Hardening
-
evalMonotonicSpline/evalMonotonicSplineLutsort 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 sharedwindowroot 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).
- Sort properties (
- 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+Scaletransforms on ShaderEffect for orientationSteps, straighten, flip.
- QML
- 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.
- Engine Infrastructure
- Add
m_geometryBuffer,m_geometryWidth,m_geometryHeight,m_geometryBaked,m_inCropModestate toRawEngine. - Add
Q_PROPERTY(bool geometryBaked)exposed to QML. - Add
QFutureWatcher<void> m_geometryLoadWatcherfor async geometry baking.
- Add
-
applyGeometryTransforms()Static Utility- Reusable
QImagetransform: orientation (N×90°) → flip → straighten → crop on rotated frame. - Transform order matches
ImageDeveloper::develop().
- Reusable
-
reloadWithGeometry()- Async re-decode RAW from disk → apply geometry → store in
m_geometryBuffer. - Sets
geometryBaked = true, emitsimageLoaded.
- Async re-decode RAW from disk → apply geometry → store in
-
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_geometryBufferwhen geometry is baked, otherwise existing pipeline.
- Returns
- RawViewport Bridge
-
geometryBakedQ_PROPERTY,geometryBakedChangedsignal. -
Q_INVOKABLE reloadWithGeometry(),enterCropMode(),exitCropMode(). -
updatePaintNode()syncsm_imageWidth/m_imageHeightwhen 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.
- ShaderEffect transforms conditional on
- 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.
- 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()andImageDeveloper::develop().
- Unified deterministic normalized→pixel crop mapping in engine/export:
- 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.
- 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.
- Added comparative analysis against darktable in
- 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.
- Added reusable
SettingsSelectionDialog.qmlcomponent 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::applyJsonToStateonly applies keys present in the preset map). - Registered the new component in QML module files (
qmldir,CMakeLists.txt). - Updated SPECIFICATION.md and TASKS.md.
- Added reusable
PhotoContextMenu.qmlcomponent for thumbnail/viewport contextual actions. - Wired right-click activation in:
- Library grid thumbnails (
LibraryView.qml) - Filmstrip thumbnails (
App.qml) - Develop viewport (
App.qml)
- Library grid thumbnails (
- 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.
- Copy settings (opens reusable
- Extended
AppStateManagerwith 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.
- Pop up error when continue session folder is not found, then reset it and return to WelcomeView
- Auto log cleanup
- 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
- Perspective Correction
- Keystone/perspective transform controls.
- Lens Correction
- Integrate
lensfunfor automatic distortion/vignette removal.
- Integrate
- Let the use decide whether to use auto brightness or not (and threshold)