Zone-system exposure control for digital cinema. Ten zones — each with a dedicated stop adjustment. Precise tonal placement based on Ansel Adams' system, applied to moving images.
Most colorists match shots by eye — nudging lift, gamma, gain until it looks close. That works, but it's slow and inconsistent. Parade Match reads your actual parade numbers and remaps each channel mathematically.
You tell it where your source shot's blacks and whites sit per channel, and where you want them to sit. It handles the rest. The result is a repeatable, verifiable correction — not an approximation.
| Parameter | Range / Default | Description |
|---|---|---|
| Src Black R/G/B | -0.2–0.6 · Default 0.0 | Shadow floor of the reference shot per channel. Read from parade waveform. |
| Src White R/G/B | 0.3–2.0 · Default 1.0 | Highlight ceiling of the reference shot per channel. |
| Tgt Black R/G/B | -0.2–0.6 · Default 0.0 | Target shadow position — where you want shadows to sit after matching. |
| Tgt White R/G/B | 0.3–2.0 · Default 1.0 | Target highlight position — where you want the highlights to sit after matching. |
| Mid Correction | 0.5–2.0 · Default 1.0 | Gamma adjustment on the matched result. <1.0 lifts midtones, >1.0 pulls them down. |
| Strength | 0–1 · Default 1.0 | Blend back to original. 1.0 = full correction applied. |
// ═══════════════════════════════════════════════════════════════
// ODIX Parade Match v1.0
// Per-channel lift/gain matching from RGB parade readings
//
// USAGE:
// 1. Open your reference shot. Read its parade:
// note the shadow floor and highlight ceiling per channel.
// 2. Enter those values in SOURCE BLACK R/G/B and
// SOURCE WHITE R/G/B.
// 3. Switch to your target shot (the one to match).
// Enter its parade values in TARGET BLACK/WHITE.
// 4. The tool remaps each channel so the parade aligns.
// 5. Use Strength to blend back if needed.
//
// by Odbat Batsaikhan — odixbat.com — @odixbat
// ═══════════════════════════════════════════════════════════════
DEFINE_UI_PARAMS(p_SrcBlkR, Src Black R, DCTLUI_SLIDER_FLOAT, 0.0, -0.2, 0.6, 0.001)
DEFINE_UI_PARAMS(p_SrcBlkG, Src Black G, DCTLUI_SLIDER_FLOAT, 0.0, -0.2, 0.6, 0.001)
DEFINE_UI_PARAMS(p_SrcBlkB, Src Black B, DCTLUI_SLIDER_FLOAT, 0.0, -0.2, 0.6, 0.001)
DEFINE_UI_PARAMS(p_SrcWhtR, Src White R, DCTLUI_SLIDER_FLOAT, 1.0, 0.3, 2.0, 0.001)
DEFINE_UI_PARAMS(p_SrcWhtG, Src White G, DCTLUI_SLIDER_FLOAT, 1.0, 0.3, 2.0, 0.001)
DEFINE_UI_PARAMS(p_SrcWhtB, Src White B, DCTLUI_SLIDER_FLOAT, 1.0, 0.3, 2.0, 0.001)
DEFINE_UI_PARAMS(p_TgtBlkR, Tgt Black R, DCTLUI_SLIDER_FLOAT, 0.0, -0.2, 0.6, 0.001)
DEFINE_UI_PARAMS(p_TgtBlkG, Tgt Black G, DCTLUI_SLIDER_FLOAT, 0.0, -0.2, 0.6, 0.001)
DEFINE_UI_PARAMS(p_TgtBlkB, Tgt Black B, DCTLUI_SLIDER_FLOAT, 0.0, -0.2, 0.6, 0.001)
DEFINE_UI_PARAMS(p_TgtWhtR, Tgt White R, DCTLUI_SLIDER_FLOAT, 1.0, 0.3, 2.0, 0.001)
DEFINE_UI_PARAMS(p_TgtWhtG, Tgt White G, DCTLUI_SLIDER_FLOAT, 1.0, 0.3, 2.0, 0.001)
DEFINE_UI_PARAMS(p_TgtWhtB, Tgt White B, DCTLUI_SLIDER_FLOAT, 1.0, 0.3, 2.0, 0.001)
DEFINE_UI_PARAMS(p_Strength, Strength, DCTLUI_SLIDER_FLOAT, 1.0, 0.0, 1.0, 0.01)
DEFINE_UI_PARAMS(p_MidCorrect, Mid Correction, DCTLUI_SLIDER_FLOAT, 1.0, 0.5, 2.0, 0.01)
__DEVICE__ float channelRemap(float v, float srcLo, float srcHi, float dstLo, float dstHi) {
float range = srcHi - srcLo;
if (_fabs(range) < 0.00001f) return dstLo;
float t = (v - srcLo) / range;
return dstLo + t * (dstHi - dstLo);
}
__DEVICE__ float3 transform(int p_Width, int p_Height, int p_X, int p_Y, float p_R, float p_G, float p_B) {
float r_m = channelRemap(p_R, p_SrcBlkR, p_SrcWhtR, p_TgtBlkR, p_TgtWhtR);
float g_m = channelRemap(p_G, p_SrcBlkG, p_SrcWhtG, p_TgtBlkG, p_TgtWhtG);
float b_m = channelRemap(p_B, p_SrcBlkB, p_SrcWhtB, p_TgtBlkB, p_TgtWhtB);
float midPivot = (p_TgtBlkR + p_TgtWhtR) * 0.5f;
if (p_MidCorrect != 1.0f) {
float g_val = 1.0f / p_MidCorrect;
r_m = midPivot + _powf(_fmaxf((r_m - midPivot) / (1.0f - midPivot + 0.001f), 0.0f), g_val) * (1.0f - midPivot);
g_m = midPivot + _powf(_fmaxf((g_m - midPivot) / (1.0f - midPivot + 0.001f), 0.0f), g_val) * (1.0f - midPivot);
b_m = midPivot + _powf(_fmaxf((b_m - midPivot) / (1.0f - midPivot + 0.001f), 0.0f), g_val) * (1.0f - midPivot);
}
return make_float3(
p_R + (r_m - p_R) * p_Strength,
p_G + (g_m - p_G) * p_Strength,
p_B + (b_m - p_B) * p_Strength
);
}