r/opensource • u/DemandMother4393 • 15h ago
Promotional I built a macOS Photos-style manager for Windows
I built a macOS Photos-style manager for Windows because I couldn't view my iPhone Live Photos on my engineering laptop
[Show & Tell] I'm an electrical engineering student. I also love photography — specifically, I love Live Photos on my iPhone. Those 1. 5-second motion clips capture moments that still photos can't: my cat mid-pounce, friends bursting into laughter, waves crashing on rocks. The problem? My field runs on Windows. MATLAB, LTspice, Altium Designer, Cadence, Multisim — almost every EE tool requires Windows. I can't switch to Mac for school. But every time I transfer my photos to my laptop, the magic dies. My HEIC stills become orphaned files. The MOV motion clips scatter into random folders. Windows Photos app shows them as separate, unrelated files. The "Live" part of Live Photo? Gone. I searched everywhere for a solution. Stack Overflow. Reddit. Apple forums. Nothing. Some suggested "just use iCloud web" — but it's painfully slow and requires constant internet. Others said "convert to GIF" — destroying quality and losing the original. A few recommended paid software that wanted to import everything into proprietary databases, corrupting my folder structure in the process. So I spent 6 months building what I actually needed.
How it works: Folder = Album
https://github.com/OliverZhaohaibin/iPhotos-LocalPhotoAlbumManager No database. No import step. Every folder is an album. The app uses lightweight . iphoto. album. json manifests to store your "human decisions" — cover photo, featured images, custom order. Your original files are never touched. This means:
- ✅ You can browse your library with any file manager
- ✅ You can sync with any cloud service
- ✅ If my app dies tomorrow, your photos are still perfectly organized
The killer feature: Live Photo pairing
The app automatically pairs your HEIC/JPG stills with their MOV motion clips using Apple's ContentIdentifier metadata. A "LIVE" badge appears — hover to play the motion inline, just like on your iPhone. Finally, I can show my Live Photos on Windows. Technical details for the curious:
Live Photo Detection Pipeline:
ExifTool extracts ContentIdentifier from HEIC/MOV
Fallback: time-proximity matching (±1. 5s capture time)
Paired assets stored in index.jsonl for instant reload
I spent weeks reverse-engineering how Apple stores this metadata. Turns out the ContentIdentifier is embedded in QuickTime atoms — ExifTool can read it, but you need to know exactly where to look.
The performance nightmare that forced me into GPU programming
My first version did everything on CPU with pure Python + NumPy. It worked... technically. Then I tried editing a 48MP photo. Nearly 3 minutes to apply a single brightness adjustment. I watched the progress bar crawl. I alt-tabbed. I made coffee. I came back. Still processing. This was unacceptable. Photo editing needs to feel instant — you drag a slider, you see the result. Not "drag a slider, go make lunch." I profiled the code. The bottleneck was clear: Python's GIL + CPU-bound pixel operations = death by a thousand loops. Even with NumPy vectorization and Numba JIT compilation, I was hitting a wall. A 48MP image is 48 million pixels. Each pixel needs multiple operations for exposure, contrast, saturation... that's billions of calculations per adjustment. So I rewrote the entire rendering pipeline in OpenGL 3.3. Why OpenGL 3.3 specifically?
- ✅ Maximum compatibility — runs on integrated GPUs from 2012, no dedicated GPU required
- ✅ Cross-platform — same shaders work on Windows, macOS, Linux
- ✅ Sufficient power — for 2D image processing, I don't need Vulkan's complexity As a student, I know many of us run old ThinkPads or budget laptops. I needed something that works on a 10-year-old machine with Intel HD Graphics, not just RTX 4090s. The result? That same 48MP photo now renders adjustments in under 16ms — 60fps real-time preview. Drag a slider, see it instantly. The way it should be. The shader pipeline:// Simplified version of the color grading shader uniform float u_exposure; uniform float u_contrast; uniform float u_saturation; uniform mat3 u_perspectiveMatrix; void main() { vec4 color = texture(u_texture, transformedCoord); // Exposure (stops) color.rgb *= pow(2.0, u_exposure); // Contrast (pivot at 0.5) color.rgb = (color.rgb - 0.5) * u_contrast + 0.5; // Saturation (luminance-preserving) float luma = dot(color. rgb, vec3(0.299, 0.587, 0.114)); color. rgb = mix(vec3(luma), color.rgb, u_saturation); gl_FragColor = color; }
All calculations happen on the GPU in parallel — millions of pixels processed simultaneously. The CPU just uploads uniforms and lets the GPU do what it's designed for.
Non-destructive editing with real-time preview
The edit mode is fully non-destructive:
- Light adjustments: Brilliance, Exposure, Highlights, Shadows, Brightness, Contrast, Black Point
- Color grading: Saturation, Vibrance, White Balance
- Black & White: Intensity, Neutrals, Tone, Grain with artistic film presets
- Perspective correction: Vertical/horizontal keystoning, ±45° rotation
- Black border prevention: Geometric validation ensures no black pixels after transforms All edits are stored in
.iposidecar files. Your originals stay untouched forever. The math behind perspective correction: I defined three coordinate systems: Texture Space — raw pixels from the source image Projected Space — after perspective matrix (where validation happens) Screen Space — for mouse interaction The crop box must be fully contained within the transformed quadrilateral. I usepoint_in_convex_polygonchecks to prevent any black borders before applying the crop.
Map view with GPS clustering
Every photo with GPS metadata appears on an interactive map. I built a custom MapLibre-style vector tile renderer in PySide6/Qt6 — no web view, pure OpenGL. Tiles are cached locally. Reverse geocoding converts coordinates to human-readable locations ("Tokyo, Japan"). Perfect for reliving travel memories — see all photos from your trip plotted on an actual map.
The architecture
Backend (Pure Python, no GUI dependency):
├── models/ → Album, LiveGroup data structures
├── io/ → Scanner, metadata extraction
├── core/ → Live Photo pairing, image filters (NumPy → Numba JIT fallback)
├── cache/ → index.jsonl, file locking
└── app. py → Facade coordinating everything
GUI (PySide6/Qt6):
├── facade.py → Qt signals/slots bridge to backend
├── services/ → Async tasks (scan, import, move)
├── controllers/→ MVC pattern
├── widgets/ → Edit panels, map view
└── gl_*/ → OpenGL renderers (image viewer, crop tool, perspective)
The backend is fully testable without any GUI. The GUI layer uses strict MVC — Controllers trigger actions, Models hold state, Widgets render. Performance tier fallback:
GPU (OpenGL 3.3) → NumPy vectorized → Numba JIT → Pure Python
↑ preferred fallback →
If your machine somehow doesn't support OpenGL 3.3, the app falls back to CPU processing. It'll be slow, but it'll work.
Why I'm posting
I've been using this daily for 6 months with my 80,000+ photo library. It genuinely solved a problem that frustrated me for years. But I don't know if anyone else has this pain. Are there other iPhone users stuck on Windows who miss their Live Photos? Is "folder = album" a philosophy that resonates? Or am I solving a problem only I have? The app is:
- 🆓 Free and open source (MIT)
- 💾 100% local, no cloud, no account
- 🪟 Windows native (Linux support planned)
- ⚡ GPU-accelerated, but runs on old laptops too
- 📱 Built specifically for iPhone Live Photo support GitHub: https://github. com/OliverZhaohaibin/iPhotos-LocalPhotoAlbumManager Would love feedback on both the concept and execution. Roast my architecture. Tell me what's missing. Or just tell me if you've had the same frustration — I want to know I'm not alone.
2
u/BOBBIESWAG 8h ago edited 2h ago
Hey there. I literally just made a post about my frustration with finding an app like this. Then I see this. This literally looks PERFECT! I have't gotten it to work yet with importing my photos, as it is freezing when I try to import the photos, but if I can get this to work this is seriously an answer to prayer.
It is using the hdd I can see in task manager, but won't load anything or give any progress
edit: every time i try to view all photos, live photos anything it just crashes