Skip to main content

Overview

ImageClip displays a static image for a specified duration. Images can be loaded from files or created from numpy arrays. The class automatically handles both RGB/RGBA and BGR/BGRA formats. Defined in: src/movielite/image/image_clip.py:6

Constructor

ImageClip(source: Union[str, np.ndarray], start: float = 0, duration: float = 5.0)
source
Union[str, np.ndarray]
required
Either a file path (string) or a numpy array (RGB/RGBA or BGR/BGRA format)
start
float
default:"0"
Start time in the composition (seconds)
duration
float
default:"5.0"
How long to display the image (seconds)

Raises

  • FileNotFoundError: If the image file doesn’t exist
  • ValueError: If numpy array has invalid shape (must be height × width × channels, with 3 or 4 channels)

Example

from movielite import ImageClip
import numpy as np

# Load from file
image = ImageClip("photo.png", start=0, duration=5)

# Create from numpy array (RGB)
array = np.random.randint(0, 255, (720, 1280, 3), dtype=np.uint8)
image = ImageClip(array, start=2, duration=3)

# Load image with alpha channel
logo = ImageClip("logo.png", duration=10)  # PNG with transparency

Class Methods

from_color

@classmethod
from_color(color: tuple, size: tuple, start: float = 0, duration: float = 5.0) -> ImageClip
Create a solid color image clip.
color
tuple
required
RGB or RGBA tuple with values 0-255, e.g., (255, 0, 0) for red
size
tuple
required
Image dimensions as (width, height) in pixels
start
float
default:"0"
Start time in seconds
duration
float
default:"5.0"
Duration in seconds
return
ImageClip
New ImageClip instance with solid color
Example:
# Solid red background
red_bg = ImageClip.from_color(
    color=(255, 0, 0),
    size=(1920, 1080),
    duration=10
)

# Semi-transparent blue overlay
blue_overlay = ImageClip.from_color(
    color=(0, 0, 255, 128),  # RGBA with 50% opacity
    size=(1280, 720),
    duration=5
)
Defined in: src/movielite/image/image_clip.py:70

Properties

Inherited Properties

ImageClip inherits properties from GraphicClip and MediaClip:
  • size (Tuple[int, int]): Image dimensions (width, height)
  • start (float): Start time in the composition
  • duration (float): How long the image is displayed
  • end (float): End time in the composition
  • position (Callable): Position function or static tuple
  • opacity (Callable): Opacity function or static value
  • scale (Callable): Scale function or static value

Methods

set_position

set_position(value: Union[Callable[[float], Tuple[int, int]], Tuple[int, int]]) -> Self
Set where the image appears on the canvas.
value
Union[Tuple[int, int], Callable]
required
Either a static tuple (x, y) or a function that takes time and returns (x, y)
return
ImageClip
Self for method chaining
Example:
# Static position (top-left corner)
image.set_position((0, 0))

# Center the image
video_width, video_height = 1920, 1080
image.set_position((
    (video_width - image.size[0]) // 2,
    (video_height - image.size[1]) // 2
))

# Animated position (slide from left)
image.set_position(lambda t: (int(t * 100), 50))

set_opacity

set_opacity(value: Union[Callable[[float], float], float]) -> Self
Set the opacity of the image.
value
Union[float, Callable]
required
Either a float (0.0-1.0) or a function that takes time and returns opacity
return
ImageClip
Self for method chaining
Example:
# Semi-transparent watermark
watermark.set_opacity(0.3)

# Fade in effect
image.set_opacity(lambda t: min(1.0, t / 2.0))

set_scale

set_scale(value: Union[Callable[[float], float], float]) -> Self
Scale the image.
value
Union[float, Callable]
required
Either a float or a function that takes time and returns scale multiplier
return
ImageClip
Self for method chaining
Example:
# Static scale (half size)
image.set_scale(0.5)

# Zoom animation
image.set_scale(lambda t: 1.0 + (t * 0.2))  # Grows 20% per second

set_size

set_size(width: Optional[int] = None, height: Optional[int] = None) -> Self
Resize the image, maintaining aspect ratio if only one dimension is provided.
width
Optional[int]
default:"None"
Target width in pixels
height
Optional[int]
default:"None"
Target height in pixels
return
ImageClip
Self for method chaining
The resize is applied lazily and permanently modifies the image in memory. At least one dimension must be provided.
Example:
# Resize to specific dimensions
image.set_size(width=1280, height=720)

# Resize maintaining aspect ratio
image.set_size(width=800)  # Height calculated automatically
image.set_size(height=600)  # Width calculated automatically

set_rotation

set_rotation(
    angle: Union[Callable[[float], float], float],
    unit: str = "deg",
    resample: str = "bilinear",
    expand: bool = True,
    center: Optional[Tuple[float, float]] = None,
    translate: Optional[Tuple[float, float]] = None,
    bg_color: Optional[Tuple[int, ...]] = None
) -> Self
Rotate the image.
angle
Union[float, Callable]
required
Rotation angle (static or animated). Positive values rotate counter-clockwise
unit
str
default:"deg"
Unit: "deg" (degrees) or "rad" (radians)
expand
bool
default:"True"
If True, expands canvas to fit rotated image without clipping
Example:
# Static rotation
image.set_rotation(45)  # 45 degrees

