Mozary is an iOS app that turns hundreds of your photos into a single zoomable mosaic.
- Zoom out → it looks like one image
- Zoom in → individual photos appear (and you rediscover forgotten moments)
App Link: https://apps.apple.com/us/app/mozary/id6759013945
Try it out!
The idea (why I built it)
I take a lot of photos, but I rarely revisit them.
I wanted a way to turn “a pile of photos” into something you actually want to look at.
During a trip, I saw a huge mosaic wall and thought: what if my own memories could become a mosaic artwork?
That became Mozary.
How it works (user flow)
- Choose a target image (what the mosaic becomes)
- Choose photos from your library to use as tiles (up to 1000)
- Generate (usually 5–20s, up to ~40s for 1000 photos)
- Pinch to zoom, then export as an image/video
The engineering part: making the viewer buttery smooth
The hardest part wasn’t generating the mosaic.
It was rendering it interactively.
A mosaic like 200×150 already means 30,000 tiles.
Naively drawing them every frame is a fast path to jank (or crashes).
Borrowing an idea from Google Maps: LOD (Level of Detail)
Google Maps doesn’t draw every tiny detail at every zoom level.
It switches what it renders depending on zoom.
Mozary uses a similar LOD approach (3 levels):
Zoomed out: draw a single pre-rendered image
Instead of looping through 30,000 tiles, I pack each tile color into a pixel and render one image.
Same look, dramatically cheaper.Zoomed in: render only what’s visible, in 256×256px tiles
I issue render requests only for the region currently on screen.Keep the main thread free: heavy rendering runs on a background thread
So pan/zoom stays responsive.
Result: the mosaic scrolls/zooms smoothly even at large sizes.
Color matching: RGB → Lab
Mosaic quality is mostly about color matching.
I first tried RGB distance, but it often chose tiles that were numerically close yet visually off.
RGB isn’t perceptually uniform.
Switching to Lab color space improved matches immediately:
- Convert each photo’s average color RGB → Lab
- For each grid cell, pick the tile with the smallest Euclidean distance in Lab
Simple change, big visual improvement.
Optional: Color grading when your photo set lacks colors
Sometimes your selected photos don’t cover the target’s color palette.
So I added an optional “color grading overlay”:
- overlay the target’s hue + saturation
- keep the tiles’ luminance (so the photo texture stays)
It’s subtle when your set already has enough color, but helpful when it doesn’t:
Speed tricks that mattered
Two practical optimizations made generation fast enough for real use:
- Parallelize photo analysis (average color computation)
- Downsample for analysis (I use ~40×40px instead of full-res)
Even if photos are several MB, the color info needed for matching is captured at small size—saving both memory and time.
What I want to improve next
- Reduce repeated use of the same tile photo (more even distribution)
That's it!
If you try it, I’d love feedback—especially on export quality and performance on older devices.



Top comments (0)