Table of Contents

Class ToneCurve

Namespace
Egami.Operations
Assembly
Egami.dll

A curve from 0..1 to 0..1 for one channel, as a photo editor's curves dialog draws it: inputs outside 0..1 are clamped first and results are clamped to 0..1. Use one in Curves(ToneCurve); the tone steps (Level, Gamma and the rest) are curves too, evaluated exactly.

public sealed class ToneCurve
Inheritance
ToneCurve
Inherited Members

Examples

// Curves as a photo editor draws them: a smooth curve through the points that never overshoots, here a mild S on all
// three channels and a lift in the blue shadows.
ToneCurve s = ToneCurve.FromPoints([(0, 0), (0.25f, 0.2f), (0.75f, 0.82f), (1, 1)]);
ToneCurve blue = ToneCurve.FromPoints([(0, 0.06f), (0.5f, 0.5f), (1, 1)]);
raster.Apply(o => o.ApplyFilter(ColorFilter.Curves(s, s, s.Then(blue))), Ct);

Remarks

Immutable and safe to share between threads.

Properties

Identity

Gets the curve that changes nothing.

public static ToneCurve Identity { get; }

Property Value

ToneCurve

Methods

Evaluate(float)

Returns the curve's value at x.

public float Evaluate(float x)

Parameters

x float

The input; values outside 0..1 are clamped, and NaN reads as 0.

Returns

float

The output, from 0 to 1.

FromFunction(Func<float, float>, int)

Returns a curve sampled from function at samples evenly spaced inputs and run straight between them. The function is called only here, so the curve is safe to share whatever the function captures.

public static ToneCurve FromFunction(Func<float, float> function, int samples = 4096)

Parameters

function Func<float, float>

The function; results are clamped to 0..1, and NaN reads as 0.

samples int

How many samples, from 2 to 65,536. Defaults to 4,096.

Returns

ToneCurve

The curve.

Exceptions

ArgumentNullException

function is null.

ArgumentOutOfRangeException

samples is outside 2 to 65,536.

FromPoints(ReadOnlySpan<(float X, float Y)>)

Returns the smooth curve through points: a monotone cubic (Fritsch and Carlson, 1980), so a curve through rising points rises everywhere and never overshoots, as photo editors' curves do. Before the first point and after the last the curve stays flat at their values.

public static ToneCurve FromPoints(ReadOnlySpan<(float X, float Y)> points)

Parameters

points ReadOnlySpan<(float X, float Y)>

At least two points, each coordinate from 0 to 1, with strictly increasing X.

Returns

ToneCurve

The curve.

Exceptions

ArgumentException

There are fewer than two points, a coordinate is outside 0..1, or the X values do not strictly increase.

FromTable(ReadOnlySpan<float>)

Returns the curve that passes through table's values at evenly spaced inputs (the first at 0, the last at 1) and runs straight between them, as a .cube file's 1D table and Skia's TableARGB do.

public static ToneCurve FromTable(ReadOnlySpan<float> table)

Parameters

table ReadOnlySpan<float>

At least two values, each from 0 to 1. The table is copied.

Returns

ToneCurve

The curve.

Exceptions

ArgumentException

The table has fewer than two values or a value outside 0..1.

Then(ToneCurve)

Returns the curve that applies this one and then next.

public ToneCurve Then(ToneCurve next)

Parameters

next ToneCurve

The curve applied second.

Returns

ToneCurve

The combined curve.

Exceptions

ArgumentNullException

next is null.