Skip to content

Latest commit

 

History

History
1161 lines (830 loc) · 42 KB

File metadata and controls

1161 lines (830 loc) · 42 KB

3.1 Mathematical Breakdown of Log Encodings

Theory: Logarithmic Encoding Fundamentals

Logarithmic encodings compress a wide dynamic range of scene luminance into a limited code value range (typically 10-12 bits) by allocating more quantization steps to shadow regions where human vision is most sensitive to contrast changes. This logarithmic distribution mirrors the approximately logarithmic response of the human visual system, following the Weber-Fechner law which states that perception of stimulus is proportional to the logarithm of stimulus intensity.

Core Mathematical Structure

General Log Encoding Form:

$$\text{For normalized linear scene exposure } X \geq 0: \text{if } X \leq X_{\text{toe}}: Y = m \times X + c \quad \text{(Linear segment)} \text{else}: Y = A \times \log_{10}(B \times X + C) + D \quad \text{(Logarithmic segment)}$$

Where:

  • $X$: Normalized linear scene exposure (0 = black, 1 = 18% middle gray reference)
  • $Y$: Encoded code value (typically 0-1023 for 10-bit, 0-4095 for 12-bit)
  • $X_{\text{toe}}$: Breakpoint between linear and logarithmic segments
  • $m, c$: Slope and intercept of linear toe segment
  • $A, B, C, D$: Logarithmic segment parameters controlling curve shape and mapping

Logarithmic Encoding Rationale:

The human visual system's response to light is approximately logarithmic. For a stimulus $I$, the perceived brightness $P$ follows:

$$P \propto \log_{10}(I)$$

This means equal ratios of light intensity produce equal perceived differences in brightness. A scene range from 0.001 to 1000 cd/m² (10 stops: $2^{10} = 1024$) produces perceptual differences proportional to $\log_{10}(1000/0.001) = 6$ decades. Log encoding distributes code values to match this perceptual nonlinearity.

Manufacturer-Specific Implementations

ARRI LogC4 (Current Standard - 2023+)

ARRI LogC4 represents a significant redesign from previous LogC3, eliminating the linear toe section for pure logarithmic response across the entire range. This simplifies the mathematics and provides more consistent quantization.

LogC4 Encoding Equation:

$$\text{Constants (ARRI LogC4):} a = \frac{2^{18} - 16}{117.45},\quad b = \frac{1023 - 95}{1023},\quad c = \frac{95}{1023} s = \frac{7 \ln 2 \cdot 2^{\,7 - 14c/b}}{a\,b},\qquad t = \frac{2^{\,14(-c/b) + 6} - 64}{a} \text{Encode (scene-linear } E \rightarrow \text{ LogC4 code } E' \in [0,1]): E' = \begin{cases} (E - t) / s & E < t \\[4pt] \dfrac{\log_2(a\,E + 64) - 6}{14}\; b + c & E \geq t \end{cases} \text{Decode (LogC4 code } E' \rightarrow \text{ scene-linear } E): E = \begin{cases} E' \cdot s + t & E' < 0 \\[4pt] \dfrac{2^{\,14(E' - c)/b + 6} - 64}{a} & E' \geq 0 \end{cases} CV_{\text{10bit}} = \text{round}(E' \times 1023)$$

Key Characteristics (LogC4 Specification v1.0, 2023):

  • Dynamic range: 15+ stops (0.000064 to 1.0 relative exposure)
  • Middle gray placement: 18% at code value 285/1023 (10-bit) = 0.2784 normalized
  • Pure logarithmic: No linear toe, consistent log response across all codes
  • Noise floor: 95 dB SNR at 18% gray (ARRI Alexa 35 specification)
  • Full well capacity: ~60,000 e⁻ (electrons)
  • Read noise: 12-15 e⁻ at base ISO 800

LogC4 Decoding Equation: see the "Decode" cases in the equation block above (the earlier standalone decode 10^((Y·1023/64 − 512)/64) was inconsistent with the encode — it treated Y as a 0–1023 code while the encode produced a 0–1 value — and has been removed).

Quantization Analysis for LogC4 (10-bit):

Code values below are computed from the official LogC4 curve above (verified in curves.py). Middle gray (18%) lands at CV 285; the curve spans roughly 100–735 over ±7 stops:

Stop from 18% Relative E Code Value (10-bit)
-7 (deep shadow) 0.0014 100
-6 0.0028 104
-5 0.0056 112
-4 0.0112 127
-3 0.0225 150
-2 0.0450 185
-1 0.0900 231
0 (18% gray) 0.1800 285
+1 0.3600 344
+2 0.7200 407
+3 1.4400 471
+4 2.8800 537
+5 5.7600 603
+6 11.5200 669
+7 (highlight) 23.0400 735

Perceptual Uniformity:

The just-noticeable difference (JND) in CIELAB space is approximately $\Delta E_{ab}^* = 1$. LogC4's distribution ensures that code value spacing approximates this perceptual threshold across the dynamic range, particularly in shadow regions where human vision is most sensitive.

Sony S-Log3

S-Log3 uses a modified logarithmic curve optimized for 14-stop dynamic range with a linear toe to prevent quantization artifacts in deep shadows.

S-Log3 Encoding Equation (SMPTE ST 2065-4):

