Skip to content

Commit

Permalink
Add rgb_colorspace equivalence and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
tjdcs committed Jul 5, 2024
1 parent 4fe8f4c commit f7204c7
Show file tree
Hide file tree
Showing 4 changed files with 162 additions and 0 deletions.
58 changes: 58 additions & 0 deletions colour/models/rgb/rgb_colourspace.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
from __future__ import annotations

from copy import deepcopy
from functools import partial

import numpy as np

Expand Down Expand Up @@ -277,6 +278,63 @@ def __init__(
self._use_derived_matrix_XYZ_to_RGB: bool = False
self.use_derived_matrix_XYZ_to_RGB = use_derived_matrix_XYZ_to_RGB

def __eq__(self, other: object) -> bool:
"""Return weather or not two RGB spaces are equivalent and would produce
the same results with XYZ_to_RGB and visa-versa. Can detect and compare
instances of `partial` for the cctf properties.
Parameters
----------
other : object
Returns
-------
bool
"""
if not isinstance(other, RGB_Colourspace):
return False

cctf_decoding_eq: bool
if isinstance(self.cctf_decoding, partial) and isinstance(
other.cctf_decoding, partial
):
cctf_decoding_eq = np.all(
(
self.cctf_decoding.func == other.cctf_decoding.func,
np.all(self.cctf_decoding.args == other.cctf_decoding.args),
np.all(self.cctf_decoding.keywords == other.cctf_decoding.keywords),
)
)
else:
cctf_decoding_eq = self.cctf_decoding == other.cctf_decoding

cctf_encoding_eq: bool
if isinstance(self.cctf_encoding, partial) and isinstance(
other.cctf_encoding, partial
):
cctf_encoding_eq = np.all(
(
self.cctf_encoding.func == other.cctf_encoding.func,
np.all(self.cctf_encoding.args == other.cctf_encoding.args),
np.all(self.cctf_encoding.keywords == other.cctf_encoding.keywords),
)
)
else:
cctf_encoding_eq = self.cctf_encoding == other.cctf_encoding

return np.all(
(
self.name == other.name,
np.all(self.primaries == other.primaries),
np.all(self.whitepoint == self.whitepoint),
self.whitepoint_name == self.whitepoint_name,
np.all(self.matrix_RGB_to_XYZ == other.matrix_RGB_to_XYZ),
np.all(self.matrix_XYZ_to_RGB == other.matrix_XYZ_to_RGB),
cctf_decoding_eq,
cctf_encoding_eq,
)
)

@property
def name(self) -> str:
"""
Expand Down
74 changes: 74 additions & 0 deletions colour/models/rgb/tests/test_rgb_colourspace.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import re
import textwrap
from functools import partial
from itertools import product

import numpy as np
Expand All @@ -24,6 +25,7 @@
matrix_RGB_to_RGB,
normalised_primary_matrix,
)
from colour.models.rgb.transfer_functions.gamma import gamma_function
from colour.utilities import domain_range_scale, ignore_numpy_errors

__author__ = "Colour Developers"
Expand Down Expand Up @@ -66,6 +68,77 @@ def setup_method(self):
linear_function,
)

class TestRGBSpace__eq__:
def setup_method(self):
pass
# Some pytest possible issue requires this since the encapsulating
# class has a setup_method.

@staticmethod
def get_two_rgb_spaces():
p = np.array([0.73470, 0.26530, 0.00000, 1.00000, 0.00010, -0.07700])
whitepoint = np.array([0.32168, 0.33767])
matrix_RGB_to_XYZ = np.identity(3)
matrix_XYZ_to_RGB = np.identity(3)

s1 = RGB_Colourspace(
"RGB Colourspace",
p,
whitepoint,
"ACES",
matrix_RGB_to_XYZ,
matrix_XYZ_to_RGB,
linear_function,
linear_function,
)

s2 = RGB_Colourspace(
"RGB Colourspace",
p,
whitepoint,
"ACES",
matrix_RGB_to_XYZ,
matrix_XYZ_to_RGB,
linear_function,
linear_function,
)

return s1, s2

def test_simple_eq(self):
s1, s2 = self.get_two_rgb_spaces()

assert s1 is not s2
assert s1 == s2

# Even if one space uses derived, if they return the same matrix
# they are equivalent
s2.use_derived_matrix_RGB_to_XYZ = True
s1.matrix_RGB_to_XYZ = s2.matrix_RGB_to_XYZ
s1.matrix_XYZ_to_RGB = s2.matrix_XYZ_to_RGB

assert s1 == s2

def test_partial_cctf(self):
s1, s2 = self.get_two_rgb_spaces()

s1.cctf_decoding = partial(gamma_function, exponent=2)
s1.cctf_encoding = partial(gamma_function, exponent=1 / 2)
assert s1 != s2

s2.cctf_encoding = partial(gamma_function, exponent=1 / 2)
assert s1 != s2

s2.cctf_decoding = partial(gamma_function, exponent=1.5)
assert s1 != s2

s2.cctf_decoding = partial(gamma_function, 2)
# Should be equal, but because one partial uses kwargs it is an error
assert s1 != s2

s2.cctf_decoding = partial(gamma_function, exponent=2)
assert s1 == s2

def test_required_attributes(self):
"""Test the presence of required attributes."""

Expand All @@ -92,6 +165,7 @@ def test_required_methods(self):
"__init__",
"__str__",
"__repr__",
"__eq__",
"use_derived_transformation_matrices",
"chromatically_adapt",
"copy",
Expand Down
20 changes: 20 additions & 0 deletions colour/models/rgb/transfer_functions/gamma.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,26 @@ def __call__(self, a: ArrayLike):
negative_number_handling=self.negative_number_handling,
)

def __eq__(self, other: object) -> bool:
"""Return if two gamma functions have the same parameters and therefore
produce the same results
Parameters
----------
other : object
Returns
-------
bool
"""
if not isinstance(other, GammaFunction):
return False

return (
self.exponent == other.exponent
and self.negative_number_handling == other.negative_number_handling
)


def gamma_function(
a: ArrayLike,
Expand Down
10 changes: 10 additions & 0 deletions colour/models/rgb/transfer_functions/tests/test_gamma.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,16 @@ def test_n_dimensional_gamma_function(self):
GammaFunction(2.2, "Clamp")(a), a_p, atol=TOLERANCE_ABSOLUTE_TESTS
)

def test__eq__(self):
g1 = GammaFunction(exponent=3, negative_number_handling="Clip")
g2 = GammaFunction(exponent=3, negative_number_handling="Clip")
g3 = GammaFunction(exponent=4, negative_number_handling="Clip")
g4 = GammaFunction(exponent=3, negative_number_handling="Mirror")

assert g1 == g2
assert g1 != g3
assert g1 != g4

@ignore_numpy_errors
def test_nan_gamma_function(self):
"""
Expand Down

0 comments on commit f7204c7

Please sign in to comment.