Emulsion v0.5.0

The render moved onto the GPU, and the panel in front of it was rebuilt. A full-resolution exposure drag that used to take the better part of a second now costs about 30 ms, which is the difference between adjusting a photograph and waiting for one. Beside that: three new ways out of the app — a .cube LUT for your grading system, a direct scan of the developed negative, and a slide rendering with its own tone curve — and a film simulation that is closer to the physics at almost every stage.

Added

  • GPU acceleration, on by default (Performance ▸ GPU acceleration). The whole twelve-stage pipeline runs on the graphics card. A full-resolution exposure drag is roughly 30 ms of GPU time where the CPU path takes 866 ms; 6 megapixels is about 11 ms, and an enlarger or scanner drag about 5. Turn it off and you get the identical CPU pipeline, which stays the reference: the two agree within three levels on every route, and grain is the one exception, because its random draws respond to a two-level difference by drawing differently.
  • Half-precision rendering for the clean render (Performance ▸ Precision), worth another 20% for at most one level on a few percent of a frame. Exports stay at full precision.
  • Frame meter (Performance ▸ Frame meter), a live per-stage cost breakdown drawn over the viewport. It costs nothing to leave on — nothing waits for it.
  • LUT export. File ▸ LUT writes a .cube for DaVinci Resolve and anything else that reads one. A LUT is a fixed pointwise transfer, so five of the twelve stages cannot travel in it — exposure, white balance, shadows, HDR, the whole optical stage, the coupler diffusion tail, grain, the enlarger's diffusion filter and sharpening are all forced off in the bake. The panel lists which of those you currently have on, live, because that is exactly the difference between the file and what you see. Scanned negatives are refused rather than exported wrong: that route's inversion has a jump in it, and a table cannot carry a jump.
  • Still images open — PNG, JPEG and TIFF, beside RAW files. Input ▸ Interpret as says how to read one (DaVinci Wide Gamut / Intermediate, Canon Log 3 / Cinema Gamut, sRGB and the rest), and it is the same setting the LUT bake uses, so a still and the table exported for it always agree about what the file means.
  • Scan the developed negative directly, with no enlarger and no paper in the way. Negative Conversion inverts it in the box, through the film's own characteristic curve rather than a gamma guess, so mask removal and neutrality come out exact instead of estimated. Four controls: Exposure, Contrast, a preferential shadow ramp, and Flare. With both that and Paper switched off you get the raw orange negative to inspect. No per-frame statistics anywhere — the same film and the same sliders give the same transform on every frame of a roll.
  • Scene light (Spectral ▸ Scene light). Expose the film with the light the shot was actually taken under instead of balanced light, and let the darkroom correct the cast where a darkroom corrects it — the enlarger's filtration is re-solved for the declaration. A tungsten declaration warms the shadows by up to 22 levels on Portra while the midgray barely moves, which is the crossover the real materials have.
  • Slide rendering. For a positive's scan: an exposure push and a five-slider filmic tone curve — contrast, pivot, shoulder, toe — with a live preview of the curve drawn from the same evaluator that renders it.
  • As-shot white balance. The camera's own estimate is read out of the file and the white balance module opens on it, with the temperature and tint naming that estimate and the trims carrying the exact residual, so reset and the modified indicator measure against the file in front of you rather than against a fixed default.
  • Diffusion filters, off by default, in two places: on the taking lens (Optical) and on the enlarger lens. Core, halo and bloom hold their split at any resolution, so a preview and a full-resolution export show the same filter, and there is no radius limit and no cost that grows with one.
  • Print reference correction. Measures what the print's own black and white are — a clear negative and the negative's densest patch, through the same enlarger, paper and scanner your frame goes through — and stretches them onto levels you name. It corrects luminance and rescales the triple, so colour survives the stretch. Off by default.
  • Preflash and a print chemistry. Seven controls over how the paper is developed, and a preflash that fills the paper's toe — which on a print is the highlights.
  • A film chemistry to match, with Film Gamma among its controls: it now reshapes the film's curves once, before the frame is developed, the way a change of developer would, instead of bending an axis per pixel.
  • Gamut compression, on both sides of the pipeline. Colours outside what the output can show are rolled in at constant lightness and hue through a smooth knee rather than clipped per channel, in OkLab by default with CAM16-UCS selectable. On the input side the same idea keeps impossible chromaticities out of the spectral upsampling.
  • A progress toast over the viewport while a full render runs, showing the stage it is in — leading with the RAW decode and the denoise, so a freshly opened file runs one continuous bar from LibRaw to sharpening. It stays out of the way of quick renders entirely.
  • Redesigned sidebar. Controls are grouped into floating cards that follow the workflow — file, geometry, presets, tone, film, print, application — and each module collapses to a single title bar that keeps showing the controls you pin to it.
  • Per-module density. Every module can show Favorite (only the controls you starred), Essential, or Full. Set it per module from its right-click menu, so the modules you work in stay open and the rest stay out of the way.
  • Curation modes for arranging that: one pass for starring controls into Favorite view, another for pinning them to title bars. Both dim what is outside the set instead of hiding it, so you can see what you are choosing between.
  • Module visibility list. Hide modules you never touch; they keep their settings while hidden.
  • Light theme, following the system preference. Rebuilt rather than inverted, so the marks keep their contrast and the warm/cool accents keep their meaning.
  • Every film stock is reachable. Six of them had no way to be selected at all, slide films among them. The slide stocks group under "Slide", and controls a positive film does not use are faded rather than silently ignored.
  • Reset all settings, in the new Presets group. Returns every processing control to its default, keeping the crop, the viewing settings and the export settings — the crop is how the frame is composed, not part of the look.