$$\text{For normalized linear exposure } X: Y_{\text{S-Log3}} = \begin{cases} \dfrac{X \cdot \frac{171.2102946929 - 95}{0.01125} + 95}{1023} & \text{if } X < 0.01125 \quad \text{(Linear toe)} \\[8pt] \dfrac{420 + 261.5 \cdot \log_{10}\!\big(\frac{X + 0.01}{0.19}\big)}{1023} & \text{if } X \geq 0.01125 \quad \text{(Log segment)} \end{cases}$$

10-bit Encoding:

$$CV_{\text{10bit}} = \text{round}(Y_{\text{S-Log3}} \times 1023)$$

Key S-Log3 Parameters:

  • Dynamic range: 14+ stops (Sony Venice 2: 16+ stops)
  • Middle gray placement: 18% at code value 420/1023 (10-bit) = 0.4106 normalized
  • Linear toe breakpoint: Code value 95/1023
  • Black level offset: 0.0301342 (maintains code value spacing)
  • White point: D65 (matches Rec.709/Rec.2020)
  • Color space: Typically paired with S-Gamut3 or S-Gamut3.Cine

S-Log3 Decoding Equation:

$$\text{For normalized code value } Y \in [0.0301342, 1.0]: \text{With code value } CV = Y \times 1023: X = \begin{cases} 10^{\frac{CV - 420}{261.5}} \cdot 0.19 - 0.01 & \text{if } CV \geq 171.2102946929 \\[4pt] \dfrac{(CV - 95) \cdot 0.01125}{171.2102946929 - 95} & \text{if } CV < 171.2102946929 \end{cases}$$

Comparison with S-Log2 (Legacy):

S-Log2 used a different curve designed for monitoring but introduced color accuracy issues when decoded. S-Log3 (introduced 2014) corrected these issues with:

  • Better shadow linearity
  • Improved color accuracy
  • Optimized for 14-stop sensors (Venice, Burano)
  • Compatibility with ACES pipeline

RED Log3G10

RED's Log3G10 combines logarithmic encoding with increased gain for better highlight retention.

Log3G10 Encoding Equation:

$$\text{For normalized linear exposure } X: \text{Let } X' = X + 0.01: Y_{\text{Log3G10}} = \begin{cases} 0.224282 \times \log_{10}(X' \times 155.975327 + 1) & \text{if } X' \geq 0 \\\ X' \times 15.1927 & \text{if } X' < 0 \end{cases} \text{10-bit encoding:} CV_{\text{10bit}} = \text{round}(Y_{\text{Log3G10}} \times 1023)$$

Key Log3G10 Characteristics:

  • "Gain of 10": Shifts curve right, allocating more code values to mid-highlights
  • Dynamic range: ~16-17 stops (RED V-Raptor [X] 2024)
  • Middle gray placement: 18% at code value 341/1023 (10-bit) = 0.3333 normalized
  • Optimized for: IPP2 (Image Processor Pipeline 2) workflow
  • Color spaces: RWG (RED Wide Gamut), RedColor 4

Decoding Equation:

$$X = \begin{cases} \dfrac{10^{\,Y / 0.224282} - 1}{155.975327} - 0.01 & \text{if } Y \geq 0 \\[6pt] \dfrac{Y}{15.1927} - 0.01 & \text{if } Y < 0 \end{cases}$$

Dynamic Range Calculations

Theoretical Maximum DR:

$$\text{Dynamic Range (stops)} = \log_{2}\left(\frac{L_{\text{max}}}{L_{\text{min}}}\right) \text{Where:} - L_{\text{max}}: \text{Maximum non-clipping signal} - L_{\text{min}}: \text{Noise floor (SNR = 1 or SNR = 10 dB)}$$

Practical DR Measurement (ISO 15739):

$$\text{SNR}(f) = 20 \log_{10}\left(\frac{\mu_f}{\sigma_f}\right) \text{Where:} - \mu_f: \text{Mean signal level} - \sigma_f: \text{Standard deviation of noise} \text{DR definition: SNR} \geq 1 \text{ (0 dB) or SNR} \geq 10 \text{ dB for usable signal}$$

Measured DR Examples (2024 Cinema Cameras):

Camera DR (Stops) SNR at 18% Gray Bit Depth
ARRI Alexa 35 15+ 95 dB 16-bit (ADC)
Sony Venice 2 16+ 93 dB 16-bit (ADC)
RED V-Raptor [X] 17+ 91 dB 16-bit (ADC)
Blackmagic 6K Pro 13 88 dB 12-bit (output)

Quantization and Noise Floor Analysis

Signal-to-Noise Ratio in Log Encoding:

$$\text{SNR}_{\text{dB}} = 20 \times \log_{10}\left(\frac{\text{Signal}}{\text{Noise}}\right) \text{For log encoding at 18\% gray:} \text{SNR}_{\text{log}} = 20 \times \log_{10}\left(\frac{0.18}{\sigma_{\text{read}}}\right)$$

Noise Distribution in Log Space:

$$\text{Log-transformed noise:} \text{If } Y = \log_{10}(X) + \epsilon, \text{ where } \epsilon \sim \mathcal{N}(0, \sigma_{\text{linear}}^2) \text{Then in linear space:} X_{\text{noisy}} = X \times 10^{\epsilon} \text{Noise amplitude becomes signal-dependent:} \sigma_{\text{log}}(X) = X \times \ln(10) \times \sigma_{\text{linear}} \text{This produces perceptual uniformity: relative noise constant across range}$$

Perceptual Noise Weighting:

Human vision is less sensitive to noise in bright regions. The contrast sensitivity function (CSF) describes this:

