Source code for colour.difference.din99

"""
:math:`\\Delta E_{99}` DIN99 - Colour Difference Formula
========================================================

Define the :math:`\\Delta E_{99}` *DIN99* colour difference formula.

-   :func:`colour.difference.delta_E_DIN99`

References
----------
-   :cite:`ASTMInternational2007` : ASTM International. (2007). ASTM D2244-07 -
    Standard Practice for Calculation of Color Tolerances and Color Differences
    from Instrumentally Measured Color Coordinates: Vol. i (pp. 1-10).
    doi:10.1520/D2244-16
"""

from __future__ import annotations

import typing

if typing.TYPE_CHECKING:
    from colour.hints import Literal

from dataclasses import dataclass, field

from colour.algebra import euclidean_distance
from colour.hints import Domain100, NDArrayFloat  # noqa: TC001
from colour.models import Lab_to_DIN99
from colour.models.din99 import DIN99_METHODS
from colour.utilities import (
    MixinDataclassArithmetic,
    as_float,
    as_float_array,
    get_domain_range_scale,
    validate_method,
)

__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__ = [
    "DeltaE_Specification_DIN99",
    "delta_E_DIN99",
]


@dataclass
class DeltaE_Specification_DIN99(MixinDataclassArithmetic):
    """
    Define the *DIN99* colour difference specification.

    This data structure is returned by
    :func:`colour.difference.delta_E_DIN99` when ``additional_data=True``.

    Parameters
    ----------
    dE
        Colour difference :math:`\\Delta E_{DIN99}`.
    dL
        Raw *lightness* difference in *DIN99* colourspace.
    da
        Raw :math:`\\Delta a` difference in *DIN99* colourspace.
    db
        Raw :math:`\\Delta b` difference in *DIN99* colourspace.
    """

    dE: NDArrayFloat | None = field(default_factory=lambda: None)
    dL: NDArrayFloat | None = field(default_factory=lambda: None)
    da: NDArrayFloat | None = field(default_factory=lambda: None)
    db: NDArrayFloat | None = field(default_factory=lambda: None)


@typing.overload
def delta_E_DIN99(
    Lab_1: Domain100,
    Lab_2: Domain100,
    textiles: bool = ...,
    *,
    additional_data: Literal[False] = False,
    method: str = ...,
) -> NDArrayFloat: ...


@typing.overload
def delta_E_DIN99(
    Lab_1: Domain100,
    Lab_2: Domain100,
    textiles: bool = ...,
    *,
    additional_data: Literal[True],
    method: str = ...,
) -> DeltaE_Specification_DIN99: ...


[docs] def delta_E_DIN99( Lab_1: Domain100, Lab_2: Domain100, textiles: bool = False, additional_data: bool = False, method: ( Literal["ASTMD2244-07", "DIN99", "DIN99b", "DIN99c", "DIN99d"] | str ) = "DIN99", ) -> NDArrayFloat | DeltaE_Specification_DIN99: """ Compute the colour difference :math:`\\Delta E_{DIN99}` between two specified *CIE L\\*a\\*b\\** colourspace arrays using the *DIN99* formula. Parameters ---------- Lab_1 *CIE L\\*a\\*b\\** colourspace array 1. Lab_2 *CIE L\\*a\\*b\\** colourspace array 2. textiles Textiles application specific parametric factors, :math:`k_E=2,\\ k_{CH}=0.5` weights are used instead of :math:`k_E=1,\\ k_{CH}=1`. additional_data Whether to output additional data. method Computation method to convert from *CIE L\\*a\\*b\\** colourspace to *DIN99* colourspace. See `colour.models.din99.DIN99_METHODS` for supported values. Returns ------- :class:`numpy.ndarray` or :class:`DeltaE_Specification_DIN99` Colour difference :math:`\\Delta E_{DIN99}`. Notes ----- +------------+-----------------------+-------------------+ | **Domain** | **Scale - Reference** | **Scale - 1** | +============+=======================+===================+ | ``Lab_1`` | 100 | 1 | +------------+-----------------------+-------------------+ | ``Lab_2`` | 100 | 1 | +------------+-----------------------+-------------------+ References ---------- :cite:`ASTMInternational2007` Examples -------- >>> import numpy as np >>> Lab_1 = np.array([60.2574, -34.0099, 36.2677]) >>> Lab_2 = np.array([60.4626, -34.1751, 39.4387]) >>> delta_E_DIN99(Lab_1, Lab_2) # doctest: +ELLIPSIS np.float64(1.1772166...) >>> delta_E_DIN99( ... Lab_1, ... Lab_2, ... additional_data=True, ... ) # doctest: +ELLIPSIS DeltaE_Specification_DIN99(dE=np.float64(1.1772166...), \ dL=np.float64(-0.1750930...), da=np.float64(-0.5804045...), \ db=np.float64(-1.0091144...)) >>> delta_E_DIN99(Lab_1, Lab_2, method="DIN99b") # doctest: +ELLIPSIS np.float64(1.7113129...) """ method = validate_method(method, tuple(DIN99_METHODS)) k_E = 2 if textiles else 1 k_CH = 0.5 if textiles else 1 factor = 100 if get_domain_range_scale() == "1" else 1 Lab_99_1 = Lab_to_DIN99(Lab_1, k_E, k_CH, method) * factor Lab_99_2 = Lab_to_DIN99(Lab_2, k_E, k_CH, method) * factor dE = euclidean_distance(Lab_99_1, Lab_99_2) if not additional_data: return dE dLab = as_float_array(Lab_99_1) - as_float_array(Lab_99_2) return DeltaE_Specification_DIN99( dE, as_float(dLab[..., 0]), as_float(dLab[..., 1]), as_float(dLab[..., 2]), )