示例#1
0
    def test_nan_eotf_ST2084(self):
        """
        Tests :func:`colour.models.rgb.transfer_functions.st_2084.\
eotf_ST2084` definition nan support.
        """

        eotf_ST2084(np.array([-1.0, 0.0, 1.0, -np.inf, np.inf, np.nan]))
示例#2
0
    def test_n_dimensional_eotf_ST2084(self):
        """
        Tests :func:`colour.models.rgb.transfer_functions.st_2084.\
eotf_ST2084` definition n-dimensional arrays support.
        """

        N = 0.18
        C = 1.738580491084806
        np.testing.assert_almost_equal(
            eotf_ST2084(N),
            C,
            decimal=7)

        N = np.tile(N, 6)
        C = np.tile(C, 6)
        np.testing.assert_almost_equal(
            eotf_ST2084(N),
            C,
            decimal=7)

        N = np.reshape(N, (2, 3))
        C = np.reshape(C, (2, 3))
        np.testing.assert_almost_equal(
            eotf_ST2084(N),
            C,
            decimal=7)

        N = np.reshape(N, (2, 3, 1))
        C = np.reshape(C, (2, 3, 1))
        np.testing.assert_almost_equal(
            eotf_ST2084(N),
            C,
            decimal=7)
示例#3
0
    def test_eotf_ST2084(self):
        """
        Tests :func:`colour.models.rgb.transfer_functions.st_2084.\
eotf_ST2084` definition.
        """

        self.assertAlmostEqual(
            eotf_ST2084(0.0),
            0.0,
            places=7)

        self.assertAlmostEqual(
            eotf_ST2084(0.079420969944927),
            0.18,
            places=7)

        self.assertAlmostEqual(
            eotf_ST2084(0.149945732100180),
            1.0,
            places=7)

        self.assertAlmostEqual(
            eotf_ST2084(1.0, 5000),
            5000.0,
            places=7)
示例#4
0
    def test_n_dimensional_eotf_ST2084(self):
        """
        Tests :func:`colour.models.rgb.transfer_functions.st_2084.\
eotf_ST2084` definition n-dimensional arrays support.
        """

        N = 0.18
        C = 1.738580491084806
        np.testing.assert_almost_equal(
            eotf_ST2084(N),
            C,
            decimal=7)

        N = np.tile(N, 6)
        C = np.tile(C, 6)
        np.testing.assert_almost_equal(
            eotf_ST2084(N),
            C,
            decimal=7)

        N = np.reshape(N, (2, 3))
        C = np.reshape(C, (2, 3))
        np.testing.assert_almost_equal(
            eotf_ST2084(N),
            C,
            decimal=7)

        N = np.reshape(N, (2, 3, 1))
        C = np.reshape(C, (2, 3, 1))
        np.testing.assert_almost_equal(
            eotf_ST2084(N),
            C,
            decimal=7)
示例#5
0
    def test_eotf_ST2084(self):
        """
        Tests :func:`colour.models.rgb.transfer_functions.st_2084.\
eotf_ST2084` definition.
        """

        self.assertAlmostEqual(
            eotf_ST2084(0.0),
            0.0,
            places=7)

        self.assertAlmostEqual(
            eotf_ST2084(0.079420969944927),
            0.18,
            places=7)

        self.assertAlmostEqual(
            eotf_ST2084(0.149945732100180),
            1.0,
            places=7)

        self.assertAlmostEqual(
            eotf_ST2084(1.0, 5000),
            5000.0,
            places=7)
示例#6
0
    def test_nan_eotf_ST2084(self):
        """
        Tests :func:`colour.models.rgb.transfer_functions.st_2084.\
eotf_ST2084` definition nan support.
        """

        eotf_ST2084(
            np.array([-1.0, 0.0, 1.0, -np.inf, np.inf, np.nan]))
示例#7
0
    def test_eotf_ST2084(self):
        """
        Tests :func:`colour.models.rgb.transfer_functions.st_2084.\
eotf_ST2084` definition.
        """

        self.assertAlmostEqual(eotf_ST2084(0.0), 0.0, places=7)

        self.assertAlmostEqual(eotf_ST2084(0.508078421517399), 100, places=7)

        self.assertAlmostEqual(eotf_ST2084(0.652578597563067), 400, places=7)

        self.assertAlmostEqual(eotf_ST2084(1.0, 5000), 5000.0, places=7)
