How we build film looks: solving a film simulation from photographs
Chobial's built-in films weren't eyeballed and weren't downloaded as LUTs. Each one was solved from photographs: one RAW file from a Fujifilm camera, developed in the camera once neutral and once with a film simulation, and the difference measured in CIELAB. The method is simple to state. Most of this post is about the ways it goes wrong.
Everything here was worked out against a Fujifilm X-T30 III in September 2026.
1. Get the pairs
The short version: photograph one scene, then develop it twice with the same camera, once neutral and once with the look, and solve the difference.
The important word is develop. Fujifilm cameras can re-develop a RAF file in the camera, so we shot RAW and then developed the same file repeatedly: once with Provia at default settings as the neutral anchor, and once with each simulation, also at defaults. Colour 0, highlight and shadow tone 0, grain off, colour chrome off, no white balance shift. Same sensor data, exposure and white balance; only the look changes. Ten minutes at the camera beats a hundred field shots, because it removes every confound at once.
Defaults matter. Leave a recipe's highlight tone at −1 and you've measured the simulation plus your recipe, and the recipe gets baked into the film. Three of our films, the Gold-, Kodachrome- and Ektachrome-style ones, were deliberately solved from recipes rather than stock simulations. That was a decision, not an accident.
Pair frames to files by comparing pixels, not filenames. We matched small luma signatures across four rotations. Filenames lie; pixels don't.
2. What to photograph: this limits everything else
Five café and park frames from one evening touched 5.8% of a 33×33×33 colour cube. Two thirds of their pixels had a CIELAB chroma (C*) below 8, which is to say nearly grey. Cyan, violet and magenta made up 0.12%, 0.03% and 0.01% of the pixels. A parameter with nothing behind it will take whatever value flatters its neighbours: one early fit asked for 58 degrees of magenta hue rotation, from almost no magenta.
So: shoot a colour chart. One frame of a 24-patch chart carries more usable colour than all five of those scenes together, and it covers exactly the hues real scenes skip. Failing that, deliberately include saturated blue sky, something red, something cyan, foliage, skin and a white patch, in daylight.
3. Solve against the camera's neutral, never against your own
The obvious approach is to take the RAW, develop it with our own neutral pipeline, and solve what it takes to get from there to Fujifilm's simulation. That measures two things at once: the simulation, and every way our RAW develop differs from Fujifilm's. The second part is real, but it belongs to that camera. Carry it into a film and you apply a Fujifilm-sensor correction to an iPhone whose neutral comes from somewhere else entirely.
It showed up plainly. Provia solved against our own develop came back with a chroma scale of 0.98 and hue rotations up to 17 degrees: a neutral disagreeing with a neutral. Every simulation carried that same signature. Solving Provia-to-simulation instead, both rendered by the camera, removed it, and the error on the simulations dropped from 3.7–5.2 ΔE to 1.3–3.5 immediately.
There's also a free test. Solve Provia against Provia. The answer must be ΔE 0.000, chroma 1.0000, rotation 0.00. It's the one case where the answer is known in advance, and running it caught a real bug.
4. What a film is made of
A film's colour is fitted in stages, in the same order the app applies them: curves, then colour.
Curves first, from the greys
Master, red and blue curves are read from near-neutral pixels (C* below 8). That's more than half the frame, tens of thousands of samples per bin against a few hundred for some hues, so it's the best-measured thing available.
The curves carry the film's tone and its cast on greys. That second part matters more than it sounds. A colour model that works by scaling chroma can't touch a grey, because a grey has no chroma and zero times anything is zero. For a while our Chrome- and Negative-type films looked alike for exactly this reason: on most of the picture we were applying nothing, and that's where Fujifilm puts much of each simulation's signature.
The bug worth knowing about. The first version binned each channel by the pixel's grey level. But a near-neutral pixel isn't neutral. The median red, green and blue across a bin carry whatever cast that population of pixels happened to have, and the curve then applied that cast on top of itself. Provia against Provia returned ΔE 1.4 instead of 0. Bin each channel by its own value, which is also what applying a curve to a channel does, and identity returns exactly 0.
One more trap: the red and blue curves have to be stated against the master curve's output, not the original input, because the master runs first and hands them its result.
Then the colour, fitted through the curves
Invert the curves off the target, then fit the colour layer against what's left. Fitting it beside the curves instead double-counts what the curves already did to colour. On Classic Negative that sent blue to a +24 degree rotation where the camera turns it +11.
The colour layer is deliberately shallow: a chroma scale and a hue rotation per hue, interpolated around the hue circle, plus three tone terms. Shallow enough that each part is linear in its parameters, so the fit is three least-squares problems solved exactly. There's no optimiser to distrust.
Both sides need a ridge penalty pulling toward identity. A hue with no evidence should come back saying the film leaves it alone. The tone terms need it for a different reason: a midtone contrast term, a toe and a shoulder are nearly collinear, and the unpenalised answer was a contrast of 2.2 cancelled by a shadow lift of +59.
Monochrome is its own solve
A black-and-white film is a channel mix plus a tone curve. The mix, the thing a yellow or red filter changes, is decided by how light each hue comes out, and that information is gone from the grey result. But it isn't gone from the colour frame on the other side of the pair, so the weights can be searched against it.
The tone can't be summarised in three terms. In a monochrome film the tone is the film, and a long toe running a third of the way up the scale is exactly what three terms average away. On a synthetic pair built from a known five-point curve, the three-term model recovered the channel weights to four decimals and still missed the tone by 1.94 L*. Fitting a full curve instead missed by 0.16.
5. Judging the result
ΔE over real pixels is the measure. Not a handful of "memory colour" probes like a sky blue, a skin tone and a leaf green. Three synthetic points can't speak for a distribution that's two thirds near-neutral, and they'll call a film worse on exactly the pixels it's now right about. Our Negative-type film went from 3.67 to 1.47 ΔE while its three probes got worse.
Break the error down by chroma band. A change that helps overall but hurts saturated colour is worth knowing about. The Negative rebuild improved all three bands, which is what made it safe to ship:
| Band | Before (ΔE) | After (ΔE) |
|---|---|---|
| Near-neutral | 2.93 | 0.88 |
| Mild colour | 4.09 | 1.65 |
| Saturated | 5.78 | 3.64 |
Compare films against each other, not only against their targets. The complaint that started the Negative rebuild was "Chrome and Negative look the same". The way to see it is to measure how far apart the camera keeps its two simulations (2.2–5.0 ΔE on our frames) against how far apart ours are. Each film can look accurate on its own while the pair collapses into one.
Cross-check where the data is thin. Adobe's camera-matching profiles are one step removed from the camera, but they can be measured. For Classic Negative they agreed with our frames on where warm crosses to cool (L* 46 against our 47), on the highlight hue (44° against 44.6°) and on a roughly 2:1 warm-to-cool ratio. Published writing about film simulations is mostly qualitative and repeats itself. Treat a claim as folklore until something measures it. Classic Negative's often-described "magenta highlights", measured on greys, are amber at hue 44°.
6. Shipping it
A few rules we keep:
- Write down the error. Each film's source notes carry its measured ΔE and what it does in photographic terms. If the fit is poor, it says so, rather than a test tolerance being quietly widened. Our Gold-style film sits at 3.54 ΔE, and its notes say it's a camera recipe, not a simulation.
- No trademarks in names. Films are named after what they do or what they're for (Chobial Chrome, Chobial Negative, Chobial Portrait), not after the stock they were solved from.
- Mind the wire format. A film can be shared as a QR code, so its parameters have to fit. Codes grew from about 69 bytes to about 128 when films gained curves, still comfortably a QR. Hue rotation is carried over ±32 degrees, so a fit that asks for 58 can't be shared anyway.
Seeing the result in Chobial
The films this produced are the built-ins, from Chobial Standard to Chobial B&W. To judge them yourself:
- Load a built-in film on the camera. It's live in the viewfinder; touch and hold to see the scene without it.
- Open an existing photo, go to the editor's Film tool and tap between films. The photo re-develops from its RAW each time (Develop it again).
- Hold Compare to see the clean develop underneath.
- To change one, start a new film from it: Films › + › New Film › Start From. Built-ins can't be edited, but a copy can (Make your own film).
7. What's still wrong
- Coverage, not model capacity, is the limit. A full grid of 8 hues × 3 lightness bands only took Negative from 3.47 to 2.81 ΔE, and it asked for blue to rotate −38.5° in the shadows and +35.1° in the highlights. That's noise being fitted. A 3D LUT fails the same way with more parameters: exact on a twentieth of the cube, identity across the rest. Shoot a chart.
- Chroma moves by hue alone. Films that shift colour differently in shadows and highlights are only approximated. Our Gold-style film's skin is 27° from the camera's, and nothing in the current model fixes it. A lightness term helped in testing (our Nostalgia film went from 2.89 to 2.28) but not enough to justify changing the shared film format.
- Our neutral runs about 6° yellower than Fujifilm's on warm hues. We haven't corrected it, because every coloured surface in the frames that revealed it was warm, and fitting a rotation on that evidence would move greens, blues and skin on no evidence at all. It needs iPhone-beside-Fujifilm frames in daylight with foliage, sky and skin.
- The base tone was solved on two tungsten café scenes. It closed the shadows to 0.11 L* across both, but a daylight pair could disagree, and should be trusted over it.
None of this makes a film that's the same as the camera's. It makes one whose differences we know and can write down, which is more than a look tuned by eye can say. A film's colour stage can be exported as a .cube LUT if you want to inspect it elsewhere (making a LUT on iPhone), and the grain has its own measured curve, covered in why digital grain looks fake.
Fujifilm, Provia, Classic Chrome and Classic Negative are trademarks of FUJIFILM Corporation. Kodak, Gold, Kodachrome and Ektachrome are trademarks of Eastman Kodak Company. Chobial is not affiliated with either.
Questions
Can you measure a film simulation from photos?
Yes, if the photos are controlled. Develop one RAW file in the camera twice, once neutral and once with the simulation, and the difference between the two is the look. Random photos shot on different days mix the look with exposure, white balance and scene.
Why not just use a LUT of the film simulation?
A LUT measured from a few photos is exact where the photos had colour and says nothing about the rest of the cube. Our field frames touched 5.8% of a 33-point cube. A small model with a few meaningful parameters fails more gracefully than a LUT with thousands.
Are Chobial's films the same as Fujifilm's simulations?
No. They're our own films, solved from a Fujifilm camera's renderings and then applied to an iPhone's RAW develop. They get close on the frames we measured, and we publish where they don't.
Can I make my own film the same way?
Not with an automatic solver in the app. You can build a film by hand from the same kinds of controls (curves, a colour mixer, split toning); see Make your own film.