summaryrefslogtreecommitdiffstats
path: root/src/include/libplacebo/tone_mapping.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/include/libplacebo/tone_mapping.h')
-rw-r--r--src/include/libplacebo/tone_mapping.h268
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_