Source code for colour.models.rgb.transfer_functions.nikon_n_log
"""
Nikon N-Log Log Encoding
========================
Define the *Nikon N-Log* log encoding:
- :func:`colour.models.log_encoding_NLog`
- :func:`colour.models.log_decoding_NLog`
References
----------
- :cite:`Nikon2018` : Nikon. (2018). N-Log Specification Document - Version
1.0.0 (pp. 1-5). Retrieved September 9, 2019, from
http://download.nikonimglib.com/archive3/hDCmK00m9JDI03RPruD74xpoU905/\
N-Log_Specification_(En)01.pdf
"""
from __future__ import annotations
import numpy as np
from colour.algebra import spow
from colour.hints import ArrayLike, NDArrayFloat
from colour.models.rgb.transfer_functions import full_to_legal, legal_to_full
from colour.utilities import Structure, as_float, from_range_1, to_domain_1
__author__ = "Colour Developers"
__copyright__ = "Copyright 2013 Colour Developers"
__license__ = "BSD-3-Clause - https://opensource.org/licenses/BSD-3-Clause"
__maintainer__ = "Colour Developers"
__email__ = "colour-developers@colour-science.org"
__status__ = "Production"
__all__ = [
"CONSTANTS_NLOG",
"log_encoding_NLog",
"log_decoding_NLog",
]
CONSTANTS_NLOG: Structure = Structure(
cut1=0.328,
cut2=(452 / 1023),
a=(650 / 1023),
b=0.0075,
c=(150 / 1023),
d=(619 / 1023),
)
"""*Nikon N-Log* constants."""
[docs]
def log_encoding_NLog(
y: ArrayLike,
bit_depth: int = 10,
out_normalised_code_value: bool = True,
in_reflection: bool = True,
constants: Structure = CONSTANTS_NLOG,
) -> NDArrayFloat:
"""
Define the *Nikon N-Log* log encoding curve / opto-electronic transfer
function.
Parameters
----------
y
Reflectance :math:`y`, "y = 0.18" is equivalent to Stop 0.
bit_depth
Bit-depth used for conversion.
out_normalised_code_value
Whether the non-linear *Nikon N-Log* data :math:`x` is encoded as
normalised code values.
in_reflection
Whether the light level :math`in` to a camera is reflection.
constants
*Nikon N-Log* constants.
Returns
-------
:class:`numpy.ndarray`
*N-Log* 10-bit equivalent code value :math:`x`.
Notes
-----
+------------+-----------------------+---------------+
| **Domain** | **Scale - Reference** | **Scale - 1** |
+============+=======================+===============+
| ``y`` | [0, 1] | [0, 1] |
+------------+-----------------------+---------------+
+------------+-----------------------+---------------+
| **Range** | **Scale - Reference** | **Scale - 1** |
+============+=======================+===============+
| ``x`` | [0, 1] | [0, 1] |
+------------+-----------------------+---------------+
References
----------
:cite:`Nikon2018`
Examples
--------
>>> log_encoding_NLog(0.18) # doctest: +ELLIPSIS
0.3636677...
"""
y = to_domain_1(y)
if not in_reflection:
y = y * 0.9
cut1 = constants.cut1
a = constants.a
b = constants.b
c = constants.c
d = constants.d
x = np.where(
y < cut1,
a * spow(y + b, 1 / 3),
c * np.log(y) + d,
)
x_cv = x if out_normalised_code_value else legal_to_full(x, bit_depth)
return as_float(from_range_1(x_cv))
[docs]
def log_decoding_NLog(
x: ArrayLike,
bit_depth: int = 10,
in_normalised_code_value: bool = True,
out_reflection: bool = True,
constants: Structure = CONSTANTS_NLOG,
) -> NDArrayFloat:
"""
Define the *Nikon N-Log* log decoding curve / electro-optical transfer
function.
Parameters
----------
x
*N-Log* 10-bit equivalent code value :math:`x`
bit_depth
Bit-depth used for conversion.
in_normalised_code_value
Whether the non-linear *Nikon N-Log* data :math:`x` is encoded as
normalised code values.
out_reflection
Whether the light level :math`in` to a camera is reflection.
constants
*Nikon N-Log* constants.
Returns
-------
:class:`numpy.ndarray`
Reflectance :math:`y`.
Notes
-----
+------------+-----------------------+---------------+
| **Domain** | **Scale - Reference** | **Scale - 1** |
+============+=======================+===============+
| ``x`` | [0, 1] | [0, 1] |
+------------+-----------------------+---------------+
+------------+-----------------------+---------------+
| **Range** | **Scale - Reference** | **Scale - 1** |
+============+=======================+===============+
| ``y`` | [0, 1] | [0, 1] |
+------------+-----------------------+---------------+
References
----------
:cite:`Nikon2018`
Examples
--------
>>> log_decoding_NLog(0.36366777011713869) # doctest: +ELLIPSIS
0.1799999...
"""
x = to_domain_1(x)
x = x if in_normalised_code_value else full_to_legal(x, bit_depth)
cut2 = constants.cut2
a = constants.a
b = constants.b
c = constants.c
d = constants.d
y = np.where(
x < cut2,
spow(x / a, 3) - b,
np.exp((x - d) / c),
)
if not out_reflection:
y = y / 0.9
return as_float(from_range_1(y))