示例#8
0
    def test_domain_range_scale_eotf_ST2084(self):
        """
        Tests :func:`colour.models.rgb.transfer_functions.st_2084.\
eotf_ST2084` definition domain and range scale support.
        """

        N = 0.508078421517399
        C = eotf_ST2084(N)

        d_r = (('reference', 1), (1, 1), (100, 100))
        for scale, factor in d_r:
            with domain_range_scale(scale):
                np.testing.assert_almost_equal(
                    eotf_ST2084(N * factor), C * factor, decimal=7)
示例#9
0
def eotf_BT2100_PQ(E_p):
    """
    Defines *Recommendation ITU-R BT.2100* *Reference PQ* electro-optical
    transfer function (EOTF / EOCF).

    The EOTF maps the non-linear *PQ* signal into display light.

    Parameters
    ----------
    E_p : numeric or array_like
        :math:`E'` denotes a non-linear colour value :math:`{R', G', B'}` or
        :math:`{L', M', S'}` in *PQ* space [0, 1].

    Returns
    -------
    numeric or ndarray
        :math:`F_D` is the luminance of a displayed linear component
        :math:`{R_D, G_D, B_D}` or :math:`Y_D` or :math:`I_D`, in
        :math:`cd/m^2`.

    References
    ----------
    -   :cite:`Borer2017a`
    -   :cite:`InternationalTelecommunicationUnion2016a`

    Examples
    --------
    >>> eotf_BT2100_PQ(0.724769816665726)  # doctest: +ELLIPSIS
    779.9883608...
    """

    return eotf_ST2084(E_p, 10000)
示例#10
0
文件: ictcp.py 项目: crowsonkb/colour
def ICTCP_to_RGB(ICTCP, L_p=10000):
    """
    Converts from :math:`IC_TC_P` colour encoding to *Rec. 2020* colourspace.

    Parameters
    ----------
    ICTCP : array_like
        :math:`IC_TC_P` colour encoding array.
    L_p : numeric, optional
        Display peak luminance :math:`cd/m^2` for *SMPTE ST 2084:2014*
        non-linear encoding.

    Returns
    -------
    ndarray
        *Rec. 2020* colourspace array.

    Examples
    --------
    >>> ICTCP = np.array([0.09554079, -0.00890639, 0.01389286])
    >>> ICTCP_to_RGB(ICTCP)  # doctest: +ELLIPSIS
    array([ 0.3518145...,  0.2693475...,  0.2128802...])
    """

    LMS_p = dot_vector(ICTCP_ICTCP_TO_LMS_P_MATRIX, ICTCP)
    LMS = eotf_ST2084(LMS_p, L_p)
    RGB = dot_vector(ICTCP_LMS_TO_RGB_MATRIX, LMS)

    return RGB
示例#11
0
def oetf_reverse_BT2100_PQ(E_p):
    """
    Defines *Recommendation ITU-R BT.2100* *Reference PQ* reverse
    opto-electrical transfer function (OETF / OECF).

    Parameters
    ----------
    E_p : numeric or array_like
        :math:`E` is the resulting non-linear signal (:math:`R'`, :math:`G'`,
        :math:`B'`) in the range [0, 1].

    Returns
    -------
    numeric or ndarray
        :math:`E = {R_S, G_S, B_S; Y_S; or I_S}` is the signal determined by
        scene light and scaled by camera exposure. The values :math:`E`,
        :math:`R_S`, :math:`G_S`, :math:`B_S`, :math:`Y_S`, :math:`I_S` are in
        the range [0, 1].

    References
    ----------
    -   :cite:`Borer2017a`
    -   :cite:`InternationalTelecommunicationUnion2016a`

    Examples
    --------
    >>> oetf_reverse_BT2100_PQ(0.724769816665726)  # doctest: +ELLIPSIS
    0.0999999...
    """

    return ootf_reverse_BT2100_PQ(eotf_ST2084(E_p, 10000))