$$\text{CSF}(f) = A \times f \times \exp(-b \times f) \times \sqrt{1 + 0.06 \times \exp(b \times f)} \text{Where } f \text{ is spatial frequency, } A, b \text{ are constants}$$

Log encoding exploits this by allocating fewer code values to highlights where noise is less perceptible.

Practice: Exposure Validation and Measurement

Measuring Dynamic Range

Step-by-Step DR Measurement Workflow:

1. Capture Test Chart:
   - Use backlit transmission step chart (DSC Labs ChromaDuMonde, X-Rite ColorChecker)
   - Chart must have 20+ f-stop range (0.001 to 1000% reflectance)
   - Even, diffuse illumination with no hot spots
   - Camera at normal exposure (EI 800 for ARRI, EI 640 for Sony)

2. Analysis Software:
   - Imatest Master: Comprehensive DR analysis
   - DXO Analyzer: Industry-standard sensor testing
   - Open-source: RawTherapee, LibRaw scripts

3. Measurement Procedure:
   a. Extract RAW values (no demosaicing, no curve applied)
   b. For each patch, calculate mean and standard deviation
   c. Compute SNR = 20×log10(mean/std)
   d. Identify noise floor: SNR = 0 dB (or SNR = 10 dB for usable)
   e. Identify clip point: SNR drops rapidly or saturation

4. Calculate DR:
   DR_stops = log2(L_max / L_min)
   where L_max is signal at clip point, L_min is noise floor

5. Verify Log Curve:
   - Plot encoded CV vs. log exposure
   - Should be straight line (pure log) or piecewise linear
   - Deviations indicate incorrect encoding or decoding

In-Camera Validation Using False Color:

# False color mapping implementation (pseudo-code)

def false_color_mapping(code_value, encoding='LogC4'):
    """
    Map code values to colors for exposure visualization
    """
    if encoding == 'LogC4':
        # ARRI LogC4 false color zones
        if code_value < 150:
            return (128, 0, 128)    # Purple: noise floor
        elif code_value < 300:
            return (0, 0, 255)      # Blue: deep shadows
        elif code_value < 450:
            return (0, 255, 255)    # Cyan: shadow detail
        elif code_value < 600:
            return (0, 255, 0)      # Green: 18% gray reference
        elif code_value < 750:
            return (255, 255, 0)    # Yellow: skin tones
        elif code_value < 900:
            return (255, 0, 0)      # Red: highlights
        else:
            return (255, 0, 255)    # Magenta: warning zone

    elif encoding == 'SLog3':
        # Sony S-Log3 false color zones (adjusted for different mid-gray placement)
        if code_value < 170:
            return (128, 0, 128)    # Purple
        elif code_value < 330:
            return (0, 0, 255)      # Blue
        elif code_value < 490:
            return (0, 255, 255)    # Cyan
        elif code_value < 610:
            return (0, 255, 0)      # Green (18% gray at 410 CV)
        elif code_value < 770:
            return (255, 255, 0)    # Yellow
        elif code_value < 920:
            return (255, 0, 0)      # Red
        else:
            return (255, 0, 255)    # Magenta

False Color Exposure Strategy:

  1. Target Distribution:

    • 5-10% purple (deep shadows, acceptable)
    • 20-30% blue-cyan (shadow detail)
    • 35-45% green-yellow (midtones, critical information)
    • 15-20% yellow-red (highlights)
    • 0-5% red-magenta (specular highlights only)
    • 0% pure white (clip = information loss)
  2. Warning Signs:

    • 20% purple: Severe underexposure, noise will dominate

    • No magenta/red: May be missing highlight detail
    • Solid magenta: Critical overexposure, data lost
    • Inconsistent false color across frame: Uneven lighting or filter issues

Noise Floor Analysis

Perceptual Noise Measurement:

import numpy as np
from scipy import stats

def analyze_log_noise(image_log, encoding='LogC4'):
    """
    Analyze noise characteristics in log-encoded image

    Args:
        image_log: Log-encoded image (10-bit or 12-bit)
        encoding: Type of log encoding used

    Returns:
        dict with SNR, perceptual noise, and noise floor metrics
    """

    # Decode log to linear
    if encoding == 'LogC4':
        image_linear = logc4_to_linear(image_log / 1023.0)
    elif encoding == 'SLog3':
        image_linear = slog3_to_linear(image_log / 1023.0)

    # Extract middle gray patch (18%)
    gray_patch = extract_patch(image_linear, 0.18)
    noise_std = np.std(gray_patch)
    signal_mean = np.mean(gray_patch)

    # Calculate SNR
    snr_db = 20 * np.log10(signal_mean / noise_std)

    # Perceptual weighting (human visual system)
    # CIELAB delta-E weighting
    perceptual_noise = noise_std * (1 / np.sqrt(signal_mean))

    # Find noise floor (darkest usable patch)
    noise_floor_cv = find_noise_floor(image_log)
    noise_floor_linear = log_to_linear(noise_floor_cv / 1023.0)

    return {
        'snr_db': snr_db,
        'perceptual_noise': perceptual_noise,
        'noise_floor_cv': noise_floor_cv,
        'noise_floor_linear': noise_floor_linear,
        'dynamic_range': calculate_dr(image_linear)
    }

# Target values for LogC4 at 18% gray (ARRI Alexa 35 spec):
# SNR: ≥95 dB (measured)
# Perceptual noise: <1.5% JND threshold
# Noise floor: ~95 CV (10-bit) for SNR = 10 dB

