Branch data Line data Source code
1 : : /*
2 : : * This file is part of libplacebo.
3 : : *
4 : : * libplacebo is free software; you can redistribute it and/or
5 : : * modify it under the terms of the GNU Lesser General Public
6 : : * License as published by the Free Software Foundation; either
7 : : * version 2.1 of the License, or (at your option) any later version.
8 : : *
9 : : * libplacebo is distributed in the hope that it will be useful,
10 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 : : * GNU Lesser General Public License for more details.
13 : : *
14 : : * You should have received a copy of the GNU Lesser General Public
15 : : * License along with libplacebo. If not, see <http://www.gnu.org/licenses/>.
16 : : */
17 : :
18 : : #ifndef LIBPLACEBO_COLORSPACE_H_
19 : : #define LIBPLACEBO_COLORSPACE_H_
20 : :
21 : : #include <stdbool.h>
22 : : #include <stddef.h>
23 : : #include <stdint.h>
24 : :
25 : : #include <libplacebo/common.h>
26 : :
27 : : PL_API_BEGIN
28 : :
29 : : // The underlying color representation (e.g. RGB, XYZ or YCbCr)
30 : : enum pl_color_system {
31 : : PL_COLOR_SYSTEM_UNKNOWN = 0,
32 : : // YCbCr-like color systems:
33 : : PL_COLOR_SYSTEM_BT_601, // ITU-R Rec. BT.601 (SD)
34 : : PL_COLOR_SYSTEM_BT_709, // ITU-R Rec. BT.709 (HD)
35 : : PL_COLOR_SYSTEM_SMPTE_240M, // SMPTE-240M
36 : : PL_COLOR_SYSTEM_BT_2020_NC, // ITU-R Rec. BT.2020 (non-constant luminance)
37 : : PL_COLOR_SYSTEM_BT_2020_C, // ITU-R Rec. BT.2020 (constant luminance)
38 : : PL_COLOR_SYSTEM_BT_2100_PQ, // ITU-R Rec. BT.2100 ICtCp PQ variant
39 : : PL_COLOR_SYSTEM_BT_2100_HLG, // ITU-R Rec. BT.2100 ICtCp HLG variant
40 : : PL_COLOR_SYSTEM_DOLBYVISION, // Dolby Vision (see pl_dovi_metadata)
41 : : PL_COLOR_SYSTEM_YCGCO, // YCgCo (derived from RGB)
42 : : // Other color systems:
43 : : PL_COLOR_SYSTEM_RGB, // Red, Green and Blue
44 : : PL_COLOR_SYSTEM_XYZ, // Digital Cinema Distribution Master (XYZ)
45 : : PL_COLOR_SYSTEM_COUNT
46 : : };
47 : :
48 : : PL_API bool pl_color_system_is_ycbcr_like(enum pl_color_system sys);
49 : :
50 : : // Returns the human-readable, friendly name of the color system.
51 : : PL_API const char *pl_color_system_name(enum pl_color_system sys);
52 : : PL_API extern const char *const pl_color_system_names[PL_COLOR_SYSTEM_COUNT];
53 : :
54 : : // Returns true for color systems that are linear transformations of the RGB
55 : : // equivalent, i.e. are simple matrix multiplications. For color systems with
56 : : // this property, `pl_color_repr_decode` is sufficient for conversion to RGB.
57 : : PL_API bool pl_color_system_is_linear(enum pl_color_system sys);
58 : :
59 : : // Guesses the best YCbCr-like colorspace based on a image given resolution.
60 : : // This only picks conservative values. (In particular, BT.2020 is never
61 : : // auto-guessed, even for 4K resolution content)
62 : : PL_API enum pl_color_system pl_color_system_guess_ycbcr(int width, int height);
63 : :
64 : : // Friendly names for the canonical channel names and order.
65 : : enum pl_channel {
66 : : PL_CHANNEL_NONE = -1,
67 : : PL_CHANNEL_A = 3, // alpha
68 : : // RGB system
69 : : PL_CHANNEL_R = 0,
70 : : PL_CHANNEL_G = 1,
71 : : PL_CHANNEL_B = 2,
72 : : // YCbCr-like systems
73 : : PL_CHANNEL_Y = 0,
74 : : PL_CHANNEL_CB = 1,
75 : : PL_CHANNEL_CR = 2,
76 : : // Aliases for Cb/Cr
77 : : PL_CHANNEL_U = 1,
78 : : PL_CHANNEL_V = 2
79 : : // There are deliberately no names for the XYZ system to avoid
80 : : // confusion due to PL_CHANNEL_Y.
81 : : };
82 : :
83 : : // The numerical range of the representation (where applicable).
84 : : enum pl_color_levels {
85 : : PL_COLOR_LEVELS_UNKNOWN = 0,
86 : : PL_COLOR_LEVELS_LIMITED, // Limited/TV range, e.g. 16-235
87 : : PL_COLOR_LEVELS_FULL, // Full/PC range, e.g. 0-255
88 : : PL_COLOR_LEVELS_COUNT,
89 : :
90 : : // Compatibility aliases
91 : : PL_COLOR_LEVELS_TV = PL_COLOR_LEVELS_LIMITED,
92 : : PL_COLOR_LEVELS_PC = PL_COLOR_LEVELS_FULL,
93 : : };
94 : :
95 : : // The alpha representation mode.
96 : : enum pl_alpha_mode {
97 : : PL_ALPHA_UNKNOWN = 0,
98 : : PL_ALPHA_INDEPENDENT, // alpha channel is separate from the video
99 : : PL_ALPHA_PREMULTIPLIED, // alpha channel is multiplied into the colors
100 : : PL_ALPHA_NONE, // alpha channel explicitly ignored (or absent)
101 : : PL_ALPHA_MODE_COUNT,
102 : : };
103 : :
104 : : // The underlying bit-wise representation of a color sample. For example,
105 : : // a 10-bit TV-range YCbCr value uploaded to a 16 bit texture would have
106 : : // sample_depth=16 color_depth=10 bit_shift=0.
107 : : //
108 : : // For another example, a 12-bit XYZ full range sample shifted to 16-bits with
109 : : // the lower 4 bits all set to 0 would have sample_depth=16 color_depth=12
110 : : // bit_shift=4. (libavcodec likes outputting this type of `xyz12`)
111 : : //
112 : : // To explain the meaning of `sample_depth` further; the consideration factor
113 : : // here is the fact that GPU sampling will normalized the sampled color to the
114 : : // range 0.0 - 1.0 in a manner dependent on the number of bits in the texture
115 : : // format. So if you upload a 10-bit YCbCr value unpadded as 16-bit color
116 : : // samples, all of the sampled values will be extremely close to 0.0. In such a
117 : : // case, `pl_color_repr_normalize` would return a high scaling factor, which
118 : : // would pull the color up to their 16-bit range.
119 : : struct pl_bit_encoding {
120 : : int sample_depth; // the number of bits the color is stored/sampled as
121 : : int color_depth; // the effective number of bits of the color information
122 : : int bit_shift; // a representational bit shift applied to the color
123 : : };
124 : :
125 : : // Returns whether two bit encodings are exactly identical.
126 : : PL_API bool pl_bit_encoding_equal(const struct pl_bit_encoding *b1,
127 : : const struct pl_bit_encoding *b2);
128 : :
129 : : // Parsed metadata from the Dolby Vision RPU
130 : : struct pl_dovi_metadata {
131 : : // Colorspace transformation metadata
132 : : float nonlinear_offset[3]; // input offset ("ycc_to_rgb_offset")
133 : : pl_matrix3x3 nonlinear; // before PQ, also called "ycc_to_rgb"
134 : : pl_matrix3x3 linear; // after PQ, also called "rgb_to_lms"
135 : :
136 : : // Reshape data, grouped by component
137 : : struct pl_reshape_data {
138 : : uint8_t num_pivots;
139 : : float pivots[9]; // normalized to [0.0, 1.0] based on BL bit depth
140 : : uint8_t method[8]; // 0 = polynomial, 1 = MMR
141 : : // Note: these must be normalized (divide by coefficient_log2_denom)
142 : : float poly_coeffs[8][3]; // x^0, x^1, x^2, unused must be 0
143 : : uint8_t mmr_order[8]; // 1, 2 or 3
144 : : float mmr_constant[8];
145 : : float mmr_coeffs[8][3 /* order */][7];
146 : : } comp[3];
147 : : };
148 : :
149 : : // Struct describing the underlying color system and representation. This
150 : : // information is needed to convert an encoded color to a normalized RGB triple
151 : : // in the range 0-1.
152 : : struct pl_color_repr {
153 : : enum pl_color_system sys;
154 : : enum pl_color_levels levels;
155 : : enum pl_alpha_mode alpha;
156 : : struct pl_bit_encoding bits; // or {0} if unknown
157 : :
158 : : // Metadata for PL_COLOR_SYSTEM_DOLBYVISION. Note that, for the sake of
159 : : // efficiency, this is treated purely as an opaque reference - functions
160 : : // like pl_color_repr_equal will merely do a pointer equality test.
161 : : //
162 : : // The only functions that actually dereference it in any way are
163 : : // pl_color_repr_decode, pl_shader_decode_color and pl_render_image(_mix).
164 : : const struct pl_dovi_metadata *dovi;
165 : : };
166 : :
167 : : // Some common color representations. It's worth pointing out that all of these
168 : : // presets leave `alpha` and `bits` as unknown - that is, only the system and
169 : : // levels are predefined
170 : : PL_API extern const struct pl_color_repr pl_color_repr_unknown;
171 : : PL_API extern const struct pl_color_repr pl_color_repr_rgb;
172 : : PL_API extern const struct pl_color_repr pl_color_repr_sdtv;
173 : : PL_API extern const struct pl_color_repr pl_color_repr_hdtv; // also Blu-ray
174 : : PL_API extern const struct pl_color_repr pl_color_repr_uhdtv; // SDR, NCL system
175 : : PL_API extern const struct pl_color_repr pl_color_repr_jpeg;
176 : :
177 : : // Returns whether two colorspace representations are exactly identical.
178 : : PL_API bool pl_color_repr_equal(const struct pl_color_repr *c1,
179 : : const struct pl_color_repr *c2);
180 : :
181 : : // Replaces unknown values in the first struct by those of the second struct.
182 : : PL_API void pl_color_repr_merge(struct pl_color_repr *orig,
183 : : const struct pl_color_repr *update);
184 : :
185 : : // This function normalizes the color representation such that
186 : : // color_depth=sample_depth and bit_shift=0; and returns the scaling factor
187 : : // that must be multiplied into the color value to accomplish this, assuming
188 : : // it has already been sampled by the GPU. If unknown, the color and sample
189 : : // depth will both be inferred as 8 bits for the purposes of this conversion.
190 : : PL_API float pl_color_repr_normalize(struct pl_color_repr *repr);
191 : :
192 : : // Guesses the best color levels based on the specified color levels and
193 : : // falling back to using the color system instead. YCbCr-like systems are
194 : : // assumed to be TV range, otherwise this defaults to PC range.
195 : : PL_API enum pl_color_levels pl_color_levels_guess(const struct pl_color_repr *repr);
196 : :
197 : : // The colorspace's primaries (gamut)
198 : : enum pl_color_primaries {
199 : : PL_COLOR_PRIM_UNKNOWN = 0,
200 : : // Standard gamut:
201 : : PL_COLOR_PRIM_BT_601_525, // ITU-R Rec. BT.601 (525-line = NTSC, SMPTE-C)
202 : : PL_COLOR_PRIM_BT_601_625, // ITU-R Rec. BT.601 (625-line = PAL, SECAM)
203 : : PL_COLOR_PRIM_BT_709, // ITU-R Rec. BT.709 (HD), also sRGB
204 : : PL_COLOR_PRIM_BT_470M, // ITU-R Rec. BT.470 M
205 : : PL_COLOR_PRIM_EBU_3213, // EBU Tech. 3213-E / JEDEC P22 phosphors
206 : : // Wide gamut:
207 : : PL_COLOR_PRIM_BT_2020, // ITU-R Rec. BT.2020 (UltraHD)
208 : : PL_COLOR_PRIM_APPLE, // Apple RGB
209 : : PL_COLOR_PRIM_ADOBE, // Adobe RGB (1998)
210 : : PL_COLOR_PRIM_PRO_PHOTO, // ProPhoto RGB (ROMM)
211 : : PL_COLOR_PRIM_CIE_1931, // CIE 1931 RGB primaries
212 : : PL_COLOR_PRIM_DCI_P3, // DCI-P3 (Digital Cinema)
213 : : PL_COLOR_PRIM_DISPLAY_P3, // DCI-P3 (Digital Cinema) with D65 white point
214 : : PL_COLOR_PRIM_V_GAMUT, // Panasonic V-Gamut (VARICAM)
215 : : PL_COLOR_PRIM_S_GAMUT, // Sony S-Gamut
216 : : PL_COLOR_PRIM_FILM_C, // Traditional film primaries with Illuminant C
217 : : PL_COLOR_PRIM_ACES_AP0, // ACES Primaries #0 (ultra wide)
218 : : PL_COLOR_PRIM_ACES_AP1, // ACES Primaries #1
219 : : PL_COLOR_PRIM_COUNT
220 : : };
221 : :
222 : : PL_API bool pl_color_primaries_is_wide_gamut(enum pl_color_primaries prim);
223 : :
224 : : // Returns the human-readable, friendly name of the color primaries.
225 : : PL_API const char *pl_color_primaries_name(enum pl_color_primaries prim);
226 : : PL_API extern const char *const pl_color_primaries_names[PL_COLOR_PRIM_COUNT];
227 : :
228 : : // Guesses the best primaries based on a resolution. This always guesses
229 : : // conservatively, i.e. it will never return a wide gamut color space even if
230 : : // the resolution is 4K.
231 : : PL_API enum pl_color_primaries pl_color_primaries_guess(int width, int height);
232 : :
233 : : // The colorspace's transfer function (gamma / EOTF)
234 : : enum pl_color_transfer {
235 : : PL_COLOR_TRC_UNKNOWN = 0,
236 : : // Standard dynamic range:
237 : : PL_COLOR_TRC_BT_1886, // ITU-R Rec. BT.1886 (CRT emulation + OOTF)
238 : : PL_COLOR_TRC_SRGB, // IEC 61966-2-4 sRGB (CRT emulation)
239 : : PL_COLOR_TRC_LINEAR, // Linear light content
240 : : PL_COLOR_TRC_GAMMA18, // Pure power gamma 1.8
241 : : PL_COLOR_TRC_GAMMA20, // Pure power gamma 2.0
242 : : PL_COLOR_TRC_GAMMA22, // Pure power gamma 2.2
243 : : PL_COLOR_TRC_GAMMA24, // Pure power gamma 2.4
244 : : PL_COLOR_TRC_GAMMA26, // Pure power gamma 2.6
245 : : PL_COLOR_TRC_GAMMA28, // Pure power gamma 2.8
246 : : PL_COLOR_TRC_PRO_PHOTO, // ProPhoto RGB (ROMM)
247 : : PL_COLOR_TRC_ST428, // Digital Cinema Distribution Master (XYZ)
248 : : // High dynamic range:
249 : : PL_COLOR_TRC_PQ, // ITU-R BT.2100 PQ (perceptual quantizer), aka SMPTE ST2048
250 : : PL_COLOR_TRC_HLG, // ITU-R BT.2100 HLG (hybrid log-gamma), aka ARIB STD-B67
251 : : PL_COLOR_TRC_V_LOG, // Panasonic V-Log (VARICAM)
252 : : PL_COLOR_TRC_S_LOG1, // Sony S-Log1
253 : : PL_COLOR_TRC_S_LOG2, // Sony S-Log2
254 : : PL_COLOR_TRC_COUNT
255 : : };
256 : :
257 : : // Returns the human-readable, friendly name of the color transfer.
258 : : PL_API const char *pl_color_transfer_name(enum pl_color_transfer trc);
259 : : PL_API extern const char *const pl_color_transfer_names[PL_COLOR_TRC_COUNT];
260 : :
261 : : // Returns the nominal peak of a given transfer function, relative to the
262 : : // reference white. This refers to the highest encodable signal level.
263 : : // Always equal to 1.0 for SDR curves.
264 : : //
265 : : // Note: For HLG in particular, which is scene-referred, this returns the
266 : : // highest nominal peak in scene-referred space (3.77), which may be different
267 : : // from the actual peak in display space after application of the HLG OOTF.
268 : : PL_API float pl_color_transfer_nominal_peak(enum pl_color_transfer trc);
269 : :
270 : : static inline bool pl_color_transfer_is_hdr(enum pl_color_transfer trc)
271 : : {
272 [ + + ]: 52810 : return pl_color_transfer_nominal_peak(trc) > 1.0;
273 : : }
274 : :
275 : : // This defines the display-space standard reference white level (in cd/m^2)
276 : : // that is assumed for SDR content, for use when mapping between HDR and SDR in
277 : : // display space. See ITU-R Report BT.2408 for more information.
278 : : #define PL_COLOR_SDR_WHITE 203.0f
279 : :
280 : : // This defines the assumed contrast level of an unknown SDR display. This
281 : : // will be used to determine the black point in the absence of any tagged
282 : : // minimum luminance, relative to the tagged maximum luminance (or
283 : : // PL_COLOR_SDR_WHITE in the absence of all tagging)
284 : : #define PL_COLOR_SDR_CONTRAST 1000.0f
285 : :
286 : : // This defines the default black point assumed for "infinite contrast" HDR
287 : : // displays. This is not exactly 0.0 because a value of 0.0 is interpreted
288 : : // as "unknown / missing metadata" inside struct pl_hdr_metadata, and also
289 : : // to avoid numerical issues in a variety of tone mapping functions.
290 : : // Essentially, a black level below this number is functionally meaningless
291 : : // inside libplacebo, and will be clamped to this value regardless.
292 : : //
293 : : // The value used here (1e-6) is about one 13-bit PQ step above absolute zero,
294 : : // which is a small fraction of the human JND at this brightness level, and also
295 : : // about 3 bits above the floating point machine epsilon.
296 : : #define PL_COLOR_HDR_BLACK 1e-6f
297 : :
298 : : // This defines the assumed peak brightness of a HLG display with no HDR10
299 : : // metadata. This is set to the brightness of a "nominal" HLG reference display.
300 : : #define PL_COLOR_HLG_PEAK 1000.0f
301 : :
302 : : // Represents a single CIE xy coordinate (e.g. CIE Yxy with Y = 1.0)
303 : : struct pl_cie_xy {
304 : : float x, y;
305 : : };
306 : :
307 : : // Creates a pl_cie_xyz from raw XYZ values
308 : : static inline struct pl_cie_xy pl_cie_from_XYZ(float X, float Y, float Z)
309 : : {
310 : 11 : float k = 1.0f / (X + Y + Z);
311 : 11 : struct pl_cie_xy xy = { k * X, k * Y };
312 : : return xy;
313 : : }
314 : :
315 : : // Recovers (X / Y) from a CIE xy value.
316 : : static inline float pl_cie_X(struct pl_cie_xy xy)
317 : : {
318 [ - + - + : 5078 : return xy.x / xy.y;
- + ]
319 : : }
320 : :
321 : : // Recovers (Z / Y) from a CIE xy value.
322 : : static inline float pl_cie_Z(struct pl_cie_xy xy)
323 : : {
324 [ - + - + : 5078 : return (1 - xy.x - xy.y) / xy.y;
- + ]
325 : : }
326 : :
327 : : static inline bool pl_cie_xy_equal(const struct pl_cie_xy *a,
328 : : const struct pl_cie_xy *b)
329 : : {
330 [ + + + + : 2666 : return a->x == b->x && a->y == b->y;
+ + - + -
+ - + - +
- + ]
331 : : }
332 : :
333 : : // Computes the CIE xy chromaticity coordinates of a CIE D-series illuminant
334 : : // with the given correlated color temperature.
335 : : //
336 : : // `temperature` must be between 2500 K and 25000 K, inclusive.
337 : : PL_API struct pl_cie_xy pl_white_from_temp(float temperature);
338 : :
339 : : // Represents the raw physical primaries corresponding to a color space.
340 : : struct pl_raw_primaries {
341 : : struct pl_cie_xy red, green, blue, white;
342 : : };
343 : :
344 : : // Returns whether two raw primaries are exactly identical.
345 : : PL_API bool pl_raw_primaries_equal(const struct pl_raw_primaries *a,
346 : : const struct pl_raw_primaries *b);
347 : :
348 : : // Returns whether two raw primaries are approximately equal
349 : : PL_API bool pl_raw_primaries_similar(const struct pl_raw_primaries *a,
350 : : const struct pl_raw_primaries *b);
351 : :
352 : : // Replaces unknown values in the first struct by those of the second struct.
353 : : PL_API void pl_raw_primaries_merge(struct pl_raw_primaries *orig,
354 : : const struct pl_raw_primaries *update);
355 : :
356 : : // Returns the raw primaries for a given color space.
357 : : PL_API const struct pl_raw_primaries *pl_raw_primaries_get(enum pl_color_primaries prim);
358 : :
359 : : enum pl_hdr_scaling {
360 : : PL_HDR_NORM = 0, // 0.0 is absolute black, 1.0 is PL_COLOR_SDR_WHITE
361 : : PL_HDR_SQRT, // sqrt() of PL_HDR_NORM values
362 : : PL_HDR_NITS, // absolute brightness in raw cd/m²
363 : : PL_HDR_PQ, // absolute brightness in PQ (0.0 to 1.0)
364 : : PL_HDR_SCALING_COUNT,
365 : : };
366 : :
367 : : // Generic helper for performing HDR scale conversions.
368 : : PL_API float pl_hdr_rescale(enum pl_hdr_scaling from, enum pl_hdr_scaling to, float x);
369 : :
370 : : enum pl_hdr_metadata_type {
371 : : PL_HDR_METADATA_ANY = 0,
372 : : PL_HDR_METADATA_NONE,
373 : : PL_HDR_METADATA_HDR10, // HDR10 static mastering display metadata
374 : : PL_HDR_METADATA_HDR10PLUS, // HDR10+ dynamic metadata
375 : : PL_HDR_METADATA_CIE_Y, // CIE Y derived dynamic luminance metadata
376 : : PL_HDR_METADATA_TYPE_COUNT,
377 : : };
378 : :
379 : : // Bezier curve for HDR metadata
380 : : struct pl_hdr_bezier {
381 : : float target_luma; // target luminance (cd/m²) for this OOTF
382 : : float knee_x, knee_y; // cross-over knee point (0-1)
383 : : float anchors[15]; // intermediate bezier curve control points (0-1)
384 : : uint8_t num_anchors;
385 : : };
386 : :
387 : : // Represents raw HDR metadata as defined by SMPTE 2086 / CTA 861.3, which is
388 : : // often attached to HDR sources and can be forwarded to HDR-capable displays,
389 : : // or used to guide the libplacebo built-in tone mapping. Values left as 0
390 : : // are treated as unknown by libplacebo.
391 : : //
392 : : // Note: This means that a value of `min_luma == 0.0` gets treated as "minimum
393 : : // luminance not known", which in practice may end up inferring a default
394 : : // contrast of 1000:1 for SDR transfer functions. To avoid this, the user should
395 : : // set these fields to a low positive value, e.g. PL_COLOR_HDR_BLACK, to signal
396 : : // a "zero" black point (i.e. infinite contrast display).
397 : : struct pl_hdr_metadata {
398 : : // --- PL_HDR_METADATA_HDR10
399 : : // Mastering display metadata.
400 : : struct pl_raw_primaries prim; // mastering display primaries
401 : : float min_luma, max_luma; // min/max luminance (in cd/m²)
402 : :
403 : : // Content light level. (Note: this is ignored by libplacebo itself)
404 : : float max_cll; // max content light level (in cd/m²)
405 : : float max_fall; // max frame average light level (in cd/m²)
406 : :
407 : : // --- PL_HDR_METADATA_HDR10PLUS
408 : : float scene_max[3]; // maxSCL in cd/m² per component (RGB)
409 : : float scene_avg; // average of maxRGB in cd/m²
410 : : struct pl_hdr_bezier ootf; // reference OOTF (optional)
411 : :
412 : : // --- PL_HDR_METADATA_CIE_Y
413 : : float max_pq_y; // maximum PQ luminance (in PQ, 0-1)
414 : : float avg_pq_y; // averaged PQ luminance (in PQ, 0-1)
415 : : };
416 : :
417 : : PL_API extern const struct pl_hdr_metadata pl_hdr_metadata_empty; // equal to {0}
418 : : PL_API extern const struct pl_hdr_metadata pl_hdr_metadata_hdr10; // generic HDR10 display
419 : :
420 : : // Returns whether two sets of HDR metadata are exactly identical.
421 : : PL_API bool pl_hdr_metadata_equal(const struct pl_hdr_metadata *a,
422 : : const struct pl_hdr_metadata *b);
423 : :
424 : : // Replaces unknown values in the first struct by those of the second struct.
425 : : PL_API void pl_hdr_metadata_merge(struct pl_hdr_metadata *orig,
426 : : const struct pl_hdr_metadata *update);
427 : :
428 : : // Returns `true` if `data` contains a complete set of a given metadata type.
429 : : // Note: for PL_HDR_METADATA_HDR10, only `min_luma` and `max_luma` are
430 : : // considered - CLL/FALL and primaries are irrelevant for HDR tone-mapping.
431 : : PL_API bool pl_hdr_metadata_contains(const struct pl_hdr_metadata *data,
432 : : enum pl_hdr_metadata_type type);
433 : :
434 : : // Rendering intent for colorspace transformations. These constants match the
435 : : // ICC specification (Table 23)
436 : : enum pl_rendering_intent {
437 : : PL_INTENT_AUTO = -1, // not a valid ICC intent, but used to auto-infer
438 : : PL_INTENT_PERCEPTUAL = 0,
439 : : PL_INTENT_RELATIVE_COLORIMETRIC = 1,
440 : : PL_INTENT_SATURATION = 2,
441 : : PL_INTENT_ABSOLUTE_COLORIMETRIC = 3
442 : : };
443 : :
444 : : // Struct describing a physical color space. This information is needed to
445 : : // turn a normalized RGB triple into its physical meaning, as well as to convert
446 : : // between color spaces.
447 : : struct pl_color_space {
448 : : enum pl_color_primaries primaries;
449 : : enum pl_color_transfer transfer;
450 : :
451 : : // HDR metadata for this color space, if present. (Optional)
452 : : struct pl_hdr_metadata hdr;
453 : : };
454 : :
455 : : #define pl_color_space(...) (&(struct pl_color_space) { __VA_ARGS__ })
456 : :
457 : : // Returns whether or not a color space is considered as effectively HDR.
458 : : // This is true when the effective signal peak is greater than the SDR
459 : : // reference white (1.0), taking into account `csp->hdr`.
460 : : PL_API bool pl_color_space_is_hdr(const struct pl_color_space *csp);
461 : :
462 : : // Returns whether or not a color space is "black scaled", in which case 0.0 is
463 : : // the true black point. This is true for SDR signals other than BT.1886, as
464 : : // well as for HLG.
465 : : PL_API bool pl_color_space_is_black_scaled(const struct pl_color_space *csp);
466 : :
467 : : // Linearize/delinearize input color, given a specified color space. In essence,
468 : : // this corresponds to the ITU-R EOTF and its inverse (not the OETF).
469 : : // The linear color will be scaled so that 1.0 is the diffuse white. The
470 : : // non-linear color will be scaled so that 1.0 is the maximum representable
471 : : // value.
472 : : //
473 : : // Note: This is a no-op if csp->transfer == PL_COLOR_TRC_LINEAR.
474 : : PL_API void pl_color_linearize(const struct pl_color_space *csp, float color[3]);
475 : : PL_API void pl_color_delinearize(const struct pl_color_space *csp, float color[3]);
476 : :
477 : : struct pl_nominal_luma_params {
478 : : // The color space to infer luminance from
479 : : const struct pl_color_space *color;
480 : :
481 : : // Which type of metadata to draw values from
482 : : enum pl_hdr_metadata_type metadata;
483 : :
484 : : // This field controls the scaling of `out_*`
485 : : enum pl_hdr_scaling scaling;
486 : :
487 : : // Fields to write the detected nominal luminance to. (Optional)
488 : : //
489 : : // For SDR displays, this will default to a contrast level of 1000:1 unless
490 : : // indicated otherwise in the `min/max_luma` static HDR10 metadata fields.
491 : : float *out_min;
492 : : float *out_max;
493 : :
494 : : // Field to write the detected average luminance to, or 0.0 in the absence
495 : : // of dynamic metadata. (Optional)
496 : : float *out_avg;
497 : : };
498 : :
499 : : #define pl_nominal_luma_params(...) \
500 : : (&(struct pl_nominal_luma_params) { __VA_ARGS__ })
501 : :
502 : : // Returns the effective luminance described by a pl_color_space.
503 : : PL_API void pl_color_space_nominal_luma_ex(const struct pl_nominal_luma_params *params);
504 : :
505 : : // Replaces unknown values in the first struct by those of the second struct.
506 : : PL_API void pl_color_space_merge(struct pl_color_space *orig,
507 : : const struct pl_color_space *update);
508 : :
509 : : // Returns whether two colorspaces are exactly identical.
510 : : PL_API bool pl_color_space_equal(const struct pl_color_space *c1,
511 : : const struct pl_color_space *c2);
512 : :
513 : : // Go through a color-space and explicitly default all unknown fields to
514 : : // reasonable values. After this function is called, none of the values will be
515 : : // PL_COLOR_*_UNKNOWN or 0.0, except for the dynamic HDR metadata fields.
516 : : PL_API void pl_color_space_infer(struct pl_color_space *space);
517 : :
518 : : // Like `pl_color_space_infer`, but takes default values from the reference
519 : : // color space (excluding certain special cases like HDR or wide gamut).
520 : : PL_API void pl_color_space_infer_ref(struct pl_color_space *space,
521 : : const struct pl_color_space *ref);
522 : :
523 : : // Infer both the source and destination gamut simultaneously, and also adjust
524 : : // values for optimal display. This is mostly the same as
525 : : // `pl_color_space_infer(src)` followed by `pl_color_space_infer_ref`, but also
526 : : // takes into account the SDR contrast levels and PQ black points. This is
527 : : // basically the logic used by `pl_shader_color_map` and `pl_renderer` to
528 : : // decide the output color space in a conservative way and compute the final
529 : : // end-to-end color transformation that needs to be done.
530 : : PL_API void pl_color_space_infer_map(struct pl_color_space *src,
531 : : struct pl_color_space *dst);
532 : :
533 : : // Some common color spaces. Note: These don't necessarily have all fields
534 : : // filled, in particular `hdr` is left unset.
535 : : PL_API extern const struct pl_color_space pl_color_space_unknown;
536 : : PL_API extern const struct pl_color_space pl_color_space_srgb;
537 : : PL_API extern const struct pl_color_space pl_color_space_bt709;
538 : : PL_API extern const struct pl_color_space pl_color_space_hdr10;
539 : : PL_API extern const struct pl_color_space pl_color_space_bt2020_hlg;
540 : : PL_API extern const struct pl_color_space pl_color_space_monitor; // typical display
541 : :
542 : : // This represents metadata about extra operations to perform during colorspace
543 : : // conversion, which correspond to artistic adjustments of the color.
544 : : struct pl_color_adjustment {
545 : : // Brightness boost. 0.0 = neutral, 1.0 = solid white, -1.0 = solid black
546 : : float brightness;
547 : : // Contrast boost. 1.0 = neutral, 0.0 = solid black
548 : : float contrast;
549 : : // Saturation gain. 1.0 = neutral, 0.0 = grayscale
550 : : float saturation;
551 : : // Hue shift, corresponding to a rotation around the [U, V] subvector, in
552 : : // radians. 0.0 = neutral
553 : : float hue;
554 : : // Gamma adjustment. 1.0 = neutral, 0.0 = solid black
555 : : float gamma;
556 : : // Color temperature shift. 0.0 = 6500 K, -1.0 = 3000 K, 1.0 = 10000 K
557 : : float temperature;
558 : : };
559 : :
560 : : #define PL_COLOR_ADJUSTMENT_NEUTRAL \
561 : : .contrast = 1.0, \
562 : : .saturation = 1.0, \
563 : : .gamma = 1.0,
564 : :
565 : : #define pl_color_adjustment(...) (&(struct pl_color_adjustment) { PL_COLOR_ADJUSTMENT_NEUTRAL __VA_ARGS__ })
566 : : PL_API extern const struct pl_color_adjustment pl_color_adjustment_neutral;
567 : :
568 : : // Represents the chroma placement with respect to the luma samples. This is
569 : : // only relevant for YCbCr-like colorspaces with chroma subsampling.
570 : : enum pl_chroma_location {
571 : : PL_CHROMA_UNKNOWN = 0,
572 : : PL_CHROMA_LEFT, // MPEG2/4, H.264
573 : : PL_CHROMA_CENTER, // MPEG1, JPEG
574 : : PL_CHROMA_TOP_LEFT,
575 : : PL_CHROMA_TOP_CENTER,
576 : : PL_CHROMA_BOTTOM_LEFT,
577 : : PL_CHROMA_BOTTOM_CENTER,
578 : : PL_CHROMA_COUNT,
579 : : };
580 : :
581 : : // Fills *x and *y with the offset in luma pixels corresponding to a given
582 : : // chroma location.
583 : : //
584 : : // Note: PL_CHROMA_UNKNOWN defaults to PL_CHROMA_LEFT
585 : : PL_API void pl_chroma_location_offset(enum pl_chroma_location loc, float *x, float *y);
586 : :
587 : : // Returns an RGB->XYZ conversion matrix for a given set of primaries.
588 : : // Multiplying this into the RGB color transforms it to CIE XYZ, centered
589 : : // around the color space's white point.
590 : : PL_API pl_matrix3x3 pl_get_rgb2xyz_matrix(const struct pl_raw_primaries *prim);
591 : :
592 : : // Similar to pl_get_rgb2xyz_matrix, but gives the inverse transformation.
593 : : PL_API pl_matrix3x3 pl_get_xyz2rgb_matrix(const struct pl_raw_primaries *prim);
594 : :
595 : : // Returns a primary adaptation matrix, which converts from one set of
596 : : // primaries to another. This is an RGB->RGB transformation. For rendering
597 : : // intents other than PL_INTENT_ABSOLUTE_COLORIMETRIC, the white point is
598 : : // adapted using the Bradford matrix.
599 : : PL_API pl_matrix3x3 pl_get_color_mapping_matrix(const struct pl_raw_primaries *src,
600 : : const struct pl_raw_primaries *dst,
601 : : enum pl_rendering_intent intent);
602 : :
603 : : // Return a chromatic adaptation matrix, which converts from one white point to
604 : : // another, using the CAT16 matrix. This is an RGB->RGB transformation.
605 : : PL_API pl_matrix3x3 pl_get_adaptation_matrix(struct pl_cie_xy src, struct pl_cie_xy dst);
606 : :
607 : : // Returns true if 'b' is entirely contained in 'a'. Useful for figuring out if
608 : : // colorimetric clipping will occur or not.
609 : : PL_API bool pl_primaries_superset(const struct pl_raw_primaries *a,
610 : : const struct pl_raw_primaries *b);
611 : :
612 : : // Returns true if `prim` forms a nominally valid set of primaries. This does
613 : : // not check whether or not these primaries are actually physically realisable,
614 : : // merely that they satisfy the requirements for colorspace math (to avoid NaN).
615 : : PL_API bool pl_primaries_valid(const struct pl_raw_primaries *prim);
616 : :
617 : : // Returns true if two primaries are 'compatible', which is the case if
618 : : // they preserve the relationship between primaries (red=red, green=green,
619 : : // blue=blue). In other words, this is false for synthetic primaries that have
620 : : // channels misordered from the convention (e.g. for some test ICC profiles).
621 : : PL_API bool pl_primaries_compatible(const struct pl_raw_primaries *a,
622 : : const struct pl_raw_primaries *b);
623 : :
624 : : // Clip points in the first gamut (src) to be fully contained inside the second
625 : : // gamut (dst). Only works on compatible primaries (pl_primaries_compatible).
626 : : PL_API struct pl_raw_primaries
627 : : pl_primaries_clip(const struct pl_raw_primaries *src,
628 : : const struct pl_raw_primaries *dst);
629 : :
630 : : // Primary-dependent RGB->LMS matrix for the IPTPQc4 color system. This is
631 : : // derived from the HPE XYZ->LMS matrix with 4% crosstalk added.
632 : : PL_API pl_matrix3x3 pl_ipt_rgb2lms(const struct pl_raw_primaries *prim);
633 : : PL_API pl_matrix3x3 pl_ipt_lms2rgb(const struct pl_raw_primaries *prim);
634 : :
635 : : // Primary-independent L'M'S' -> IPT matrix for the IPTPQc4 color system, and
636 : : // its inverse. This is identical to the Ebner & Fairchild (1998) IPT matrix.
637 : : PL_API extern const pl_matrix3x3 pl_ipt_lms2ipt;
638 : : PL_API extern const pl_matrix3x3 pl_ipt_ipt2lms;
639 : :
640 : : // Cone types involved in human vision
641 : : enum pl_cone {
642 : : PL_CONE_L = 1 << 0,
643 : : PL_CONE_M = 1 << 1,
644 : : PL_CONE_S = 1 << 2,
645 : :
646 : : // Convenience aliases
647 : : PL_CONE_NONE = 0,
648 : : PL_CONE_LM = PL_CONE_L | PL_CONE_M,
649 : : PL_CONE_MS = PL_CONE_M | PL_CONE_S,
650 : : PL_CONE_LS = PL_CONE_L | PL_CONE_S,
651 : : PL_CONE_LMS = PL_CONE_L | PL_CONE_M | PL_CONE_S,
652 : : };
653 : :
654 : : // Structure describing parameters for simulating color blindness
655 : : struct pl_cone_params {
656 : : enum pl_cone cones; // Which cones are *affected* by the vision model
657 : : float strength; // Coefficient for how strong the defect is
658 : : // (1.0 = Unaffected, 0.0 = Full blindness)
659 : : };
660 : :
661 : : #define pl_cone_params(...) (&(struct pl_cone_params) { __VA_ARGS__ })
662 : :
663 : : // Built-in color blindness models
664 : : PL_API extern const struct pl_cone_params pl_vision_normal; // No distortion (92%)
665 : : PL_API extern const struct pl_cone_params pl_vision_protanomaly; // Red deficiency (0.66%)
666 : : PL_API extern const struct pl_cone_params pl_vision_protanopia; // Red absence (0.59%)
667 : : PL_API extern const struct pl_cone_params pl_vision_deuteranomaly; // Green deficiency (2.7%)
668 : : PL_API extern const struct pl_cone_params pl_vision_deuteranopia; // Green absence (0.56%)
669 : : PL_API extern const struct pl_cone_params pl_vision_tritanomaly; // Blue deficiency (0.01%)
670 : : PL_API extern const struct pl_cone_params pl_vision_tritanopia; // Blue absence (0.016%)
671 : : PL_API extern const struct pl_cone_params pl_vision_monochromacy; // Blue cones only (<0.001%)
672 : : PL_API extern const struct pl_cone_params pl_vision_achromatopsia; // Rods only (<0.0001%)
673 : :
674 : : // Returns a cone adaptation matrix. Applying this to an RGB color in the given
675 : : // color space will apply the given cone adaptation coefficients for simulating
676 : : // a type of color blindness.
677 : : //
678 : : // For the color blindness models which don't entail complete loss of a cone,
679 : : // you can partially counteract the effect by using a similar model with the
680 : : // `strength` set to its inverse. For example, to partially counteract
681 : : // deuteranomaly, you could generate a cone matrix for PL_CONE_M with the
682 : : // strength 2.0 (or some other number above 1.0).
683 : : PL_API pl_matrix3x3 pl_get_cone_matrix(const struct pl_cone_params *params,
684 : : const struct pl_raw_primaries *prim);
685 : :
686 : : // Returns a color decoding matrix for a given combination of source color
687 : : // representation and adjustment parameters. This mutates `repr` to reflect the
688 : : // change. If `params` is NULL, it defaults to &pl_color_adjustment_neutral.
689 : : //
690 : : // This function always performs a conversion to RGB. To convert to other
691 : : // colorspaces (e.g. between YUV systems), obtain a second YUV->RGB matrix
692 : : // and invert it using `pl_transform3x3_invert`.
693 : : //
694 : : // Note: For BT.2020 constant-luminance, this outputs chroma information in the
695 : : // range [-0.5, 0.5]. Since the CL system conversion is non-linear, further
696 : : // processing must be done by the caller. The channel order is CrYCb.
697 : : //
698 : : // Note: For BT.2100 ICtCp, this outputs in the color space L'M'S'. Further
699 : : // non-linear processing must be done by the caller.
700 : : //
701 : : // Note: XYZ system is expected to be in DCDM X'Y'Z' encoding (ST 428-1), in
702 : : // practice this means normalizing by (48.0 / 52.37) factor and applying 2.6 gamma
703 : : PL_API pl_transform3x3 pl_color_repr_decode(struct pl_color_repr *repr,
704 : : const struct pl_color_adjustment *params);
705 : :
706 : : // Common struct to describe an ICC profile
707 : : struct pl_icc_profile {
708 : : // Points to the in-memory representation of the ICC profile. This is
709 : : // allowed to be NULL, in which case the `pl_icc_profile` represents "no
710 : : // profile”.
711 : : const void *data;
712 : : size_t len;
713 : :
714 : : // If a profile is set, this signature must uniquely identify it (including
715 : : // across restarts, for caching), ideally using a checksum of the profile
716 : : // contents. The user is free to choose the method of determining this
717 : : // signature, but note the existence of the
718 : : // `pl_icc_profile_compute_signature` helper.
719 : : uint64_t signature;
720 : : };
721 : :
722 : : #define pl_icc_profile(...) &(struct pl_icc_profile) { __VA_ARGS__ }
723 : :
724 : : // This doesn't do a comparison of the actual contents, only of the signature.
725 : : PL_API bool pl_icc_profile_equal(const struct pl_icc_profile *p1,
726 : : const struct pl_icc_profile *p2);
727 : :
728 : : // Sets `signature` to a hash of `profile->data`, if non-NULL. Provided as a
729 : : // convenience function for the sake of users ingesting arbitrary ICC profiles
730 : : // from sources where they can't reliably detect profile changes.
731 : : //
732 : : // Note: This is based on a very fast hash, and will compute a signature for
733 : : // even large (10 MB) ICC profiles in, typically, a fraction of a millisecond.
734 : : PL_API void pl_icc_profile_compute_signature(struct pl_icc_profile *profile);
735 : :
736 : : PL_API_END
737 : :
738 : : #endif // LIBPLACEBO_COLORSPACE_H_
|