示例#12
0
文件: ictcp.py 项目: yixw/colour
def ICTCP_to_RGB(ICTCP, L_p=10000):
    """
    Converts from :math:`IC_TC_P` colour encoding to *ITU-R BT.2020*
    colourspace.

    Parameters
    ----------
    ICTCP : array_like
        :math:`IC_TC_P` colour encoding array.
    L_p : numeric, optional
        Display peak luminance :math:`cd/m^2` for *SMPTE ST 2084:2014*
        non-linear encoding.

    Returns
    -------
    ndarray
        *ITU-R BT.2020* colourspace array.

    Notes
    -----

    +------------+-----------------------+------------------+
    | **Domain** | **Scale - Reference** | **Scale - 1**    |
    +============+=======================+==================+
    | ``ICTCP``  | ``I``  : [0, 1]       | ``I``  : [0, 1]  |
    |            |                       |                  |
    |            | ``CT`` : [-1, 1]      | ``CT`` : [-1, 1] |
    |            |                       |                  |
    |            | ``CP`` : [-1, 1]      | ``CP`` : [-1, 1] |
    +------------+-----------------------+------------------+

    +------------+-----------------------+------------------+
    | **Range**  | **Scale - Reference** | **Scale - 1**    |
    +============+=======================+==================+
    | ``RGB``    | [0, 1]                | [0, 1]           |
    +------------+-----------------------+------------------+

    References
    ----------
    :cite:`Dolby2016a`, :cite:`Lu2016c`

    Examples
    --------
    >>> ICTCP = np.array([0.07351364, 0.00475253, 0.09351596])
    >>> ICTCP_to_RGB(ICTCP)  # doctest: +ELLIPSIS
    array([ 0.4562052...,  0.0308107...,  0.0409195...])
    """

    ICTCP = to_domain_1(ICTCP)

    LMS_p = dot_vector(ICTCP_ICTCP_TO_LMS_P_MATRIX, ICTCP)

    with domain_range_scale('ignore'):
        LMS = eotf_ST2084(LMS_p, L_p)

    RGB = dot_vector(ICTCP_LMS_TO_RGB_MATRIX, LMS)

    return from_range_1(RGB)
示例#13
0
def ICaCb_to_XYZ(ICaCb: ArrayLike) -> NDArray:
    """
    Convert from :math:`IC_AC_B` tristimulus values to *CIE XYZ* colourspace.

    Parameters
    ----------
    ICaCb
        :math:`IC_AC_B` tristimulus values.

    Returns
    -------
    :class:`numpy.ndarray`
        *CIE XYZ* colourspace array.

    Notes
    -----
    +------------+-----------------------+-----------------+
    | **Domain** | **Scale - Reference** | **Scale - 1**   |
    +============+=======================+=================+
    | ``ICaCb``  | ``I`` : [0, 1]        | ``I`` : [0, 1]  |
    |            |                       |                 |
    |            | ``Ca`` : [-1, 1]      | ``Ca``: [-1, 1] |
    |            |                       |                 |
    |            | ``Cb`` : [-1, 1]      | ``Cb``: [-1, 1] |
    +------------+-----------------------+-----------------+

    +------------+-----------------------+-----------------+
    | **Range**  | **Scale - Reference** | **Scale - 1**   |
    +============+=======================+=================+
    | ``XYZ``    | [0, 1]                | [0, 1]          |
    +------------+-----------------------+-----------------+

    References
    ----------
    :cite:`Frohlich2017`

    Examples
    --------
    >>> XYZ = np.array([0.06875297, 0.05753352, 0.02081548])
    >>> ICaCb_to_XYZ(XYZ)
    array([ 0.20654008,  0.12197225,  0.05136951])
    """

    ICaCb = to_domain_1(ICaCb)
    LMS_prime = vector_dot(MATRIX_ICACB_LMS_TO_XYZ_2, ICaCb)

    with domain_range_scale("ignore"):
        LMS = eotf_ST2084(LMS_prime)

    return from_range_1(vector_dot(MATRIX_ICACB_LMS_TO_XYZ, LMS))
