/*
* 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 .
*/
#ifndef LIBPLACEBO_TONE_MAPPING_H_
#define LIBPLACEBO_TONE_MAPPING_H_
#include
#include
#include
#include
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
PL_DEPRECATED_IN(v6.311) const char *param_desc;
PL_DEPRECATED_IN(v6.311) float param_min;
PL_DEPRECATED_IN(v6.311) float param_def;
PL_DEPRECATED_IN(v6.311) float param_max;
};
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
PL_DEPRECATED_IN(v6.311) float param; // 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_