# python>3
import unittest
from pathlib import Path
from typing import Tuple
import PyOpenColorIO as ocio
import numpy
import numpy.testing
def make_img(color: Tuple[float, float, float]):
"""Create a 64x64 RGB image with the given color."""
return numpy.full((64, 64, 3), color, dtype=numpy.float32)
class TestGradingPrimaryTransform(unittest.TestCase):
config_path = Path(
r"YOURCONFIG\config.ocio"
)
def setUp(self) -> None:
self.config: ocio.Config = ocio.Config().CreateFromFile(str(self.config_path))
self.img1 = make_img((0.5, 0.1, 0.1))
self.gp: ocio.GradingPrimary = ocio.GradingPrimary(ocio.GRADING_LIN)
return
def tearDown(self) -> None:
self.config = None
self.img1 = None
self.gp = None
return
def _apply_gp_on_img(self):
tsfm_gp = ocio.GradingPrimaryTransform(
self.gp,
ocio.GRADING_LIN,
False,
)
proc: ocio.Processor = self.config.getProcessor(tsfm_gp)
proc: ocio.CPUProcessor = proc.getDefaultCPUProcessor()
proc.applyRGB(self.img1)
return
def test_contrast_r(self):
self.gp.contrast = ocio.GradingRGBM(0.1, 1.0, 1.0, 1.0)
self._apply_gp_on_img()
expected = make_img((0.22305, 0.1, 0.1))
numpy.testing.assert_almost_equal(
self.img1,
expected,
4,
f"img1 is actually {self.img1[1][1]} while expected is {expected[1][1]}",
)
def test_contrast_r_triggered(self):
"""
Trying to see if contrast need to be manually triggered by another
parameter change.
"""
self.gp.contrast = ocio.GradingRGBM(0.1, 1.0, 1.0, 1.0)
self.gp.clampBlack = 0.15
self._apply_gp_on_img()
expected = make_img((0.22305, 0.15, 0.15))
numpy.testing.assert_almost_equal(
self.img1,
expected,
4,
f"img1 is actually {self.img1[1][1]} while expected is {expected[1][1]}",
)
def test_contrast_rg(self):
self.gp.contrast = ocio.GradingRGBM(0.1, 0.2, 1.0, 1.0)
self._apply_gp_on_img()
expected = make_img((0.22305, 0.04880, 0.1))
numpy.testing.assert_almost_equal(
self.img1,
expected,
4,
f"img1 is actually {self.img1[1][1]} while expected is {expected[1][1]}",
)
def test_contrast_rgb(self):
self.gp.contrast = ocio.GradingRGBM(0.1, 0.2, 1.2, 1.0)
self._apply_gp_on_img()
expected = make_img((0.22305, 0.04880, 0.11965))
numpy.testing.assert_almost_equal(
self.img1,
expected,
4,
f"img1 is actually {self.img1[1][1]} while expected is {expected[1][1]}",
)
def test_contrast_master(self):
self.gp.contrast = ocio.GradingRGBM(1.0, 1.0, 1.0, 0.66)
self._apply_gp_on_img()
expected = make_img((0.36858, 0.07372, 0.07372))
numpy.testing.assert_almost_equal(
self.img1,
expected,
4,
f"img1 is actually {self.img1[1][1]} while expected is {expected[1][1]}",
)
def test_exposure_rgb(self):
self.gp.exposure = ocio.GradingRGBM(0.0, 0.2, 0.6, 1.0)
self._apply_gp_on_img()
expected = make_img((0.5, 0.11487, 0.15157))
numpy.testing.assert_almost_equal(
self.img1,
expected,
4,
f"img1 is actually {self.img1[1][1]} while expected is {expected[1][1]}",
)
def test_exposure_master(self):
self.gp.exposure = ocio.GradingRGBM(0.0, 0.0, 0.0, 0.5)
self._apply_gp_on_img()
expected = make_img((0.70711, 0.14142, 0.14142))
numpy.testing.assert_almost_equal(
self.img1,
expected,
4,
f"img1 is actually {self.img1[1][1]} while expected is {expected[1][1]}",
)
if __name__ == "__main__":
unittest.main()
Hello, yes me again, I'm sorry but seems this poor GradingPrimary class didn't get as much love as it should have.
This time I'm simply modifying the
contrastattribute but I can't manage to get a result I can reproduce in Nuke, nor understand the logic behindGradingRGBM.As mentioned in issue #1640 , some attribute require a
GradingRGBMinstance and other a float. But I don't understand why do weneed to specify a red/green/blue value when the output result observed doesn't change the overall "hue" at all but just act as a regular contrast on the 3 channels.
Even when modifying the
masterand attribute and leaving ther/g/battributes at 1.0 (test_contrast_master), the result is still different than expected.As always here are the following test suite I ran, expected values are computed from Nuke using the same 0.18 pivot.
The 2 last tests are with exposure to try to get the logic, but once again r/g/b give unexpected result while this time the master value
works as expected.
unittest.py (code not relevant anymore, check next comment)
(Here only the last test
test_exposure_masterpass)I'm looking forward to seeing if this is a user error on this one or some bug.
CONTEXT: Windows10, OCIO 2.1.0
Cheers.
Liam.
Edit
Check last comment.