diff options
Diffstat (limited to 'src/include/libplacebo/gamut_mapping.h')
-rw-r--r-- | src/include/libplacebo/gamut_mapping.h | 182 |
1 files changed, 182 insertions, 0 deletions
diff --git a/src/include/libplacebo/gamut_mapping.h b/src/include/libplacebo/gamut_mapping.h new file mode 100644 index 0000000..a92a73b --- /dev/null +++ b/src/include/libplacebo/gamut_mapping.h @@ -0,0 +1,182 @@ +/* + * This file is part of libplacebo. + * + * libplacebo is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * libplacebo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with libplacebo. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef LIBPLACEBO_GAMUT_MAPPING_H_ +#define LIBPLACEBO_GAMUT_MAPPING_H_ + +#include <libplacebo/common.h> +#include <libplacebo/colorspace.h> + +PL_API_BEGIN + +struct pl_gamut_map_params; +struct pl_gamut_map_function { + const char *name; // Identifier + const char *description; // Friendly / longer name + + // The gamut-mapping function itself. Iterates over all values in `lut`, + // and adapts them as needed. + void (*map)(float *lut, const struct pl_gamut_map_params *params); + + // Returns true if `map` supports both stretching and contracting the + // gamut. In this case, `map` is always executed, even if the output gamut + // is larger than the input gamut. + bool bidirectional; + + // Private data. Unused by libplacebo, but may be accessed by `map`. + void *priv; +}; + +struct pl_gamut_map_constants { + // (Relative) chromaticity protection zone for perceptual mapping [0,1] + float perceptual_deadzone; + + // Strength of the perceptual saturation mapping component [0,1] + float perceptual_strength; + + // I vs C curve gamma to use for colorimetric clipping [0,10] + float colorimetric_gamma; + + // Knee point to use for softclipping methods (perceptual, softclip) [0,1] + float softclip_knee; + + // Desaturation strength (for softclip only) [0,1] + float softclip_desat; +}; + +#define PL_GAMUT_MAP_CONSTANTS \ + .colorimetric_gamma = 1.80f, \ + .softclip_knee = 0.70f, \ + .softclip_desat = 0.35f, \ + .perceptual_deadzone = 0.30f, \ + .perceptual_strength = 0.80f, + +struct pl_gamut_map_params { + // If `function` is NULL, defaults to `pl_gamut_map_clip`. + const struct pl_gamut_map_function *function; + + // The desired input/output primaries. This affects the subjective color + // volume in which the desired mapping shall take place. + struct pl_raw_primaries input_gamut; + struct pl_raw_primaries output_gamut; + + // Minimum/maximum luminance (PQ) of the target display. Note that the same + // value applies to both the input and output, since it's assumed that tone + // mapping has already happened by this stage. This effectively defines the + // legal gamut boundary in RGB space. + // + // This also defines the I channel value range, for `pl_gamut_map_generate` + float min_luma; + float max_luma; + + // Common constants, should be initialized to PL_GAMUT_MAP_CONSTANTS if + // not intending to override them further. + struct pl_gamut_map_constants constants; + + // -- LUT generation options (for `pl_gamut_map_generate` only) + + // The size of the resulting LUT, per channel. + // + // Note: For quality, it's generally best to increase h > I > C + int lut_size_I; + int lut_size_C; + int lut_size_h; + + // The stride (in number of floats) between elements in the resulting LUT. + int lut_stride; + + // -- Removed parameters + float chroma_margin PL_DEPRECATED; // non-functional +}; + +#define pl_gamut_map_params(...) (&(struct pl_gamut_map_params) { \ + .constants = { PL_GAMUT_MAP_CONSTANTS }, \ + __VA_ARGS__ \ +}) + +// Note: Only does pointer equality testing on `function` +PL_API bool pl_gamut_map_params_equal(const struct pl_gamut_map_params *a, + const struct pl_gamut_map_params *b); + +// Returns true if the given gamut mapping configuration effectively represents +// a no-op configuration. Gamut mapping can be skipped in this case. +PL_API bool pl_gamut_map_params_noop(const struct pl_gamut_map_params *params); + +// Generate a gamut-mapping LUT for a given configuration. LUT samples are +// stored as IPTPQc4 values, but the LUT itself is indexed by IChPQc4,spanning +// the effective range [min_luma, max_luma] × [0, 0.5] × [-pi,pi]. +// +// This ordering is designed to keep frequently co-occurring values close in +// memory, while permitting simple wrapping of the 'h' component. +PL_API void pl_gamut_map_generate(float *out, const struct pl_gamut_map_params *params); + +// Samples a gamut mapping function for a single IPTPQc4 value. The input +// values are updated in-place. +PL_API void pl_gamut_map_sample(float x[3], const struct pl_gamut_map_params *params); + +// Performs no gamut-mapping, just hard clips out-of-range colors per-channel. +PL_API extern const struct pl_gamut_map_function pl_gamut_map_clip; + +// Performs a perceptually balanced (saturation) gamut mapping, using a soft +// knee function to preserve in-gamut colors, followed by a final softclip +// operation. This works bidirectionally, meaning it can both compress and +// expand the gamut. Behaves similar to a blend of `saturation` and `softclip`. +PL_API extern const struct pl_gamut_map_function pl_gamut_map_perceptual; + +// Performs a perceptually balanced gamut mapping using a soft knee function to +// roll-off clipped regions, and a hue shifting function to preserve saturation. +PL_API extern const struct pl_gamut_map_function pl_gamut_map_softclip; + +// Performs relative colorimetric clipping, while maintaining an exponential +// relationship between brightness and chromaticity. +PL_API extern const struct pl_gamut_map_function pl_gamut_map_relative; + +// Performs simple RGB->RGB saturation mapping. The input R/G/B channels are +// mapped directly onto the output R/G/B channels. Will never clip, but will +// distort all hues and/or result in a faded look. +PL_API extern const struct pl_gamut_map_function pl_gamut_map_saturation; + +// Performs absolute colorimetric clipping. Like pl_gamut_map_relative, but +// does not adapt the white point. +PL_API extern const struct pl_gamut_map_function pl_gamut_map_absolute; + +// Performs constant-luminance colorimetric clipping, desaturing colors +// towards white until they're in-range. +PL_API extern const struct pl_gamut_map_function pl_gamut_map_desaturate; + +// Uniformly darkens the input slightly to prevent clipping on blown-out +// highlights, then clamps colorimetrically to the input gamut boundary, +// biased slightly to preserve chromaticity over luminance. +PL_API extern const struct pl_gamut_map_function pl_gamut_map_darken; + +// Performs no gamut mapping, but simply highlights out-of-gamut pixels. +PL_API extern const struct pl_gamut_map_function pl_gamut_map_highlight; + +// Linearly/uniformly desaturates the image in order to bring the entire +// image into the target gamut. +PL_API extern const struct pl_gamut_map_function pl_gamut_map_linear; + +// A list of built-in gamut mapping functions, terminated by NULL +PL_API extern const struct pl_gamut_map_function * const pl_gamut_map_functions[]; +PL_API extern const int pl_num_gamut_map_functions; // excluding trailing NULL + +// Find the gamut mapping function with the given name, or NULL on failure. +PL_API const struct pl_gamut_map_function *pl_find_gamut_map_function(const char *name); + +PL_API_END + +#endif // LIBPLACEBO_GAMUT_MAPPING_H_ |