Spaces:
Sleeping
Sleeping
| import numpy as np | |
| def apply_s_curve_tone_mapping( | |
| x: np.ndarray, | |
| shadow_boost: float = 0., | |
| highlight_boost: float = 0., | |
| contrast: float = 0., | |
| exposure: float = 0. | |
| ) -> np.ndarray: | |
| """ | |
| Apply an S-curve tone mapping to input x with given parameters. | |
| Parameters: | |
| x : array-like | |
| Input values in the range [0, 1]. | |
| shadow_boost : float | |
| Shadow boost parameter. Positive values increase the steepness in shadows. | |
| highlight_boost : float | |
| Highlight boost parameter. Positive values increase the steepness in highlights. | |
| contrast : float | |
| Contrast parameter. Positive values increase the steepness at midtones. | |
| exposure : float | |
| Exposure adjustment parameter. When exposure=0, 0.5 maps to 0.5. | |
| Exposure defines the mapping of 0.5 to 0.5 * (2 ** exposure). | |
| Returns: | |
| y : array-like | |
| Tone-mapped output values in the range [0, 1]. | |
| """ | |
| # Compute the midtone mapped value based on exposure | |
| midtone_mapped_value = 0.5 * (2 ** exposure) | |
| midtone_mapped_value = np.clip(midtone_mapped_value, 0, 1) | |
| # Define the slopes (derivatives) at the three key points | |
| s0 = 1 + shadow_boost # Slope at x = 0 (shadows) | |
| s1 = 1 + contrast # Slope at x = 0.5 (midtone) | |
| s2 = 1 + highlight_boost # Slope at x = 1 (highlights) | |
| # Initialize the output array | |
| y = np.zeros_like(x) | |
| # Segment 1: x in [0, 0.5] | |
| idx1 = x <= 0.5 | |
| x0, x1 = 0.0, 0.5 | |
| y0, y1 = 0.0, midtone_mapped_value | |
| m0, m1 = s0, s1 | |
| delta_x = x1 - x0 | |
| t = (x[idx1] - x0) / delta_x # Normalize x to parameter t in [0, 1] | |
| # Hermite basis functions | |
| h00 = 2 * t ** 3 - 3 * t ** 2 + 1 | |
| h10 = t ** 3 - 2 * t ** 2 + t | |
| h01 = -2 * t ** 3 + 3 * t ** 2 | |
| h11 = t ** 3 - t ** 2 | |
| # Calculate the spline for the first segment | |
| y[idx1] = (h00 * y0 + h10 * m0 * delta_x + h01 * y1 + h11 * m1 * delta_x) | |
| # Segment 2: x in (0.5, 1] | |
| idx2 = x > 0.5 | |
| x0, x1 = 0.5, 1.0 | |
| y0, y1 = midtone_mapped_value, 1.0 | |
| m0, m1 = s1, s2 | |
| delta_x = x1 - x0 | |
| t = (x[idx2] - x0) / delta_x # Normalize x to parameter t in [0, 1] | |
| # Hermite basis functions for the second segment | |
| h00 = 2 * t ** 3 - 3 * t ** 2 + 1 | |
| h10 = t ** 3 - 2 * t ** 2 + t | |
| h01 = -2 * t ** 3 + 3 * t ** 2 | |
| h11 = t ** 3 - t ** 2 | |
| # Calculate the spline for the second segment | |
| y[idx2] = (h00 * y0 + h10 * m0 * delta_x + h01 * y1 + h11 * m1 * delta_x) | |
| # Ensure the output is within [0, 1] | |
| y = np.clip(y, 0, 1) | |
| return y | |