A cross-platform photo manager and lightweight DAM that organises your collection by metadata, develops RAWs/JPEGs non-destructively, and stays out of the way β no local database, no cloud sync, your folders + sidecar XMP are the source of truth.
PhotoManager helps photographers and photo enthusiasts:
- Organise sprawling photo libraries by detecting creation dates from EXIF, GPS, filename patterns, and file-system metadata, then sorting into a
yyyy/yyyyMMdd/HHmmssfolder hierarchy. - Cull with Picasa-style picks/rejects (P/X/U hotkeys), star ratings, color labels, perceptual-hash duplicate detection, and side-by-side compare.
- Tag with keywords, GPS coordinates (manual map picker, GPX track sync, reverse geocoding, map bookmarks), face detection + clustering, and ONNX-based object detection.
- Develop with a Lightroom-lite pipeline: tone (exposure, contrast, highlights, shadows, whites, blacks, clarity, vibrance, saturation), white balance, sharpening + noise reduction, master + R/G/B + parametric curves, HSL, color grading, B&W mixer, split toning, vignette + grain, lens corrections, calibration, crop + perspective, brush/linear/radial local masks with luminance + hue range filters and Add/Subtract/Intersect compositing.
- Search the library by keyword, person, place, rating, color label, or any-text β with saved searches, an in-memory index, and instant re-query.
- Export geotagged photos to KML for Google Earth or any GPX viewer.
- ποΈ Develop window redesign β right-hand control surface restructured into 6 focused tabs (β‘ Basic / π€ AI / βοΈ Crop / π¨ Color / π Masks / π Effects) instead of a single 1300-line vertical scroll. AI tab puts Magic Enhance, mask helpers, and per-feature AI fixers front-and-centre.
- πͺ Magic Enhance β one-click "fix everything" pipeline that auto-detects low-light / noise / haze / low-res via
PhotoIssueDetectorand runs only the matching stages (Zero-DCE++ β NAFNet β FBCNN β AOD-Net β auto-WB β auto-tone β CLAHE β upscale). Scores before/after with NIMA so the status bar reports the aesthetic delta. - π 4-mode compare cycle in the develop preview β After only / Split (left/right) / Overlay with alpha slider (NEW: dial a partial blend between source and developed) / Slider wipe (custom grabbable handle, not the default blue circle).
- π Zoom + pan inside the preview β mouse-wheel zooms anchored at the cursor (10 %β3200 %), right-drag pans, double-right-click resets. Only the image transforms; the slider thumb, alpha bar, and other controls stay at fixed screen positions. Slider-mode wipe clip is transform-aware so the wipe edge stays under the Thumb during zoom/pan.
- π Rich bottom status bar β phase indicator (idle / loading / developing / ready (N edits) / AI work / error) + diagnostic strip + AI ETA progress bar. Anchored to the very bottom of the window like a conventional status bar.
- π€ New AI catalog β DDColor (paper-tiny + artistic, ECCV 2023 colorizer), FBCNN (JPEG/DCT artifact removal), SegFormer-B0 ADE20K (multi-class masks: grass / water / road / building / person / mountain / sand / rock / foliage / snow), Depth Anything V2 small (monocular depth), Zero-DCE++ (low-light), AOD-Net (dehazing), NIMA MobileNetV2 (aesthetic scoring), HAT-S Γ4, AnimeSharp Γ4, CodeFormer (face restoration). All flow through the existing ModelRegistry lazy-download path.
- πΈ Depth-aware bokeh β Depth Anything V2 +
DepthBokehBlurproduces realistic portrait blur with depth-distance falloff. One-click "πΈ Bokeh blur" button writesIMG.bokeh.jpgnext to the source. - π«οΈ Per-feature AI buttons in the AI tab β π¦ Brighten low-light (Zero-DCE++), π«οΈ Remove haze (AOD-Net), π₯ Motion deblur (NAFNet-GoPro), π Score photo (NIMA), βοΈ Suggest crops (NIMA-ranked aspect ratios). Each writes a sidecar JPEG so source is untouched.
- π§Ή Pure-C# additions β DPID detail-preserving downscaler, CLAHE local contrast, Reinhard HDR tone mapping, AutoStraighten via Hough-vote horizon detection. All measurable wins on smartphone shots, no ONNX required.
- π¨ Alpha-flatten on load β every loader path (
RawImageLoader,ImagePreviewLoader,RegionThumbnailExtractor,PanoramaStitchWindow,PanoramaViewerWindow) now src-over composites alpha onto white viaAlphaFlattener.FlattenOntoWhite, so transparent GIFs / PNGs render correctly through the JPEG-encoding preview path. Magick.NET fallback scoped to PNGCrushCS-handled extensions only (was flattening GIF transparency against the GIF's black background).
- π€ AI denoise + AI upscale in the develop pipeline β NAFNet-SIDD ONNX denoiser (slider 0β¦1) and Real-ESRGAN-x4 upscaler (1Γ/2Γ/4Γ). Tile-based, lazy-downloaded via the same model registry as MODNet/YOLO; degrades to a no-op when the model isn't installed.
- π·οΈ Auto-keyword tagging via SigLIP β
Tools β Auto-keyword scanβ¦runs CLIP-style image+text embeddings against a 700+-word vocabulary and writes the top-K hits as flatdc:subjectkeywords. Library-scan flow with progress + per-file preview. - π― Auto-crop suggestions β saliency-driven crop candidates at common aspect ratios (1:1, 4:5, 3:2, 16:9, 2:3, 5:7), ranked by Sobel-edge density. Pop the flyout from the develop window's auto-tools row, click a thumbnail to apply.
- π Edit history / version stack β every Save Asβ¦ pushes the prior
pm:developSettingsonto apm:developHistory[]list (cap 20). The π Edit history button browses snapshots and rolls back any one. - π Virtual copies β sibling
IMG.copyN.xmpsidecars hold alternate develop variants without duplicating pixels. Each copy surfaces as its own grid row; right-click β Promote copy to original. Open in Develop targets the copy. - π Timeline scrubber β horizontal histogram of photos-per-day (auto-bucketed Day/Week/Month) above the grid; click a bar to filter to that bucket. Toggle the strip with π in the search row.
- π Quick collection (Lightroom-style) β B-key on a grid row toggles in/out of a per-session bucket. π Quick toggle filters to the bucket; Tools β Quick collection submenu offers Clear / Select-in-grid / Open-in-Develop-apply-to-selection. β -badge column on the grid.
- β¨ Memories β
Tools β β¨ Memoriesβ¦surfaces "on this day" / "on this trip" photos relative to the selected anchor: same-month/day across years, plus same-bookmark-area within Β±N km. - π§ Smart Patch Selection in panorama stitchers β per-frame Laplacian-variance sharpness mask with adaptive median threshold; blurry / obstructed regions are excluded so they don't bleed into the panorama. Drives all three stitcher backends (mask-zeroed BGR for OpenCV, weight-scaled feathering for tripod). Toggle via checkbox; ~1s per frame extra.
- π¬ Video β frames extractor (ffmpeg) β drop a video sweep into PhotoManager and ffmpeg splits it into JPEG frames at user-pickable FPS / quality / time-window. Frames pipe straight into the panorama stitcher with one click. Friendly install banner (
winget/brew/apt) when ffmpeg isn't on PATH. - π Spherical (360Β°) stitcher β third mode in the panorama stitcher: feed N overlapping frames, get a 2:1 equirectangular canvas straight into the 360Β° viewer (no save round-trip). OpenCvSharp4-backed.
- π HDR merge from bracketed exposures β Greg-Ward MTB alignment + Debevec/Malik response-curve recovery + Reinhard / Drago tone mapping. Pure C#, no native deps. Mismatched-dimension brackets auto-fit-and-pad to the largest frame; manual exposure-time entry when EXIF is missing.
- π 360Β° equirectangular viewer β pan-around viewer for spherical photos with drag yaw/pitch + scroll FOV; auto-detects via 2:1 aspect or
GPano:ProjectionTypemetadata. Save the current perspective view as a JPEG. - πΌ Panorama stitcher β two modes: tripod (cylindrical re-projection + sequential SSD pairwise alignment + linear feathering, no deps) for sweep shots, and hand-held (OpenCvSharp4 high-level
Stitcherfor gigapixel hand-shot panos). - π³ Hierarchical keyword tree β
Travel > Italy > Romestyle. Selecting a leaf writes leaf + ancestors as flatdc:subjectkeywords so other tools see standard keywords; the tree itself lives in app-data JSON. - π Calendar view β month-grid of photos by capture date with day-tile thumbnails and drill-into-day pane.
- π Burst grouping β cluster photos taken in rapid succession by
DateTimeOriginalproximity + filename similarity; tag each group with apm:burstIdkeyword. - π― Geofence auto-tagging β when a photo's GPS lands inside a saved bookmark's radius, merge the bookmark's place fields. Auto-on-scan toggle + manual "Apply geofences to selection" dialog.
- βοΈπ Sun / moon position calculator β NOAA solar + Almanac lunar (azimuth + altitude + twilight description) for any photo's time + location. Used by the world-map sun-arrow follow-up.
- π€ Heuristic sky mask β top-N% rows + blue-dominance + low-saturation + low-edge classifier; appends a brush-mask local adjustment for the detected sky.
- π Red-eye removal β flood-fill blob detector inside face bounds (or whole image when face detector unavailable) + luminance-preserving desaturation.
- π§ Watermark layer β text + opacity + position + font-size, applied at render time only (non-destructive). Round-trips via
pm:developSettings. - πͺ Develop preset on import β pick a
DevelopTemplateStorepreset in Settings and every newly-imported file with no embedded settings gets it stamped in automatically. - π¬ 3D LUT support β drop
.cube/.3dlfiles into%AppData%/PhotoManager/luts/and they appear as a "Look" picker in the develop window with an opacity slider. Round-trips viacrs:LookNameso 3rd-party tools see the assigned look. - βοΈ Click-drag crop overlay β eight drag-handles + dimmed exterior + rule-of-thirds guides on the develop preview. Auto-shows when the user has a non-default crop, toggleable via a "Show crop handles" button.
- π§ Smart-album rule builder β composable rules (rating β₯, keyword, person, location, color label, pick state, date range, GPS box) AND/OR-combined; persisted polymorphically in
UserSettingsData. - π Quality flags scan β Laplacian-variance sharpness + histogram clipping; tags blurry / over- / under-exposed photos with
qa:keywords for one-click culling. - π€ GPX track preview on the world map β load a GPX file, see the route polyline alongside your photo pins.
- π Nearby-photo radius search β in the world map, switch to Nearby mode, click anywhere β photos within a log-scale 100mβ50km radius are highlighted, the rest dimmed.
- βοΈ Settings window + Recent folders + Status-bar progress β File β Settings consolidates theme, default rename template, recent-folders depth, geocoder/elevation toggles, rate limit. File menu lists last-5 source/output folders. A shared
OperationProgressstrip below the status bar shows long ops with a Cancel button. - π AI subject mask β MODNet ONNX segmentation auto-creates a brush-mask local adjustment so you can tweak the subject without touching the background.
- π Side-by-side compare β four modes inside the develop window: After only, split view (with grid splitter), overlay-with-alpha-slider (partial blend), or movable wipe (grabbable Thumb handle, transform-aware so it stays under the cursor through zoom/pan).
- π¨ Theme toggle β Light / Dark / System default, persisted across sessions, theme-aware tile / border brushes.
- πͺ Drag-drop folders onto the source tree (adds them as roots) or files onto the grid (switches to target mode and scans).
- π€ KML export β
Tools β Export KMLβ¦walks the in-memory index and writes one Placemark per geotagged photo. - π Duplicate detection β 64-bit perceptual hash + Hamming-distance clustering; no DB, in-memory only.
- πΊοΈ Map favourites + reverse-geocode batch β bookmark "Pizzeria Roma", apply GPS + place names to a selection in one click; resolve city/country across the whole selection.
- β β Picks / rejects β P/X/U hotkeys, π© column, cull-filter chip that AND-combines with star ratings + color labels.
- βοΈ Batch rename with metadata tokens (
{date:yyyy-MM-dd}_{city}_{name}), π batch date shift (camera-clock offset).
- β Cross-platform desktop UI (Avalonia 11 β Windows, macOS, Linux), single-file self-contained executables per platform
- β HDR merge from bracketed exposures (alignment + response curve + tone mapping, hand-rolled in pure C#)
- β Panorama stitching: tripod (cylindrical reprojection) + hand-held gigapixel (OpenCvSharp4) + spherical 360Β° (equirectangular output, viewer-ready); optional Smart Patch Selection masks out blurry / obstructed regions per frame
- β Video β frames extractor (ffmpeg subprocess; cancellable; pipes into the panorama stitcher)
- β 360Β° equirectangular spherical-photo viewer with drag-pan + scroll-zoom
- β
Lightroom-lite develop pipeline (~all non-AI Adobe parameters), non-destructive via XMP
pm:developSettingsround-trip - β
Edit history snapshot stack (
pm:developHistory[], cap 20) + virtual copies (IMG.copyN.xmpsibling sidecars) β multiple develop variants per source file with one-click promote-to-original - β AI denoise (NAFNet-SIDD ONNX) + AI upscale (Real-ESRGAN-x4 ONNX) develop-pipeline stages, lazy-downloaded via model registry
- β Auto-keyword tagging via SigLIP (CLIP-style image+text embeddings against a 700+-word vocabulary, library-scan flow)
- β Saliency-driven auto-crop suggestions at common aspect ratios (Sobel-edge density)
- β
3D LUT (.cube / .3dl) creative-look picker with opacity blend and
crs:LookNameround-trip - β Watermark layer (text + opacity + position + font-size) rendered at output time only
- β Develop preset auto-applied to newly-imported files (via Settings)
- β Click-drag crop overlay with corner + edge handles, dimmed exterior, rule-of-thirds guides
- β AI subject mask (MODNet ONNX) + heuristic sky mask + red-eye removal β brush-dab local adjustments
- β Face detection + clustering (UltraFace + ArcFace ONNX), object detection (YOLOv8 ONNX)
- β GPS map editor, GPX geotagging, reverse geocoding, elevation lookup, triangulation/resection, world map
- β World-map GPX track overlay + Nearby-photo radius search (haversine, log-scale 100mβ50km)
- β Map favourites/bookmarks, KML export, batch reverse-geocode, geofence auto-tagging on scan
- β Sun / moon position calculator (NOAA solar + Almanac lunar) with twilight regime
- β Library search (in-memory index, no DB), saved searches, smart-album rule builder (composable clauses)
- β
Hierarchical keyword tree flattens to flat
dc:subjecton write - β Calendar view (photos by capture date in a month grid) and burst-stacks detector
- β Timeline scrubber strip (auto-bucketed Day/Week/Month histogram of photos-per-day, click-to-filter)
- β Quick collection (per-session bucket; B-hotkey toggle, β badge, filter mode, batch-edit just the bucket)
- β Memories window (on-this-day / on-this-trip discovery relative to the selected anchor)
- β Side-by-side compare (After / Split / Overlay / Slider) inside the develop window, with mouse-wheel zoom + right-drag pan over the preview
- β Rich develop-window status bar (phase indicator, diagnostic strip, AI ETA progress bar) anchored to the very bottom of the window
- β Tabbed develop right panel (Basic / AI / Crop / Color / Masks / Effects) instead of a single vertical scroll
- β Magic Enhance one-click pipeline (Zero-DCE++ + NAFNet + AOD-Net + CLAHE + auto-WB + auto-tone + optional Real-ESRGAN, gated by per-issue heuristics)
- β
Picasa-style picks/rejects (
xmp:Pick/xmp:Reject) with P/X/U hotkeys; quality-flag scan tags blurry / over- / under-exposed photos - β Perceptual-hash duplicate detection
- β Settings window (theme, default rename template, recent-folders depth, default develop preset, geocoder/elevation toggles, rate limit, geofence-on-scan toggle)
- β Recent folders submenu (last 5 source + 5 output folders, persisted)
- β
Status-bar progress strip with Cancel for long ops, bound to a shared
IProgress<T>sink - β Theme toggle (Light / Dark / System), persisted in user settings, theme-aware tile / border brushes
- β Drag-drop folders onto source tree / files onto grid
- β Batch rename with metadata-token templates; batch date shift; batch metadata edit
- β Multiple date source detection (EXIF SubIFD, IFD0, GPS, filename, file system) with reliability scoring
- β
Folder structure organisation (
yyyy/yyyyMMdd/HHmmss); duplicate handling with sequential numbering - β Command-line interface for automation (preview/dry-run, recursive)
- β MVC pattern (UI), atomic metadata writes (preserved mtime), comprehensive unit + integration tests
- AI sky mask using a dedicated ONNX model (heuristic version is shipped)
- Sun/moon arrows on the world map (calculator is shipped; map overlay is the follow-up)
- Healing brush / spot remover
- Photometric modelling (photogrammetry / surface normals β requires user-story scoping)
- Crash-safe metadata write-back queue
- Background pre-cache of thumbnails
- Scanning: The application scans specified directories for image files
- Metadata Extraction: Extracts dates from multiple sources:
- GPS timestamp data
- EXIF metadata (DateTimeOriginal, DateTime)
- Filename patterns (supports 40+ date formats)
- File system dates (creation, modification)
- Date Selection: Uses a reliability scoring algorithm to select the most probable original date
- Organization: Moves files into a structured folder hierarchy:
InputDirectory/ βββ 2024/ β βββ 20240115/ β β βββ 143022.jpg β β βββ 143022 (2).jpg β β βββ 145533.png
PhotoManager/
βββ PhotoManager.Core/ # Shared business logic and models
β βββ Models/ # Data models and DTOs
β βββ Services/ # Business logic services
β βββ Interfaces/ # Service contracts
β βββ Enums/ # Shared enumerations
βββ PhotoManager.Tests/ # Unit and integration tests
β βββ Unit/ # Unit tests for individual components
β βββ Integration/ # End-to-end workflow tests
βββ PhotoManager.UI/ # Avalonia desktop application (cross-platform)
β βββ Controllers/ # MVC controllers
β βββ Views/ # Avalonia AXAML windows and dialogs
β βββ Models/ # View models
β βββ Resources/ # Localization resources
βββ PhotoManager.CLI/ # Command-line interface
βββ README.md # This file
βββ TODO.md # Development roadmap
βββ CLAUDE.md # AI assistant instructions
- .NET 8.0 SDK or later
- Visual Studio 2022 or VS Code with C# extension
# Clone the repository
git clone <repository-url>
cd PhotoManager
# Restore dependencies
dotnet restore
# Build all projects
dotnet build
# Run tests
dotnet testdotnet run --project PhotoManager.UIdotnet run --project PhotoManager.CLI -- --source "C:\Photos\Input"
# With options
dotnet run --project PhotoManager.CLI -- \
--source "C:\Photos\Input" \
--recursive \
--pattern "{Year}/{Date}/{Time}{Extension}" \
--dry-run# Run all tests
dotnet test
# Run with coverage
dotnet test /p:CollectCoverage=true /p:CoverletOutputFormat=cobertura
# Run specific test category
dotnet test --filter Category=UnitThe application follows a clean architecture pattern with separation of concerns:
- Core: Contains business logic, models, and interfaces. No UI dependencies.
- UI: Avalonia 11 desktop application using MVC pattern; runs on Windows, macOS, and Linux from one codebase.
- CLI: Command-line interface for automation.
- Tests: Comprehensive test coverage using NUnit.
PhotoManager has no local database. The truth lives in:
- The folder structure (file location = "imported")
- The file's own metadata (EXIF, XMP packet)
- XMP sidecar files (
.xmpnext to each photo) for fields the format doesn't support natively
Caches (face embeddings, perceptual hashes, library index) are in-memory only and rebuilt on scan. Settings live in a small JSON file under %AppData%/PhotoManager/.
The system assigns reliability scores to different date sources:
- GPS Data (Score: 50) - Most reliable for photos with location data
- EXIF SubIFD (Score: 40) - Original capture date
- EXIF IFD0 (Score: 30) - Last modification date
- Filename (Score: 20) - Parsed from filename patterns
- File Modified (Score: 10) - File system modification date
- File Created (Score: 1) - File system creation date
Settings can be configured through:
- UI: Settings dialog
- CLI: Command-line arguments or config file
- Config file:
appsettings.json
- Image files only β video support is not on the roadmap.
- No cloud storage integration; PhotoManager works entirely on local files. The XMP sidecars and embedded XMP packets are designed to interoperate cleanly with cloud-syncing tools that respect them.
- The AI subject mask requires a one-time ~25 MB MODNet ONNX download (
Tools β Download detection modelsβ¦or clickπ Detect subjectand confirm the prompt). - The video β frames extractor requires
ffmpegto be installed and on PATH (winget install ffmpeg/brew install ffmpeg/apt install ffmpeg). PhotoManager doesn't bundle the ffmpeg binary because of its size. - The spherical 360Β° stitcher uses OpenCV's mosaic-into-canvas fallback (true cleanroom equirectangular reprojection isn't reachable through OpenCvSharp4 4.10's bindings). Output is a 2:1 canvas with the stitched mosaic centred; full-sphere coverage requires aligned input.
- pHash duplicate detection is in-memory only β re-scanning a 10k+ photo library re-computes hashes (mtime-keyed cache short-circuits unchanged files).
- The application requires read/write access to specified directories
- No network communication or data collection
- Settings stored locally in user profile
- No sensitive data is logged or transmitted
Contributions are welcome! Please read our contributing guidelines before submitting PRs.
LGPLv3 - See LICENSE file for details
For issues, feature requests, or questions, please open an issue on GitHub.
If this project saves you time or money, consider supporting its development:
Licensed under LGPL-3.0-or-later β see LICENSE.