示例#14
0
def eotf_BT2100_PQ(E_p):
    """
    Defines *Recommendation ITU-R BT.2100* *Reference PQ* electro-optical
    transfer function (EOTF / EOCF).

    The EOTF maps the non-linear *PQ* signal into display light.

    Parameters
    ----------
    E_p : numeric or array_like
        :math:`E'` denotes a non-linear colour value :math:`{R', G', B'}` or
        :math:`{L', M', S'}` in *PQ* space [0, 1].

    Returns
    -------
    numeric or ndarray
        :math:`F_D` is the luminance of a displayed linear component
        :math:`{R_D, G_D, B_D}` or :math:`Y_D` or :math:`I_D`, in
        :math:`cd/m^2`.

    Notes
    -----

    +------------+-----------------------+---------------+
    | **Domain** | **Scale - Reference** | **Scale - 1** |
    +============+=======================+===============+
    | ``E_p``    | [0, 1]                | [0, 1]        |
    +------------+-----------------------+---------------+

    +------------+-----------------------+---------------+
    | **Range**  | **Scale - Reference** | **Scale - 1** |
    +============+=======================+===============+
    | ``F_D``    | [0, 1]                | [0, 1]        |
    +------------+-----------------------+---------------+

    References
    ----------
    :cite:`Borer2017a`, :cite:`InternationalTelecommunicationUnion2016a`

    Examples
    --------
    >>> eotf_BT2100_PQ(0.724769816665726)  # doctest: +ELLIPSIS
    779.9883608...
    """

    return eotf_ST2084(E_p, 10000)
示例#15
0
def oetf_reverse_BT2100_PQ(E_p):
    """
    Defines *Recommendation ITU-R BT.2100* *Reference PQ* reverse
    opto-electrical transfer function (OETF / OECF).

    Parameters
    ----------
    E_p : numeric or array_like
        :math:`E'` is the resulting non-linear signal (:math:`R'`, :math:`G'`,
        :math:`B'`).

    Returns
    -------
    numeric or ndarray
        :math:`E = {R_S, G_S, B_S; Y_S; or I_S}` is the signal determined by
        scene light and scaled by camera exposure.

    Notes
    -----

    +------------+-----------------------+---------------+
    | **Domain** | **Scale - Reference** | **Scale - 1** |
    +============+=======================+===============+
    | ``E_p``    | [0, 1]                | [0, 1]        |
    +------------+-----------------------+---------------+

    +------------+-----------------------+---------------+
    | **Range**  | **Scale - Reference** | **Scale - 1** |
    +============+=======================+===============+
    | ``E``      | [0, 1]                | [0, 1]        |
    +------------+-----------------------+---------------+

    References
    ----------
    :cite:`Borer2017a`, :cite:`InternationalTelecommunicationUnion2016a`

    Examples
    --------
    >>> oetf_reverse_BT2100_PQ(0.724769816665726)  # doctest: +ELLIPSIS
    0.0999999...
    """

    return ootf_reverse_BT2100_PQ(eotf_ST2084(E_p, 10000))
