def test_constructor_with_keywords(self): """ Test ExposureContrastTransform constructor with keywords and validate its values. """ exp_tr = OCIO.ExposureContrastTransform( style=self.TEST_STYLE, exposure=self.TEST_EXPOSURE, contrast=self.TEST_CONTRAST, gamma=self.TEST_GAMMA, pivot=self.TEST_PIVOT, logExposureStep=self.TEST_LOGEXPOSURESTEP, logMidGray=self.TEST_LOGMIDGRAY, dynamicExposure=True, dynamicContrast=True, dynamicGamma=True, direction=self.TEST_DIRECTION) self.assertEqual(exp_tr.getStyle(), self.TEST_STYLE) self.assertEqual(exp_tr.getExposure(), self.TEST_EXPOSURE) self.assertEqual(exp_tr.getContrast(), self.TEST_CONTRAST) self.assertEqual(exp_tr.getGamma(), self.TEST_GAMMA) self.assertEqual(exp_tr.getPivot(), self.TEST_PIVOT) self.assertEqual(exp_tr.getLogExposureStep(), self.TEST_LOGEXPOSURESTEP) self.assertEqual(exp_tr.getLogMidGray(), self.TEST_LOGMIDGRAY) self.assertTrue(exp_tr.isExposureDynamic()) self.assertTrue(exp_tr.isContrastDynamic()) self.assertTrue(exp_tr.isGammaDynamic()) self.assertEqual(exp_tr.getDirection(), self.TEST_DIRECTION) # With keywords not in their proper order. exp_tr2 = OCIO.ExposureContrastTransform( direction=self.TEST_DIRECTION, dynamicGamma=True, dynamicContrast=True, dynamicExposure=True, logMidGray=self.TEST_LOGMIDGRAY, style=self.TEST_STYLE, exposure=self.TEST_EXPOSURE, contrast=self.TEST_CONTRAST, gamma=self.TEST_GAMMA, pivot=self.TEST_PIVOT, logExposureStep=self.TEST_LOGEXPOSURESTEP) self.assertEqual(exp_tr2.getStyle(), self.TEST_STYLE) self.assertEqual(exp_tr2.getExposure(), self.TEST_EXPOSURE) self.assertEqual(exp_tr2.getContrast(), self.TEST_CONTRAST) self.assertEqual(exp_tr2.getGamma(), self.TEST_GAMMA) self.assertEqual(exp_tr2.getPivot(), self.TEST_PIVOT) self.assertEqual(exp_tr2.getLogExposureStep(), self.TEST_LOGEXPOSURESTEP) self.assertEqual(exp_tr2.getLogMidGray(), self.TEST_LOGMIDGRAY) self.assertTrue(exp_tr2.isExposureDynamic()) self.assertTrue(exp_tr2.isContrastDynamic()) self.assertTrue(exp_tr2.isGammaDynamic()) self.assertEqual(exp_tr2.getDirection(), self.TEST_DIRECTION)
def test_uniform(self): # Test dynamic exposure and gamma config = OCIO.Config() tr = OCIO.ExposureContrastTransform(dynamicExposure=True, dynamicGamma=True) proc = config.getProcessor(tr) desc = OCIO.GpuShaderDesc.CreateShaderDesc() gpu_proc = proc.getDefaultGPUProcessor() gpu_proc.extractGpuShaderInfo(desc) uniforms = desc.getUniforms() self.assertEqual(len(uniforms), 2) self.assertEqual(uniforms[0][0], "ocio_exposure_contrast_exposureVal") self.assertEqual(uniforms[0][1].type, OCIO.UNIFORM_DOUBLE) self.assertEqual(uniforms[0][1].getDouble(), 0.0) self.assertEqual(uniforms[1][0], "ocio_exposure_contrast_gammaVal") self.assertEqual(uniforms[1][1].type, OCIO.UNIFORM_DOUBLE) self.assertEqual(uniforms[1][1].getDouble(), 1.0) # Can dynamically modify uniforms dyn_exposure = desc.getDynamicProperty(OCIO.DYNAMIC_PROPERTY_EXPOSURE) dyn_exposure.setDouble(2.0) self.assertEqual(uniforms[0][1].getDouble(), 2.0) dyn_gamma = desc.getDynamicProperty(OCIO.DYNAMIC_PROPERTY_GAMMA) dyn_gamma.setDouble(0.5) self.assertEqual(uniforms[1][1].getDouble(), 0.5) # Uniforms are present in shader src text = desc.getShaderText() self.assertEqual(text.count("uniform float"), 2) # Iterates uniform name and data for name, uniform_data in uniforms: self.assertIsInstance(name, STRING_TYPES) self.assertIsInstance(uniform_data, OCIO.GpuShaderDesc.UniformData)
def test_create_group_transform(self): # Test createGroupTransform() function. cfg = OCIO.Config().CreateRaw() group = OCIO.GroupTransform() m = OCIO.MatrixTransform(offset=[1., 1., 1., 0.]) group.appendTransform(m) p = cfg.getProcessor(group) procGroup = p.createGroupTransform() self.assertEqual(len(procGroup), 1) iterProcGroup = iter(procGroup) t1 = next(iterProcGroup) self.assertEqual(t1.getTransformType(), OCIO.TRANSFORM_TYPE_MATRIX) ec = OCIO.ExposureContrastTransform(exposure=1.1, contrast=1.2) group.appendTransform(ec) p = cfg.getProcessor(group) procGroup = p.createGroupTransform() self.assertEqual(len(procGroup), 2) iterProcGroup = iter(procGroup) t1 = next(iterProcGroup) self.assertEqual(t1.getTransformType(), OCIO.TRANSFORM_TYPE_MATRIX) t2 = next(iterProcGroup) self.assertEqual(t2.getTransformType(), OCIO.TRANSFORM_TYPE_EXPOSURE_CONTRAST)
def test_constructor_with_positional(self): """ Test ExposureContrastTransform constructor without keywords and validate its values. """ exp_tr = OCIO.ExposureContrastTransform( self.TEST_STYLE, self.TEST_EXPOSURE, self.TEST_CONTRAST, self.TEST_GAMMA, self.TEST_PIVOT, self.TEST_LOGEXPOSURESTEP, self.TEST_LOGMIDGRAY, True, True, True, self.TEST_DIRECTION) self.assertEqual(exp_tr.getStyle(), self.TEST_STYLE) self.assertEqual(exp_tr.getExposure(), self.TEST_EXPOSURE) self.assertEqual(exp_tr.getContrast(), self.TEST_CONTRAST) self.assertEqual(exp_tr.getGamma(), self.TEST_GAMMA) self.assertEqual(exp_tr.getPivot(), self.TEST_PIVOT) self.assertEqual(exp_tr.getLogExposureStep(), self.TEST_LOGEXPOSURESTEP) self.assertEqual(exp_tr.getLogMidGray(), self.TEST_LOGMIDGRAY) self.assertTrue(exp_tr.isExposureDynamic()) self.assertTrue(exp_tr.isContrastDynamic()) self.assertTrue(exp_tr.isGammaDynamic()) self.assertEqual(exp_tr.getDirection(), self.TEST_DIRECTION)
def test_cache_id(self): # Test getCacheID() function. cfg = OCIO.Config().CreateRaw() ec = OCIO.ExposureContrastTransform() # Make the transform dynamic. ec.makeContrastDynamic() p = cfg.getProcessor(ec) self.assertEqual(p.getCacheID(), '$3686dc0e9e639d52b07172b7b0a5c61b')
def test_cache_id(self): # Test getCacheID() function. cfg = OCIO.Config().CreateRaw() ec = OCIO.ExposureContrastTransform() # Make the transform dynamic. ec.makeContrastDynamic() p = cfg.getProcessor(ec) self.assertEqual(p.getCacheID(), '$4c4a89725a9a2164f1f8afe60c8967a0')
def test_is_noop(self): # Test isNoOp() function. cfg = OCIO.Config().CreateRaw() ec = OCIO.ExposureContrastTransform() p = cfg.getProcessor(ec) self.assertTrue(p.isNoOp()) # Make the transform dynamic. ec.makeContrastDynamic() p = cfg.getProcessor(ec) self.assertFalse(p.isNoOp())
def test_dynamic_property(self): tr = OCIO.ExposureContrastTransform( style=OCIO.EXPOSURE_CONTRAST_LINEAR, dynamicExposure=True) proc = self.config.getProcessor(tr) cpu_proc = proc.getDefaultCPUProcessor() # Validate default +0 stops exposure self.assertEqual(cpu_proc.applyRGB([1.0, 1.0, 1.0]), [1.0, 1.0, 1.0]) # Change dynamic exposure to +1 stops and validate dyn_prop = cpu_proc.getDynamicProperty(OCIO.DYNAMIC_PROPERTY_EXPOSURE) dyn_prop.setDouble(1.0) self.assertEqual(cpu_proc.applyRGB([1.0, 1.0, 1.0]), [2.0, 2.0, 2.0])
def ocio_viewer( RGB=None, source=None, display=None, view=None, exposure=0.0, contrast=1.0, gamma=1.0, style=ocio.EXPOSURE_CONTRAST_LINEAR, use_gpu=False, config=None, context=None, ): cfg = config or create_new_config() context = context or cfg.getCurrentContext() exposure_contrast_transform = ocio.ExposureContrastTransform( exposure=exposure, gamma=gamma, contrast=contrast, style=style ) processor = cfg.getProcessor( context=context, direction=ocio.TRANSFORM_DIR_FORWARD, transform=ocio.GroupTransform( [ exposure_contrast_transform, ocio.DisplayViewTransform( src=source or "scene_linear", display=display or cfg.getDefaultDisplay(), view=view or cfg.getDefaultView(), ), ] ), ) if RGB is None: return processor else: RGB_out = np.copy(RGB) RGB_out = apply_ocio_processor(processor, RGB_out, use_gpu=use_gpu) return RGB_out
def test_dynamic_properties(self): # Test dynamic property related functions. cfg = OCIO.Config().CreateRaw() ec = OCIO.ExposureContrastTransform() ec.setContrast(1.1) ec.setExposure(1.2) p = cfg.getProcessor(ec) # Processor created from non-dynamic transform is not dynamic. self.assertFalse(p.isDynamic()) # Make the transform dynamic. ec.makeContrastDynamic() p = cfg.getProcessor(ec) # Processor is dynamic. self.assertTrue(p.isDynamic()) # Contrast is dynamic. self.assertTrue(p.hasDynamicProperty(OCIO.DYNAMIC_PROPERTY_CONTRAST)) # Exposure is not dynamic. self.assertFalse(p.hasDynamicProperty(OCIO.DYNAMIC_PROPERTY_EXPOSURE)) # Only dynamic Dynamic Properties (i.e. isDynamic returns true) may be modified after the # processor is created. As Dynamic Properties are decoupled between instances and # processor types, the value change only affects this instance so a corresponding CPU # processing instance will not have the new value. dpc = p.getDynamicProperty(OCIO.DYNAMIC_PROPERTY_CONTRAST) # Accessing a Dynamic Property that does not exist triggers an exception. with self.assertRaises(OCIO.Exception): p.getDynamicProperty(OCIO.DYNAMIC_PROPERTY_EXPOSURE) self.assertEqual(dpc.getType(), OCIO.DYNAMIC_PROPERTY_CONTRAST) # Initial contrast value. self.assertEqual(dpc.getDouble(), 1.1) dpc.setDouble(1.15) self.assertEqual(dpc.getDouble(), 1.15) # Value can be accessed only using the appropriate accessor. DYNAMIC_PROPERTY_CONTRAST is # a double, so get/setDouble should be used. Trying to get a different type throws an # error. with self.assertRaises(OCIO.Exception): dpc.getGradingPrimary()
def setUp(self): self.exp_tr = OCIO.ExposureContrastTransform()
def update_ocio_proc(self, input_cs=None, display=None, view=None, channel=None): """ Update one or more aspects of the OCIO GPU renderer. Parameters are cached so not providing a parameter maintains the existing state. This will trigger a GL update IF the underlying OCIO ops in the processor have changed. :param str input_cs: Override the input color space name (how the image texture should be interpreted by OCIO). If this is wrong, the rendered results will look wrong in most cases. :param str display: OCIO display representing the current display device colors are being viewed on. :param str view: OCIO view defining the output transform for the given display. :param int channel: ImagePlaneChannels value to toggle channel isolation. """ if input_cs: self._ocio_input_cs = input_cs if display: self._ocio_display = display if view: self._ocio_view = view if channel is not None: self._update_ocio_channel_hot(channel) # Can a processor be made? if not all((self._ocio_input_cs, self._ocio_display, self._ocio_view)): return config = ocio.GetCurrentConfig() # Build transforms needed for viewing pipeline exposure_tr = ocio.ExposureContrastTransform( exposure=self._ocio_exposure, dynamicExposure=True) channel_view_tr = ocio.MatrixTransform.View( channelHot=self._ocio_channel_hot, lumaCoef=config.getDefaultLumaCoefs()) display_view_tr = ocio.DisplayViewTransform(src=self._ocio_input_cs, display=self._ocio_display, view=self._ocio_view) gamma_tr = ocio.ExposureContrastTransform(gamma=self._ocio_gamma, pivot=1.0, dynamicGamma=True) # Mimic OCIO v1 DisplayTransform for consistency with DCCs viewing_pipeline = ocio.LegacyViewingPipeline() viewing_pipeline.setLinearCC(exposure_tr) viewing_pipeline.setChannelView(channel_view_tr) viewing_pipeline.setDisplayViewTransform(display_view_tr) viewing_pipeline.setDisplayCC(gamma_tr) # Create processor proc = viewing_pipeline.getProcessor(config) if proc.getCacheID() != self._ocio_proc_cache_id: self._ocio_shader_desc = ocio.GpuShaderDesc.CreateShaderDesc( language=ocio.GPU_LANGUAGE_GLSL_4_0) self._ocio_proc_cache_id = proc.getCacheID() ocio_gpu_proc = proc.getDefaultGPUProcessor() ocio_gpu_proc.extractGpuShaderInfo(self._ocio_shader_desc) self._allocate_ocio_tex() self._build_program() # Set initial dynamic property state self._update_ocio_dyn_prop(ocio.DYNAMIC_PROPERTY_EXPOSURE, self._ocio_exposure) self._update_ocio_dyn_prop(ocio.DYNAMIC_PROPERTY_GAMMA, self._ocio_gamma) self.update()