Noise Floor Detection Algorithm:

def find_noise_floor(image_log, patch_size=64, threshold_snr=10.0):
    """
    Find the code value where SNR drops to threshold

    Args:
        image_log: Log-encoded image
        patch_size: Size of patches to analyze
        threshold_snr: SNR threshold in dB (default 10 dB)

    Returns:
        Code value at noise floor
    """

    # Sample patches at different exposure levels
    cv_samples = np.arange(0, 1024, 32)
    snr_values = []

    for cv_center in cv_samples:
        # Extract patch around this CV
        mask = (image_log >= cv_center - 16) & (image_log <= cv_center + 16)
        if np.sum(mask) > 100:  # Minimum pixels
            patch = image_log[mask]
            signal = np.mean(patch)
            noise = np.std(patch)
            if noise > 0:
                snr = 20 * np.log10(signal / noise)
                snr_values.append(snr)
            else:
                snr_values.append(-np.inf)

    # Find CV where SNR crosses threshold
    snr_values = np.array(snr_values)
    noise_floor_idx = np.where(snr_values < threshold_snr)[0]

    if len(noise_floor_idx) > 0:
        return cv_samples[noise_floor_idx[0]]
    else:
        return 0  # Below measurable range

Exposure Index Verification

Testing EI vs. Native ISO:

Test Procedure:
1. Set camera to EI 800 (LogC4 base, typical native ISO)
2. Light gray card to T2.8 at EI 800 (verify with incident meter)
3. Capture at multiple EIs:
   - EI 400 (meter for +1 stop over)
   - EI 800 (normal metering)
   - EI 1600 (meter for -1 stop under)
   - EI 3200 (meter for -2 stops under)
4. Decode all to linear (apply inverse log curve)
5. Measure gray level in linear space
6. Compare SNR at each EI

Expected Results (LogC4 on Alexa 35):
EI 400:
  - Gray ~0.36 (+1 stop above reference 0.18)
  - SNR: ~98 dB (+3 dB over baseline)
  - Shadow improvement: 3 dB better
  - Highlight risk: Reduced headroom by 1 stop

EI 800 (native):
  - Gray ~0.18 (reference middle gray)
  - SNR: ~95 dB (baseline specification)
  - Balanced headroom and shadows
  - Standard DR: 15 stops

EI 1600:
  - Gray ~0.09 (-1 stop below reference)
  - SNR: ~92 dB (-3 dB from baseline)
  - Shadow penalty: 3 dB noisier
  - Highlight protection: +1 stop additional headroom

EI 3200:
  - Gray ~0.045 (-2 stops below reference)
  - SNR: ~89 dB (-6 dB from baseline)
  - Shadow penalty: 6 dB noisier (significant)
  - Highlight protection: +2 stops additional headroom

EI Selection Guidelines:

Scenario-based EI Strategy:

High-key scenes (bright, daylight exterior):
- Use EI 400-600
- Trade-off: Reduced highlight headroom for cleaner shadows
- Benefit: Shadow SNR improved by 2-3 dB
- Risk: Clipping if lighting changes unexpectedly

Normal scenes (balanced contrast):
- Use native EI (800 for ARRI, 640-800 for Sony, 800 for RED)
- Balanced DR allocation
- Standard exposure latitude
- Minimal quality trade-offs

Low-key scenes (dark, night interior):
- Use EI 1000-1600
- Trade-off: Noisier shadows for highlight protection
- Benefit: Additional 1-2 stops highlight headroom
- Risk: Shadow noise may become visible in grade

Mixed lighting (unknown DR):
- Use EI 640-800 (slightly under native)
- Conservative approach protects highlights
- Shadow noise acceptable in most contexts
- Easier to recover in post than clipped highlights

Failure Modes: Common Log Encoding Problems

Overexposure in Log

Symptoms:

Quantitative detection thresholds:

  • Skin tones above 750 CV (LogC4) or 770 CV (S-Log3): "Plastic" appearance
  • 90% of frame above 750 CV: Severe overexposure

  • Any channel >1000 CV (10-bit) approaching clip: Warning
  • 5% of frame at 1023 CV: Critical clipping, information lost

Recovery Limits:

def highlight_recovery_potential(image_log, encoding='LogC4'):
    """
    Analyze recoverable highlight information
    """
    if encoding == 'LogC4':
        clip_point = 1023
        warning_zone = 950
        recovery_limit = 0.3  # stops

    # Count pixels near clip
    near_clip = np.sum(image_log > warning_zone)
    total_pixels = image_log.size
    percent_near_clip = 100.0 * near_clip / total_pixels

    # Estimate recovery potential
    if percent_near_clip > 5:
        return {
            'recoverable': False,
            'detail_loss': 'Severe',
            'recommendation': 'Reshoot with reduced exposure'
        }
    elif percent_near_clip > 1:
        return {
            'recoverable': 'Limited',
            'detail_loss': 'Moderate',
            'recommendation': 'Reduce exposure 1/3-2/3 stop'
        }
    elif percent_near_clip > 0.1:
        return {
            'recoverable': True,
            'detail_loss': 'Minimal',
            'recommendation': 'Acceptable specular highlights'
        }
    else:
        return {
            'recoverable': True,
            'detail_loss': 'None',
            'recommendation': 'Exposure optimal'
        }

