diff options
Diffstat (limited to 'src/include/libplacebo/tone_mapping.h')
-rw-r--r-- | src/include/libplacebo/tone_mapping.h | 268 |
1 files changed, 268 insertions, 0 deletions
diff --git a/src/include/libplacebo/tone_mapping.h b/src/include/libplacebo/tone_mapping.h new file mode 100644 index 0000000..48f1eb7 --- /dev/null +++ b/src/include/libplacebo/tone_mapping.h @@ -0,0 +1,268 @@ +/* + * 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_TONE_MAPPING_H_ +#define LIBPLACEBO_TONE_MAPPING_H_ + +#include <stddef.h> +#include <stdbool.h> + +#include <libplacebo/common.h> +#include <libplacebo/colorspace.h> + +PL_API_BEGIN + +struct pl_tone_map_params; +struct pl_tone_map_function { + const char *name; // Identifier + const char *description; // Friendly / longer name + + // This controls the type of values input/output to/from `map` + enum pl_hdr_scaling scaling; + + // The tone-mapping function itself. Iterates over all values in `lut`, and + // adapts them as needed. + // + // Note that the `params` struct fed into this function is guaranteed to + // satisfy `params->input_scaling == params->output_scaling == scaling`, + // and also obeys `params->input_max >= params->output_max`. + void (*map)(float *lut, const struct pl_tone_map_params *params); + + // Inverse tone mapping function. Optional. If absent, this tone mapping + // curve only works in the forwards direction. + // + // For this function, `params->input_max <= params->output_max`. + void (*map_inverse)(float *lut, const struct pl_tone_map_params *params); + + // Private data. Unused by libplacebo, but may be accessed by `map`. + void *priv; + + // --- Deprecated fields + const char *param_desc PL_DEPRECATED; + float param_min PL_DEPRECATED; + float param_def PL_DEPRECATED; + float param_max PL_DEPRECATED; +}; + +struct pl_tone_map_constants { + // Configures the knee point, as a ratio between the source average and + // target average (in PQ space). An adaptation of 1.0 always adapts the + // source scene average brightness to the (scaled) target average, + // while a value of 0.0 never modifies scene brightness. [0,1] + // + // Affects all methods that use the ST2094 knee point determination + // (currently ST2094-40, ST2094-10 and spline) + float knee_adaptation; + + // Configures the knee point minimum and maximum, respectively, as + // a percentage of the PQ luminance range. Provides a hard limit on the + // knee point chosen by `knee_adaptation`. + float knee_minimum; // (0, 0.5) + float knee_maximum; // (0.5, 1.0) + + // Default knee point to use in the absence of source scene average + // metadata. Normally, this is ignored in favor of picking the knee + // point as the (relative) source scene average brightness level. + float knee_default; // [knee_minimum, knee_maximum] + + // Knee point offset (for BT.2390 only). Note that a value of 0.5 is + // the spec-defined default behavior, which differs from the libplacebo + // default of 1.0. [0.5, 2] + float knee_offset; + + // For the single-pivot polynomial (spline) function, this controls the + // coefficients used to tune the slope of the curve. This tuning is designed + // to make the slope closer to 1.0 when the difference in peaks is low, + // and closer to linear when the difference between peaks is high. + float slope_tuning; // [0,10] + float slope_offset; // [0,1] + + // Contrast setting for the spline function. Higher values make the curve + // steeper (closer to `clip`), preserving midtones at the cost of losing + // shadow/highlight details, while lower values make the curve shallowed + // (closer to `linear`), preserving highlights at the cost of losing midtone + // contrast. Values above 1.0 are possible, resulting in an output with more + // contrast than the input. + float spline_contrast; // [0,1.5] + + // For the reinhard function, this specifies the local contrast coefficient + // at the display peak. Essentially, a value of 0.5 implies that the + // reference white will be about half as bright as when clipping. (0,1) + float reinhard_contrast; + + // For legacy functions (mobius, gamma) which operate on linear light, this + // directly sets the corresponding knee point. (0,1) + float linear_knee; + + // For linear methods (linear, linearlight), this controls the linear + // exposure/gain applied to the image. (0,10] + float exposure; +}; + +#define PL_TONE_MAP_CONSTANTS \ + .knee_adaptation = 0.4f, \ + .knee_minimum = 0.1f, \ + .knee_maximum = 0.8f, \ + .knee_default = 0.4f, \ + .knee_offset = 1.0f, \ + .slope_tuning = 1.5f, \ + .slope_offset = 0.2f, \ + .spline_contrast = 0.5f, \ + .reinhard_contrast = 0.5f, \ + .linear_knee = 0.3f, \ + .exposure = 1.0f, + +struct pl_tone_map_params { + // If `function` is NULL, defaults to `pl_tone_map_clip`. + const struct pl_tone_map_function *function; + + // Common constants, should be initialized to PL_TONE_MAP_CONSTANTS if + // not intending to override them further. + struct pl_tone_map_constants constants; + + // The desired input/output scaling of the tone map. If this differs from + // `function->scaling`, any required conversion will be performed. + // + // Note that to maximize LUT efficiency, it's *highly* recommended to use + // either PL_HDR_PQ or PL_HDR_SQRT as the input scaling, except when + // using `pl_tone_map_sample`. + enum pl_hdr_scaling input_scaling; + enum pl_hdr_scaling output_scaling; + + // The size of the resulting LUT. (For `pl_tone_map_generate` only) + size_t lut_size; + + // The characteristics of the input, in `input_scaling` units. + float input_min; + float input_max; + float input_avg; // or 0 if unknown + + // The desired characteristics of the output, in `output_scaling` units. + float output_min; + float output_max; + + // The input HDR metadata. Only used by a select few tone-mapping + // functions, currently only SMPTE ST2094. (Optional) + struct pl_hdr_metadata hdr; + + // --- Deprecated fields + float param PL_DEPRECATED; // see `constants` +}; + +#define pl_tone_map_params(...) (&(struct pl_tone_map_params) { __VA_ARGS__ }); + +// Note: Only does pointer equality testing on `function` +PL_API bool pl_tone_map_params_equal(const struct pl_tone_map_params *a, + const struct pl_tone_map_params *b); + +// Clamps/defaults the parameters, including input/output maximum. +PL_API void pl_tone_map_params_infer(struct pl_tone_map_params *params); + +// Returns true if the given tone mapping configuration effectively represents +// a no-op configuration. Tone mapping can be skipped in this case (although +// strictly speaking, the LUT would still clip illegal input values) +PL_API bool pl_tone_map_params_noop(const struct pl_tone_map_params *params); + +// Generate a tone-mapping LUT for a given configuration. This will always +// span the entire input range, as given by `input_min` and `input_max`. +PL_API void pl_tone_map_generate(float *out, const struct pl_tone_map_params *params); + +// Samples a tone mapping function at a single position. Note that this is less +// efficient than `pl_tone_map_generate` for generating multiple values. +// +// Ignores `params->lut_size`. +PL_API float pl_tone_map_sample(float x, const struct pl_tone_map_params *params); + +// Performs no tone-mapping, just clips out-of-range colors. Retains perfect +// color accuracy for in-range colors but completely destroys out-of-range +// information. Does not perform any black point adaptation. +PL_API extern const struct pl_tone_map_function pl_tone_map_clip; + +// EETF from SMPTE ST 2094-40 Annex B, which uses the provided OOTF based on +// Bezier curves to perform tone-mapping. The OOTF used is adjusted based on +// the ratio between the targeted and actual display peak luminances. In the +// absence of HDR10+ metadata, falls back to a simple constant bezier curve. +PL_API extern const struct pl_tone_map_function pl_tone_map_st2094_40; + +// EETF from SMPTE ST 2094-10 Annex B.2, which takes into account the input +// signal average luminance in addition to the maximum/minimum. +// +// Note: This does *not* currently include the subjective gain/offset/gamma +// controls defined in Annex B.3. (Open an issue with a valid sample file if +// you want such parameters to be respected.) +PL_API extern const struct pl_tone_map_function pl_tone_map_st2094_10; + +// EETF from the ITU-R Report BT.2390, a hermite spline roll-off with linear +// segment. +PL_API extern const struct pl_tone_map_function pl_tone_map_bt2390; + +// EETF from ITU-R Report BT.2446, method A. Can be used for both forward +// and inverse tone mapping. +PL_API extern const struct pl_tone_map_function pl_tone_map_bt2446a; + +// Simple spline consisting of two polynomials, joined by a single pivot point, +// which is tuned based on the source scene average brightness (taking into +// account dynamic metadata if available). This function can be used +// for both forward and inverse tone mapping. +PL_API extern const struct pl_tone_map_function pl_tone_map_spline; + +// Very simple non-linear curve. Named after Erik Reinhard. +PL_API extern const struct pl_tone_map_function pl_tone_map_reinhard; + +// Generalization of the reinhard tone mapping algorithm to support an +// additional linear slope near black. The name is derived from its function +// shape (ax+b)/(cx+d), which is known as a Möbius transformation. +PL_API extern const struct pl_tone_map_function pl_tone_map_mobius; + +// Piece-wise, filmic tone-mapping algorithm developed by John Hable for use in +// Uncharted 2, inspired by a similar tone-mapping algorithm used by Kodak. +// Popularized by its use in video games with HDR rendering. Preserves both +// dark and bright details very well, but comes with the drawback of changing +// the average brightness quite significantly. This is sort of similar to +// pl_tone_map_reinhard with `reinhard_contrast=0.24`. +PL_API extern const struct pl_tone_map_function pl_tone_map_hable; + +// Fits a gamma (power) function to transfer between the source and target +// color spaces, effectively resulting in a perceptual hard-knee joining two +// roughly linear sections. This preserves details at all scales, but can result +// in an image with a muted or dull appearance. +PL_API extern const struct pl_tone_map_function pl_tone_map_gamma; + +// Linearly stretches the input range to the output range, in PQ space. This +// will preserve all details accurately, but results in a significantly +// different average brightness. Can be used for inverse tone-mapping in +// addition to regular tone-mapping. +PL_API extern const struct pl_tone_map_function pl_tone_map_linear; + +// Like `pl_tone_map_linear`, but in linear light (instead of PQ). Works well +// for small range adjustments but may cause severe darkening when +// downconverting from e.g. 10k nits to SDR. +PL_API extern const struct pl_tone_map_function pl_tone_map_linear_light; + +// A list of built-in tone mapping functions, terminated by NULL +PL_API extern const struct pl_tone_map_function * const pl_tone_map_functions[]; +PL_API extern const int pl_num_tone_map_functions; // excluding trailing NULL + +// Find the tone mapping function with the given name, or NULL on failure. +PL_API const struct pl_tone_map_function *pl_find_tone_map_function(const char *name); + +// Deprecated alias, do not use +#define pl_tone_map_auto pl_tone_map_spline + +PL_API_END + +#endif // LIBPLACEBO_TONE_MAPPING_H_ |