示例#16
0
def Izazbz_to_XYZ(
    Izazbz: ArrayLike,
    constants: Optional[Structure] = None,
    method: Union[
        Literal["Safdar 2017", "Safdar 2021", "ZCAM"], str
    ] = "Safdar 2017",
) -> NDArray:
    """
    Convert from :math:`I_za_zb_z` colourspace to *CIE XYZ* tristimulus
    values.

    Parameters
    ----------
    Izazbz
        :math:`I_za_zb_z` colourspace array where :math:`I_z` is the
        achromatic response, :math:`a_z` is redness-greenness and
        :math:`b_z` is yellowness-blueness.
    constants
        :math:`J_za_zb_z` colourspace constants.
    method
        Computation methods, *Safdar 2021* and *ZCAM* methods are equivalent.

    Returns
    -------
    :class:`numpy.ndarray`
        *CIE XYZ* tristimulus values under
        *CIE Standard Illuminant D Series D65*.

    Warnings
    --------
    The underlying *SMPTE ST 2084:2014* transfer function is an absolute
    transfer function.

    Notes
    -----
    -   The underlying *SMPTE ST 2084:2014* transfer function is an absolute
        transfer function, thus the domain and range values for the *Reference*
        and *1* scales are only indicative that the data is not affected by
        scale transformations.

    +------------+-----------------------+------------------+
    | **Domain** | **Scale - Reference** | **Scale - 1**    |
    +============+=======================+==================+
    | ``Izazbz`` | ``Iz`` : [0, 1]       | ``Iz`` : [0, 1]  |
    |            |                       |                  |
    |            | ``az`` : [-1, 1]      | ``az`` : [-1, 1] |
    |            |                       |                  |
    |            | ``bz`` : [-1, 1]      | ``bz`` : [-1, 1] |
    +------------+-----------------------+------------------+

    +------------+-----------------------+------------------+
    | **Range**  | **Scale - Reference** | **Scale - 1**    |
    +============+=======================+==================+
    | ``XYZ``    | ``UN``                | ``UN``           |
    +------------+-----------------------+------------------+

    References
    ----------
    :cite:`Safdar2017`, :cite:`Safdar2021`

    Examples
    --------
    >>> Izazbz = np.array([0.01207793, 0.00924302, 0.00526007])
    >>> Izazbz_to_XYZ(Izazbz)  # doctest: +ELLIPSIS
    array([ 0.2065401...,  0.1219723...,  0.0513696...])
    """

    Izazbz = as_float_array(Izazbz)

    method = validate_method(method, IZAZBZ_METHODS)

    constants = optional(
        constants,
        CONSTANTS_JZAZBZ_SAFDAR2017
        if method == "safdar 2017"
        else CONSTANTS_JZAZBZ_SAFDAR2021,
    )

    if method == "safdar 2017":
        LMS_p = vector_dot(MATRIX_JZAZBZ_IZAZBZ_TO_LMS_P_SAFDAR2017, Izazbz)
    else:
        Izazbz[..., 0] += constants.d_0
        LMS_p = vector_dot(MATRIX_JZAZBZ_IZAZBZ_TO_LMS_P_SAFDAR2021, Izazbz)

    with domain_range_scale("ignore"):
        LMS = eotf_ST2084(LMS_p, 10000, constants)

    X_p_D65, Y_p_D65, Z_p_D65 = tsplit(
        vector_dot(MATRIX_JZAZBZ_LMS_TO_XYZ, LMS)
    )

    X_D65 = (X_p_D65 + (constants.b - 1) * Z_p_D65) / constants.b
    Y_D65 = (Y_p_D65 + (constants.g - 1) * X_D65) / constants.g

    XYZ_D65 = tstack([X_D65, Y_D65, Z_p_D65])

    return XYZ_D65
示例#17
0
def JzAzBz_to_XYZ(JzAzBz, constants=JZAZBZ_CONSTANTS):
    """
    Converts from :math:`J_zA_zB_z` colourspace to *CIE XYZ* tristimulus
    values.

    Parameters
    ----------
    JzAzBz : array_like
        :math:`J_zA_zB_z` colourspace array  where :math:`J_z` is Lightness,
        :math:`A_z` is redness-greenness and :math:`B_z` is
        yellowness-blueness.
    constants : Structure, optional
        :math:`J_zA_zB_z` colourspace constants.

    Returns
    -------
    ndarray
        *CIE XYZ* tristimulus values under
        *CIE Standard Illuminant D Series D65*.

    Notes
    -----

    +------------+-----------------------+------------------+
    | **Domain** | **Scale - Reference** | **Scale - 1**    |
    +============+=======================+==================+
    | ``JzAzBz`` | ``Jz`` : [0, 1]       | ``Jz`` : [0, 1]  |
    |            |                       |                  |
    |            | ``Az`` : [-1, 1]      | ``Az`` : [-1, 1] |
    |            |                       |                  |
    |            | ``Bz`` : [-1, 1]      | ``Bz`` : [-1, 1] |
    +------------+-----------------------+------------------+

    +------------+-----------------------+------------------+
    | **Range**  | **Scale - Reference** | **Scale - 1**    |
    +============+=======================+==================+
    | ``XYZ``    | [0, 1]                | [0, 1]           |
    +------------+-----------------------+------------------+

    References
    ----------
    :cite:`Safdar2017`

    Examples
    --------
    >>> JzAzBz = np.array([0.00535048, 0.00924302, 0.00526007])
    >>> JzAzBz_to_XYZ(JzAzBz)  # doctest: +ELLIPSIS
    array([ 0.2065402...,  0.1219723...,  0.0513696...])
    """

    J_z, A_z, B_z = tsplit(to_domain_1(JzAzBz))

    I_z = ((J_z + constants.d_0) / (1 + constants.d - constants.d *
                                    (J_z + constants.d_0)))
    LMS_p = dot_vector(JZAZBZ_IZAZBZ_TO_LMS_P_MATRIX, tstack([I_z, A_z, B_z]))

    with domain_range_scale('ignore'):
        LMS = eotf_ST2084(LMS_p, 10000, constants)

    X_p_D65, Y_p_D65, Z_p_D65 = tsplit(
        dot_vector(JZAZBZ_LMS_TO_XYZ_MATRIX, LMS))

    X_D65 = (X_p_D65 + (constants.b - 1) * Z_p_D65) / constants.b
    Y_D65 = (Y_p_D65 + (constants.g - 1) * X_D65) / constants.g

    XYZ_D65 = tstack([X_D65, Y_D65, Z_p_D65])

    return from_range_1(XYZ_D65)