Prevention Workflow:

  1. Set Zebras:

    • Threshold: 95% (LogC4: ~950 CV, S-Log3: ~970 CV)
    • Coverage: <1% of frame acceptable for specular highlights
    • Skin tones should NOT trigger zebras
  2. False Color Monitoring:

    • Look for magenta in skin tones (warning sign)
    • Green zone should be 40-50% of typical face
    • Some yellow-red acceptable (specular highlights on skin)
  3. Waveform Analysis:

    • Check for "flat-topping" above 900 CV
    • Healthy waveform: Peaks reach 850-950 CV
    • Overexposed: Flat plateau at 950-1023 CV
  4. Exposure Strategy:

    • Expose for maximum highlight WITHOUT clipping
    • Underexpose 1/3 stop if uncertain (safer than over)
    • Use negative fill or ND grad if highlights too hot

Underexposure in Log

Symptoms and Thresholds:

Shadow SNR degradation:

Acceptable: Middle gray >400 CV (LogC4)
  - SNR >50 dB: Invisible noise
  - Grade flexibility maintained

Warning zone: Middle gray 300-400 CV
  - SNR 40-50 dB: Barely visible noise
  - Grade with caution, use denoising

Critical: Middle gray <300 CV
  - SNR <40 dB: Visible noise, banding
  - May be unusable for critical delivery
  - Consider reshoot or extreme denoising

Quantitative Recovery Limits:

Underexposure Recovery Analysis (LogC4 10-bit):

-1 stop under (middle gray ~200 CV):
  - SNR penalty: ~3 dB
  - Recovery: Lift in grade
  - Quality: Still acceptable with denoising
  - Use case: Slight underexposure, recoverable

-1.5 stops under (middle gray ~150 CV):
  - SNR penalty: ~4.5 dB
  - Recovery: Aggressive lift + denoising
  - Quality: May be acceptable for non-critical scenes
  - Use case: Moderate underexposure, risky

-2 stops under (middle gray ~100 CV):
  - SNR penalty: ~6 dB
  - Recovery: Extreme denoising required
  - Quality: Often unusable, visible artifacts
  - Use case: Severe underexposure, consider reshoot

-2.5+ stops under (middle gray <70 CV):
  - SNR penalty: >7.5 dB
  - Recovery: Extremely difficult
  - Quality: Usually unusable for professional delivery
  - Use case: Failure, reshoot required

Denoising Strategies:

Underexposure Recovery Pipeline:

1. Temporal Denoising (best for stationary shots):
   - Average 3-7 frames (motion-adaptive)
   - Reduces noise by √N (N = frames averaged)
   - Trade-off: Motion blur if objects moving

2. Spatial Denoising (single frame):
   - Bilateral filter, non-local means
   - AI denoising (DaVinci Resolve Super Scale, Neat Video)
   - Trade-off: Detail loss vs. noise reduction

3. Hybrid Denoising (best quality):
   - Combine temporal and spatial denoising
   - Apply temporal first, spatial for residual noise
   - Mask skin tones to preserve detail

4. Selective Denoising:
   - Apply only to shadow regions (avoid midtones/highlights)
   - Use power windows or qualifier masks
   - Preserve edges and texture in critical areas

Log Curve Mismatch

Problem: Applying wrong manufacturer LUT (e.g., LogC LUT to S-Log3 footage)

Detection Method:

def detect_log_curve_mismatch(image_10bit, metadata):
    """
    Detect if wrong log LUT has been applied
    """
    # Measure 18% gray card code value
    gray_card_cv = np.mean(image_10bit[gray_mask])

    # Expected CVs for 18% gray (10-bit):
    expected = {
        'LogC3': 398,
        'LogC4': 400,
        'S-Log3': 410,
        'S-Log2': 485,
        'Log3G10': 450,
        'C-Log': 436
    }

    # Find closest match
    differences = {curve: abs(cv - gray_card_cv)
                   for curve, cv in expected.items()}
    closest_curve = min(differences, key=differences.get)
    min_difference = differences[closest_curve]

    if min_difference > 20:
        return {
            'mismatch': True,
            'measured_cv': gray_card_cv,
            'expected_curve': metadata.get('log_type'),
            'actual_curve': closest_curve,
            'difference': min_difference,
            'recommendation': f'Apply {closest_curve} IDT instead'
        }
    else:
        return {
            'mismatch': False,
            'curve': closest_curve,
            'measured_cv': gray_card_cv,
            'difference': min_difference
        }

Visual Detection Signs:

Wrong Log LUT Symptoms:

LogC LUT applied to S-Log3:
  - Mid-gray too bright (410→400 CV shift looks dark)
  - Color saturation off
  - Shadow rolloff doesn't match
  - May appear "contrasty" or "muddy"

S-Log LUT applied to LogC4:
  - Mid-gray too dark (400→410 CV shift looks bright)
  - Highlights may clip prematurely
  - Skin tones appear magenta-shifted
  - Overall "washed out" appearance

Fix:
1. Verify metadata for actual log type
2. Apply correct manufacturer LUT
3. Use color management system (ACES, OCIO) to avoid manual LUT selection
4. Test with known chart (Macbeth ColorChecker)

Bit-Depth Banding

Cause: Insufficient bit depth for smooth gradients in log shadows

Detection Thresholds:

Banding Visibility by Bit Depth (Log Encoding):

8-bit Log:
  - Visible banding below 200 CV
  - Severe posterization in gradients
  - NOT recommended for professional work
  - Use case: Only for preview/proxy

