def test_serialize_chromakey_effect_to_dictionary(): effect = ChromaKeyEffect( defringe=0.3, inverted=True, softness=0.2, tolerance=0.05, hue=RGBA( red=255, green=127, blue=63, alpha=31, ), ) schema = EffectSchema() actual = schema.dump(effect) pprint(actual) expected = { 'effectName': 'ChromaKey', 'category': 'categoryVisualEffects', 'parameters': { 'clrCompensation': 0.0, 'color-alpha': 0.12156862745098039, 'color-blue': 0.24705882352941178, 'color-green': 0.4980392156862745, 'color-red': 1.0, 'defringe': 0.3, 'enabled': 1, 'invertEffect': 1.0, 'softness': 0.2, 'tolerance': 0.05, } } assert actual == expected
def test_add_effect(self, project: Project, media_root: Path): media_path = media_root / 'llama.jpg' bin_media = project.media_bin.import_media(media_path) track = project.timeline.tracks.insert_track(2, 'test-track') effect = ChromaKeyEffect() media_id = track.medias.add_media(bin_media, 0).id media = track.medias[media_id] new_effect = ChromaKeyEffect(hue=RGBA(128, 0, 0, 255)) media.effects.add_effect(new_effect) assert len(media.effects) == 1 assert media.effects[0] == new_effect
def __init__(self, tolerance=None, softness=None, hue=None, defringe=None, inverted=None, compensation=None): super().__init__(name=CHROMA_KEY_NAME) if tolerance is None: tolerance = self.DEFAULT_TOLERANCE if not (self.MINIMUM_TOLERANCE <= tolerance <= self.MAXIMUM_TOLERANCE): raise ValueError( f"{self.name} tolerance out of range {self.MINIMUM_TOLERANCE} " f"to {self.MAXIMUM_TOLERANCE}" ) if softness is None: softness = self.DEFAULT_SOFTNESS if not (self.MINIMUM_SOFTNESS <= softness <= self.MAXIMUM_SOFTNESS): raise ValueError( f"{self.name} softness out of range {self.MINIMUM_SOFTNESS} " f"to {self.MAXIMUM_SOFTNESS}" ) if defringe is None: defringe = self.DEFAULT_DEFRINGE if not (self.MINIMUM_DEFRINGE <= defringe <= self.MAXIMUM_DEFRINGE): raise ValueError( f"{self.name} defringe out of range {self.MINIMUM_DEFRINGE} " f"to {self.MAXIMUM_DEFRINGE}" ) if compensation is None: compensation = self.DEFAULT_COMPENSATION if not (self.MINIMUM_COMPENSATION <= compensation <= self.MAXIMUM_COMPENSATION): raise ValueError( f"{self.name} compensation out of range {self.MINIMUM_COMPENSATION} " f"to {self.MAXIMUM_COMPENSATION}" ) if inverted is None: inverted = self.DEFAULT_INVERTED if hue is None: hue = self.DEFAULT_COLOR elif isinstance(hue, str): hue = RGBA.from_hex(hue) self._tolerance = tolerance self._softness = softness self._defringe = defringe self._inverted = inverted self._hue = hue self._compensation = compensation
def make_chroma_key_effect(self, data, **kwargs): parameters = data["parameters"] return ChromaKeyEffect( tolerance=parameters["tolerance"], softness=parameters["softness"], hue=RGBA.from_floats( red=parameters["red"], green=parameters["green"], blue=parameters["blue"], alpha=parameters["alpha"], ), defringe=parameters["defringe"], inverted=parameters["inverted"], compensation=parameters["compensation"] )
class ChromaKeyEffect(VisualEffect): DEFAULT_TOLERANCE = 0.1 MINIMUM_TOLERANCE = 0.0 MAXIMUM_TOLERANCE = 1.0 DEFAULT_SOFTNESS = 0.1 MINIMUM_SOFTNESS = 0.0 MAXIMUM_SOFTNESS = 1.0 DEFAULT_DEFRINGE = 0.0 MINIMUM_DEFRINGE = -1.0 MAXIMUM_DEFRINGE = 1.0 DEFAULT_INVERTED = False DEFAULT_COLOR = RGBA(0, 255, 0, 255) DEFAULT_COMPENSATION = 0.0 # Confusingly, this is called "hue" in the Camtasia GUI. MINIMUM_COMPENSATION = 0.0 MAXIMUM_COMPENSATION = 1.0 def __init__(self, tolerance=None, softness=None, hue=None, defringe=None, inverted=None, compensation=None): super().__init__(name=CHROMA_KEY_NAME) if tolerance is None: tolerance = self.DEFAULT_TOLERANCE if not (self.MINIMUM_TOLERANCE <= tolerance <= self.MAXIMUM_TOLERANCE): raise ValueError( f"{self.name} tolerance out of range {self.MINIMUM_TOLERANCE} " f"to {self.MAXIMUM_TOLERANCE}" ) if softness is None: softness = self.DEFAULT_SOFTNESS if not (self.MINIMUM_SOFTNESS <= softness <= self.MAXIMUM_SOFTNESS): raise ValueError( f"{self.name} softness out of range {self.MINIMUM_SOFTNESS} " f"to {self.MAXIMUM_SOFTNESS}" ) if defringe is None: defringe = self.DEFAULT_DEFRINGE if not (self.MINIMUM_DEFRINGE <= defringe <= self.MAXIMUM_DEFRINGE): raise ValueError( f"{self.name} defringe out of range {self.MINIMUM_DEFRINGE} " f"to {self.MAXIMUM_DEFRINGE}" ) if compensation is None: compensation = self.DEFAULT_COMPENSATION if not (self.MINIMUM_COMPENSATION <= compensation <= self.MAXIMUM_COMPENSATION): raise ValueError( f"{self.name} compensation out of range {self.MINIMUM_COMPENSATION} " f"to {self.MAXIMUM_COMPENSATION}" ) if inverted is None: inverted = self.DEFAULT_INVERTED if hue is None: hue = self.DEFAULT_COLOR elif isinstance(hue, str): hue = RGBA.from_hex(hue) self._tolerance = tolerance self._softness = softness self._defringe = defringe self._inverted = inverted self._hue = hue self._compensation = compensation @property def tolerance(self): return self._tolerance @property def softness(self): return self._softness @property def defringe(self): return self._defringe @property def inverted(self): return self._inverted @property def compensation(self): return self._compensation @property def hue(self): return self._hue @property def alpha(self): return self._hue.alpha / RGBA.MAXIMUM_CHANNEL @property def red(self): return self._hue.red / RGBA.MAXIMUM_CHANNEL @property def green(self): return self._hue.green / RGBA.MAXIMUM_CHANNEL @property def blue(self): return self._hue.blue / RGBA.MAXIMUM_CHANNEL @property def parameters(self): return Parameters(self) @property def metadata(self): return { f"default-{self.name}-{key}": self._metadata_value(value) for key, value in self._metadata().items() } @staticmethod def _metadata_value(value): """Render a metadata value in the way Camtasia expects """ if isinstance(value, Real): if value == 0: value = 0 return str(value).replace(" ", "") def _metadata(self): return { COLOR_KEY: self.DEFAULT_COLOR.as_tuple(), DEFRINGE_KEY: self.DEFAULT_DEFRINGE, INVERT_EFFECT_KEY: int(self.DEFAULT_INVERTED), SOFTNESS_KEY: self.DEFAULT_SOFTNESS, TOLERANCE_KEY: self.DEFAULT_TOLERANCE, COMPENSATION_KEY: self.DEFAULT_COMPENSATION, } def _key(self): return super()._key() + ( self.tolerance, self.softness, self.defringe, self.inverted, self.compensation, self.red, self.green, self.blue, self.alpha, ) def __repr__(self): return ( f"{type(self).__name__}(tolerance={self.tolerance}, softness={self.softness}, " f"hue={self.hue}, defringe={self.defringe}, inverted={self.inverted}, " f"compensation={self.compensation})" )
def test_construct_chromakey_effect_with_hex(): color = "#FF7F3F1F" expected = RGBA(255, 127, 63, 31) effect = ChromaKeyEffect(hue=color) assert effect.hue == expected
def test_construct_chromakey_effect_with_rgba(): expected = RGBA(255, 127, 63, 31) effect = ChromaKeyEffect(hue=expected) assert effect.hue == expected