Coverage for models/rgb/transfer_functions/nikon_n_log.py: 59%
41 statements
« prev ^ index » next coverage.py v7.11.0, created at 2025-11-16 22:49 +1300
« prev ^ index » next coverage.py v7.11.0, created at 2025-11-16 22:49 +1300
1"""
2Nikon N-Log Log Encoding
3========================
5Define the *Nikon N-Log* log encoding.
7- :func:`colour.models.log_encoding_NLog`
8- :func:`colour.models.log_decoding_NLog`
10References
11----------
12- :cite:`Nikon2018` : Nikon. (2018). N-Log Specification Document - Version
13 1.0.0 (pp. 1-5). Retrieved September 9, 2019, from
14 http://download.nikonimglib.com/archive3/hDCmK00m9JDI03RPruD74xpoU905/\
15N-Log_Specification_(En)01.pdf
16"""
18from __future__ import annotations
20import numpy as np
22from colour.algebra import spow
23from colour.hints import ( # noqa: TC001
24 Domain1,
25 Range1,
26)
27from colour.models.rgb.transfer_functions import full_to_legal, legal_to_full
28from colour.utilities import Structure, as_float, from_range_1, optional, to_domain_1
30__author__ = "Colour Developers"
31__copyright__ = "Copyright 2013 Colour Developers"
32__license__ = "BSD-3-Clause - https://opensource.org/licenses/BSD-3-Clause"
33__maintainer__ = "Colour Developers"
34__email__ = "colour-developers@colour-science.org"
35__status__ = "Production"
37__all__ = [
38 "CONSTANTS_NLOG",
39 "log_encoding_NLog",
40 "log_decoding_NLog",
41]
43CONSTANTS_NLOG: Structure = Structure(
44 cut1=0.328,
45 cut2=(452 / 1023),
46 a=(650 / 1023),
47 b=0.0075,
48 c=(150 / 1023),
49 d=(619 / 1023),
50)
51"""*Nikon N-Log* constants."""
54def log_encoding_NLog(
55 y: Domain1,
56 bit_depth: int = 10,
57 out_normalised_code_value: bool = True,
58 in_reflection: bool = True,
59 constants: Structure | None = None,
60) -> Range1:
61 """
62 Apply the *Nikon N-Log* log encoding opto-electronic transfer function (OETF).
64 Parameters
65 ----------
66 y
67 Linear light reflectance :math:`y`, where :math:`y = 0.18` represents
68 middle grey at Stop 0.
69 bit_depth
70 Bit-depth used for conversion.
71 out_normalised_code_value
72 Whether to return the *Nikon N-Log* encoded data :math:`x` as
73 normalised code values.
74 in_reflection
75 Whether the input light level represents reflected light.
76 constants
77 *Nikon N-Log* constants.
79 Returns
80 -------
81 :class:`numpy.ndarray`
82 *N-Log* 10-bit equivalent code value :math:`x`.
84 Notes
85 -----
86 +------------+-----------------------+---------------+
87 | **Domain** | **Scale - Reference** | **Scale - 1** |
88 +============+=======================+===============+
89 | ``y`` | 1 | 1 |
90 +------------+-----------------------+---------------+
92 +------------+-----------------------+---------------+
93 | **Range** | **Scale - Reference** | **Scale - 1** |
94 +============+=======================+===============+
95 | ``x`` | 1 | 1 |
96 +------------+-----------------------+---------------+
98 References
99 ----------
100 :cite:`Nikon2018`
102 Examples
103 --------
104 >>> log_encoding_NLog(0.18) # doctest: +ELLIPSIS
105 0.3636677...
106 """
108 y = to_domain_1(y)
109 constants = optional(constants, CONSTANTS_NLOG)
111 if not in_reflection:
112 y = y * 0.9
114 cut1 = constants.cut1
115 a = constants.a
116 b = constants.b
117 c = constants.c
118 d = constants.d
120 x = np.where(
121 y < cut1,
122 a * spow(y + b, 1 / 3),
123 c * np.log(y) + d,
124 )
126 x_cv = x if out_normalised_code_value else legal_to_full(x, bit_depth)
128 return as_float(from_range_1(x_cv))
131def log_decoding_NLog(
132 x: Domain1,
133 bit_depth: int = 10,
134 in_normalised_code_value: bool = True,
135 out_reflection: bool = True,
136 constants: Structure | None = None,
137) -> Range1:
138 """
139 Apply the *Nikon N-Log* log decoding inverse opto-electronic transfer
140 function (OETF).
142 Parameters
143 ----------
144 x
145 *N-Log* 10-bit equivalent code value :math:`x`.
146 bit_depth
147 Bit-depth used for conversion.
148 in_normalised_code_value
149 Whether the non-linear *Nikon N-Log* data :math:`x` is encoded as
150 normalised code values.
151 out_reflection
152 Whether the light level :math:`y` to a camera is reflection.
153 constants
154 *Nikon N-Log* constants.
156 Returns
157 -------
158 :class:`numpy.ndarray`
159 Linear light reflectance :math:`y`, where :math:`y = 0.18` represents
160 middle grey at Stop 0.
162 Notes
163 -----
164 +------------+-----------------------+---------------+
165 | **Domain** | **Scale - Reference** | **Scale - 1** |
166 +============+=======================+===============+
167 | ``x`` | 1 | 1 |
168 +------------+-----------------------+---------------+
170 +------------+-----------------------+---------------+
171 | **Range** | **Scale - Reference** | **Scale - 1** |
172 +============+=======================+===============+
173 | ``y`` | 1 | 1 |
174 +------------+-----------------------+---------------+
176 References
177 ----------
178 :cite:`Nikon2018`
180 Examples
181 --------
182 >>> log_decoding_NLog(0.36366777011713869) # doctest: +ELLIPSIS
183 0.1799999...
184 """
186 x = to_domain_1(x)
187 constants = optional(constants, CONSTANTS_NLOG)
189 x = x if in_normalised_code_value else full_to_legal(x, bit_depth)
191 cut2 = constants.cut2
192 a = constants.a
193 b = constants.b
194 c = constants.c
195 d = constants.d
197 y = np.where(
198 x < cut2,
199 spow(x / a, 3) - b,
200 np.exp((x - d) / c),
201 )
203 if not out_reflection:
204 y = y / 0.9
206 return as_float(from_range_1(y))