10-bit Log:
  - Banding typically imperceptible at normal viewing
  - May see banding in extreme gradients if pushed heavily in grade
  - Minimum acceptable for production
  - Use case: Standard production, most deliverables

12-bit Log:
  - No visible banding at normal viewing
  - Banding only visible under extreme grade push
  - Recommended for high-end work
  - Use case: VFX plates, archival masters

16-bit Float:
  - No banding even under extreme manipulation
  - Ideal for mastering and complex grades
  - Use case: Archival, future-proofing, extensive VFX

Quantization Error Analysis:

$$\text{For 10-bit encoding across 15 stops:} \Delta X_{\text{stop}} = \frac{1024}{15} \approx 68 \text{ CV/stop (average)} \text{In shadows (-6 stops from 18% gray):} \Delta X_{\text{shadow}} \approx 16 \text{ CV between adjacent steps} \text{Just-Noticeable Difference (JND) in CIELAB:} \Delta E_{ab}^* \approx 1 \text{ (minimum perceptible difference)} \text{For banding to be visible:} \Delta E_{ab}^* > 1 \text{ between adjacent code values} \text{10-bit adequacy:} \Delta X_{\text{shadow}} \approx 16 \text{ CV} \gg 1 \text{ JND} \text{Thus, 10-bit is typically sufficient for log encoding}$$

Prevention and Mitigation:

Banding Prevention Strategies:

1. Use Sufficient Bit Depth:
   - Minimum 10-bit for production
   - 12-bit preferred for critical work
   - 16-bit float for archival

2. Apply Dithering:
   noise = \text{Uniform}(-0.5, +0.5) \times \text{dither\_strength}
   \text{output} = \text{round}(\text{signal} + \text{noise})

   Dither strength by region:
   - Shadows (0-300 CV): 0.5-1.0 CV
   - Midtones (300-700 CV): 0.3-0.5 CV
   - Highlights (700-1023 CV): 0.1-0.3 CV

3. Use Higher Internal Bit Depth:
   - Process in 32-bit float internally
   - Apply dither only at final output
   - Maintain precision throughout pipeline

4. Avoid Aggressive Shadow Pushes:
   - ETTR during capture (optimal exposure)
   - Minimal shadow lift in grade
   - Use denoising before large contrast adjustments

Quantization Artifacts

Symptom: Posterization in subtle gradients (skies, walls, shadows)

Mathematical Cause:

$$\text{Quantization error per level:} \text{For } b \text{-bit encoding:} N_{\text{levels}} = 2^b \Delta = \frac{1}{2^b - 1} \text{Quantization error distribution:} e \sim \text{Uniform}\left(-\frac{\Delta}{2}, +\frac{\Delta}{2}\right) \text{Standard deviation:} \sigma_e = \frac{\Delta}{\sqrt{12}} = \frac{1}{(2^b - 1)\sqrt{12}} \text{For 10-bit:} \sigma_{10} = \frac{1}{1023 \times \sqrt{12}} \approx 0.000284 \text{ (0.29 CV)} \text{For 12-bit:} \sigma_{12} = \frac{1}{4095 \times \sqrt{12}} \approx 0.000071 \text{ (0.07 CV)} \text{JND threshold:} \text{Visible if } \Delta E_{ab}^* > 1$$

Mitigation Strategies:

Quantization Artifact Prevention:

1. Shoot Higher Bit Depth:
   - 12-bit ProRes preferred over 10-bit
   - RAW (12-16-bit) for maximum quality
   - Acceptable quality vs. file size trade-off

2. Apply Noise/Dither During Grade:
   - Add controlled noise before final output
   - Randomizes quantization error
   - Masks banding in gradients

3. Optimize Exposure:
   - ETTR for maximum SNR
   - Better exposure = less visible quantization
   - Reduces need for noise masking

4. Use Proper Codecs:
   - Intra-frame compression (ProRes, DNxHD)
   - Avoid long-GOP codecs for critical footage
   - Higher bitrate = fewer compression artifacts

Mini Glossary: Log Encoding Terms

Log Encoding: A non-linear transfer function allocating more code values to shadows and fewer to highlights, following the logarithmic response of human vision (Weber-Fechner law).

Code Value (CV): Digital number representing pixel brightness, ranging 0-(2^bit_depth-1). For 10-bit: 0-1023, for 12-bit: 0-4095.

Middle Gray: 18% reflectance standard, used as exposure reference point. Maps to specific code values: LogC4 ~400/1023, S-Log3 ~410/1023, Log3G10 ~450/1023 (10-bit).

Dynamic Range: Ratio of maximum non-clipping signal to noise floor, expressed in stops (log2 ratio) or decibels (20×log10 ratio). Cinema cameras: 13-17 stops typical (2024).

Noise Floor: Minimum signal level where image information exists, typically SNR = 1 (0 dB) or SNR = 10 dB for usable signal.

Log Curve: Mathematical function mapping linear scene exposure to code values, typically piecewise with linear toe and logarithmic main segment.

Toe: Linear portion of log curve near black, controlling shadow rolloff and noise characteristics. LogC4 eliminates toe for pure log response.

Knee: Upper portion of some gamma curves where highlight rolloff begins, less common in pure log encodings.

EI (Exposure Index): Metadata parameter affecting middle gray placement without changing analog gain. Different from ISO (analog gain).

ISO Speed: Exposure index setting affecting analog gain before A/D conversion, changes SNR and DR characteristics.