示例#18
0
文件: ictcp.py 项目: wenh06/colour
def ICTCP_to_RGB(ICTCP, L_p=10000):
    """
    Converts from :math:`IC_TC_P` colour encoding to *ITU-R BT.2020*
    colourspace.

    Parameters
    ----------
    ICTCP : array_like
        :math:`IC_TC_P` colour encoding array.
    L_p : numeric, optional
        Display peak luminance :math:`cd/m^2` for *SMPTE ST 2084:2014*
        non-linear encoding. This parameter should stay at its default
        :math:`10000 cd/m^2` value for practical applications. It is exposed so
        that the definition can be used as a fitting function.

    Returns
    -------
    ndarray
        *ITU-R BT.2020* colourspace array.

    Warnings
    --------
    The underlying *SMPTE ST 2084:2014* transfer function is an absolute
    transfer function.

    Notes
    -----

    -   The underlying *SMPTE ST 2084:2014* transfer function is an absolute
        transfer function, thus the domain and range values for the *Reference*
        and *1* scales are only indicative that the data is not affected by
        scale transformations.

    +------------+-----------------------+------------------+
    | **Domain** | **Scale - Reference** | **Scale - 1**    |
    +============+=======================+==================+
    | ``ICTCP``  | ``I``  : [0, 1]       | ``I``  : [0, 1]  |
    |            |                       |                  |
    |            | ``CT`` : [-1, 1]      | ``CT`` : [-1, 1] |
    |            |                       |                  |
    |            | ``CP`` : [-1, 1]      | ``CP`` : [-1, 1] |
    +------------+-----------------------+------------------+

    +------------+-----------------------+------------------+
    | **Range**  | **Scale - Reference** | **Scale - 1**    |
    +============+=======================+==================+
    | ``RGB``    | ``UN``                | ``UN``           |
    +------------+-----------------------+------------------+

    References
    ----------
    :cite:`Dolby2016a`, :cite:`Lu2016c`

    Examples
    --------
    >>> ICTCP = np.array([0.07351364, 0.00475253, 0.09351596])
    >>> ICTCP_to_RGB(ICTCP)  # doctest: +ELLIPSIS
    array([ 0.4562052...,  0.0308107...,  0.0409195...])
    """

    ICTCP = to_domain_1(ICTCP)

    LMS_p = vector_dot(MATRIX_ICTCP_ICTCP_TO_LMS_P, ICTCP)

    with domain_range_scale('ignore'):
        LMS = eotf_ST2084(LMS_p, L_p)

    RGB = vector_dot(MATRIX_ICTCP_LMS_TO_RGB, LMS)

    return from_range_1(RGB)
