def test_nan_eotf_inverse_BT2020(self): """ Tests :func:`colour.models.rgb.transfer_functions.itur_bt_2020.\ eotf_inverse_BT2020` definition nan support. """ eotf_inverse_BT2020( np.array([-1.0, 0.0, 1.0, -np.inf, np.inf, np.nan]))
def test_eotf_inverse_BT2020(self): """ Tests :func:`colour.models.rgb.transfer_functions.itur_bt_2020.\ eotf_inverse_BT2020` definition. """ self.assertAlmostEqual(eotf_inverse_BT2020(0.0), 0.0, places=7) self.assertAlmostEqual( eotf_inverse_BT2020(0.18), 0.409007728864150, places=7) self.assertAlmostEqual(eotf_inverse_BT2020(1.0), 1.0, places=7)
def test_domain_range_scale_eotf_inverse_BT2020(self): """ Tests :func:`colour.models.rgb.transfer_functions.itur_bt_2020.\ eotf_inverse_BT2020` definition domain and range scale support. """ E = 0.18 E_p = eotf_inverse_BT2020(E) 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_inverse_BT2020(E * factor), E_p * factor, decimal=7)
def test_n_dimensional_eotf_inverse_BT2020(self): """ Tests :func:`colour.models.rgb.transfer_functions.itur_bt_2020.\ eotf_inverse_BT2020` definition n-dimensional arrays support. """ E = 0.18 E_p = eotf_inverse_BT2020(E) E = np.tile(E, 6) E_p = np.tile(E_p, 6) np.testing.assert_almost_equal(eotf_inverse_BT2020(E), E_p, decimal=7) E = np.reshape(E, (2, 3)) E_p = np.reshape(E_p, (2, 3)) np.testing.assert_almost_equal(eotf_inverse_BT2020(E), E_p, decimal=7) E = np.reshape(E, (2, 3, 1)) E_p = np.reshape(E_p, (2, 3, 1)) np.testing.assert_almost_equal(eotf_inverse_BT2020(E), E_p, decimal=7)
def RGB_to_YcCbcCrc(RGB, out_bits=10, out_legal=True, out_int=False, is_12_bits_system=False, **kwargs): """ Converts an array of *RGB* linear values to the corresponding *Yc'Cbc'Crc'* colour encoding values array. Parameters ---------- RGB : array_like Input *RGB* array of linear float values. out_bits : int, optional Bit depth for integer output, or used in the calculation of the denominator for legal range float values, i.e. 8-bit means the float value for legal white is *235 / 255*. Ignored if ``out_legal`` and ``out_int`` are both *False*. Default is *10*. out_legal : bool, optional Whether to return legal range values. Default is *True*. out_int : bool, optional Whether to return values as ``out_bits`` integer code values. Default is *False*. is_12_bits_system : bool, optional *Recommendation ITU-R BT.2020* OETF (OECF) adopts different parameters for 10 and 12 bit systems. Default is *False*. Other Parameters ---------------- out_range : array_like, optional Array overriding the computed range such as *out_range = (Y_min, Y_max, C_min, C_max)*. If ``out_range`` is undefined, *Y_min*, *Y_max*, *C_min* and *C_max* will be computed using :func:`colour.models.rgb.ycbcr.YCbCr_ranges` definition. Returns ------- ndarray *Yc'Cbc'Crc'* colour encoding array of integer or float values. Notes ----- +----------------+-----------------------+---------------+ | **Domain \\*** | **Scale - Reference** | **Scale - 1** | +================+=======================+===============+ | ``RGB`` | [0, 1] | [0, 1] | +----------------+-----------------------+---------------+ +----------------+-----------------------+---------------+ | **Range \\*** | **Scale - Reference** | **Scale - 1** | +================+=======================+===============+ | ``YcCbcCrc`` | [0, 1] | [0, 1] | +----------------+-----------------------+---------------+ \\* This definition has input and output integer switches, thus the domain-range scale information is only given for the floating point mode. Warnings -------- This definition is specifically for usage with *Recommendation ITU-R BT.2020* when adopting the constant luminance implementation. References ---------- :cite:`InternationalTelecommunicationUnion2015h`, :cite:`Wikipedia2004d` Examples -------- >>> RGB = np.array([0.18, 0.18, 0.18]) >>> RGB_to_YcCbcCrc(RGB, out_legal=True, out_bits=10, out_int=True, ... is_12_bits_system=False) ... # doctest: +ELLIPSIS array([422, 512, 512]...) """ R, G, B = tsplit(to_domain_1(RGB)) Y_min, Y_max, C_min, C_max = kwargs.get( 'out_range', YCbCr_ranges(out_bits, out_legal, out_int)) Yc = 0.2627 * R + 0.6780 * G + 0.0593 * B with domain_range_scale('ignore'): Yc = eotf_inverse_BT2020(Yc, is_12_bits_system=is_12_bits_system) R = eotf_inverse_BT2020(R, is_12_bits_system=is_12_bits_system) B = eotf_inverse_BT2020(B, is_12_bits_system=is_12_bits_system) Cbc = np.where((B - Yc) <= 0, (B - Yc) / 1.9404, (B - Yc) / 1.5816) Crc = np.where((R - Yc) <= 0, (R - Yc) / 1.7184, (R - Yc) / 0.9936) Yc *= Y_max - Y_min Yc += Y_min Cbc *= C_max - C_min Crc *= C_max - C_min Cbc += (C_max + C_min) / 2 Crc += (C_max + C_min) / 2 YcCbcCrc = tstack([Yc, Cbc, Crc]) YcCbcCrc = (np.round(YcCbcCrc).astype(DEFAULT_INT_DTYPE) if out_int else from_range_1(YcCbcCrc)) return YcCbcCrc