Source code for colour.models.hunter_rdab

"""
Hunter Rd,a,b Colour Scale
==========================

Define the *Hunter Rd,a,b* colour scale transformations:

-   :func:`colour.XYZ_to_Hunter_Rdab`
-   :func:`colour.Hunter_Rdab_to_XYZ`

References
----------
-   :cite:`HunterLab2012a` : HunterLab. (2012). Hunter Rd,a,b Color Scale -
    History and Application.
    https://hunterlabdotcom.files.wordpress.com/2012/07/\
an-1016-hunter-rd-a-b-color-scale-update-12-07-03.pdf
"""

from __future__ import annotations

from colour.colorimetry import TVS_ILLUMINANTS_HUNTERLAB
from colour.hints import ArrayLike, NDArrayFloat
from colour.models import XYZ_to_K_ab_HunterLab1966
from colour.utilities import from_range_100, to_domain_100, tsplit, tstack

__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__ = [
    "XYZ_to_Hunter_Rdab",
    "Hunter_Rdab_to_XYZ",
]


[docs] def XYZ_to_Hunter_Rdab( XYZ: ArrayLike, XYZ_n: ArrayLike = TVS_ILLUMINANTS_HUNTERLAB["CIE 1931 2 Degree Standard Observer"][ "D65" ].XYZ_n, K_ab: ArrayLike = TVS_ILLUMINANTS_HUNTERLAB["CIE 1931 2 Degree Standard Observer"][ "D65" ].K_ab, ) -> NDArrayFloat: """ Convert from *CIE XYZ* tristimulus values to *Hunter Rd,a,b* colour scale. Parameters ---------- XYZ *CIE XYZ* tristimulus values. XYZ_n Reference *illuminant* tristimulus values. K_ab Reference *illuminant* chromaticity coefficients, if ``K_ab`` is set to *None* it will be computed using :func:`colour.XYZ_to_K_ab_HunterLab1966`. Returns ------- :class:`numpy.ndarray` *Hunter Rd,a,b* colour scale array. Notes ----- +------------+------------------------+--------------------+ | **Domain** | **Scale - Reference** | **Scale - 1** | +============+========================+====================+ | ``XYZ`` | [0, 100] | [0, 1] | +------------+------------------------+--------------------+ | ``XYZ_n`` | [0, 100] | [0, 1] | +------------+------------------------+--------------------+ +------------+------------------------+--------------------+ | **Range** | **Scale - Reference** | **Scale - 1** | +============+========================+====================+ | ``R_d_ab`` | ``R_d`` : [0, 100] | ``R_d`` : [0, 1] | | | | | | | ``a_Rd`` : [-100, 100] | ``a_Rd`` : [-1, 1] | | | | | | | ``b_Rd`` : [-100, 100] | ``b_Rd`` : [-1, 1] | +------------+------------------------+--------------------+ References ---------- :cite:`HunterLab2012a` Examples -------- >>> import numpy as np >>> XYZ = np.array([0.20654008, 0.12197225, 0.05136952]) * 100 >>> D65 = TVS_ILLUMINANTS_HUNTERLAB["CIE 1931 2 Degree Standard Observer"]["D65"] >>> XYZ_to_Hunter_Rdab(XYZ, D65.XYZ_n, D65.K_ab) ... # doctest: +ELLIPSIS array([ 12.197225 ..., 57.1253787..., 17.4624134...]) """ X, Y, Z = tsplit(to_domain_100(XYZ)) X_n, Y_n, Z_n = tsplit(to_domain_100(XYZ_n)) K_a, K_b = ( tsplit(XYZ_to_K_ab_HunterLab1966(XYZ_n)) if K_ab is None else tsplit(K_ab) ) f = 0.51 * ((21 + 0.2 * Y) / (1 + 0.2 * Y)) Y_Yn = Y / Y_n R_d = Y a_Rd = K_a * f * (X / X_n - Y_Yn) b_Rd = K_b * f * (Y_Yn - Z / Z_n) R_d_ab = tstack([R_d, a_Rd, b_Rd]) return from_range_100(R_d_ab)
[docs] def Hunter_Rdab_to_XYZ( R_d_ab: ArrayLike, XYZ_n: ArrayLike = TVS_ILLUMINANTS_HUNTERLAB["CIE 1931 2 Degree Standard Observer"][ "D65" ].XYZ_n, K_ab: ArrayLike = TVS_ILLUMINANTS_HUNTERLAB["CIE 1931 2 Degree Standard Observer"][ "D65" ].K_ab, ) -> NDArrayFloat: """ Convert from *Hunter Rd,a,b* colour scale to *CIE XYZ* tristimulus values. Parameters ---------- R_d_ab *Hunter Rd,a,b* colour scale array. XYZ_n Reference *illuminant* tristimulus values. K_ab Reference *illuminant* chromaticity coefficients, if ``K_ab`` is set to *None* it will be computed using :func:`colour.XYZ_to_K_ab_HunterLab1966`. Returns ------- :class:`numpy.ndarray` *CIE XYZ* tristimulus values. Notes ----- +------------+------------------------+--------------------+ | **Domain** | **Scale - Reference** | **Scale - 1** | +============+========================+====================+ | ``R_d_ab`` | ``R_d`` : [0, 100] | ``R_d`` : [0, 1] | | | | | | | ``a_Rd`` : [-100, 100] | ``a_Rd`` : [-1, 1] | | | | | | | ``b_Rd`` : [-100, 100] | ``b_Rd`` : [-1, 1] | +------------+------------------------+--------------------+ | ``XYZ_n`` | [0, 100] | [0, 1] | +------------+------------------------+--------------------+ +------------+------------------------+--------------------+ | **Range** | **Scale - Reference** | **Scale - 1** | +============+========================+====================+ | ``XYZ`` | [0, 100] | [0, 1] | +------------+------------------------+--------------------+ References ---------- :cite:`HunterLab2012a` Examples -------- >>> import numpy as np >>> R_d_ab = np.array([12.19722500, 57.12537874, 17.46241341]) >>> D65 = TVS_ILLUMINANTS_HUNTERLAB["CIE 1931 2 Degree Standard Observer"]["D65"] >>> Hunter_Rdab_to_XYZ(R_d_ab, D65.XYZ_n, D65.K_ab) array([ 20.654008, 12.197225, 5.136952]) """ R_d, a_Rd, b_Rd = tsplit(to_domain_100(R_d_ab)) X_n, Y_n, Z_n = tsplit(to_domain_100(XYZ_n)) K_a, K_b = ( tsplit(XYZ_to_K_ab_HunterLab1966(XYZ_n)) if K_ab is None else tsplit(K_ab) ) f = 0.51 * ((21 + 0.2 * R_d) / (1 + 0.2 * R_d)) Rd_Yn = R_d / Y_n X = (a_Rd / (K_a * f) + Rd_Yn) * X_n Z = -(b_Rd / (K_b * f) - Rd_Yn) * Z_n XYZ = tstack([X, R_d, Z]) return from_range_100(XYZ)