Hyperbolic Stretch

Six pivot-aware stretch functions in one tool — SASpro's Universal Hyperbolic Stretch, the Generalised Hyperbolic Stretch of Cranfield & Payne, plus ArcSinh, Logarithmic, Exponential, and Power of Inverted Pixels — each anchored at a symmetry point you choose, with shadow/highlight protection and per-channel control.

1. Using the tool

Pick a function, set the symmetry point (pivot), and shape the stretch with its parameters while the preview updates live. All functions except Power of Inverted Pixels are pivot-aware: they pass through your chosen point so tones below and above it move in a controlled, continuous way.

Choosing the function

Setting the symmetry point (pivot)

Parameters & controls

ControlWhat it does
ChannelApply to K (brightness / all RGB), or a single R/G/B.
α / β (UHS)Slope at SP / shadow–highlight bias.
D / b (GHS)Stretch amount (entered log-scaled) / concentration around SP.
LP / HP / BP (GHS)Shadow- and highlight-protection points and a black-point, all in [0,1] (see §2.3). These replace the generic LP/HP below in GHS mode.
Strength (ArcSinh / Log / Exp / PIP)Intensity of the lift/compression for those functions.
LP / HP (other functions)Shadow/highlight protection weights in [0,1] that blend the result back toward the identity on each side of the pivot (see §2.6).
γA final gamma applied after the stretch (shared by all functions).
Fine adjustment (▾)The down-arrow on α/β/D/b/γ reveals a high-resolution slider spanning a small window around the current value, for sub-step precision.
Auto-stretch (display only)Stretches the preview for visibility on linear data. Mouse-over readouts and the pivot pick still use the real, unstretched values.
HistogramOpens a histogram with SP / LP / HP / BP marker lines; hovering the image draws value lines on it.
Toggle Preview / Apply / ResetShow the result, commit it as a “Hyperbolic Stretch” step, or return all sliders to defaults.
Grip (bottom-left)Drag to the canvas to mint a shortcut with the function, channel and all sliders baked in, or drop on an image to apply headlessly.

2. Technical details

Every function builds a monotone lookup table on [0,1] and is applied per selected channel. All are anchored so the pivot maps to itself.

2.1 Common framework

Each function defines a raw response; it is then normalised so the curve passes through three points — f(0)=0, f(SP)=SP, f(1)=1 — by scaling the two halves independently. For a raw response raw(x) the left half [0, SP] is mapped as

f=\mathrm{SP}\cdot\frac{\mathrm{raw}(x)-\mathrm{raw}(0)}{\mathrm{raw}(\mathrm{SP})-\mathrm{raw}(0)}

and the right half [SP, 1] symmetrically onto [SP, 1]. LP/HP protection and gamma (§2.6) are applied afterward, and the LUT is finally forced monotone (a running maximum) so the transform can never invert.

2.2 Universal Hyperbolic Stretch (UHS)

SASpro's own function. The raw response is a rational sigmoid whose exponent is the slope control and whose denominator weight is the bias:

\mathrm{raw}(u)=\frac{u^{\alpha}}{u^{\alpha}+\beta\,(1-u)^{\alpha}}

α sets the slope directly at the symmetry point, and β biases the two halves against each other (the right half uses 1/β), so shadows and highlights can be pushed asymmetrically. The result is renormalised through the midpoints so it passes through (0,0), (SP, SP) and (1,1). This is not a reparameterisation of GHS — UHS gives you a direct handle on the local slope at SP, where GHS sets a global amount and a concentration.

2.3 Generalised Hyperbolic Stretch (GHS)

The GHS method and its equations are the work of Mike Cranfield and David Payne. SASpro claims authorship of neither; this is an independent NumPy implementation of their published formulation, offered with credit and thanks. Project & licence: ghsastro.co.uk/information/ (GPLv3, as is SASpro).

The family is the integral of a local stretch kernel taken outward from the symmetry point. With t = |x − SP| and stretch amount D, the monotone building block g(t) (with g(0)=0) takes one of four forms selected by b:

g(t)=1-(1+D\,b\,t)^{-1/b}\qquad(b>0,\ \mathrm{hyperbolic})
g(t)=1-e^{-D\,t}\qquad(b=0,\ \mathrm{exponential})
g(t)=\ln(1+D\,t)\qquad(b=-1,\ \mathrm{logarithmic})
g(t)=\frac{(1+D\,B\,t)^{(B-1)/B}-1}{B-1}\qquad(b<0,\ B=-b)

The transform is the odd extension about SP,

G(x)=\mathrm{sign}(x-\mathrm{SP})\;g\!\left(\,|x-\mathrm{SP}|\,\right)

then affinely rescaled so f(0)=0 and f(1)=1. Shadow/highlight protection replaces G with its own tangent line outside [LP, HP] — this is what stops the stretch amplifying read-noise below LP or blowing out stellar cores above HP:

G(x)=g(t_L)+g'(t_L)\,(x-\mathrm{LP})\qquad(x<\mathrm{LP},\ t_L=\mathrm{SP}-\mathrm{LP})

A black point BP is subtracted first (x → max(0, (x−BP)/(1−BP))), and D is entered in the UI as ln(D+1) so the slider is linear across the useful range:

D=e^{D_{\mathrm{slider}}}-1

2.4 ArcSinh / Logarithmic / Exponential

Three pivot-aware functions sharing the two-half normalisation of §2.1. With d = x − SP and strength s:

\mathrm{arcsinh:}\quad \mathrm{raw}(x)=\mathrm{arcsinh}\!\left(s\,d\right)
\mathrm{log:}\quad \mathrm{raw}(x)=\mathrm{sign}(d)\,\ln(1+s\,|d|)
\mathrm{exp:}\quad \mathrm{raw}(x)=e^{\,s\,d}-1

ArcSinh gives the gentlest highlight roll-off; Log compresses the bright end harder; Exp lifts away from the pivot.

2.5 Power of Inverted Pixels (PIP)

A fixed-shape power curve whose exponent falls with intensity, so faint tones are lifted while bright ones are left near-linear. It has no pivot:

f(x)=x^{\,1-s\,x}\qquad s\in[0,2]

2.6 Shared post-steps

For every pivot-aware function, LP and HP blend the result back toward the identity on their side of the pivot (0 = full stretch, 1 = untouched), then a shared gamma is applied:

v'=(1-\mathrm{LP})\,v+\mathrm{LP}\,x\quad(x\leq\mathrm{SP})\,,\qquad v'=v^{\,1/\gamma}

(HP does the same for x ≥ SP.) Note these generic LP/HP weights are distinct from GHS's LP/HP protection points in §2.3 — in GHS mode the generic LP/HP controls are hidden.

2.7 Notes