Skip to main content

RenderArgs

Struct RenderArgs 

Source
pub struct RenderArgs {
Show 19 fields pub input: PathBuf, pub output: PathBuf, pub stock: StockArgs, pub ev: Exposure, pub print_ev: f64, pub balance_from: Option<f64>, pub input_encoding: EncodingArg, pub grain: bool, pub size: Option<u32>, pub frame_mm: f64, pub grain_um: Option<f64>, pub grain_seed: u64, pub gpu: bool, pub couplers: bool, pub no_emulsion: bool, pub halation: bool, pub interimage: bool, pub scanner: bool, pub scan_optics_um: Option<f64>,
}
Expand description

kalo render

Fields§

§input: PathBuf

Input image. 8/16-bit sRGB by default; pass –input-encoding linear for a linear-light TIFF. A camera raw (ARW, NEF, CR3, RAF, DNG, …) is decoded to linear light directly, if this build has the raw feature.

§output: PathBuf

Output image. The extension picks the format (png, tiff, …).

§stock: StockArgs

Film, paper and development.

§ev: Exposure

Exposure offset in stops, applied before the negative.

Pass auto to meter the frame instead of naming the offset: the render then places the frame’s mean luminance at 18 % grey, the way an averaging exposure meter and a laboratory’s average printer both do. The report says what it solved, so the result can be repeated with a fixed number. A scene whose key is not the average — a night street, a snowfield — is better served by a fixed offset.

§print_ev: f64

Print exposure in stops, on top of the exposure that prints a mid grey as a mid grey.

The print is solved so that an 18 % grey negative lands at the paper’s target: this is the timer, not the balance. Positive is more light and a darker print, which is what a printer would call “one stop more”.

§balance_from: Option<f64>

Print on the balance solved for this development, not the requested one.

This is a test strip’s one exposure: a print is made at each development with the enlarger where the first print set it, so the comparison is the development and not the timer.

§input_encoding: EncodingArg

How to interpret the values stored in the input file.

§grain: bool

Add grain to the negative, as a particle process on the film’s scale.

The graininess depends on how much film area a pixel covers, so it needs –frame-mm to know how big the frame is.

§size: Option<u32>

Render at this width, in pixels, instead of at the input’s own.

The bench works at the size a screen can show, and a 26 megapixel camera file is not that. It is a resize and not a crop — the whole frame — and the grain is computed for the sampling that results, because a smaller render is a coarser scan and should look like one.

§frame_mm: f64

Width of the film frame the image represents, in millimetres.

36 is a 35 mm still frame; use 24 for half-frame, and the short side if the image is portrait.

§grain_um: Option<f64>

Correlation length of the grain in micrometres, overriding the stock’s.

The distance over which neighbouring pixels agree, as measured from a flat scan by scripts/grain_spectrum.py — on a mid-density flat, where the developed silver is what the scanner sees. Until a stock’s own is measured, the model uses the mean spacing the granularity figure implies, which is a lower bound.

Note the stencil: five taps, so a clump much wider than a pixel is drawn narrower than asked. Below about 3 µm per pixel the render is a close-up of the film and the kernel is the limit.

§grain_seed: u64

Grain seed. The same seed and the same image give the same grain.

§gpu: bool

Render on the CPU.

The GPU is the default: everything the model does — both exposure paths, grain, halation, the DIR couplers — except a baked table and a dictionary prior, which are solvers rather than models. A render that needs one, or a machine with no adapter, falls back to the CPU and says so. Use this flag to stay on the CPU anyway.

§couplers: bool

Add DIR couplers: development inhibition between layers, with diffusion.

This is what produces interimage colour correction and the Mackie line along an edge. The matrix is a placeholder.

§no_emulsion: bool

Skip the film’s own blur, from the measured modulation-transfer curve.

It is on by default and is a no-op below about 12 megapixels: a 35 mm frame sampled every 30 µm cannot show a 3 µm blur. Render at 12000 pixels across and it starts to bite.

§halation: bool

Add halation: light scattered in the emulsion and reflected off the base.

Needs –frame-mm for the same reason grain does — the kernels are expressed in micrometres of film, not in pixels.

§interimage: bool

Add the cyan-sensitive layer’s inhibitor (ADR 0018).

Fuji’s fourth layer releases development inhibitor against the red-sensitive layer instead of forming cyan dye, which is why PRO 400H’s cyan curve shows no second emulsion. The effect is local: it takes cyan away where that layer sees more cyan light than the frame’s average and lets it through where it sees less, so a uniform frame is unchanged and an edge is not. Its strength and diffusion length are placeholders, so this is a demonstration of the mechanism, not a prediction — and it is a no-op for a stock whose sheet gives no such layer.

§scanner: bool

Scan the print: the scanner’s measured texture, and its optics when asked for.

The texture is the one a negative scan showed: 0.60 % of density through a 48 µm aperture, correlated over 3.2 µm, and mostly common to the three channels — which is how it was shown to be the scan and not the film. Until this stage the render is the print’s reflectance; this is what turns it into a scan of the print, noise and all.

§scan_optics_um: Option<f64>

Gaussian optics of the scan, in micrometres, on the print.

Unmeasured, which is why it defaults to off: the scan that measured the texture cannot separate the optics from the texture that rides on it, and a point-spread function invented from that measurement would be a second number pretending to be the first. Enabling it enables –scanner.

Trait Implementations§

Source§

impl Args for RenderArgs

Source§

fn group_id() -> Option<Id>

Report the ArgGroup::id for this set of arguments
Source§

fn augment_args<'b>(__clap_app: Command) -> Command

Append to Command so it can instantiate Self via FromArgMatches::from_arg_matches_mut Read more
Source§

fn augment_args_for_update<'b>(__clap_app: Command) -> Command

Append to Command so it can instantiate self via FromArgMatches::update_from_arg_matches_mut Read more
Source§

impl Debug for RenderArgs

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl FromArgMatches for RenderArgs

Source§

fn from_arg_matches(__clap_arg_matches: &ArgMatches) -> Result<Self, Error>

Instantiate Self from ArgMatches, parsing the arguments as needed. Read more
Source§

fn from_arg_matches_mut( __clap_arg_matches: &mut ArgMatches, ) -> Result<Self, Error>

Instantiate Self from ArgMatches, parsing the arguments as needed. Read more
Source§

fn update_from_arg_matches( &mut self, __clap_arg_matches: &ArgMatches, ) -> Result<(), Error>

Assign values from ArgMatches to self.
Source§

fn update_from_arg_matches_mut( &mut self, __clap_arg_matches: &mut ArgMatches, ) -> Result<(), Error>

Assign values from ArgMatches to self.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> Downcast<T> for T

Source§

fn downcast(&self) -> &T

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> Upcast<T> for T

Source§

fn upcast(&self) -> Option<&T>

Source§

impl<T> WasmNotSend for T
where T: Send,

Source§

impl<T> WasmNotSendSync for T

Source§

impl<T> WasmNotSync for T
where T: Sync,