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: PathBufInput 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: PathBufOutput image. The extension picks the format (png, tiff, …).
stock: StockArgsFilm, paper and development.
ev: ExposureExposure 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: f64Print 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: EncodingArgHow to interpret the values stored in the input file.
grain: boolAdd 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: f64Width 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: u64Grain seed. The same seed and the same image give the same grain.
gpu: boolRender 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: boolAdd 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: boolSkip 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: boolAdd 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: boolAdd 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: boolScan 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
impl Args for RenderArgs
Source§fn augment_args<'b>(__clap_app: Command) -> Command
fn augment_args<'b>(__clap_app: Command) -> Command
Source§fn augment_args_for_update<'b>(__clap_app: Command) -> Command
fn augment_args_for_update<'b>(__clap_app: Command) -> Command
Command so it can instantiate self via
FromArgMatches::update_from_arg_matches_mut Read moreSource§impl Debug for RenderArgs
impl Debug for RenderArgs
Source§impl FromArgMatches for RenderArgs
impl FromArgMatches for RenderArgs
Source§fn from_arg_matches(__clap_arg_matches: &ArgMatches) -> Result<Self, Error>
fn from_arg_matches(__clap_arg_matches: &ArgMatches) -> Result<Self, Error>
Source§fn from_arg_matches_mut(
__clap_arg_matches: &mut ArgMatches,
) -> Result<Self, Error>
fn from_arg_matches_mut( __clap_arg_matches: &mut ArgMatches, ) -> Result<Self, Error>
Source§fn update_from_arg_matches(
&mut self,
__clap_arg_matches: &ArgMatches,
) -> Result<(), Error>
fn update_from_arg_matches( &mut self, __clap_arg_matches: &ArgMatches, ) -> Result<(), Error>
ArgMatches to self.Source§fn update_from_arg_matches_mut(
&mut self,
__clap_arg_matches: &mut ArgMatches,
) -> Result<(), Error>
fn update_from_arg_matches_mut( &mut self, __clap_arg_matches: &mut ArgMatches, ) -> Result<(), Error>
ArgMatches to self.Auto Trait Implementations§
impl Forget for RenderArgs
impl Freeze for RenderArgs
impl Move for RenderArgs
impl RefUnwindSafe for RenderArgs
impl Send for RenderArgs
impl Sync for RenderArgs
impl Unpin for RenderArgs
impl UnsafeUnpin for RenderArgs
impl UnwindSafe for RenderArgs
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
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