def test_n_dimensional_chromatic_adaptation_matrix_VonKries(self): """ Tests :func:`colour.adaptation.vonkries.\ chromatic_adaptation_matrix_VonKries` definition n-dimensional arrays support. """ XYZ_w = np.array([0.95045593, 1.00000000, 1.08905775]) XYZ_wr = np.array([0.96429568, 1.00000000, 0.82510460]) M = np.array([ [1.04257389, 0.03089108, -0.05281257], [0.02219345, 1.00185663, -0.02107375], [-0.00116488, -0.00342053, 0.76178907], ]) np.testing.assert_almost_equal(chromatic_adaptation_matrix_VonKries( XYZ_w, XYZ_wr), M, decimal=7) XYZ_w = np.tile(XYZ_w, (6, 1)) XYZ_wr = np.tile(XYZ_wr, (6, 1)) M = np.reshape(np.tile(M, (6, 1)), (6, 3, 3)) np.testing.assert_almost_equal(chromatic_adaptation_matrix_VonKries( XYZ_w, XYZ_wr), M, decimal=7) XYZ_w = np.reshape(XYZ_w, (2, 3, 3)) XYZ_wr = np.reshape(XYZ_wr, (2, 3, 3)) M = np.reshape(M, (2, 3, 3, 3)) np.testing.assert_almost_equal(chromatic_adaptation_matrix_VonKries( XYZ_w, XYZ_wr), M, decimal=7)
def test_n_dimensional_chromatic_adaptation_matrix_VonKries(self): """ Tests :func:`colour.adaptation.vonkries.\ chromatic_adaptation_matrix_VonKries` definition n-dimensional arrays support. """ XYZ_w = np.array([1.09846607, 1.00000000, 0.35582280]) XYZ_wr = np.array([0.95042855, 1.00000000, 1.08890037]) M = np.array([[0.86876537, -0.14165393, 0.38719611], [-0.10300724, 1.05840142, 0.15386462], [0.00781674, 0.02678750, 2.96081771]]) np.testing.assert_almost_equal( chromatic_adaptation_matrix_VonKries(XYZ_w, XYZ_wr), M, decimal=7) XYZ_w = np.tile(XYZ_w, (6, 1)) XYZ_wr = np.tile(XYZ_wr, (6, 1)) M = np.reshape(np.tile(M, (6, 1)), (6, 3, 3)) np.testing.assert_almost_equal( chromatic_adaptation_matrix_VonKries(XYZ_w, XYZ_wr), M, decimal=7) XYZ_w = np.reshape(XYZ_w, (2, 3, 3)) XYZ_wr = np.reshape(XYZ_wr, (2, 3, 3)) M = np.reshape(M, (2, 3, 3, 3)) np.testing.assert_almost_equal( chromatic_adaptation_matrix_VonKries(XYZ_w, XYZ_wr), M, decimal=7)
def test_n_dimensional_chromatic_adaptation_matrix_VonKries(self): """ Tests :func:`colour.adaptation.vonkries.\ chromatic_adaptation_matrix_VonKries` definition n-dimensional arrays support. """ XYZ_w = np.array([1.09846607, 1.00000000, 0.35582280]) XYZ_wr = np.array([0.95042855, 1.00000000, 1.08890037]) M = np.array([[0.86876537, -0.14165393, 0.38719611], [-0.10300724, 1.05840142, 0.15386462], [0.00781674, 0.02678750, 2.96081771]]) # yapf: disable np.testing.assert_almost_equal(chromatic_adaptation_matrix_VonKries( XYZ_w, XYZ_wr), M, decimal=7) XYZ_w = np.tile(XYZ_w, (6, 1)) XYZ_wr = np.tile(XYZ_wr, (6, 1)) M = np.reshape(np.tile(M, (6, 1)), (6, 3, 3)) np.testing.assert_almost_equal(chromatic_adaptation_matrix_VonKries( XYZ_w, XYZ_wr), M, decimal=7) XYZ_w = np.reshape(XYZ_w, (2, 3, 3)) XYZ_wr = np.reshape(XYZ_wr, (2, 3, 3)) M = np.reshape(M, (2, 3, 3, 3)) np.testing.assert_almost_equal(chromatic_adaptation_matrix_VonKries( XYZ_w, XYZ_wr), M, decimal=7)
def test_n_dimensional_chromatic_adaptation_matrix_VonKries(self): """ Tests :func:`colour.adaptation.vonkries.\ chromatic_adaptation_matrix_VonKries` definition n-dimensional arrays support. """ XYZ_w = np.array([0.95045593, 1.00000000, 1.08905775]) XYZ_wr = np.array([0.96429568, 1.00000000, 0.82510460]) M = chromatic_adaptation_matrix_VonKries(XYZ_w, XYZ_wr) XYZ_w = np.tile(XYZ_w, (6, 1)) XYZ_wr = np.tile(XYZ_wr, (6, 1)) M = np.reshape(np.tile(M, (6, 1)), (6, 3, 3)) np.testing.assert_almost_equal(chromatic_adaptation_matrix_VonKries( XYZ_w, XYZ_wr), M, decimal=7) XYZ_w = np.reshape(XYZ_w, (2, 3, 3)) XYZ_wr = np.reshape(XYZ_wr, (2, 3, 3)) M = np.reshape(M, (2, 3, 3, 3)) np.testing.assert_almost_equal(chromatic_adaptation_matrix_VonKries( XYZ_w, XYZ_wr), M, decimal=7)
def test_nan_chromatic_adaptation_matrix_VonKries(self): """ Tests :func:`colour.adaptation.vonkries.\ chromatic_adaptation_matrix_VonKries` definition nan support. """ cases = [-1.0, 0.0, 1.0, -np.inf, np.inf, np.nan] cases = set(permutations(cases * 3, r=3)) for case in cases: XYZ_w = np.array(case) XYZ_wr = np.array(case) chromatic_adaptation_matrix_VonKries(XYZ_w, XYZ_wr)
def test_domain_range_scale_chromatic_adaptation_VonKries(self): """ Tests :func:`colour.adaptation.vonkries.\ chromatic_adaptation_matrix_VonKries` definition domain and range scale support. """ XYZ_w = np.array([0.95045593, 1.00000000, 1.08905775]) XYZ_wr = np.array([0.96429568, 1.00000000, 0.82510460]) M = chromatic_adaptation_matrix_VonKries(XYZ_w, XYZ_wr) d_r = (('reference', 1), (1, 1), (100, 0.01)) for scale, factor in d_r: with domain_range_scale(scale): np.testing.assert_almost_equal( chromatic_adaptation_matrix_VonKries( XYZ_w * factor, XYZ_wr * factor), M, decimal=7)
def RGB_to_RGB(RGB, input_colourspace, output_colourspace, chromatic_adaptation_transform='CAT02'): """ Converts from given input *RGB* colourspace to output *RGB* colourspace using given *chromatic adaptation* method. Parameters ---------- RGB : array_like *RGB* colourspace array. input_colourspace : RGB_Colourspace *RGB* input colourspace. output_colourspace : RGB_Colourspace *RGB* output colourspace. chromatic_adaptation_transform : unicode, optional **{'CAT02', 'XYZ Scaling', 'Von Kries', 'Bradford', 'Sharp', 'Fairchild', 'CMCCAT97', 'CMCCAT2000', 'CAT02_BRILL_CAT', 'Bianco', 'Bianco PC'}**, *Chromatic adaptation* transform. Returns ------- ndarray *RGB* colourspace array. Notes ----- - Input / output *RGB* colourspace arrays are in domain / range [0, 1]. - Input / output *RGB* colourspace arrays are assumed to be representing linear light values. Examples -------- >>> from colour import sRGB_COLOURSPACE, PROPHOTO_RGB_COLOURSPACE >>> RGB = np.array([0.01103742, 0.12734226, 0.11632971]) >>> RGB_to_RGB( ... RGB, ... sRGB_COLOURSPACE, ... PROPHOTO_RGB_COLOURSPACE) # doctest: +ELLIPSIS array([ 0.0643538..., 0.1157289..., 0.1158038...]) """ cat = chromatic_adaptation_matrix_VonKries( xy_to_XYZ(input_colourspace.whitepoint), xy_to_XYZ(output_colourspace.whitepoint), chromatic_adaptation_transform) M = dot_matrix(cat, input_colourspace.RGB_to_XYZ_matrix) M = dot_matrix(output_colourspace.XYZ_to_RGB_matrix, M) RGB = dot_vector(M, RGB) return RGB
def test_n_dimensional_chromatic_adaptation_matrix_VonKries(self): """ Tests :func:`colour.adaptation.vonkries.\ chromatic_adaptation_matrix_VonKries` definition n-dimensional arrays support. """ XYZ_w = np.array([0.95045593, 1.00000000, 1.08905775]) XYZ_wr = np.array([0.96429568, 1.00000000, 0.82510460]) M = chromatic_adaptation_matrix_VonKries(XYZ_w, XYZ_wr) XYZ_w = np.tile(XYZ_w, (6, 1)) XYZ_wr = np.tile(XYZ_wr, (6, 1)) M = np.reshape(np.tile(M, (6, 1)), (6, 3, 3)) np.testing.assert_almost_equal( chromatic_adaptation_matrix_VonKries(XYZ_w, XYZ_wr), M, decimal=7) XYZ_w = np.reshape(XYZ_w, (2, 3, 3)) XYZ_wr = np.reshape(XYZ_wr, (2, 3, 3)) M = np.reshape(M, (2, 3, 3, 3)) np.testing.assert_almost_equal( chromatic_adaptation_matrix_VonKries(XYZ_w, XYZ_wr), M, decimal=7)
def RGB_to_RGB(RGB, input_colourspace, output_colourspace, chromatic_adaptation_transform='CAT02'): """ Converts from given input *RGB* colourspace to output *RGB* colourspace using given *chromatic adaptation* method. Parameters ---------- RGB : array_like *RGB* colourspace array. input_colourspace : RGB_Colourspace *RGB* input colourspace. output_colourspace : RGB_Colourspace *RGB* output colourspace. chromatic_adaptation_transform : unicode, optional **{'CAT02', 'XYZ Scaling', 'Von Kries', 'Bradford', 'Sharp', 'Fairchild, 'CMCCAT97', 'CMCCAT2000', 'CAT02_BRILL_CAT', 'Bianco', 'Bianco PC'}**, *Chromatic adaptation* transform. Returns ------- ndarray *RGB* colourspace array. Notes ----- - *RGB* colourspace arrays are in domain [0, 1]. Examples -------- >>> from colour import sRGB_COLOURSPACE, PROPHOTO_RGB_COLOURSPACE >>> RGB = np.array([0.01103604, 0.12734466, 0.11631037]) >>> RGB_to_RGB( ... RGB, ... sRGB_COLOURSPACE, ... PROPHOTO_RGB_COLOURSPACE) # doctest: +ELLIPSIS array([ 0.0643338..., 0.1157362..., 0.1157614...]) """ cat = chromatic_adaptation_matrix_VonKries( xy_to_XYZ(input_colourspace.whitepoint), xy_to_XYZ(output_colourspace.whitepoint), chromatic_adaptation_transform) M = dot_matrix(cat, input_colourspace.RGB_to_XYZ_matrix) M = dot_matrix(output_colourspace.XYZ_to_RGB_matrix, M) RGB = dot_vector(M, RGB) return RGB
def RGB_to_RGB_matrix(input_colourspace, output_colourspace, chromatic_adaptation_transform='CAT02'): """ Computes the matrix :math:`M` converting from given input *RGB* colourspace to output *RGB* colourspace using given *chromatic adaptation* method. Parameters ---------- input_colourspace : RGB_Colourspace *RGB* input colourspace. output_colourspace : RGB_Colourspace *RGB* output colourspace. chromatic_adaptation_transform : unicode, optional **{'CAT02', 'XYZ Scaling', 'Von Kries', 'Bradford', 'Sharp', 'Fairchild', 'CMCCAT97', 'CMCCAT2000', 'CAT02_BRILL_CAT', 'Bianco', 'Bianco PC', None}**, *Chromatic adaptation* transform, if *None* no chromatic adaptation is performed. Returns ------- ndarray Conversion matrix :math:`M`. Examples -------- >>> from colour.models import sRGB_COLOURSPACE, PROPHOTO_RGB_COLOURSPACE >>> RGB_to_RGB_matrix(sRGB_COLOURSPACE, PROPHOTO_RGB_COLOURSPACE) ... # doctest: +ELLIPSIS array([[ 0.5288241..., 0.3340609..., 0.1373616...], [ 0.0975294..., 0.8790074..., 0.0233981...], [ 0.0163599..., 0.1066124..., 0.8772485...]]) """ M = input_colourspace.RGB_to_XYZ_matrix if chromatic_adaptation_transform is not None: M_CAT = chromatic_adaptation_matrix_VonKries( xy_to_XYZ(input_colourspace.whitepoint), xy_to_XYZ(output_colourspace.whitepoint), chromatic_adaptation_transform) M = dot_matrix(M_CAT, input_colourspace.RGB_to_XYZ_matrix) M = dot_matrix(output_colourspace.XYZ_to_RGB_matrix, M) return M
def XYZ_to_RGB(XYZ, illuminant_XYZ, illuminant_RGB, XYZ_to_RGB_matrix, chromatic_adaptation_transform='CAT02', encoding_cctf=None): """ Converts from *CIE XYZ* tristimulus values to *RGB* colourspace array. Parameters ---------- XYZ : array_like *CIE XYZ* tristimulus values. illuminant_XYZ : array_like *CIE XYZ* tristimulus values *illuminant* *xy* chromaticity coordinates or *CIE xyY* colourspace array. illuminant_RGB : array_like *RGB* colourspace *illuminant* *xy* chromaticity coordinates or *CIE xyY* colourspace array. XYZ_to_RGB_matrix : array_like *Normalised primary matrix*. chromatic_adaptation_transform : unicode, optional **{'CAT02', 'XYZ Scaling', 'Von Kries', 'Bradford', 'Sharp', 'Fairchild', 'CMCCAT97', 'CMCCAT2000', 'CAT02_BRILL_CAT', 'Bianco', 'Bianco PC', None}**, *Chromatic adaptation* transform, if *None* no chromatic adaptation is performed. encoding_cctf : object, optional Encoding colour component transfer function (Encoding CCTF) or opto-electronic transfer function (OETF / OECF). Returns ------- ndarray *RGB* colourspace array. Notes ----- +--------------------+-----------------------+---------------+ | **Domain** | **Scale - Reference** | **Scale - 1** | +====================+=======================+===============+ | ``XYZ`` | [0, 1] | [0, 1] | +--------------------+-----------------------+---------------+ | ``illuminant_XYZ`` | [0, 1] | [0, 1] | +--------------------+-----------------------+---------------+ | ``illuminant_RGB`` | [0, 1] | [0, 1] | +--------------------+-----------------------+---------------+ +--------------------+-----------------------+---------------+ | **Range** | **Scale - Reference** | **Scale - 1** | +====================+=======================+===============+ | ``RGB`` | [0, 1] | [0, 1] | +--------------------+-----------------------+---------------+ Examples -------- >>> XYZ = np.array([0.21638819, 0.12570000, 0.03847493]) >>> illuminant_XYZ = np.array([0.34570, 0.35850]) >>> illuminant_RGB = np.array([0.31270, 0.32900]) >>> chromatic_adaptation_transform = 'Bradford' >>> XYZ_to_RGB_matrix = np.array( ... [[3.24062548, -1.53720797, -0.49862860], ... [-0.96893071, 1.87575606, 0.04151752], ... [0.05571012, -0.20402105, 1.05699594]] ... ) >>> XYZ_to_RGB(XYZ, illuminant_XYZ, illuminant_RGB, XYZ_to_RGB_matrix, ... chromatic_adaptation_transform) # doctest: +ELLIPSIS array([ 0.4559557..., 0.0303970..., 0.0408724...]) """ XYZ = to_domain_1(XYZ) if chromatic_adaptation_transform is not None: M_CAT = chromatic_adaptation_matrix_VonKries( xyY_to_XYZ(xy_to_xyY(illuminant_XYZ)), xyY_to_XYZ(xy_to_xyY(illuminant_RGB)), transform=chromatic_adaptation_transform) XYZ = dot_vector(M_CAT, XYZ) RGB = dot_vector(XYZ_to_RGB_matrix, XYZ) if encoding_cctf is not None: with domain_range_scale('ignore'): RGB = encoding_cctf(RGB) return from_range_1(RGB)
def test_chromatic_adaptation_matrix_VonKries(self): """ Tests :func:`colour.adaptation.vonkries.\ chromatic_adaptation_matrix_VonKries` definition. """ np.testing.assert_almost_equal( chromatic_adaptation_matrix_VonKries( np.array([1.09846607, 1.00000000, 0.35582280]), np.array([0.95042855, 1.00000000, 1.08890037])), np.array([[0.86876537, -0.14165393, 0.38719611], [-0.10300724, 1.05840142, 0.15386462], [0.00781674, 0.02678750, 2.96081771]]), decimal=7) # yapf: disable np.testing.assert_almost_equal( chromatic_adaptation_matrix_VonKries( np.array([0.99092745, 1.00000000, 0.85313273]), np.array([1.01679082, 1.00000000, 0.67610122])), np.array([[1.03379528, 0.03065322, -0.04486819], [0.02195826, 0.99354348, -0.01793687], [-0.00102726, -0.00281712, 0.79698769]]), decimal=7) # yapf: disable np.testing.assert_almost_equal( chromatic_adaptation_matrix_VonKries( np.array([0.98070597, 1.00000000, 1.18224949]), np.array([0.92833635, 1.00000000, 1.03664720])), np.linalg.inv( chromatic_adaptation_matrix_VonKries( np.array([0.92833635, 1.00000000, 1.03664720]), np.array([0.98070597, 1.00000000, 1.18224949])))) np.testing.assert_almost_equal( chromatic_adaptation_matrix_VonKries( np.array([1.09846607, 1.00000000, 0.35582280]), np.array([0.95042855, 1.00000000, 1.08890037]), transform='XYZ Scaling'), np.array([[0.86523251, 0.00000000, 0.00000000], [0.00000000, 1.00000000, 0.00000000], [0.00000000, 0.00000000, 3.06023214]]), decimal=7) # yapf: disable np.testing.assert_almost_equal( chromatic_adaptation_matrix_VonKries( np.array([1.09846607, 1.00000000, 0.35582280]), np.array([0.95042855, 1.00000000, 1.08890037]), transform='Bradford'), np.array([[0.84467949, -0.11793553, 0.39489408], [-0.13664085, 1.10412369, 0.12919812], [0.07986716, -0.13493155, 3.19288296]]), decimal=7) # yapf: disable np.testing.assert_almost_equal( chromatic_adaptation_matrix_VonKries( np.array([1.09846607, 1.00000000, 0.35582280]), np.array([0.95042855, 1.00000000, 1.08890037]), transform='Von Kries'), np.array([[0.93949221, -0.23393727, 0.42820614], [-0.02569635, 1.02638463, 0.00517656], [0.00000000, 0.00000000, 3.06023214]]), decimal=7) # yapf: disable
def RGB_to_XYZ(RGB, illuminant_RGB, illuminant_XYZ, RGB_to_XYZ_matrix, chromatic_adaptation_transform='CAT02', decoding_cctf=None): """ Converts given *RGB* colourspace array to *CIE XYZ* tristimulus values. Parameters ---------- RGB : array_like *RGB* colourspace array. illuminant_RGB : array_like *RGB* colourspace *illuminant* chromaticity coordinates or *CIE xyY* colourspace array. illuminant_XYZ : array_like *CIE XYZ* tristimulus values *illuminant* chromaticity coordinates or *CIE xyY* colourspace array. RGB_to_XYZ_matrix : array_like *Normalised primary matrix*. chromatic_adaptation_transform : unicode, optional **{'CAT02', 'XYZ Scaling', 'Von Kries', 'Bradford', 'Sharp', 'Fairchild', 'CMCCAT97', 'CMCCAT2000', 'CAT02_BRILL_CAT', 'Bianco', 'Bianco PC', None}**, *Chromatic adaptation* transform, if *None* no chromatic adaptation is performed. decoding_cctf : object, optional Decoding colour component transfer function (Decoding CCTF) or electro-optical transfer function (EOTF / EOCF). Returns ------- ndarray *CIE XYZ* tristimulus values. Notes ----- +--------------------+-----------------------+---------------+ | **Domain** | **Scale - Reference** | **Scale - 1** | +====================+=======================+===============+ | ``RGB`` | [0, 1] | [0, 1] | +--------------------+-----------------------+---------------+ | ``illuminant_XYZ`` | [0, 1] | [0, 1] | +--------------------+-----------------------+---------------+ | ``illuminant_RGB`` | [0, 1] | [0, 1] | +--------------------+-----------------------+---------------+ +--------------------+-----------------------+---------------+ | **Range** | **Scale - Reference** | **Scale - 1** | +====================+=======================+===============+ | ``XYZ`` | [0, 1] | [0, 1] | +--------------------+-----------------------+---------------+ Examples -------- >>> RGB = np.array([0.45595571, 0.03039702, 0.04087245]) >>> illuminant_RGB = np.array([0.31270, 0.32900]) >>> illuminant_XYZ = np.array([0.34570, 0.35850]) >>> chromatic_adaptation_transform = 'Bradford' >>> RGB_to_XYZ_matrix = np.array( ... [[0.41240000, 0.35760000, 0.18050000], ... [0.21260000, 0.71520000, 0.07220000], ... [0.01930000, 0.11920000, 0.95050000]] ... ) >>> RGB_to_XYZ(RGB, illuminant_RGB, illuminant_XYZ, RGB_to_XYZ_matrix, ... chromatic_adaptation_transform) # doctest: +ELLIPSIS array([ 0.2163881..., 0.1257 , 0.0384749...]) """ RGB = to_domain_1(RGB) if decoding_cctf is not None: with domain_range_scale('ignore'): RGB = decoding_cctf(RGB) XYZ = dot_vector(RGB_to_XYZ_matrix, RGB) if chromatic_adaptation_transform is not None: M_CAT = chromatic_adaptation_matrix_VonKries( xyY_to_XYZ(xy_to_xyY(illuminant_RGB)), xyY_to_XYZ(xy_to_xyY(illuminant_XYZ)), transform=chromatic_adaptation_transform) XYZ = dot_vector(M_CAT, XYZ) return from_range_1(XYZ)
def XYZ_to_RGB(XYZ, illuminant_XYZ, illuminant_RGB, XYZ_to_RGB_matrix, chromatic_adaptation_transform='CAT02', OECF=None): """ Converts from *CIE XYZ* tristimulus values to given *RGB* colourspace. Parameters ---------- XYZ : array_like *CIE XYZ* tristimulus values. illuminant_XYZ : array_like *CIE XYZ* tristimulus values *illuminant* *xy* chromaticity coordinates or *CIE xyY* colourspace array. illuminant_RGB : array_like *RGB* colourspace *illuminant* *xy* chromaticity coordinates or *CIE xyY* colourspace array. XYZ_to_RGB_matrix : array_like *Normalised primary matrix*. chromatic_adaptation_transform : unicode, optional **{'CAT02', 'XYZ Scaling', 'Von Kries', 'Bradford', 'Sharp', 'Fairchild, 'CMCCAT97', 'CMCCAT2000', 'CAT02_BRILL_CAT', 'Bianco', 'Bianco PC'}**, *Chromatic adaptation* transform. OECF : object, optional *Opto-electronic conversion function*. Returns ------- ndarray *RGB* colourspace array. Notes ----- - Input *CIE XYZ* tristimulus values are in domain [0, 1]. - Input *illuminant_XYZ* *xy* chromaticity coordinates or *CIE xyY* colourspace array are in domain [0, :math:`\infty`]. - Input *illuminant_RGB* *xy* chromaticity coordinates or *CIE xyY* colourspace array are in domain [0, :math:`\infty`]. - Output *RGB* colourspace array is in domain [0, 1]. Examples -------- >>> XYZ = np.array([0.07049534, 0.10080000, 0.09558313]) >>> illuminant_XYZ = np.array([0.34567, 0.35850]) >>> illuminant_RGB = np.array([0.31271, 0.32902]) >>> chromatic_adaptation_transform = 'Bradford' >>> XYZ_to_RGB_matrix = np.array([ ... [3.24100326, -1.53739899, -0.49861587], ... [-0.96922426, 1.87592999, 0.04155422], ... [0.05563942, -0.20401120, 1.05714897]]) >>> XYZ_to_RGB( ... XYZ, ... illuminant_XYZ, ... illuminant_RGB, ... XYZ_to_RGB_matrix, ... chromatic_adaptation_transform) # doctest: +ELLIPSIS array([ 0.0110360..., 0.1273446..., 0.1163103...]) """ M = chromatic_adaptation_matrix_VonKries( xyY_to_XYZ(xy_to_xyY(illuminant_XYZ)), xyY_to_XYZ(xy_to_xyY(illuminant_RGB)), transform=chromatic_adaptation_transform) XYZ_a = dot_vector(M, XYZ) RGB = dot_vector(XYZ_to_RGB_matrix, XYZ_a) if OECF is not None: RGB = OECF(RGB) return RGB
def XYZ_to_RGB(XYZ, illuminant_XYZ, illuminant_RGB, XYZ_to_RGB_matrix, chromatic_adaptation_transform='CAT02', encoding_cctf=None): """ Converts from *CIE XYZ* tristimulus values to given *RGB* colourspace. Parameters ---------- XYZ : array_like *CIE XYZ* tristimulus values. illuminant_XYZ : array_like *CIE XYZ* tristimulus values *illuminant* *xy* chromaticity coordinates or *CIE xyY* colourspace array. illuminant_RGB : array_like *RGB* colourspace *illuminant* *xy* chromaticity coordinates or *CIE xyY* colourspace array. XYZ_to_RGB_matrix : array_like *Normalised primary matrix*. chromatic_adaptation_transform : unicode, optional **{'CAT02', 'XYZ Scaling', 'Von Kries', 'Bradford', 'Sharp', 'Fairchild', 'CMCCAT97', 'CMCCAT2000', 'CAT02_BRILL_CAT', 'Bianco', 'Bianco PC'}**, *Chromatic adaptation* transform. encoding_cctf : object, optional Encoding colour component transfer function (Encoding CCTF) or opto-electronic transfer function (OETF / OECF). Returns ------- ndarray *RGB* colourspace array. Notes ----- - Input *CIE XYZ* tristimulus values are in domain [0, 1]. - Input *illuminant_XYZ* *xy* chromaticity coordinates or *CIE xyY* colourspace array are in domain [0, :math:`\infty`]. - Input *illuminant_RGB* *xy* chromaticity coordinates or *CIE xyY* colourspace array are in domain [0, :math:`\infty`]. - Output *RGB* colourspace array is in range [0, 1]. Examples -------- >>> XYZ = np.array([0.07049534, 0.10080000, 0.09558313]) >>> illuminant_XYZ = np.array([0.34570, 0.35850]) >>> illuminant_RGB = np.array([0.31270, 0.32900]) >>> chromatic_adaptation_transform = 'Bradford' >>> XYZ_to_RGB_matrix = np.array([ ... [3.24062548, -1.53720797, -0.49862860], ... [-0.96893071, 1.87575606, 0.04151752], ... [0.05571012, -0.20402105, 1.05699594]]) >>> XYZ_to_RGB( ... XYZ, ... illuminant_XYZ, ... illuminant_RGB, ... XYZ_to_RGB_matrix, ... chromatic_adaptation_transform) # doctest: +ELLIPSIS array([ 0.0110015..., 0.1273504..., 0.1163271...]) """ M = chromatic_adaptation_matrix_VonKries( xyY_to_XYZ(xy_to_xyY(illuminant_XYZ)), xyY_to_XYZ(xy_to_xyY(illuminant_RGB)), transform=chromatic_adaptation_transform) XYZ_a = dot_vector(M, XYZ) RGB = dot_vector(XYZ_to_RGB_matrix, XYZ_a) if encoding_cctf is not None: RGB = encoding_cctf(RGB) return RGB
def test_chromatic_adaptation_matrix_VonKries(self): """ Tests :func:`colour.adaptation.vonkries.\ chromatic_adaptation_matrix_VonKries` definition. """ np.testing.assert_almost_equal( chromatic_adaptation_matrix_VonKries( np.array([0.95045593, 1.00000000, 1.08905775]), np.array([0.96429568, 1.00000000, 0.82510460])), np.array([ [1.04257389, 0.03089108, -0.05281257], [0.02219345, 1.00185663, -0.02107375], [-0.00116488, -0.00342053, 0.76178907], ]), decimal=7) np.testing.assert_almost_equal( chromatic_adaptation_matrix_VonKries( np.array([0.95045593, 1.00000000, 1.08905775]), np.array([1.09846607, 1.00000000, 0.35582280])), np.array([ [1.17159793, 0.16088780, -0.16158366], [0.11462057, 0.96182051, -0.06497572], [-0.00413024, -0.00912739, 0.33871096], ]), decimal=7) np.testing.assert_almost_equal( chromatic_adaptation_matrix_VonKries( np.array([0.95045593, 1.00000000, 1.08905775]), np.array([0.99144661, 1.00000000, 0.67315942])), np.linalg.inv( chromatic_adaptation_matrix_VonKries( np.array([0.99144661, 1.00000000, 0.67315942]), np.array([0.95045593, 1.00000000, 1.08905775]))), decimal=7) np.testing.assert_almost_equal( chromatic_adaptation_matrix_VonKries( np.array([0.95045593, 1.00000000, 1.08905775]), np.array([0.96429568, 1.00000000, 0.82510460]), transform='XYZ Scaling'), np.array([ [1.01456117, 0.00000000, 0.00000000], [0.00000000, 1.00000000, 0.00000000], [0.00000000, 0.00000000, 0.75763163], ]), decimal=7) np.testing.assert_almost_equal( chromatic_adaptation_matrix_VonKries( np.array([0.95045593, 1.00000000, 1.08905775]), np.array([0.96429568, 1.00000000, 0.82510460]), transform='Bradford'), np.array([ [1.04792979, 0.02294687, -0.05019227], [0.02962781, 0.99043443, -0.01707380], [-0.00924304, 0.01505519, 0.75187428], ]), decimal=7) np.testing.assert_almost_equal( chromatic_adaptation_matrix_VonKries( np.array([0.95045593, 1.00000000, 1.08905775]), np.array([0.96429568, 1.00000000, 0.82510460]), transform='Von Kries'), np.array([ [1.01611856, 0.05535971, -0.05219186], [0.00608087, 0.99555604, -0.00122642], [0.00000000, 0.00000000, 0.75763163], ]), decimal=7)
def test_chromatic_adaptation_matrix_VonKries(self): """ Tests :func:`colour.adaptation.vonkries.chromatic_adaptation_matrix_VonKries` definition. """ np.testing.assert_almost_equal( chromatic_adaptation_matrix_VonKries( np.array([1.09846607, 1., 0.3558228]), np.array([0.95042855, 1., 1.08890037])), np.array([[0.86876537, -0.14165393, 0.38719611], [-0.10300724, 1.05840142, 0.15386462], [0.00781674, 0.0267875, 2.96081771]]), decimal=7) np.testing.assert_almost_equal( chromatic_adaptation_matrix_VonKries( np.array([0.99092745, 1., 0.85313273]), np.array([1.01679082, 1., 0.67610122])), np.array([[1.03379528e+00, 3.06532172e-02, -4.48681876e-02], [2.19582633e-02, 9.93543483e-01, -1.79368671e-02], [-1.02726253e-03, -2.81711777e-03, 7.96987686e-01]]), decimal=7) np.testing.assert_almost_equal( chromatic_adaptation_matrix_VonKries( np.array([0.98070597, 1., 1.18224949]), np.array([0.92833635, 1., 1.0366472])), np.linalg.inv(chromatic_adaptation_matrix_VonKries( np.array([0.92833635, 1., 1.0366472]), np.array([0.98070597, 1., 1.18224949])))) np.testing.assert_almost_equal( chromatic_adaptation_matrix_VonKries( np.array([1.09846607, 1., 0.3558228]), np.array([0.95042855, 1., 1.08890037]), transform='XYZ Scaling'), np.array([[0.86523251, 0., 0.], [0., 1., 0.], [0., 0., 3.06023214]]), decimal=7) np.testing.assert_almost_equal( chromatic_adaptation_matrix_VonKries( np.array([1.09846607, 1., 0.3558228]), np.array([0.95042855, 1., 1.08890037]), transform='Bradford'), np.array([[0.84467949, -0.11793553, 0.39489408], [-0.13664085, 1.10412369, 0.12919812], [0.07986716, -0.13493155, 3.19288296]]), decimal=7) np.testing.assert_almost_equal( chromatic_adaptation_matrix_VonKries( np.array([1.09846607, 1., 0.3558228]), np.array([0.95042855, 1., 1.08890037]), transform='Von Kries'), np.array([[0.93949221, -0.23393727, 0.42820614], [-0.02569635, 1.02638463, 0.00517656], [0., 0., 3.06023214]]), decimal=7)
def RGB_to_XYZ(RGB, illuminant_RGB, illuminant_XYZ, RGB_to_XYZ_matrix, chromatic_adaptation_transform='CAT02', inverse_transfer_function=None): """ Converts from *RGB* colourspace to *CIE XYZ* colourspace using given *RGB* colourspace matrix, *illuminants*, *chromatic adaptation* method, *normalised primary matrix* and *transfer function*. Parameters ---------- RGB : array_like, (3,) *RGB* colourspace matrix. illuminant_RGB : array_like *RGB* colourspace *illuminant* chromaticity coordinates. illuminant_XYZ : array_like *CIE XYZ* colourspace *illuminant* chromaticity coordinates. RGB_to_XYZ_matrix : array_like, (3, 3) *Normalised primary matrix*. chromatic_adaptation_transform : unicode, optional {'CAT02', 'XYZ Scaling', 'Von Kries', 'Bradford', 'Sharp', 'Fairchild, 'CMCCAT97', 'CMCCAT2000', 'CAT02_BRILL_CAT', 'Bianco', 'Bianco PC'}, *Chromatic adaptation* transform. inverse_transfer_function : object, optional *Inverse transfer function*. Returns ------- ndarray, (3,) *CIE XYZ* colourspace matrix. Notes ----- - Input *RGB* colourspace matrix is in domain [0, 1]. - Input *illuminant_RGB* *xy* chromaticity coordinates are in domain [0, 1]. - Input *illuminant_XYZ* *xy* chromaticity coordinates are in domain [0, 1]. - Output *CIE XYZ* colourspace matrix is in domain [0, 1]. Examples -------- >>> RGB = np.array([0.01103604, 0.12734466, 0.11631037]) >>> illuminant_RGB = (0.31271, 0.32902) >>> illuminant_XYZ = (0.34567, 0.35850) >>> chromatic_adaptation_transform = 'Bradford' >>> RGB_to_XYZ_matrix = np.array([ ... [0.41238656, 0.35759149, 0.18045049], ... [0.21263682, 0.71518298, 0.0721802], ... [0.01933062, 0.11919716, 0.95037259]]) >>> RGB_to_XYZ( ... RGB, ... illuminant_RGB, ... illuminant_XYZ, ... RGB_to_XYZ_matrix, ... chromatic_adaptation_transform) # doctest: +ELLIPSIS array([ 0.0704953..., 0.1008 , 0.0955831...]) """ RGB = np.ravel(RGB) if inverse_transfer_function is not None: RGB = np.array([inverse_transfer_function(x) for x in RGB]) XYZ = np.dot(RGB_to_XYZ_matrix.reshape((3, 3)), RGB.reshape((3, 1))) cat = chromatic_adaptation_matrix_VonKries( xy_to_XYZ(illuminant_RGB), xy_to_XYZ(illuminant_XYZ), transform=chromatic_adaptation_transform) XYZ_a = np.dot(cat, XYZ.reshape((3, 1))) return np.ravel(XYZ_a)
def RGB_to_XYZ(RGB, illuminant_RGB, illuminant_XYZ, RGB_to_XYZ_matrix, chromatic_adaptation_transform='CAT02', EOCF=None): """ Converts from given *RGB* colourspace to *CIE XYZ* tristimulus values. Parameters ---------- RGB : array_like *RGB* colourspace array. illuminant_RGB : array_like *RGB* colourspace *illuminant* chromaticity coordinates or *CIE xyY* colourspace array. illuminant_XYZ : array_like *CIE XYZ* tristimulus values *illuminant* chromaticity coordinates or *CIE xyY* colourspace array. RGB_to_XYZ_matrix : array_like *Normalised primary matrix*. chromatic_adaptation_transform : unicode, optional **{'CAT02', 'XYZ Scaling', 'Von Kries', 'Bradford', 'Sharp', 'Fairchild, 'CMCCAT97', 'CMCCAT2000', 'CAT02_BRILL_CAT', 'Bianco', 'Bianco PC'}**, *Chromatic adaptation* transform. EOCF : object, optional *Electro-optical conversion function*. Returns ------- ndarray *CIE XYZ* tristimulus values. Notes ----- - Input *RGB* colourspace array is in domain [0, 1]. - Input *illuminant_RGB* *xy* chromaticity coordinates or *CIE xyY* colourspace array are in domain [0, :math:`\infty`]. - Input *illuminant_XYZ* *xy* chromaticity coordinates or *CIE xyY* colourspace array are in domain [0, :math:`\infty`]. - Output *CIE XYZ* tristimulus values are in domain [0, 1]. Examples -------- >>> RGB = np.array([0.01103604, 0.12734466, 0.11631037]) >>> illuminant_RGB = np.array([0.31271, 0.32902]) >>> illuminant_XYZ = np.array([0.34567, 0.35850]) >>> chromatic_adaptation_transform = 'Bradford' >>> RGB_to_XYZ_matrix = np.array([ ... [0.41238656, 0.35759149, 0.18045049], ... [0.21263682, 0.71518298, 0.07218020], ... [0.01933062, 0.11919716, 0.95037259]]) >>> RGB_to_XYZ( ... RGB, ... illuminant_RGB, ... illuminant_XYZ, ... RGB_to_XYZ_matrix, ... chromatic_adaptation_transform) # doctest: +ELLIPSIS array([ 0.0704953..., 0.1008 , 0.0955831...]) """ if EOCF is not None: RGB = EOCF(RGB) M = chromatic_adaptation_matrix_VonKries( xyY_to_XYZ(xy_to_xyY(illuminant_RGB)), xyY_to_XYZ(xy_to_xyY(illuminant_XYZ)), transform=chromatic_adaptation_transform) XYZ = dot_vector(RGB_to_XYZ_matrix, RGB) XYZ_a = dot_vector(M, XYZ) return XYZ_a
def RGB_to_XYZ(RGB, illuminant_RGB, illuminant_XYZ, RGB_to_XYZ_matrix, chromatic_adaptation_transform='CAT02', decoding_cctf=None): """ Converts from given *RGB* colourspace to *CIE XYZ* tristimulus values. Parameters ---------- RGB : array_like *RGB* colourspace array. illuminant_RGB : array_like *RGB* colourspace *illuminant* chromaticity coordinates or *CIE xyY* colourspace array. illuminant_XYZ : array_like *CIE XYZ* tristimulus values *illuminant* chromaticity coordinates or *CIE xyY* colourspace array. RGB_to_XYZ_matrix : array_like *Normalised primary matrix*. chromatic_adaptation_transform : unicode, optional **{'CAT02', 'XYZ Scaling', 'Von Kries', 'Bradford', 'Sharp', 'Fairchild', 'CMCCAT97', 'CMCCAT2000', 'CAT02_BRILL_CAT', 'Bianco', 'Bianco PC'}**, *Chromatic adaptation* transform. decoding_cctf : object, optional Decoding colour component transfer function (Decoding CCTF) or electro-optical transfer function (EOTF / EOCF). Returns ------- ndarray *CIE XYZ* tristimulus values. Notes ----- - Input *RGB* colourspace array is in domain [0, 1]. - Input *illuminant_RGB* *xy* chromaticity coordinates or *CIE xyY* colourspace array are in domain [0, :math:`\infty`]. - Input *illuminant_XYZ* *xy* chromaticity coordinates or *CIE xyY* colourspace array are in domain [0, :math:`\infty`]. - Output *CIE XYZ* tristimulus values are in range [0, 1]. Examples -------- >>> RGB = np.array([0.01100154, 0.12735048, 0.11632713]) >>> illuminant_RGB = np.array([0.31270, 0.32900]) >>> illuminant_XYZ = np.array([0.34570, 0.35850]) >>> chromatic_adaptation_transform = 'Bradford' >>> RGB_to_XYZ_matrix = np.array([ ... [0.41240000, 0.35760000, 0.18050000], ... [0.21260000, 0.71520000, 0.07220000], ... [0.01930000, 0.11920000, 0.95050000]]) >>> RGB_to_XYZ( ... RGB, ... illuminant_RGB, ... illuminant_XYZ, ... RGB_to_XYZ_matrix, ... chromatic_adaptation_transform) # doctest: +ELLIPSIS array([ 0.0704953..., 0.1008 , 0.0955831...]) """ if decoding_cctf is not None: RGB = decoding_cctf(RGB) M = chromatic_adaptation_matrix_VonKries( xyY_to_XYZ(xy_to_xyY(illuminant_RGB)), xyY_to_XYZ(xy_to_xyY(illuminant_XYZ)), transform=chromatic_adaptation_transform) XYZ = dot_vector(RGB_to_XYZ_matrix, RGB) XYZ_a = dot_vector(M, XYZ) return XYZ_a
def camera_space_to_XYZ_matrix(xy, CCT_calibration_illuminant_1, CCT_calibration_illuminant_2, M_color_matrix_1, M_color_matrix_2, M_camera_calibration_1, M_camera_calibration_2, analog_balance, M_forward_matrix_1, M_forward_matrix_2, chromatic_adaptation_transform='Bradford'): """ Returns the *Camera Space* to *CIE XYZ* matrix for given *xy* white balance chromaticity coordinates. Parameters ---------- xy : array_like *xy* white balance chromaticity coordinates. CCT_calibration_illuminant_1 : numeric Correlated colour temperature of *CalibrationIlluminant1*. CCT_calibration_illuminant_2 : numeric Correlated colour temperature of *CalibrationIlluminant2*. M_color_matrix_1 : array_like *ColorMatrix1* tag matrix. M_color_matrix_2 : array_like *ColorMatrix2* tag matrix. M_camera_calibration_1 : array_like *CameraCalibration1* tag matrix. M_camera_calibration_2 : array_like *CameraCalibration2* tag matrix. analog_balance : array_like *AnalogBalance* tag vector. M_forward_matrix_1 : array_like *ForwardMatrix1* tag matrix. M_forward_matrix_2 : array_like *ForwardMatrix2* tag matrix. chromatic_adaptation_transform : unicode, optional **{'CAT02', 'XYZ Scaling', 'Von Kries', 'Bradford', 'Sharp', 'Fairchild', 'CMCCAT97', 'CMCCAT2000', 'CAT02_BRILL_CAT', 'Bianco', 'Bianco PC'}**, Chromatic adaptation transform. Returns ------- ndarray *Camera Space* to *CIE XYZ* matrix. Notes ----- - The reference illuminant is D50 as defined per :attr:`colour_hdri.models.dataset.dng.ADOBE_DNG_XYZ_ILLUMINANT` attribute. References ---------- - :cite:`AdobeSystems2012f` - :cite:`AdobeSystems2012g` - :cite:`AdobeSystems2015d` - :cite:`McGuffog2012a` Examples -------- >>> M_color_matrix_1 = np.array( ... [[0.5309, -0.0229, -0.0336], ... [-0.6241, 1.3265, 0.3337], ... [-0.0817, 0.1215, 0.6664]]) >>> M_color_matrix_2 = np.array( ... [[0.4716, 0.0603, -0.0830], ... [-0.7798, 1.5474, 0.2480], ... [-0.1496, 0.1937, 0.6651]]) >>> M_camera_calibration_1 = np.identity(3) >>> M_camera_calibration_2 = np.identity(3) >>> analog_balance = np.ones(3) >>> M_forward_matrix_1 = np.array( ... [[0.8924, -0.1041, 0.1760], ... [0.4351, 0.6621, -0.0972], ... [0.0505, -0.1562, 0.9308]]) >>> M_forward_matrix_2 = np.array( ... [[0.8924, -0.1041, 0.1760], ... [0.4351, 0.6621, -0.0972], ... [0.0505, -0.1562, 0.9308]]) >>> camera_space_to_XYZ_matrix( # doctest: +ELLIPSIS ... np.array([0.32816244, 0.34698169]), ... 2850, ... 6500, ... M_color_matrix_1, ... M_color_matrix_2, ... M_camera_calibration_1, ... M_camera_calibration_2, ... analog_balance, ... M_forward_matrix_1, ... M_forward_matrix_2) array([[ 2.1604087..., -0.1041... , 0.2722498...], [ 1.0533324..., 0.6621... , -0.1503561...], [ 0.1222553..., -0.1562... , 1.4398304...]]) """ # *ForwardMatrix1* and *ForwardMatrix2* are not included in the camera # profile. if is_identity(M_forward_matrix_1) and is_identity(M_forward_matrix_2): M_camera_to_XYZ = np.linalg.inv( XYZ_to_camera_space_matrix(xy, CCT_calibration_illuminant_1, CCT_calibration_illuminant_2, M_color_matrix_1, M_color_matrix_2, M_camera_calibration_1, M_camera_calibration_2, analog_balance)) M_CAT = chromatic_adaptation_matrix_VonKries( xy_to_XYZ(xy), xy_to_XYZ(ADOBE_DNG_XYZ_ILLUMINANT), chromatic_adaptation_transform) M_camera_space_to_XYZ = dot_matrix(M_CAT, M_camera_to_XYZ) else: uv = UCS_to_uv(XYZ_to_UCS(xy_to_XYZ(xy))) CCT, _D_uv = uv_to_CCT_Robertson1968(uv) M_CC = interpolated_matrix(CCT, CCT_calibration_illuminant_1, CCT_calibration_illuminant_2, M_camera_calibration_1, M_camera_calibration_2) # The reference implementation :cite:`AdobeSystems2015d` diverges from # the white-paper :cite:`AdobeSystems2012f`: # The reference implementation directly computes the camera neutral by # multiplying directly the interpolated colour matrix :math:`CM` with # the tristimulus values of the *xy* white balance chromaticity # coordinates. # The current implementation is based on the white-paper so that the # interpolated camera calibration matrix :math:`CC` and the # analog balance matrix :math:`AB` are accounted for. camera_neutral = xy_to_camera_neutral( xy, CCT_calibration_illuminant_1, CCT_calibration_illuminant_2, M_color_matrix_1, M_color_matrix_2, M_camera_calibration_1, M_camera_calibration_2, analog_balance) M_AB = np.diagflat(analog_balance) M_reference_neutral = dot_vector(np.linalg.inv(dot_matrix(M_AB, M_CC)), camera_neutral) M_D = np.linalg.inv(np.diagflat(M_reference_neutral)) M_FM = interpolated_matrix(CCT, CCT_calibration_illuminant_1, CCT_calibration_illuminant_2, M_forward_matrix_1, M_forward_matrix_2) M_camera_space_to_XYZ = dot_matrix( dot_matrix(M_FM, M_D), np.linalg.inv(dot_matrix(M_AB, M_CC))) return M_camera_space_to_XYZ
def XYZ_to_RGB(XYZ, illuminant_XYZ, illuminant_RGB, XYZ_to_RGB_matrix, chromatic_adaptation_transform='CAT02', transfer_function=None): """ Converts from *CIE XYZ* colourspace to *RGB* colourspace using given *CIE XYZ* colourspace matrix, *illuminants*, *chromatic adaptation* method, *normalised primary matrix* and *transfer function*. Parameters ---------- XYZ : array_like, (3,) *CIE XYZ* colourspace matrix. illuminant_XYZ : array_like *CIE XYZ* colourspace *illuminant* *xy* chromaticity coordinates. illuminant_RGB : array_like *RGB* colourspace *illuminant* *xy* chromaticity coordinates. XYZ_to_RGB_matrix : array_like, (3, 3) *Normalised primary matrix*. chromatic_adaptation_transform : unicode, optional {'CAT02', 'XYZ Scaling', 'Von Kries', 'Bradford', 'Sharp', 'Fairchild, 'CMCCAT97', 'CMCCAT2000', 'CAT02_BRILL_CAT', 'Bianco', 'Bianco PC'}, *Chromatic adaptation* transform. transfer_function : object, optional *Transfer function*. Returns ------- ndarray, (3,) *RGB* colourspace matrix. Notes ----- - Input *CIE XYZ* colourspace matrix is in domain [0, 1]. - Input *illuminant_XYZ* *xy* chromaticity coordinates are in domain [0, 1]. - Input *illuminant_RGB* *xy* chromaticity coordinates are in domain [0, 1]. - Output *RGB* colourspace matrix is in domain [0, 1]. Examples -------- >>> XYZ = np.array([0.07049534, 0.1008, 0.09558313]) >>> illuminant_XYZ = (0.34567, 0.35850) >>> illuminant_RGB = (0.31271, 0.32902) >>> chromatic_adaptation_transform = 'Bradford' >>> XYZ_to_RGB_matrix = np.array([ ... [3.24100326, -1.53739899, -0.49861587], ... [-0.96922426, 1.87592999, 0.04155422], ... [0.05563942, -0.2040112, 1.05714897]]) >>> XYZ_to_RGB( ... XYZ, ... illuminant_XYZ, ... illuminant_RGB, ... XYZ_to_RGB_matrix, ... chromatic_adaptation_transform) # doctest: +ELLIPSIS array([ 0.0110360..., 0.1273446..., 0.1163103...]) """ XYZ = np.ravel(XYZ) cat = chromatic_adaptation_matrix_VonKries( xy_to_XYZ(illuminant_XYZ), xy_to_XYZ(illuminant_RGB), transform=chromatic_adaptation_transform) XYZ_a = np.dot(cat, XYZ) RGB = np.dot(XYZ_to_RGB_matrix.reshape((3, 3)), XYZ_a.reshape((3, 1))) RGB = np.ravel(RGB) if transfer_function is not None: RGB = np.array([transfer_function(x) for x in RGB]) return RGB