DEV Community

Yuiko Koyanagi
Yuiko Koyanagi

Posted on

I built “Mozary”: An iOS App That Turns Your Photos Into a Zoomable Mosaic

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!

#buildinpublic #mobileapp #computervision #imageprocessing #productdevelopment | Yuiko Koyanagi

I’ve been building a photo mosaic app that creates an image from images. You pick a target photo, and the app composes it using many smaller photos—so from a distance it looks like one picture, but when you zoom in, you can still see each individual photo clearly. I put a lot of work into the processing pipeline, and the generation is genuinely fast (the video isn’t sped up). Now it’s in app review—excited to share more once it’s live! #buildinpublic #mobileapp #computervision #imageprocessing #productdevelopment

favicon linkedin.com

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)

  1. Choose a target image (what the mosaic becomes)
  2. Choose photos from your library to use as tiles (up to 1000)
  3. Generate (usually 5–20s, up to ~40s for 1000 photos)
  4. 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.

App Link: https://apps.apple.com/us/app/mozary/id6759013945

Top comments (0)