| Title: | Build Stop Motion Animations from Image Sequences |
|---|---|
| Description: | A pipeline-friendly toolkit for assembling stop motion animations from sequences of still images. Provides functions to read image directories, restructure frame sequences (duplicate, splice, arrange), apply per-frame pixel transformations (rotate, wiggle, flip, flop, blur, scale, crop, trim, border, background), and export the result as a GIF. All transformation functions accept a 'frames' argument to target any subset of frames, bridging the gap between 'magick' functions that operate on an entire image stack and fine-grained stop motion editing. |
| Authors: | Alban Sagouis [aut, cre, cph] (ORCID: <https://orcid.org/0000-0002-3827-1063>) |
| Maintainer: | Alban Sagouis <[email protected]> |
| License: | MIT + file LICENSE |
| Version: | 0.1.0 |
| Built: | 2026-05-25 10:30:36 UTC |
| Source: | https://github.com/albansagouis/stopmotion |
Returns a new magick-image object with frames placed in the order
given by order. Use this after read when the
lexicographic filename sort does not match the intended frame sequence.
arrange(images, order)arrange(images, order)
images |
an object of class |
order |
integer vector of frame indices giving the desired order.
Must be a permutation of |
a magick-image object with frames in the requested order.
After each operation a message listing the updated frame sequence is
printed in interactive sessions. Use
stopmotion_verbosity(FALSE) to suppress these messages, or set
options(stopmotion.verbose = FALSE) in your script or
‘.Rprofile’.
## Not run: images <- read(dir = "../frames/") # Swap the first and second frame. images <- arrange(images, order = c(2L, 1L, 3L)) ## End(Not run)## Not run: images <- read(dir = "../frames/") # Swap the first and second frame. images <- arrange(images, order = c(2L, 1L, 3L)) ## End(Not run)
Set the background colour of images
background(images, color = "white", frames = NULL)background(images, color = "white", frames = NULL)
images |
an object of class |
color |
a character string specifying a colour,
e.g. |
frames |
integer vector of frame indices to duplicate. Defaults to
|
a magick-image object
After each operation a message listing the updated frame sequence is
printed in interactive sessions. Use
stopmotion_verbosity(FALSE) to suppress these messages, or set
options(stopmotion.verbose = FALSE) in your script or
‘.Rprofile’.
## Not run: dino_dir <- system.file("extdata", package = "stopmotion") images <- read(dir = dino_dir) background(images = images, color = "white") background(images = images, color = "white", frames = 1) ## End(Not run)## Not run: dino_dir <- system.file("extdata", package = "stopmotion") images <- read(dir = dino_dir) background(images = images, color = "white") background(images = images, color = "white", frames = 1) ## End(Not run)
Applies a Gaussian blur to selected frames. Wraps magick::image_blur.
blur(images, radius = 1, sigma = 0.5, frames = NULL)blur(images, radius = 1, sigma = 0.5, frames = NULL)
images |
an object of class |
radius |
a non-negative number specifying the blur radius in pixels. |
sigma |
a non-negative number specifying the standard deviation of the
Gaussian, controlling blur strength. Use |
frames |
integer vector of frame indices to duplicate. Defaults to
|
a magick-image object
After each operation a message listing the updated frame sequence is
printed in interactive sessions. Use
stopmotion_verbosity(FALSE) to suppress these messages, or set
options(stopmotion.verbose = FALSE) in your script or
‘.Rprofile’.
## Not run: dino_dir <- system.file("extdata", package = "stopmotion") images <- read(dir = dino_dir) blur(images = images, radius = 2, sigma = 1) blur(images = images, radius = 2, sigma = 1, frames = 1:3) ## End(Not run)## Not run: dino_dir <- system.file("extdata", package = "stopmotion") images <- read(dir = dino_dir) blur(images = images, radius = 2, sigma = 1) blur(images = images, radius = 2, sigma = 1, frames = 1:3) ## End(Not run)
Adds a coloured border around selected frames. Wraps
magick::image_border.
border(images, color = "lightgray", geometry = "10x10", frames = NULL)border(images, color = "lightgray", geometry = "10x10", frames = NULL)
images |
an object of class |
color |
a character string specifying the border colour,
e.g. |
geometry |
a geometry string specifying border width and height,
e.g. |
frames |
integer vector of frame indices to duplicate. Defaults to
|
a magick-image object
After each operation a message listing the updated frame sequence is
printed in interactive sessions. Use
stopmotion_verbosity(FALSE) to suppress these messages, or set
options(stopmotion.verbose = FALSE) in your script or
‘.Rprofile’.
## Not run: dino_dir <- system.file("extdata", package = "stopmotion") images <- read(dir = dino_dir) border(images = images, color = "black", geometry = "5x5") border(images = images, color = "white", geometry = "10x10", frames = 1:3) ## End(Not run)## Not run: dino_dir <- system.file("extdata", package = "stopmotion") images <- read(dir = dino_dir) border(images = images, color = "black", geometry = "5x5") border(images = images, color = "white", geometry = "10x10", frames = 1:3) ## End(Not run)
Transforms selected frames so that two user-supplied reference points (e.g.
left and right eye positions) map onto the same pixel locations across all
frames. The transformation is a full affine warp — rotation, scaling, and
translation are applied simultaneously — computed from the two point
correspondences via magick::image_distort.
centre(images, points, reference = 1L, frames = NULL) center(images, points, reference = 1L, frames = NULL)centre(images, points, reference = 1L, frames = NULL) center(images, points, reference = 1L, frames = NULL)
images |
an object of class |
points |
a |
reference |
integer. The frame whose reference points define the target
alignment. All other selected frames are warped to match it. The reference
frame itself is left unchanged. Defaults to |
frames |
integer vector of frame indices to duplicate. Defaults to
|
a magick-image object of the same length as images.
After each operation a message listing the updated frame sequence is
printed in interactive sessions. Use
stopmotion_verbosity(FALSE) to suppress these messages, or set
options(stopmotion.verbose = FALSE) in your script or
‘.Rprofile’.
## Not run: dino_dir <- system.file("extdata", package = "stopmotion") images <- read(dir = dino_dir) # Manually record eye positions for each frame (e.g. using locator()) points <- data.frame( frame = c(1L, 1L, 2L, 2L, 3L, 3L), x = c(210, 390, 215, 388, 208, 392), y = c(180, 182, 176, 179, 183, 181) ) centre(images = images, points = points, reference = 1L) ## End(Not run)## Not run: dino_dir <- system.file("extdata", package = "stopmotion") images <- read(dir = dino_dir) # Manually record eye positions for each frame (e.g. using locator()) points <- data.frame( frame = c(1L, 1L, 2L, 2L, 3L, 3L), x = c(210, 390, 215, 388, 208, 392), y = c(180, 182, 176, 179, 183, 181) ) centre(images = images, points = points, reference = 1L) ## End(Not run)
Crops selected frames to a given geometry. Wraps magick::image_crop.
crop(images, geometry, gravity = NULL, repage = TRUE, frames = NULL)crop(images, geometry, gravity = NULL, repage = TRUE, frames = NULL)
images |
an object of class |
geometry |
a geometry string specifying the cropped region,
e.g. |
gravity |
anchor point for the crop: one of |
repage |
logical. If |
frames |
integer vector of frame indices to duplicate. Defaults to
|
a magick-image object
After each operation a message listing the updated frame sequence is
printed in interactive sessions. Use
stopmotion_verbosity(FALSE) to suppress these messages, or set
options(stopmotion.verbose = FALSE) in your script or
‘.Rprofile’.
## Not run: dino_dir <- system.file("extdata", package = "stopmotion") images <- read(dir = dino_dir) crop(images = images, geometry = "200x200+50+50") crop(images = images, geometry = "200x200", gravity = "Center", frames = 1:3) ## End(Not run)## Not run: dino_dir <- system.file("extdata", package = "stopmotion") images <- read(dir = dino_dir) crop(images = images, geometry = "200x200+50+50") crop(images = images, geometry = "200x200", gravity = "Center", frames = 1:3) ## End(Not run)
Duplicate frames
duplicate(images, style = c("linear", "looped", "shuffle"), frames = NULL)duplicate(images, style = c("linear", "looped", "shuffle"), frames = NULL)
images |
an object of class |
style |
one of
|
frames |
integer vector of frame indices to duplicate. Defaults to
|
a magick-image object with duplicate frames inserted.
After each operation a message listing the updated frame sequence is
printed in interactive sessions. Use
stopmotion_verbosity(FALSE) to suppress these messages, or set
options(stopmotion.verbose = FALSE) in your script or
‘.Rprofile’.
## Not run: dino_dir <- system.file("extdata", package = "stopmotion") images <- read(dir = dino_dir) duplicate(images = images, style = "shuffle", frames = 1:2) ## End(Not run)## Not run: dino_dir <- system.file("extdata", package = "stopmotion") images <- read(dir = dino_dir) duplicate(images = images, style = "shuffle", frames = 1:2) ## End(Not run)
Flip images vertically
flip(images, frames = NULL)flip(images, frames = NULL)
images |
an object of class |
frames |
integer vector of frame indices to duplicate. Defaults to
|
a magick-image object
After each operation a message listing the updated frame sequence is
printed in interactive sessions. Use
stopmotion_verbosity(FALSE) to suppress these messages, or set
options(stopmotion.verbose = FALSE) in your script or
‘.Rprofile’.
## Not run: dino_dir <- system.file("extdata", package = "stopmotion") images <- read(dir = dino_dir) flip(images = images, frames = 2:3) ## End(Not run)## Not run: dino_dir <- system.file("extdata", package = "stopmotion") images <- read(dir = dino_dir) flip(images = images, frames = 2:3) ## End(Not run)
Mirrors selected frames along the vertical axis (left-right reflection).
For a vertical flip (top-bottom), see flip.
Wraps magick::image_flop.
flop(images, frames = NULL)flop(images, frames = NULL)
images |
an object of class |
frames |
integer vector of frame indices to duplicate. Defaults to
|
a magick-image object
After each operation a message listing the updated frame sequence is
printed in interactive sessions. Use
stopmotion_verbosity(FALSE) to suppress these messages, or set
options(stopmotion.verbose = FALSE) in your script or
‘.Rprofile’.
## Not run: dino_dir <- system.file("extdata", package = "stopmotion") images <- read(dir = dino_dir) flop(images = images) flop(images = images, frames = 2:3) ## End(Not run)## Not run: dino_dir <- system.file("extdata", package = "stopmotion") images <- read(dir = dino_dir) flop(images = images) flop(images = images, frames = 2:3) ## End(Not run)
Arranges selected frames into a single composite image.
Wraps magick::image_montage.
montage( images, geometry = NULL, tile = NULL, gravity = "Center", bg = "white", shadow = FALSE, frames = NULL )montage( images, geometry = NULL, tile = NULL, gravity = "Center", bg = "white", shadow = FALSE, frames = NULL )
images |
an object of class |
geometry |
a geometry string controlling the size and spacing of each
tile, e.g. |
tile |
a string specifying the grid layout, e.g. |
gravity |
anchor point for each tile's label and content: one of
|
bg |
background colour string, e.g. |
shadow |
logical. Whether to add a drop-shadow under each tile. |
frames |
integer vector of frame indices to duplicate. Defaults to
|
a magick-image object containing a single composite frame.
## Not run: dino_dir <- system.file("extdata", package = "stopmotion") images <- read(dir = dino_dir) montage(images) montage(images, frames = 1:4, tile = "4x1", geometry = "128x128+4+4") ## End(Not run)## Not run: dino_dir <- system.file("extdata", package = "stopmotion") images <- read(dir = dino_dir) montage(images) montage(images, frames = 1:4, tile = "4x1", geometry = "128x128+4+4") ## End(Not run)
Converts a stack of frames into an animated GIF for display, with each
frame's index and label overlaid as text. In an interactive session the
animation opens in the system viewer; in a knitr/Quarto document it is
embedded as an inline animated GIF. Wraps magick::image_animate.
preview(images, fps = 10, loop = 0, frames = NULL, label = TRUE)preview(images, fps = 10, loop = 0, frames = NULL, label = TRUE)
images |
an object of class |
fps |
playback speed in frames per second. Must be a positive integer
divisor of 100, because GIF delay is stored in hundredths of a second
( |
loop |
a non-negative integer giving the number of times the animation
loops. |
frames |
integer vector of frame indices to duplicate. Defaults to
|
label |
logical. Whether to overlay the frame index and label on each
frame. Defaults to |
a magick-image object containing the animated sequence.
## Not run: dino_dir <- system.file("extdata", package = "stopmotion") images <- read(dir = dino_dir) preview(images) preview(images, fps = 5) preview(images, label = FALSE) ## End(Not run)## Not run: dino_dir <- system.file("extdata", package = "stopmotion") images <- read(dir = dino_dir) preview(images) preview(images, fps = 5) preview(images, label = FALSE) ## End(Not run)
Reads all image files from dir (optionally filtered by
pattern) and returns them as a magick-image object.
read(dir, pattern = "")read(dir, pattern = "")
dir |
path to directory containing the images relative to working directory. |
pattern |
an optional regular expression. Only file names which match the regular expression will be returned. |
an object of class magick-image
Frames are loaded in the order returned by list.files,
which sorts filenames lexicographically. This means the filesystem
filename order determines the stop-motion frame order. Name your files
accordingly (e.g. frame_001.png, frame_002.png, ...) to
guarantee the intended sequence. If you need to reorder frames after
loading, use arrange.
## Not run: dino_dir <- system.file("extdata", package = "stopmotion") images <- read(dir = dino_dir) ## End(Not run)## Not run: dino_dir <- system.file("extdata", package = "stopmotion") images <- read(dir = dino_dir) ## End(Not run)
Replaces selected frames with a rotated version in place. For large-angle
transformations. For a small-angle hand-held rock effect, see
wiggle.
rotate(images, degrees, frames = NULL)rotate(images, degrees, frames = NULL)
images |
an object of class |
degrees |
a number in |
frames |
integer vector of frame indices to duplicate. Defaults to
|
a magick-image object
After each operation a message listing the updated frame sequence is
printed in interactive sessions. Use
stopmotion_verbosity(FALSE) to suppress these messages, or set
options(stopmotion.verbose = FALSE) in your script or
‘.Rprofile’.
## Not run: dino_dir <- system.file("extdata", package = "stopmotion") images <- read(dir = dino_dir) rotate(images = images, degrees = 90, frames = 2L) ## End(Not run)## Not run: dino_dir <- system.file("extdata", package = "stopmotion") images <- read(dir = dino_dir) rotate(images = images, degrees = 90, frames = 2L) ## End(Not run)
Scale images
scale(images, geometry, frames = NULL)scale(images, geometry, frames = NULL)
images |
an object of class |
geometry |
a character string specifying the target geometry,
e.g. |
frames |
integer vector of frame indices to duplicate. Defaults to
|
a magick-image object
After each operation a message listing the updated frame sequence is
printed in interactive sessions. Use
stopmotion_verbosity(FALSE) to suppress these messages, or set
options(stopmotion.verbose = FALSE) in your script or
‘.Rprofile’.
## Not run: dino_dir <- system.file("extdata", package = "stopmotion") images <- read(dir = dino_dir) scale(images = images, geometry = "50%") scale(images = images, geometry = "50%", frames = 2:3) ## End(Not run)## Not run: dino_dir <- system.file("extdata", package = "stopmotion") images <- read(dir = dino_dir) scale(images = images, geometry = "50%") scale(images = images, geometry = "50%", frames = 2:3) ## End(Not run)
Splice frames into a film
splice(images, insert, after)splice(images, insert, after)
images |
an object of class |
insert |
an object of class |
after |
integer scalar (or vector of scalars) giving the frame
number(s) after which |
a magick-image object
After each operation a message listing the updated frame sequence is
printed in interactive sessions. Use
stopmotion_verbosity(FALSE) to suppress these messages, or set
options(stopmotion.verbose = FALSE) in your script or
‘.Rprofile’.
## Not run: dino_dir <- system.file("extdata", package = "stopmotion") images <- read(dir = dino_dir) splice(images = images, insert = magick::wizard, after = 1) ## End(Not run)## Not run: dino_dir <- system.file("extdata", package = "stopmotion") images <- read(dir = dino_dir) splice(images = images, insert = magick::wizard, after = 1) ## End(Not run)
Convenience wrapper around options(stopmotion.verbose = ) for
enabling or disabling the frame-sequence messages printed after each
operation. By default messages are shown in interactive sessions and
suppressed in non-interactive contexts (e.g. knitr/Quarto rendering).
stopmotion_verbosity(verbose)stopmotion_verbosity(verbose)
verbose |
|
the previous value of the option, invisibly.
old <- stopmotion_verbosity(FALSE) on.exit(stopmotion_verbosity(old))old <- stopmotion_verbosity(FALSE) on.exit(stopmotion_verbosity(old))
Removes border pixels from selected frames by detecting the background
colour and trimming uniform edges. Wraps magick::image_trim.
trim(images, fuzz = 0, frames = NULL)trim(images, fuzz = 0, frames = NULL)
images |
an object of class |
fuzz |
a number in |
frames |
integer vector of frame indices to duplicate. Defaults to
|
a magick-image object
After each operation a message listing the updated frame sequence is
printed in interactive sessions. Use
stopmotion_verbosity(FALSE) to suppress these messages, or set
options(stopmotion.verbose = FALSE) in your script or
‘.Rprofile’.
## Not run: dino_dir <- system.file("extdata", package = "stopmotion") images <- read(dir = dino_dir) trim(images = images) trim(images = images, fuzz = 10, frames = 1:3) ## End(Not run)## Not run: dino_dir <- system.file("extdata", package = "stopmotion") images <- read(dir = dino_dir) trim(images = images) trim(images = images, fuzz = 10, frames = 1:3) ## End(Not run)
Inserts two rotated copies after each selected frame — one tilted
+degrees and one tilted -degrees — creating a hand-held
stop-motion rock effect. For large-angle permanent rotations, see
rotate.
wiggle(images, degrees = 3, frames = NULL)wiggle(images, degrees = 3, frames = NULL)
images |
an object of class |
degrees |
a positive number specifying the tilt angle in degrees.
Both |
frames |
integer vector of frame indices to duplicate. Defaults to
|
a magick-image object with 2 extra frames per selected frame.
After each operation a message listing the updated frame sequence is
printed in interactive sessions. Use
stopmotion_verbosity(FALSE) to suppress these messages, or set
options(stopmotion.verbose = FALSE) in your script or
‘.Rprofile’.
## Not run: dino_dir <- system.file("extdata", package = "stopmotion") images <- read(dir = dino_dir) wiggle(images = images, degrees = 3, frames = 1:2) ## End(Not run)## Not run: dino_dir <- system.file("extdata", package = "stopmotion") images <- read(dir = dino_dir) wiggle(images = images, degrees = 3, frames = 1:2) ## End(Not run)