def test_n_dimensional_oetf_ST2084(self): """ Tests :func:`colour.models.rgb.transfer_functions.st_2084.\ oetf_ST2084` definition n-dimensional arrays support. """ C = 0.18 N = 0.079420969944927 np.testing.assert_almost_equal( oetf_ST2084(C), N, decimal=7) C = np.tile(C, 6) N = np.tile(N, 6) np.testing.assert_almost_equal( oetf_ST2084(C), N, decimal=7) C = np.reshape(C, (2, 3)) N = np.reshape(N, (2, 3)) np.testing.assert_almost_equal( oetf_ST2084(C), N, decimal=7) C = np.reshape(C, (2, 3, 1)) N = np.reshape(N, (2, 3, 1)) np.testing.assert_almost_equal( oetf_ST2084(C), N, decimal=7)
def test_oetf_ST2084(self): """ Tests :func:`colour.models.rgb.transfer_functions.st_2084.\ oetf_ST2084` definition. """ self.assertAlmostEqual( oetf_ST2084(0.0), 0.000000730955903, places=7) self.assertAlmostEqual( oetf_ST2084(0.18), 0.079420969944927, places=7) self.assertAlmostEqual( oetf_ST2084(1), 0.149945732100180, places=7) self.assertAlmostEqual( oetf_ST2084(5000, 5000), 1.0, places=7)
def test_nan_oetf_ST2084(self): """ Tests :func:`colour.models.rgb.transfer_functions.st_2084.\ oetf_ST2084` definition nan support. """ oetf_ST2084( np.array([-1.0, 0.0, 1.0, -np.inf, np.inf, np.nan]))
def test_domain_range_scale_oetf_ST2084(self): """ Tests :func:`colour.models.rgb.transfer_functions.st_2084.\ oetf_ST2084` definition domain and range scale support. """ C = 100 N = oetf_ST2084(C) d_r = (('reference', 1), (1, 1), (100, 100)) for scale, factor in d_r: with domain_range_scale(scale): np.testing.assert_almost_equal(oetf_ST2084(C * factor), N * factor, decimal=7)
def RGB_to_ICTCP(RGB, L_p=10000): """ Converts from *Rec. 2020* colourspace to :math:`IC_TC_P` colour encoding. Parameters ---------- RGB : array_like *Rec. 2020* colourspace array. L_p : numeric, optional Display peak luminance :math:`cd/m^2` for *SMPTE ST 2084:2014* non-linear encoding. Returns ------- ndarray :math:`IC_TC_P` colour encoding array. Examples -------- >>> RGB = np.array([0.35181454, 0.26934757, 0.21288023]) >>> RGB_to_ICTCP(RGB) # doctest: +ELLIPSIS array([ 0.0955407..., -0.0089063..., 0.0138928...]) """ LMS = dot_vector(ICTCP_RGB_TO_LMS_MATRIX, RGB) LMS_p = oetf_ST2084(LMS, L_p) ICTCP = dot_vector(ICTCP_LMS_P_TO_ICTCP_MATRIX, LMS_p) return ICTCP
def oetf_BT2100_PQ(E): """ Defines *Recommendation ITU-R BT.2100* *Reference PQ* opto-electrical transfer function (OETF / OECF). The OETF maps relative scene linear light into the non-linear *PQ* signal value. Parameters ---------- E : numeric or array_like :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]. Returns ------- numeric or ndarray :math:`E` is the resulting non-linear signal (:math:`R'`, :math:`G'`, :math:`B'`) in the range [0, 1]. References ---------- - :cite:`Borer2017a` - :cite:`InternationalTelecommunicationUnion2016a` Examples -------- >>> oetf_BT2100_PQ(0.1) # doctest: +ELLIPSIS 0.7247698... """ return oetf_ST2084(ootf_BT2100_PQ(E), 10000)
def eotf_reverse_BT2100_PQ(F_D): """ Defines *Recommendation ITU-R BT.2100* *Reference PQ* reverse electro-optical transfer function (EOTF / EOCF). Parameters ---------- F_D : numeric or array_like :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`. Returns ------- numeric or ndarray :math:`E'` denotes a non-linear colour value :math:`{R', G', B'}` or :math:`{L', M', S'}` in *PQ* space [0, 1]. References ---------- - :cite:`Borer2017a` - :cite:`InternationalTelecommunicationUnion2016a` Examples -------- >>> eotf_reverse_BT2100_PQ(779.988360834085370) # doctest: +ELLIPSIS 0.7247698... """ return oetf_ST2084(F_D, 10000)
def RGB_to_ICTCP(RGB, L_p=10000): """ Converts from *ITU-R BT.2020* colourspace to :math:`IC_TC_P` colour encoding. Parameters ---------- RGB : array_like *ITU-R BT.2020* colourspace array. L_p : numeric, optional Display peak luminance :math:`cd/m^2` for *SMPTE ST 2084:2014* non-linear encoding. Returns ------- ndarray :math:`IC_TC_P` colour encoding array. Notes ----- +------------+-----------------------+------------------+ | **Domain** | **Scale - Reference** | **Scale - 1** | +============+=======================+==================+ | ``RGB`` | [0, 1] | [0, 1] | +------------+-----------------------+------------------+ +------------+-----------------------+------------------+ | **Range** | **Scale - Reference** | **Scale - 1** | +============+=======================+==================+ | ``ICTCP`` | ``I`` : [0, 1] | ``I`` : [0, 1] | | | | | | | ``CT`` : [-1, 1] | ``CT`` : [-1, 1] | | | | | | | ``CP`` : [-1, 1] | ``CP`` : [-1, 1] | +------------+-----------------------+------------------+ References ---------- :cite:`Dolby2016a`, :cite:`Lu2016c` Examples -------- >>> RGB = np.array([0.45620519, 0.03081071, 0.04091952]) >>> RGB_to_ICTCP(RGB) # doctest: +ELLIPSIS array([ 0.0735136..., 0.0047525..., 0.0935159...]) """ RGB = to_domain_1(RGB) LMS = dot_vector(ICTCP_RGB_TO_LMS_MATRIX, RGB) with domain_range_scale('ignore'): LMS_p = oetf_ST2084(LMS, L_p) ICTCP = dot_vector(ICTCP_LMS_P_TO_ICTCP_MATRIX, LMS_p) return from_range_1(ICTCP)
def test_n_dimensional_oetf_ST2084(self): """ Tests :func:`colour.models.rgb.transfer_functions.st_2084.\ oetf_ST2084` definition n-dimensional arrays support. """ C = 100 N = oetf_ST2084(C) C = np.tile(C, 6) N = np.tile(N, 6) np.testing.assert_almost_equal(oetf_ST2084(C), N, decimal=7) C = np.reshape(C, (2, 3)) N = np.reshape(N, (2, 3)) np.testing.assert_almost_equal(oetf_ST2084(C), N, decimal=7) C = np.reshape(C, (2, 3, 1)) N = np.reshape(N, (2, 3, 1)) np.testing.assert_almost_equal(oetf_ST2084(C), N, decimal=7)
def oetf_BT2100_PQ(E): """ Defines *Recommendation ITU-R BT.2100* *Reference PQ* opto-electrical transfer function (OETF / OECF). The OETF maps relative scene linear light into the non-linear *PQ* signal value. Parameters ---------- E : numeric or array_like :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. Returns ------- numeric or ndarray :math:`E'` is the resulting non-linear signal (:math:`R'`, :math:`G'`, :math:`B'`). Notes ----- +------------+-----------------------+---------------+ | **Domain** | **Scale - Reference** | **Scale - 1** | +============+=======================+===============+ | ``E`` | [0, 1] | [0, 1] | +------------+-----------------------+---------------+ +------------+-----------------------+---------------+ | **Range** | **Scale - Reference** | **Scale - 1** | +============+=======================+===============+ | ``E_p`` | [0, 1] | [0, 1] | +------------+-----------------------+---------------+ References ---------- :cite:`Borer2017a`, :cite:`InternationalTelecommunicationUnion2016a` Examples -------- >>> oetf_BT2100_PQ(0.1) # doctest: +ELLIPSIS 0.7247698... """ return oetf_ST2084(ootf_BT2100_PQ(E), 10000)
def eotf_reverse_BT2100_PQ(F_D): """ Defines *Recommendation ITU-R BT.2100* *Reference PQ* reverse electro-optical transfer function (EOTF / EOCF). Parameters ---------- F_D : numeric or array_like :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`. Returns ------- numeric or ndarray :math:`E'` denotes a non-linear colour value :math:`{R', G', B'}` or :math:`{L', M', S'}` in *PQ* space [0, 1]. Notes ----- +------------+-----------------------+---------------+ | **Domain** | **Scale - Reference** | **Scale - 1** | +============+=======================+===============+ | ``F_D`` | [0, 1] | [0, 1] | +------------+-----------------------+---------------+ +------------+-----------------------+---------------+ | **Range** | **Scale - Reference** | **Scale - 1** | +============+=======================+===============+ | ``E_p`` | [0, 1] | [0, 1] | +------------+-----------------------+---------------+ References ---------- :cite:`Borer2017a`, :cite:`InternationalTelecommunicationUnion2016a` Examples -------- >>> eotf_reverse_BT2100_PQ(779.988360834085370) # doctest: +ELLIPSIS 0.7247698... """ return oetf_ST2084(F_D, 10000)
def XYZ_to_JzAzBz(XYZ_D65, constants=JZAZBZ_CONSTANTS): """ Converts from *CIE XYZ* tristimulus values to :math:`J_zA_zB_z` colourspace. Parameters ---------- XYZ_D65 : array_like *CIE XYZ* tristimulus values under *CIE Standard Illuminant D Series D65*. constants : Structure, optional :math:`J_zA_zB_z` colourspace constants. Returns ------- ndarray :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. Notes ----- +------------+-----------------------+------------------+ | **Domain** | **Scale - Reference** | **Scale - 1** | +============+=======================+==================+ | ``XYZ`` | [0, 1] | [0, 1] | +------------+-----------------------+------------------+ +------------+-----------------------+------------------+ | **Range** | **Scale - Reference** | **Scale - 1** | +============+=======================+==================+ | ``JzAzBz`` | ``Jz`` : [0, 1] | ``Jz`` : [0, 1] | | | | | | | ``Az`` : [-1, 1] | ``Az`` : [-1, 1] | | | | | | | ``Bz`` : [-1, 1] | ``Bz`` : [-1, 1] | +------------+-----------------------+------------------+ References ---------- :cite:`Safdar2017` Examples -------- >>> XYZ = np.array([0.20654008, 0.12197225, 0.05136952]) >>> XYZ_to_JzAzBz(XYZ) # doctest: +ELLIPSIS array([ 0.0053504..., 0.0092430..., 0.0052600...]) """ X_D65, Y_D65, Z_D65 = tsplit(to_domain_1(XYZ_D65)) X_p_D65 = constants.b * X_D65 - (constants.b - 1) * Z_D65 Y_p_D65 = constants.g * Y_D65 - (constants.g - 1) * X_D65 XYZ_p_D65 = tstack([X_p_D65, Y_p_D65, Z_D65]) LMS = dot_vector(JZAZBZ_XYZ_TO_LMS_MATRIX, XYZ_p_D65) with domain_range_scale('ignore'): LMS_p = oetf_ST2084(LMS, 10000, constants) I_z, A_z, B_z = tsplit(dot_vector(JZAZBZ_LMS_P_TO_IZAZBZ_MATRIX, LMS_p)) J_z = ((1 + constants.d) * I_z) / (1 + constants.d * I_z) - constants.d_0 JzAzBz = tstack([J_z, A_z, B_z]) return from_range_1(JzAzBz)