示例#19
0
文件: jzazbz.py 项目: wenh06/colour
def JzAzBz_to_XYZ(JzAzBz, constants=CONSTANTS_JZAZBZ):
    """
    Converts from :math:`J_zA_zB_z` colourspace to *CIE XYZ* tristimulus
    values.

    Parameters
    ----------
    JzAzBz : array_like
        :math:`J_zA_zB_z` colourspace array  where :math:`J_z` is Lightness,
        :math:`A_z` is redness-greenness and :math:`B_z` is
        yellowness-blueness.
    constants : Structure, optional
        :math:`J_zA_zB_z` colourspace constants.

    Returns
    -------
    ndarray
        *CIE XYZ* tristimulus values under
        *CIE Standard Illuminant D Series D65*.

    Warnings
    --------
    The underlying *SMPTE ST 2084:2014* transfer function is an absolute
    transfer function.

    Notes
    -----

    -   The underlying *SMPTE ST 2084:2014* transfer function is an absolute
        transfer function, thus the domain and range values for the *Reference*
        and *1* scales are only indicative that the data is not affected by
        scale transformations.

    +------------+-----------------------+------------------+
    | **Domain** | **Scale - Reference** | **Scale - 1**    |
    +============+=======================+==================+
    | ``JzAzBz`` | ``Jz`` : [0, 1]       | ``Jz`` : [0, 1]  |
    |            |                       |                  |
    |            | ``Az`` : [-1, 1]      | ``Az`` : [-1, 1] |
    |            |                       |                  |
    |            | ``Bz`` : [-1, 1]      | ``Bz`` : [-1, 1] |
    +------------+-----------------------+------------------+

    +------------+-----------------------+------------------+
    | **Range**  | **Scale - Reference** | **Scale - 1**    |
    +============+=======================+==================+
    | ``XYZ``    | ``UN``                | ``UN``           |
    +------------+-----------------------+------------------+

    References
    ----------
    :cite:`Safdar2017`

    Examples
    --------
    >>> JzAzBz = np.array([0.00535048, 0.00924302, 0.00526007])
    >>> JzAzBz_to_XYZ(JzAzBz)  # doctest: +ELLIPSIS
    array([ 0.2065402...,  0.1219723...,  0.0513696...])
    """

    J_z, A_z, B_z = tsplit(to_domain_1(JzAzBz))

    I_z = ((J_z + constants.d_0) / (1 + constants.d - constants.d *
                                    (J_z + constants.d_0)))
    LMS_p = vector_dot(MATRIX_JZAZBZ_IZAZBZ_TO_LMS_P, tstack([I_z, A_z, B_z]))

    with domain_range_scale('ignore'):
        LMS = eotf_ST2084(LMS_p, 10000, constants)

    X_p_D65, Y_p_D65, Z_p_D65 = tsplit(
        vector_dot(MATRIX_JZAZBZ_LMS_TO_XYZ, LMS))

    X_D65 = (X_p_D65 + (constants.b - 1) * Z_p_D65) / constants.b
    Y_D65 = (Y_p_D65 + (constants.g - 1) * X_D65) / constants.g

    XYZ_D65 = tstack([X_D65, Y_D65, Z_p_D65])

    return from_range_1(XYZ_D65)
