Levels (Histogram Transform)

Classic black / midtones / white levels: set the black and white points, then bend the midtones with a PixInsight-style Midtones Transfer Function. Live curve, histogram overlay, per-channel, and mask-aware.

1. Using the tool

Drag the three handles on the curve (or use the sliders/spin-boxes), watch the preview and the original-vs-result histogram, then Apply. The curve's black and white handles carry the midtone proportionally, so narrowing the range doesn't jump the midpoint.

ControlWhat it does
ChannelL (luminance, chroma preserved), K (brightness — same curve on R, G, B), or a single R/G/B. Mono images are locked to L.
Black pointInput level mapped to 0. Everything at or below it is clipped to black.
MidtonesThe input level pulled to mid-grey (0.5) — the gamma-like bend between black and white.
White pointInput level mapped to 1. Everything at or above it is clipped to white.
Live previewRecompute the preview on every change (debounced).
Curve + histogramDraggable B/M/W handles; the histogram shows original (dim) vs result (bright) for R/G/B and luminance.
Apply / Apply as New / ResetWrite to the document, open the result as a new view, or return the handles to 0 / 0.5 / 1.
Grip (bottom-left)Drag to the canvas to mint a Levels shortcut, or drop on an image to apply headlessly.

The clip readout reports, for the selected channel, how many pixels the current black/white points drive to pure black or white; a min/max readout shows the data's actual range.

2. Technical details

Two stages per channel: a linear black/white rescale, then a non-linear midtones transfer. Everything operates on float data in [0,1].

2.1 Black / white rescale

The black point b and white point w linearly remap and clip the input:

t=\mathrm{clip}\left(\frac{x-b}{w-b},\;0,\;1\right)

2.2 Midtones transfer

The rescaled value is bent by the PixInsight Midtones Transfer Function with a single midtone parameter m:

M(t;m)=\frac{(m-1)\,t}{(2m-1)\,t-m}

It is pinned at the ends and sends the midtone to mid-grey:

M(0;m) = 0 (black stays black) M(1;m) = 1 (white stays white) M(m;m) = 0.5 (the midtone input maps to mid-grey)

The Midtones handle is an absolute input level; it is converted to the MTF parameter relative to the black/white window before the curve is evaluated, so the midpoint stays meaningful as you move the end points:

m=\frac{m_{\mathrm{abs}}-b}{w-b}

This is the same midtones transfer that Statistical Stretch uses — here you place black/mid/white by hand (midtone → 0.5), whereas Statistical Stretch solves the midtone analytically to land a target median.

2.3 Channel modes

2.4 Clipping stats

For the selected channel's values v (L and K use the luminance proxy), the readout counts what the current end points clip:

n_{\mathrm{low}}=\#\{v\leq b\}\,,\qquad n_{\mathrm{high}}=\#\{v\geq w\}

2.5 Masking

If the document has an active mask, the transform is blended back against the original over the mask (and the mask is resized to match — downsampled for the preview, full-res on apply, so what you see matches what you get):

\mathrm{out}=\mathrm{base}\cdot(1-\mathrm{mask})+\mathrm{out}\cdot\mathrm{mask}

2.6 Notes