# Spinning animation
image.set_rotation(lambda t: t * 180)  # 180 degrees per second

set_mask

set_mask(mask: GraphicClip) -> Self
Apply a mask to control which pixels are visible.
mask
GraphicClip
required
A GraphicClip to use as mask (white = visible, black = transparent)
return
ImageClip
Self for method chaining
Example:
image = ImageClip("photo.png")
circle_mask = ImageClip("circle_mask.png")
image.set_mask(circle_mask)  # Image appears in circular shape

add_effect

add_effect(effect: GraphicEffect) -> Self
Apply a visual effect.
effect
GraphicEffect
required
A visual effect instance from movielite.vfx
return
ImageClip
Self for method chaining
Example:
from movielite import vfx

image = ImageClip("photo.png", duration=5)
image.add_effect(vfx.FadeIn(1.0))
image.add_effect(vfx.FadeOut(1.0))
image.add_effect(vfx.Blur(radius=3))

add_transform

add_transform(callback: Callable[[np.ndarray, float], np.ndarray]) -> Self
Apply a custom transformation.
callback
Callable[[np.ndarray, float], np.ndarray]
required
Function that takes (frame, time) and returns transformed frame (BGR/BGRA uint8)
return
ImageClip
Self for method chaining
Example:
import cv2

def make_grayscale(frame, t):
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    return cv2.cvtColor(gray, cv2.COLOR_GRAY2BGR)

image.add_transform(make_grayscale)

Image Format Handling

File Loading

When loading from a file path, ImageClip uses OpenCV’s cv2.imread() with IMREAD_UNCHANGED flag to preserve alpha channels.

Numpy Array Conversion

When loading from a numpy array:
  • RGB/RGBA arrays: Converted to BGR/BGRA (OpenCV format)
  • Fully opaque BGRA: Alpha channel dropped to save memory (converted to BGR)

Memory Optimization

Defined in image_clip.py:39-44:
if img.shape[2] == 4:
    alpha = img[:, :, 3]
    if (alpha == 255).all():
        # Fully opaque, drop alpha channel
        img = cv2.cvtColor(img, cv2.COLOR_BGRA2BGR)
This optimization reduces memory usage when alpha channel is not needed.

Complete Examples

Example 1: Lower Third Text Bar

from movielite import VideoClip, ImageClip, TextClip, VideoWriter, vfx
from pictex import Canvas

video = VideoClip("interview.mp4")

# Semi-transparent background bar
bar = ImageClip.from_color(
    color=(0, 0, 0, 200),  # Semi-transparent black
    size=(video.size[0], 120),
    duration=5
)
bar.set_position((0, video.size[1] - 120))
bar.add_effect(vfx.FadeIn(0.5))
bar.add_effect(vfx.FadeOut(0.5))

# Name text
canvas = Canvas().font_size(50).color("white").background_color("transparent")
name = TextClip("John Doe", duration=5, canvas=canvas)
name.set_position((40, video.size[1] - 100))
name.add_effect(vfx.FadeIn(0.5))

writer = VideoWriter("output.mp4", fps=video.fps, size=video.size)
writer.add_clips([video, bar, name])
writer.write()

Example 2: Photo Slideshow

from movielite import ImageClip, VideoWriter, vfx, vtx

# Create clips for each photo
photos = [
    ImageClip("photo1.jpg", start=0, duration=3),
    ImageClip("photo2.jpg", start=2.5, duration=3),
    ImageClip("photo3.jpg", start=5, duration=3),
]

# Resize all to same size
for photo in photos:
    photo.set_size(width=1920, height=1080)

# Add crossfade transitions
for i in range(len(photos) - 1):
    photos[i].add_transition(photos[i + 1], vtx.CrossFade(0.5))

# Add fade effects
photos[0].add_effect(vfx.FadeIn(0.5))
photos[-1].add_effect(vfx.FadeOut(0.5))

writer = VideoWriter("slideshow.mp4", fps=30, size=(1920, 1080))
writer.add_clips(photos)
writer.write()

Example 3: Animated Logo Watermark

from movielite import VideoClip, ImageClip, VideoWriter
import math

video = VideoClip("main.mp4")

# Load logo with transparency
logo = ImageClip("logo.png", duration=video.duration)
logo.set_size(width=200)

# Position in bottom-right corner with padding
logo.set_position((
    video.size[0] - logo.size[0] - 20,
    video.size[1] - logo.size[1] - 20
))

# Subtle pulsing animation
logo.set_opacity(lambda t: 0.5 + 0.1 * math.sin(t * 2))
logo.set_scale(lambda t: 1.0 + 0.05 * math.sin(t * 2))

writer = VideoWriter("output.mp4", fps=video.fps, size=video.size)
writer.add_clips([video, logo])
writer.write()

See Also

Build docs developers (and LLMs) love