A muddy orange memory becomes a film with real color, measured once per shot, applied identically to every frame (per-frame color would flicker).
Age fades the three color channels by different amounts, so the whole image drifts toward one muddy tint. The fix: build a separate histogram for Red, Green and Blue, find where each channel's real range sits, and stretch each independently to fill 0-255. A uniform cast gets pulled apart and neutralized, and the folded math becomes three 256-entry lookup tables, so the heavy pass is pure array indexing, zero per-pixel math.
Gray-world white balance assumes that, averaged over a scene, the world is neutral gray, so it scales the channels until their averages match. Usually fine. It fails badly when one strong color fills the frame. In Yossi's reel: a boy in a bright red shirt.
Gray-world sees all that red, decides the average is "too warm," and shoves the entire image toward the opposite color, green, until the average goes neutral. The shirt calms down… and the boy's skin turns a sickly teal.
The fix is a smarter measurement: estimate the balance from the near-neutral pixels only, the genuinely low-saturation parts (skin highlights, teeth, a white collar), which is where a real cast actually shows, and leave saturated content alone. On the red shot, the numbers matched the eyes: gray-world crushed the red-over-blue balance from +43 to +15 (neutralizing a genuinely red scene); near-neutral held it at +43, faithful to the film.
if neutral_wb: # opt-in
mask = saturation(pixels) < 0.15 # only near-grays vote
gains = graymean / channel_mean(pixels[mask])
else:
gains = graymean / channel_mean(all_pixels) # classic gray-world
Old film grows a blue cast in the shadows specifically, so we pull blue down but only in the dark areas (the effect ramps from full at black to zero by mid-gray). Finally the grade: blend a warm film look-up table and a modest saturation boost.
0.4 down to 0.22. The grade got more honest.clip_percent: 0.5,
white_balance: true, neutral_wb: true,
blue_shadow: 0.15, lut: film_warm,
lut_blend: 0.22, saturation: 1.2.
(No contrast here, the Light stage owns tone, so the two never fight.)