Effects
Effects can be applied to layers by decorating layer methods within sequence classes. Layers can be combined with an arbitrary number of effects. From a functional point of view, effects post-process images generated by layer tasks. There is a set of readily available effects in bewegung
. However, new custom effects can be easily added as well.
Available Effects
- class bewegung.FadeInEffect(blend_time)
Fade-in effect. Decorator for layers.
- Parameters
blend_time (
TimeABC
) – Duration of effect relative to the beginning of the parent sequence
- class bewegung.FadeOutEffect(blend_time)
Fade-out effect. Decorator for layers.
- Parameters
blend_time (
TimeABC
) – Duration of effect relative to the beginning of the parent sequence
Defining Custom Effects
Custom effects are implemented by deriving from bewegung.EffectBase
. Once derived, they can be directly applied to layers.
The EffectBase
Class
- class bewegung.EffectBase
Base for all effect classes - not an effect on its own. Derive new effect classes from this class. Decorator for layers.
Mutable.
If the orginal cunstructor method is overridden, it must be called from the child class.
- __call__(layer)
Decorator function, decorating
bewegung.core.layer.Layer
objects (wrapping user-defined layer methods). The effect is registered viabewegung.core.layer.Layer.register_effect()
and returns the otherwise unchanged layer object.Do not override!
- Parameters
layer (
LayerABC
) – Layer to which the effect is applied.- Return type
LayerABC
- apply(cvs)
Applies effect to image.
Must be reimplemented!
- Parameters
cvs (
Image
) – Input Pillow Image object
- apply_(cvs, video, sequence, time)
Internal interface for layer objects. Applies the effect to a Pillow Image object and returns the modified image. The function automatically determines what arguments the
apply
method of an actual effect requests other thancvs
. Possible options are:video: Parent video object
sequence: Parent sequence object
time: Time within parent video
reltime: Relative time within parent sequence
Do not override!
- Parameters
cvs (
Image
) – Input Pillow Image objectvideo (
VideoABC
) – Parent video objectsequence (
SequenceABC
) – Parent sequence objecttime (
TimeABC
) – Time within parent video
- Return type
Image
Note
Similar to prepare task methods and layer task methods, the apply
method in classes derived from bewegung.EffectBase
can request parameters on demand. See bewegung.EffectBase.apply_()
for details.
A Minimal Effect based on ImageFilter
The following example illustrates how to build a custom effect around a filter function from the ImageFilter
module (part of pillow
).
from PIL import Image, ImageFilter
from bewegung import Video, Vector2D, Color, EffectBase
class BlurEffect(EffectBase): # derive from EffectBase
def __init__(self, radius: float):
if radius < 0:
raise ValueError('radius must be positive or zero')
super().__init__()
self._filter = ImageFilter.GaussianBlur(radius) # setup filter
def apply(self, cvs: Image.Image) -> Image.Image: # request nothing but the image
return cvs.filter(self._filter) # apply filter to image and return
v = Video(width = 480, height = 270, seconds = 1.0)
@v.sequence()
class Foo:
@v.layer()
def lineA(self, canvas): # layer without effect
canvas.draw_polygon(
Vector2D(5, 5), Vector2D(v.width - 5, v.height - 5),
line_width = 3,
line_color = Color(255, 0, 0, 255),
)
return canvas
@BlurEffect(radius = 2.0) # decorate layer with filter
@v.layer()
def lineB(self, canvas): # layer with effect
canvas.draw_polygon(
Vector2D(v.width - 5, 5), Vector2D(5, v.height - 5),
line_width = 3,
line_color = Color(255, 0, 0, 255),
)
return canvas
v.reset()
v.render_frame(v.time(0))
The bewegung.EffectBase.apply()
method is basically the only method that must be re-implemented by a custom effect. However, the constructor of this class can optionally be re-implemented if required to add parameters to an effect decorator object. In the latter case, one must not forget to call the constructor of the original underlying class (super().__init__()
).