Coverage for colour/models/rgb/transfer_functions/gamma.py: 100%
23 statements
« prev ^ index » next coverage.py v7.11.0, created at 2025-11-15 19:01 +1300
« prev ^ index » next coverage.py v7.11.0, created at 2025-11-15 19:01 +1300
1"""
2Gamma Colour Component Transfer Function
3========================================
5Define the gamma encoding / decoding colour component transfer function
6related objects.
8- :func:`colour.gamma_function`
9"""
11from __future__ import annotations
13import typing
15import numpy as np
17from colour.algebra import spow
19if typing.TYPE_CHECKING:
20 from colour.hints import ArrayLike, Literal, NDArrayFloat
22from colour.utilities import as_float, as_float_array, validate_method
24__author__ = "Colour Developers"
25__copyright__ = "Copyright 2013 Colour Developers"
26__license__ = "BSD-3-Clause - https://opensource.org/licenses/BSD-3-Clause"
27__maintainer__ = "Colour Developers"
28__email__ = "colour-developers@colour-science.org"
29__status__ = "Production"
31__all__ = [
32 "gamma_function",
33]
36def gamma_function(
37 a: ArrayLike,
38 exponent: ArrayLike = 1,
39 negative_number_handling: (
40 Literal["Clamp", "Indeterminate", "Mirror", "Preserve"] | str
41 ) = "Indeterminate",
42) -> NDArrayFloat:
43 """
44 Apply a gamma encoding or decoding transformation to the specified array.
46 Parameters
47 ----------
48 a
49 Array to encode or decode.
50 exponent
51 Encoding or decoding exponent.
52 negative_number_handling
53 Behaviour for ``a`` negative numbers and the definition return
54 value:
56 - *Indeterminate*: The behaviour will be indeterminate and the
57 definition return value might contain *nans*.
58 - *Mirror*: The definition return value will be mirrored around
59 the abscissa and ordinate axes, i.e., Blackmagic Design:
60 Davinci Resolve behaviour.
61 - *Preserve*: The definition will preserve any negative number
62 in ``a``, i.e., The Foundry Nuke behaviour.
63 - *Clamp*: The definition will clamp any negative number in
64 ``a`` to 0.
66 Returns
67 -------
68 :class:`numpy.ndarray`
69 Encoded or decoded array.
71 Examples
72 --------
73 >>> gamma_function(0.18, 2.2) # doctest: +ELLIPSIS
74 0.0229932...
75 >>> gamma_function(-0.18, 2.0) # doctest: +ELLIPSIS
76 0.0323999...
77 >>> gamma_function(-0.18, 2.2)
78 nan
79 >>> gamma_function(-0.18, 2.2, "Mirror") # doctest: +ELLIPSIS
80 -0.0229932...
81 >>> gamma_function(-0.18, 2.2, "Preserve") # doctest: +ELLIPSIS
82 -0.1...
83 >>> gamma_function(-0.18, 2.2, "Clamp") # doctest: +ELLIPSIS
84 0.0
85 """
87 a = as_float_array(a)
88 exponent = as_float_array(exponent)
89 negative_number_handling = validate_method(
90 negative_number_handling,
91 ("Indeterminate", "Mirror", "Preserve", "Clamp"),
92 '"{0}" negative number handling is invalid, it must be one of {1}!',
93 )
95 if negative_number_handling == "indeterminate":
96 return as_float(a**exponent)
98 if negative_number_handling == "mirror":
99 return spow(a, exponent)
101 if negative_number_handling == "preserve":
102 return as_float(np.where(a <= 0, a, a**exponent))
104 # negative_number_handling == 'clamp':
105 return as_float(np.where(a <= 0, 0, a**exponent))