Back to Blog

Building Noira Cam: Film Looks, Image Editing, and Faking a Real Lens Blur

May 29, 2026

I just shipped Noira Cam, an iOS app for shooting and editing photos with a film look. The goal was to bring that cinematic, analog feeling to the phone in your pocket. Along the way I learned a ton about how digital images actually work under the hood, so I want to walk you through the journey, including the one feature that turned into a proper rabbit hole.

Crafting the looks

The first big chunk of work was the presets, or as I call them in the app, the looks (Noira, Street, Haze, and more). Everything runs on Core Image, with chains of CIFilter stacked on top of each other.

Here is the thing I did not appreciate before building this: a film look is not a single filter, it is a recipe. Take split toning, the technique of tinting shadows one color and highlights another (think teal shadows and warm orange highlights, the classic cinematic grade). To pull that off you build a luminance mask, a grayscale version of the image where bright pixels are white and dark pixels are black. You use that mask to apply the highlight tint only where the image is bright, and the inverted mask to apply the shadow tint only where it is dark. Layer a film finish on top (a vignette, halation glow around the bright areas, and grain) and suddenly a flat digital photo starts to feel like it came off a roll of film.

The lesson here was about restraint. You nudge the halation up, the highlights bloom beautifully, but now the image feels hazy, so you pull it back and it feels flat again. Good presets live in a very narrow band, and finding that band is mostly patience.

The Studio editor

Next came the Studio, the editing side of the app: import a photo, apply a look, fine tune the grade, crop, and export, all without ever touching the original file.

The key idea worth sharing is non destructive editing. Instead of baking each change into the pixels as you go, you store the edits as a set of parameters (a recipe) and only render the final image when you actually need it. This is why pro photo apps let you go back weeks later and change a single slider. It keeps everything fast and reversible. The cost is plumbing: juggling Core Image contexts, handling RAW files, respecting orientation, and exporting at full resolution without running out of memory.

And then there was Depth

This is the part I find genuinely fascinating.

First, a tiny bit of photography, because it explains why this is hard. On a real camera, the aperture is the opening inside the lens that lets light through, and you can make it wider or narrower. A wide aperture (a low f number like f1.4) does two things: it lets in a lot of light, and it makes the depth of field very shallow. Depth of field is just the slice of the scene that is actually in focus. With a shallow depth of field, your subject is razor sharp while everything in front of and behind it falls into a soft, creamy blur. That blur is what people mean by bokeh, and it is what makes a portrait feel cinematic. It comes from physics: a wide opening and a big piece of glass focusing light onto a sensor.

Now here is the catch. A phone has none of that. The aperture is fixed and tiny, the lens is the size of a grain of rice, and the sensor is minuscule. Physically, almost everything in a phone photo is in focus, which is exactly why phone snapshots can look flat compared to a real camera. So a phone cannot create that blur optically. It has to fake it in software, convincingly enough that your eye believes there was a real lens behind it. That is the whole challenge, and it turns into a beautiful little engineering puzzle.

What I wanted was real depth of field: not a lazy blur on the edges of the frame, but a believable lens blur that respects the geometry of the scene, with the subject crisp and the background gently melting away.

To blur a scene by distance, you first need to know the distance of every pixel. That is a depth map, a grayscale image where the value of each pixel encodes how far it is from the camera. There were two ways to get one.

The first is native Portrait photos. When you shoot in Portrait mode, Apple quietly bakes auxiliary data into the file: a disparity map, a portrait effects matte (a clean cutout of the subject), and even a semantic hair matte. Core Image can read all of it through options like auxiliaryPortraitEffectsMatte. If the depth is already in the file, use it.

The second case is every other photo, which has no depth data at all. For those I run Apple's Depth Anything V2 Small model through Core ML. You feed it a downscaled image (the model expects 518 by 392), and it predicts a depth map from a single 2D photo, no special hardware required. Then you upscale that prediction back to full resolution. The fact that a small on device model can hallucinate plausible depth from an ordinary snapshot still feels a little like magic.

The fun part: making the blur believable

Once you have a depth map, the actual blur is the elegant bit. The concept is called the circle of confusion: in a real lens, a point that is out of focus does not land as a point on the sensor, it spreads into a small disc, and the further it is from the focus plane, the bigger that disc. So for each pixel you measure how far its depth is from the depth you chose to focus on, and you blur it proportionally. Pixels right at the focus distance stay razor sharp, and everything else softens based on how far away it is. To keep the subject perfectly crisp even when the depth map is fuzzy at the edges, I blend the sharp original back in using a person mask, which comes either from the Portrait matte or from a Vision person segmentation request.

A few things genuinely surprised me and are worth knowing if you ever go down this road:

  • Disparity is not depth. Disparity is roughly the inverse of distance, so near and far come out flipped, and the raw values rarely sit in a clean range. You almost always have to normalize and stretch them yourself before they are useful.
  • Coordinate systems do not agree. The UI thinks in top left origin, Core Image thinks in bottom left, so the point a user taps to focus and the coordinates the filter expects live in different worlds. Mapping a tap on a face to the right spot in the render is its own little task.
  • Orientation has to be consistent across the photo, the depth map, and the matte, or the blur lands on the wrong part of the image.

None of these are roadblocks once you understand them. They are just the kind of detail that separates a demo that works on one photo from something that holds up across a whole camera roll.

An honorable mention: Focos

I cannot write about this without tipping my hat to the app Focos. They handle depth simulation and virtual aperture about as close to perfectly as I have seen on a phone, with bokeh that genuinely looks like it came out of a fast lens. Studying how good that experience feels set the bar for what I was aiming at. Huge kudos to that team, if you are deep into computational photography, it is absolutely worth a look.

What I learned

Imaging work has a wonderful way of teaching you how things actually work. Before this app, depth of field was just a slider to me. Now I understand it as distance maps, circles of confusion, masks, and a lot of careful coordinate math, and that understanding changed how I see every photo I take.

Seeing a flat photo suddenly gain a soft, believable lens blur, with the subject popping out from the background, made the whole rabbit hole worth it.

Give it a try

If you care about how your photos feel, I would love for you to try Noira Cam. Shoot with the film looks, play around in the Studio, and pull up the Depth tool on a photo to refocus it after the fact. It is the feature I learned the most building, and the one I am proudest of.

You can download Noira Cam on the App Store. If you build something cool with it, or just have feedback, I would love to hear it. I put a lot of heart (and a lot of curiosity) into this one.