Color math and conversion library for comprehensive color space transformations and color difference calculations.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Color appearance models provide advanced predictions of how colors appear under different viewing conditions. These models account for factors like ambient lighting, surround conditions, and adaptation state to predict color appearance more accurately than basic colorimetric calculations.
The most widely adopted color appearance model, providing comprehensive color appearance predictions.
class CIECAM02:
"""CIE CAM02 color appearance model."""
def __init__(self, xyz_color, **viewing_conditions):
"""
Initialize CIE CAM02 model.
Parameters:
- xyz_color: XYZ color values under test illuminant
- viewing_conditions: Dictionary with keys:
- 'white_point': XYZ values of reference white
- 'L_A': Adapting luminance (cd/m²)
- 'Y_b': Background luminance factor
- 'surround': Surround condition ('average', 'dim', 'dark')
- 'discount_illuminant': Boolean for discount-the-illuminant mode
Attributes:
- J: Lightness
- C: Chroma
- h: Hue angle
- H: Hue quadrature
- M: Colorfulness
- s: Saturation
- Q: Brightness
"""
def correlates(self):
"""Get all appearance correlates as dictionary."""
def to_xyz(self):
"""Convert back to XYZ color space."""Enhanced version of CIE CAM02 with improved performance.
class CIECAM02m1:
"""Modified CIE CAM02 color appearance model."""
def __init__(self, xyz_color, **viewing_conditions):
"""
Initialize modified CIE CAM02 model.
Parameters:
- xyz_color: XYZ color values
- viewing_conditions: Same as CIECAM02 with modifications
Notes:
- Improved chromatic adaptation transform
- Better performance in extreme viewing conditions
- Enhanced numerical stability
"""Rochester Institute of Technology color appearance model.
class RLAB:
"""RLAB color appearance model."""
def __init__(self, xyz_color, **parameters):
"""
Initialize RLAB model.
Parameters:
- xyz_color: XYZ color values
- parameters: Dictionary with model parameters:
- 'reference_white': XYZ white point
- 'reference_illuminant': Reference illuminant
- 'sigma': Surround parameter
- 'D': Degree of adaptation
Attributes:
- L_R: RLAB lightness
- a_R: RLAB red-green
- b_R: RLAB yellow-blue
"""Large field color appearance model optimized for large visual fields.
class LLAB:
"""LLAB color appearance model."""
def __init__(self, xyz_color, **parameters):
"""
Initialize LLAB model.
Parameters:
- xyz_color: XYZ color values
- parameters: Dictionary with model parameters:
- 'reference_white': XYZ white point
- 'D': Degree of adaptation
- 'F_S': Surround factor
- 'F_L': Luminance factor
Attributes:
- L_L: LLAB lightness
- C_L: LLAB chroma
- h_L: LLAB hue
"""Guth ATD95 color vision model based on cone response.
class ATD95:
"""ATD95 color vision model."""
def __init__(self, xyz_color, **parameters):
"""
Initialize ATD95 model.
Parameters:
- xyz_color: XYZ color values
- parameters: Dictionary with model parameters:
- 'sigma': Noise parameter
- 'k_1': First constant
- 'k_2': Second constant
Attributes:
- A: Achromatic response
- T: Tritanopic response
- D: Deuteranopic response
"""Nayatani color appearance model with brightness prediction.
class Nayatani95:
"""Nayatani95 color appearance model."""
def __init__(self, xyz_color, **parameters):
"""
Initialize Nayatani95 model.
Parameters:
- xyz_color: XYZ color values
- parameters: Dictionary with model parameters:
- 'L_o': Luminance of reference white
- 'theta': Surround angle
- 'background': Background specification
Attributes:
- L_N: Lightness
- C_N: Chroma
- H_N: Hue
- B_r: Brightness
"""Hunt color appearance model with comprehensive appearance prediction.
class Hunt:
"""Hunt color appearance model."""
def __init__(self, xyz_color, **parameters):
"""
Initialize Hunt model.
Parameters:
- xyz_color: XYZ color values
- parameters: Dictionary with extensive model parameters:
- 'L_A': Adapting luminance
- 'N_c': Chromatic induction factor
- 'N_b': Brightness induction factor
- 'surround': Surround conditions
- Many additional parameters for comprehensive modeling
Attributes:
- J: Lightness
- C: Chroma
- h: Hue angle
- Q: Brightness
- M: Colorfulness
- s: Saturation
"""from colormath.color_objects import XYZColor
from colormath.color_appearance_models import CIECAM02
# Define viewing conditions
viewing_conditions = {
'white_point': (95.047, 100.000, 108.883), # D65 white point
'L_A': 64.0, # Adapting luminance (cd/m²)
'Y_b': 20.0, # Background luminance factor
'surround': 'average', # Surround condition
'discount_illuminant': False
}
# Create XYZ color
xyz_color = XYZColor(xyz_x=19.01, xyz_y=20.00, xyz_z=21.78)
# Apply CAM02 model
cam02 = CIECAM02(xyz_color, **viewing_conditions)
# Get appearance correlates
correlates = cam02.correlates()
print(f"Lightness (J): {correlates['J']:.2f}")
print(f"Chroma (C): {correlates['C']:.2f}")
print(f"Hue angle (h): {correlates['h']:.2f}")
print(f"Brightness (Q): {correlates['Q']:.2f}")
print(f"Colorfulness (M): {correlates['M']:.2f}")
print(f"Saturation (s): {correlates['s']:.2f}")from colormath.color_objects import XYZColor
from colormath.color_appearance_models import CIECAM02
from colormath.color_constants import ILLUMINANTS
# Sample color
xyz_color = XYZColor(xyz_x=25.0, xyz_y=20.0, xyz_z=15.0)
# Different illuminants
illuminants = {
'D65': ILLUMINANTS['2']['d65'],
'A': ILLUMINANTS['2']['a'],
'D50': ILLUMINANTS['2']['d50']
}
# Compare appearance under different illuminants
for illum_name, illum_xyz in illuminants.items():
white_point = [val * 100 for val in illum_xyz] # Scale to 100
viewing_conditions = {
'white_point': white_point,
'L_A': 64.0,
'Y_b': 20.0,
'surround': 'average',
'discount_illuminant': False
}
cam02 = CIECAM02(xyz_color, **viewing_conditions)
correlates = cam02.correlates()
print(f"\n{illum_name} Illuminant:")
print(f" Lightness: {correlates['J']:.2f}")
print(f" Chroma: {correlates['C']:.2f}")
print(f" Hue: {correlates['h']:.2f}")from colormath.color_objects import XYZColor
from colormath.color_appearance_models import CIECAM02
xyz_color = XYZColor(xyz_x=30.0, xyz_y=25.0, xyz_z=20.0)
base_conditions = {
'white_point': (95.047, 100.000, 108.883),
'L_A': 64.0,
'Y_b': 20.0,
'discount_illuminant': False
}
# Different surround conditions
surrounds = ['average', 'dim', 'dark']
for surround in surrounds:
conditions = base_conditions.copy()
conditions['surround'] = surround
cam02 = CIECAM02(xyz_color, **conditions)
correlates = cam02.correlates()
print(f"\n{surround.title()} Surround:")
print(f" Brightness (Q): {correlates['Q']:.2f}")
print(f" Colorfulness (M): {correlates['M']:.2f}")
print(f" Lightness (J): {correlates['J']:.2f}")from colormath.color_objects import XYZColor
from colormath.color_appearance_models import CIECAM02, RLAB, LLAB
xyz_color = XYZColor(xyz_x=20.0, xyz_y=18.0, xyz_z=22.0)
# CIE CAM02
cam02_conditions = {
'white_point': (95.047, 100.000, 108.883),
'L_A': 64.0,
'Y_b': 20.0,
'surround': 'average',
'discount_illuminant': False
}
cam02 = CIECAM02(xyz_color, **cam02_conditions)
cam02_correlates = cam02.correlates()
# RLAB
rlab_params = {
'reference_white': (95.047, 100.000, 108.883),
'reference_illuminant': 'd65',
'sigma': 1.0,
'D': 1.0
}
rlab = RLAB(xyz_color, **rlab_params)
# LLAB
llab_params = {
'reference_white': (95.047, 100.000, 108.883),
'D': 1.0,
'F_S': 1.0,
'F_L': 1.0
}
llab = LLAB(xyz_color, **llab_params)
print("Model Comparison:")
print(f"CAM02 Lightness: {cam02_correlates['J']:.2f}")
print(f"RLAB Lightness: {rlab.L_R:.2f}")
print(f"LLAB Lightness: {llab.L_L:.2f}")from colormath.color_objects import XYZColor
from colormath.color_appearance_models import CIECAM02
def predict_display_appearance(rgb_values, display_profile, viewing_environment):
"""
Predict color appearance on display under specific viewing conditions.
Parameters:
- rgb_values: List of RGB color tuples
- display_profile: Display characteristics
- viewing_environment: Viewing condition parameters
Returns:
List of appearance predictions
"""
results = []
for rgb in rgb_values:
# Convert RGB to XYZ (simplified - would use display profile)
xyz = XYZColor(
xyz_x=rgb[0] * 0.95047,
xyz_y=rgb[1] * 1.00000,
xyz_z=rgb[2] * 1.08883
)
# Apply appearance model
cam02 = CIECAM02(xyz, **viewing_environment)
correlates = cam02.correlates()
results.append({
'rgb': rgb,
'lightness': correlates['J'],
'chroma': correlates['C'],
'hue': correlates['h'],
'brightness': correlates['Q']
})
return results
# Example usage
rgb_colors = [(1.0, 0.0, 0.0), (0.0, 1.0, 0.0), (0.0, 0.0, 1.0)]
display_profile = {} # Would contain display characteristics
viewing_env = {
'white_point': (95.047, 100.000, 108.883),
'L_A': 200.0, # Bright office environment
'Y_b': 10.0,
'surround': 'average',
'discount_illuminant': True
}
appearance_predictions = predict_display_appearance(rgb_colors, display_profile, viewing_env)
for prediction in appearance_predictions:
print(f"RGB {prediction['rgb']}: J={prediction['lightness']:.1f}, C={prediction['chroma']:.1f}")from colormath.color_objects import XYZColor
from colormath.color_appearance_models import CIECAM02
def match_colors_across_conditions(source_xyz, source_conditions, target_conditions):
"""
Predict what color would match the source under target conditions.
Parameters:
- source_xyz: XYZ color under source conditions
- source_conditions: Source viewing conditions
- target_conditions: Target viewing conditions
Returns:
XYZ color that appears the same under target conditions
"""
# Get appearance under source conditions
source_cam02 = CIECAM02(source_xyz, **source_conditions)
source_correlates = source_cam02.correlates()
# Find XYZ that produces same appearance under target conditions
# This would require inverse CAM02 calculation (simplified here)
target_xyz = source_cam02.to_xyz() # Simplified
return target_xyz, source_correlates
# Example: Match color from office to home lighting
office_xyz = XYZColor(xyz_x=25.0, xyz_y=20.0, xyz_z=18.0)
office_conditions = {
'white_point': (95.047, 100.000, 108.883), # D65
'L_A': 200.0, # Bright office
'Y_b': 20.0,
'surround': 'average',
'discount_illuminant': False
}
home_conditions = {
'white_point': (109.85, 100.000, 35.585), # Illuminant A
'L_A': 20.0, # Dim home lighting
'Y_b': 15.0,
'surround': 'dim',
'discount_illuminant': False
}
matched_xyz, appearance = match_colors_across_conditions(
office_xyz, office_conditions, home_conditions
)
print(f"Original appearance: J={appearance['J']:.1f}, C={appearance['C']:.1f}, h={appearance['h']:.1f}")| Model | Best For | Strengths | Limitations |
|---|---|---|---|
| CIE CAM02 | General purpose, displays | Well-validated, comprehensive | Complex parameters |
| CIE CAM02m1 | Extreme conditions | Improved stability | Less widely adopted |
| RLAB | Print reproduction | Simple, fast | Limited scope |
| LLAB | Large field viewing | Large field optimization | Specialized use |
| ATD95 | Color vision research | Physiological basis | Research-oriented |
| Nayatani95 | Brightness prediction | Brightness focus | Less comprehensive |
| Hunt | Research applications | Very comprehensive | Extremely complex |
Install with Tessl CLI
npx tessl i tessl/pypi-colormath