示例#20
0
def ICtCp_to_RGB(
    ICtCp: ArrayLike,
    method: Union[Literal["Dolby 2016", "ITU-R BT.2100-1 HLG",
                          "ITU-R BT.2100-1 PQ", "ITU-R BT.2100-2 HLG",
                          "ITU-R BT.2100-2 PQ", ], str, ] = "Dolby 2016",
    L_p: Floating = 10000,
) -> NDArray:
    """
    Convert from :math:`IC_TC_P` colour encoding to *ITU-R BT.2020*
    colourspace.

    Parameters
    ----------
    ICtCp
        :math:`IC_TC_P` colour encoding array.
    method
        Computation method. *Recommendation ITU-R BT.2100* defines multiple
        variants of the :math:`IC_TC_P` colour encoding:

        -   *ITU-R BT.2100-1*

            -   *SMPTE ST 2084:2014* inverse electro-optical transfer
                function (EOTF) and the :math:`IC_TC_P` matrix from
                :cite:`Dolby2016a`: *Dolby 2016*, *ITU-R BT.2100-1 PQ*,
                *ITU-R BT.2100-2 PQ* methods.
            -   *Recommendation ITU-R BT.2100* *Reference HLG* opto-electrical
                transfer function (OETF) and the :math:`IC_TC_P` matrix
                from :cite:`Dolby2016a`: *ITU-R BT.2100-1 HLG* method.

        -   *ITU-R BT.2100-2*

            -   *SMPTE ST 2084:2014* inverse electro-optical transfer
                function (EOTF) and the :math:`IC_TC_P` matrix from
                :cite:`Dolby2016a`: *Dolby 2016*, *ITU-R BT.2100-1 PQ*,
                *ITU-R BT.2100-2 PQ* methods.
            -   *Recommendation ITU-R BT.2100* *Reference HLG* opto-electrical
                transfer function (OETF) and a custom :math:`IC_TC_P`
                matrix from :cite:`InternationalTelecommunicationUnion2018`:
                *ITU-R BT.2100-2 HLG* method.

    L_p
        Display peak luminance :math:`cd/m^2` for *SMPTE ST 2084:2014*
        non-linear encoding. This parameter should stay at its default
        :math:`10000 cd/m^2` value for practical applications. It is exposed so
        that the definition can be used as a fitting function.

    Returns
    -------
    :class:`numpy.ndarray`
        *ITU-R BT.2020* colourspace array.

    Warnings
    --------
    The underlying *SMPTE ST 2084:2014* transfer function is an absolute
    transfer function.

    Notes
    -----
    -   The *ITU-R BT.2100-1 PQ* and *ITU-R BT.2100-2 PQ* methods are aliases
        for the *Dolby 2016* method.
    -   The underlying *SMPTE ST 2084:2014* transfer function is an absolute
        transfer function, thus the domain and range values for the *Reference*
        and *1* scales are only indicative that the data is not affected by
        scale transformations.

    +------------+-----------------------+------------------+
    | **Domain** | **Scale - Reference** | **Scale - 1**    |
    +============+=======================+==================+
    | ``ICtCp``  | ``I``  : [0, 1]       | ``I``  : [0, 1]  |
    |            |                       |                  |
    |            | ``CT`` : [-1, 1]      | ``CT`` : [-1, 1] |
    |            |                       |                  |
    |            | ``CP`` : [-1, 1]      | ``CP`` : [-1, 1] |
    +------------+-----------------------+------------------+

    +------------+-----------------------+------------------+
    | **Range**  | **Scale - Reference** | **Scale - 1**    |
    +============+=======================+==================+
    | ``RGB``    | ``UN``                | ``UN``           |
    +------------+-----------------------+------------------+

    References
    ----------
    :cite:`Dolby2016a`, :cite:`Lu2016c`

    Examples
    --------
    >>> ICtCp = np.array([0.07351364, 0.00475253, 0.09351596])
    >>> ICtCp_to_RGB(ICtCp)  # doctest: +ELLIPSIS
    array([ 0.4562052...,  0.0308107...,  0.0409195...])
    >>> ICtCp = np.array([0.62567899, -0.01984490, 0.35911259])
    >>> ICtCp_to_RGB(ICtCp, method='ITU-R BT.2100-2 HLG')  # doctest: +ELLIPSIS
    array([ 0.4562052...,  0.0308107...,  0.0409195...])
    """

    ICtCp = as_float_array(ICtCp)
    method = validate_method(
        method,
        [
            "Dolby 2016",
            "ITU-R BT.2100-1 HLG",
            "ITU-R BT.2100-1 PQ",
            "ITU-R BT.2100-2 HLG",
            "ITU-R BT.2100-2 PQ",
        ],
    )

    is_hlg_method = "hlg" in method
    is_BT2100_2_method = "2100-2" in method

    LMS_p = (vector_dot(MATRIX_ICTCP_ICTCP_TO_LMS_P_HLG_BT2100_2, ICtCp) if
             (is_hlg_method and is_BT2100_2_method) else vector_dot(
                 MATRIX_ICTCP_ICTCP_TO_LMS_P, ICtCp))

    with domain_range_scale("ignore"):
        LMS = (oetf_inverse_HLG_BT2100(LMS_p)
               if is_hlg_method else eotf_ST2084(LMS_p, L_p))

    RGB = vector_dot(MATRIX_ICTCP_LMS_TO_RGB, LMS)

    return RGB