Changed

  • Grain is sized from the number on the box. Every stock's published RMS granularity is inverted against that stock's own emulsion layers, so the rendered grain measures back to the figure the datasheet quotes. The old parameterisation had never been checked against anything and was about twice too grainy — Portra 400 rendered at 8.9 / 9.3 / 16.0 against a published 4.5 across the board.
  • Grain has dye clouds. Particles are spread over the area they actually occupy, so a coarser grain renders larger clumps rather than only louder ones, and detail finer than the grain dissolves into it instead of staying sharp underneath.
  • Grain no longer changes with the frame's pixel count. Its blur and acutance radii are stated in micrometers, so the same stock renders the same texture on a 24 MP body and a 12 MP one, and two exports of one frame at different resolutions match.
  • The film and paper profiles were refreshed to the upstream research project's current set of 28, with Verita 200D added and two older stocks of our own dropped.
  • The enlarger's dichroic filters are in Kodak CC units, the unit an enlarger head is actually marked in. The old range left everything above its midpoint doing nothing at all; no setting is inert now. The neutral filter table was re-solved with them.
  • The developed film's inhibitor saturates, on whichever side the stock's polarity puts it — the coupler supply runs down on a negative, the arriving inhibitor saturates on a slide.
  • The highlight boost lifts the pixel, not the channel, against a ceiling you state in stops above midgray rather than against whatever the frame's brightest pixel happens to be. Hue and saturation survive it exactly, and two crops of one scene get the same treatment.
  • Sharpening runs in linear light, and its amount reaches 1.0.
  • The temperature slider spends its length evenly. It runs in mired, centred on neutral, so 50 K of travel means about as much at one end as the other. It used to move the white point 51× faster at its cold end.
  • Auto-exposure meters the whole frame, not the crop, so cropping stops changing the exposure underneath you.
  • Film and paper lists are grouped from the profile data itself rather than from a hand-written list, so a stock cannot appear in one and not the other.
  • A module's reset button, and the indicator that shows it is off its defaults, both read the engine's own starting values, a module's header switch included.
  • The spectral log-exposure surface now ships on, which stops saturated highlights running off the top of the exposure range and posterizing.
  • egui/eframe 0.32.1 to 0.35.

Fixed

  • The default white balance was not neutral. A duplicate default tint of 0 sat where the white balance module's own neutral is, multiplying every single render by (0.971, 1.0, 0.947) — a green cast on everything, which the enlarger's neutral filter table had been quietly absorbing. Fixed, and the table re-solved.
  • The developer inhibitor's spatial diffusion had been dropped from the shipping render, which left four sidebar controls doing nothing at all. It is back: worth up to 57 levels, on 78% of a frame.
  • The enlarger's diffusion filter did nothing whenever the stages around it were being run together, which was the shipping path — 154 levels off, on a third of the frame.
  • "Viewport — preview" had never worked. Changing it moved the setting and started a re-render that produced the same pixels.
  • Wide blurs painted vertical stripes. The recursive filter behind them lost its DC gain at large radii — down to 0.009 at the widest — so a large diffusion filter darkened the frame and striped it, one stripe per column.
  • The viewport was desaturated against the export on wide-gamut displays. A colour transform that had been correct under the old rendering backend became a double conversion under the new one; macOS matches the surface itself now.
  • Portrait-orientation export produced a wrong frame.
  • The spectral log-exposure surface switch did nothing whenever a table for the same film was already cached.
  • The scanner's adaptation now comes from the illuminant the scan was taken under, instead of a matrix fixed at D50 → D65 — which had left print stocks viewed under a projector white 14 levels cool, with the neutral filter table carrying yellow to cancel it.

Downloads for this version are no longer published. Upgrade to the latest release for binaries.