Exposure Latitude: Range of acceptable exposures above/below optimal before quality becomes unacceptable, typically ±1-2 stops for log formats.

Signal-to-Noise Ratio (SNR): Ratio of signal power to noise power, expressed in decibels (20×log10). Higher is better: >50 dB excellent, <30 dB objectionable.

Normalized Linear: Scene-referred linear values where 1.0 = 18% gray reference, used for log encoding calculations.

Linear Segment: Portion of log curve (typically in shadows) where response is linear rather than logarithmic, prevents quantization artifacts.

Breakpoint: Code value or exposure level where linear toe transitions to logarithmic segment.

Gamma: Power-law relationship (Y = X^γ) used in display encodings, distinct from logarithmic encodings.

Scene-Referred: Image data representing actual scene luminance values, independent of display characteristics.

Display-Referred: Image data optimized for specific display (gamma, gamut, brightness), not suitable for further processing.

De-log: Process of converting log-encoded values back to linear scene-referred values.

Look: Creative color grading applied on top of technical color transformations.

Bake-In: Permanently applying color grading/transforms during encoding, making later changes difficult or impossible.

Metadata: Sidecar information describing encoding parameters (EI, white balance, curve type, timecode).

Waveform Monitor: Scope showing luminance distribution across frame, essential for log exposure monitoring and clipping detection.

False Color: Exposure tool mapping code values to colors for visual evaluation of exposure zones and image quality.

Zebras: Camera overlay showing areas above/below user-defined threshold, typically set to 95-100% to warn of clipping.

Clip Point: Maximum code value (1023 for 10-bit, 4095 for 12-bit) where signal saturates and information is permanently lost.

Headroom: Code value range available above middle gray before clipping, typically 6-8 stops for log formats.

Footroom: Code value range available below middle gray before hitting noise floor, typically 6-8 stops for log formats.

Just-Noticeable Difference (JND): Minimum perceptible change in brightness or color, approximately ΔE* = 1 in CIELAB space.

Weber-Fechner Law: Psychological law stating perceived stimulus is proportional to logarithm of physical stimulus, basis for log encoding.

ETTR (Expose to the Right): Exposure strategy maximizing signal without clipping highlights, minimizing overall noise by placing histogram as far right as possible.

SNR_optimal: Optimal signal-to-noise ratio achieved by maximizing exposure while protecting highlights, proportional to √Exposure due to shot noise characteristics.

Quantization: Process mapping continuous analog signal to discrete digital levels, introducing quantization error inversely proportional to 2^bit_depth.

Dithering: Addition of controlled random noise before quantization to prevent banding and posterization, especially critical when down-sampling bit depth.

Banding: Visible steps in smooth gradients caused by insufficient bit depth or excessive noise reduction, appears as contouring artifacts.

Posterization: Reduction of continuous color gradients into visible bands of solid color, similar to banding but in color dimension rather than luminance.

Mach Bands: Perceptual edge enhancement at boundaries between slightly different brightness levels, exacerbated by banding and quantization artifacts.

Transfer Function: Mathematical relationship (gamma, log, PQ, HLG) between scene luminance and code values.

OETF (Opto-Electronic Transfer Function): Camera-side transfer function encoding scene luminance to electrical signal (log, gamma).

EOTF (Electro-Optical Transfer Function): Display-side transfer function decoding electrical signal to display luminance.

OOTF (Opto-Optical Transfer Function): Overall system transfer from scene luminance to display luminance, combination of OETF and EOTF.

PQ (Perceptual Quantizer): HDR transfer function (SMPTE ST 2084) for absolute luminance encoding up to 10,000 nits.

HLG (Hybrid Log-Gamma): HDR transfer function (ARIB STD-B67) using relative luminance scaling, backward compatible with SDR.

ACES (Academy Color Encoding System): Standardized color management architecture for device-independent color interchange.

IDT (Input Device Transform): Technical LUT converting camera-specific imagery (Log/RAW) to standardized working space (ACES).

ODT (Output Device Transform): Technical LUT converting working color space to display-specific output (Rec.709, P3, HDR).

Scene Linear: Working color space where pixel values are directly proportional to scene luminance, essential for VFX and compositing.

Working Color Space: Intermediate color space for grading and compositing (ACEScg, Rec.709 linear, P3 linear).

Rec.709: ITU-R BT.709 HDTV standard with Rec.709 primaries and BT.1886 gamma 2.4.

DCI-P3: Digital Cinema Initiatives P3 color space wider than Rec.709, used for theatrical projection.

Rec.2020: ITU-R BT.2020 Ultra-HD color space with very wide gamut, used for HDR and UHDTV.

Bit Depth: Number of bits per sample determining number of possible code values (2^bit_depth levels).

Full Well Capacity: Maximum electrons each photosite can hold before saturation, determines maximum signal and dynamic range.

Read Noise: Electronic noise added during sensor readout, determines shadow noise floor.

Shot Noise: Fundamental noise from random photon arrival, proportional to √N where N is photon count, sets theoretical SNR limit.

Quantum Efficiency (QE): Sensor's ability to convert photons to electrons, modern sensors 60-80% (theoretical maximum 100%).

Black Level: Pedestal offset added to signal preventing absolute zero values, subtracted during processing.

White Clipping Level: Maximum code value before saturation, 4095 for 12-bit, 1023 for 10-bit.

Linearization: Process converting non-linear (log/gamma) encoded values to linear scene-referred values.

