Source code for colour.models.rgb.transfer_functions.oppo_o_log

"""
OPPO O-Log Profile Log Encoding
===============================

Define the *OPPO O-Log Profile* log encoding.

-   :func:`colour.models.log_encoding_OPPOOLog`
-   :func:`colour.models.log_decoding_OPPOOLog`

References
----------
-   :cite:`Lai2025` : Lai, Z., Qu, T., Yan, C., & Chow, Z. (2025). OPPO O-Log \
    - Whitepaper. Retrieved March 17, 2026, from https://www.oppo.com/content/\
dam/oppo_com/en/mkt/footer/OPPO_O-Log_Profile_WhitePaper_V1.pdf
"""

from __future__ import annotations

import numpy as np

from colour.hints import (  # noqa: TC001
    Domain1,
    Range1,
)
from colour.utilities import Structure, as_float, from_range_1, optional, 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_OPPO_O_LOG",
    "log_encoding_OPPOOLog",
    "log_decoding_OPPOOLog",
]

CONSTANTS_OPPO_O_LOG: Structure = Structure(
    gamma=0.139,
    beta=0.019,
    delta=0.614,
)
"""*OPPO O-Log Profile* constants."""


[docs] def log_encoding_OPPOOLog( R: Domain1, constants: Structure | None = None, ) -> Range1: """ Apply the *OPPO O-Log Profile* log encoding opto-electronic transfer function (OETF). Parameters ---------- R Linear reflection data :math:`R`. constants *OPPO O-Log Profile* constants. Returns ------- :class:`numpy.ndarray` Logarithmically encoded value :math:`P`. References ---------- :cite:`Lai2025` Notes ----- - The scene reflection signal :math:`R` captured by the camera is represented using a floating point encoding. The :math:`R` value of 0.18 corresponds to the signal produced by an 18% reflectance reference gray chart. +------------+-----------------------+---------------+ | **Domain** | **Scale - Reference** | **Scale - 1** | +============+=======================+===============+ | ``R`` | 1 | 1 | +------------+-----------------------+---------------+ +------------+-----------------------+---------------+ | **Range** | **Scale - Reference** | **Scale - 1** | +============+=======================+===============+ | ``P`` | 1 | 1 | +------------+-----------------------+---------------+ Examples -------- >>> log_encoding_OPPOOLog(0.18) # doctest: +ELLIPSIS np.float64(0.3895913...) """ R = to_domain_1(R) constants = optional(constants, CONSTANTS_OPPO_O_LOG) gamma = constants.gamma beta = constants.beta delta = constants.delta P = gamma * np.log(R + beta) + delta return as_float(from_range_1(P))
[docs] def log_decoding_OPPOOLog( P: Domain1, constants: Structure | None = None, ) -> Range1: """ Apply the *OPPO O-Log Profile* log decoding inverse opto-electronic transfer function (OETF). Parameters ---------- P Logarithmically encoded value :math:`P`. constants *OPPO O-Log Profile* constants. Returns ------- :class:`numpy.ndarray` Linear reflection data :math:`R`. References ---------- :cite:`Lai2025` Notes ----- - The captured pixel :math:`P` value uses floating point encoding normalized to the [0, 1] range. +------------+-----------------------+---------------+ | **Domain** | **Scale - Reference** | **Scale - 1** | +============+=======================+===============+ | ``P`` | 1 | 1 | +------------+-----------------------+---------------+ +------------+-----------------------+---------------+ | **Range** | **Scale - Reference** | **Scale - 1** | +============+=======================+===============+ | ``R`` | 1 | 1 | +------------+-----------------------+---------------+ Examples -------- >>> log_decoding_OPPOOLog(0.38959139) # doctest: +ELLIPSIS np.float64(0.1800000...) """ P = to_domain_1(P) constants = optional(constants, CONSTANTS_OPPO_O_LOG) gamma = constants.gamma beta = constants.beta delta = constants.delta R = np.exp((P - delta) / gamma) - beta return as_float(from_range_1(R))