Non-Linear Encoding: Any transfer function where output is not directly proportional to input (log, gamma, PQ, HLG).

Perceptual Uniformity: Property where equal steps in code value produce equal perceptual differences, goal of log encoding.

LUT (Lookup Table): Pre-calculated mapping from input to output values, used for color space conversions and creative looks.

1D LUT: Single-channel lookup applied independently to R, G, B channels.

3D LUT: Three-dimensional lookup table mapping RGB input triplets to RGB output triplets.

Interpolation: Process of estimating values between discrete LUT entries (trilinear, tetrahedral).

Trilinear Interpolation: 3D LUT interpolation using linear interpolation along all three axes, faster but less accurate.

Tetrahedral Interpolation: 3D LUT interpolation dividing cube into tetrahedra, higher accuracy than trilinear.

Cube File: Common 3D LUT file format (.cube) with human-readable text listing RGB triplets.

Shaper LUT: 1D LUT applied before 3D LUT to optimize sample distribution for log encoding.

Tone Mapping: Dynamic range compression mapping scene-referred HDR to display-referred SDR/HDR output.

Gamut Mapping: Converting colors from source gamut to destination gamut while preserving perceptual attributes.

Gamut: 3D volume or 2D area of reproducible colors within specific color space.

Primary Chromaticities: CIE 1931 x,y coordinates defining red, green, blue primary locations.

White Point: Chromaticity coordinates of reference white (D65 for Rec.709, DCI for P3).

D65: Standard illuminant representing average daylight (6504K), white point for Rec.709, sRGB, Rec.2020.

DCI White: Digital Cinema Initiatives white point (x=0.314, y=0.351), slightly greener than D65.

Chromaticity: Color quality independent of luminance, defined by hue and saturation (CIE x,y or u',v').

LMS Color Space: Color space based on human cone responses (Long, Medium, Short wavelengths).

CAT (Chromatic Adaptation Transform): Mathematical model predicting color appearance under different illuminants.

CIECAM02: Color appearance model predicting perceived color attributes under different viewing conditions.

IPT Color Space: Perceptually uniform color space better correlating with human perception than CIELAB.

Jzazbz: Perceptually uniform color space optimized for HDR and WCG applications.

HDR (High Dynamic Range): Imagery with higher DR and/or color gamut than traditional SDR.

SDR (Standard Dynamic Range): Traditional imagery with ~6 stops DR, Rec.709 gamut, 100 nits peak brightness.

Nit (cd/m²): Unit of luminance (candela per square meter), used for display brightness specifications.

Stop: Logarithmic unit of exposure or DR, 1 stop = 2× or log2(2) ≈ 0.301 decades.

Latitude: Exposure range acceptable for creative intent, differs from technical DR.

Rating: Using camera at different EI than native ISO to adjust middle gray placement and highlight/shadow balance.

Native ISO: Manufacturer's recommended analog gain providing optimal noise, DR, highlight headroom balance.

Dual Native ISO: Feature with two analog gain circuits optimizing performance at different ISO ranges.

Pulling: Reducing exposure during RAW processing (equivalent to overexposing on set), improves shadow SNR.

Pushing: Increasing exposure during RAW processing (equivalent to underexposing on set), increases shadow noise.

Analog Gain: Amplification before A/D conversion, affects SNR and DR.

Digital Gain: Multiplication after A/D conversion, increases brightness but not SNR, essentially metadata.

Fixed Pattern Noise: Non-uniformity in sensor response, calibrated out via black subtraction.

Dark Current: Thermally generated signal during exposure, increases with temperature and time.

Binning: Combining adjacent photosites to increase sensitivity at cost of resolution.

Skipping: Reading subset of photosites for faster frame rates at cost of aliasing.

Windowing: Reading smaller portion of sensor for higher frame rates, crop factor applies.

Oversampling: Reading full sensor then downsampling, improves quality and reduces aliasing.

Compression: Reducing file size by removing redundant information, lossy (quality loss) or lossless (no quality loss).

Visually Lossless: Compression with artifacts below perception threshold under normal viewing.

Generation Loss: Quality degradation from multiple encode/decode cycles or transcodes.

Master: Highest quality version used for creating deliveries, typically camera originals or mezzanine.

Delivery: Final encoded version meeting platform specifications (codec, color space, loudness).

Transcode: Convert from one codec/format to another, typically introduces quality loss.

Quality Control (QC): Systematic review for technical compliance and creative standards.

Compliance: Meeting broadcaster/platform technical requirements.

LUT Application Order: Critical sequence of transforms (input → creative → output), wrong order causes errors.

Double Gamma: Applying gamma twice in pipeline, causes severe brightness and contrast errors.

Look Management: Systematic approach to creative looks across production (show LUTs, LMTs).

Show LUT: Standardized creative look maintaining consistency across episodes/DPs.

CDL (Color Decision List): Industry-standard elementary grade format (SOP: Slope, Offset, Power + Saturation).

ASC-CDL: American Society of Cinematographers standard for CDL interoperability.

OCIO (OpenColorIO): Open-source color management configuration system for VFX/animation pipelines.

LMT (Look Modification Transform): Optional ACES transform for creative looks within ACES pipeline.

RRT (Reference Rendering Transform): ACES transform standardizing scene-referred to output-referred.

Codec Quality: Visual quality differences between compression schemes and bitrates.

Mezzanine: Intermediate codec near-original quality (ProRes 4444, DNxHR 444).

Proxy: Low-resolution version for offline editing or remote review.