Animate is an interpreter written in Python which reads commands from an Excel file and some bitmap images and composes an animation with these commands. It can make simple animations, but also much more complex ones. No Python knowledge is needed to use the library. An overview of what animate can do can be found in the overview of examples.
Features:
- it can smoothly modify location, rotation, scale and opacity of many images in parallel
- the transitions can be independent of each other
- since Animate uses a spreadsheet to define the animation, all parameters can be driven by calculated relations in the spreadsheet
- the Z-order of images can be modified on the fly
- it can use nested scripts to generate a composed image that can be used in a script on a higher hierarchical level
- frames can be combined to produce an animated GIF or a movie
Animate heavily relies on open source software such as Python, the Python Imaging Library (PIL) and Pandas. Many thanks to the creators of this great software. Please don't forget to donate to all these great projects.
- ANIMATE
- Table of Contents
- Typical workflow
- Dependencies
- List of examples
- The
SCRIPT
command - The
TABLE
command - Types of items
- Commands and properties
- Known issues
- To do for future versions
An Animate project directory looks like this:
- An spreadsheet which holds all
SCRIPT
s andTABLE
s - A Python file which imports and calls Animate and refers to the spreadsheet and the main script
- A
../Pictures
subdirectory which holds all images used in the animation. The bitmaps are typically .png files with transparent background. They can for instance be created using Inkscape. - A
../Frames
subdirectory which holds all frames generated by Animate. Does not have to be created by the user, Animate will create this directory if it does not yet exist. Can be removed to save disk space after the project is completed.
The Excel file typically contains various sheets, each containing a SCRIPT
, TABLE
, ASSEMBLY
or CANVAS
. One SCRIPT
is the main script that is reffered to in the Python file.
The Python file typically contains just two lines of code:
from Animate import Animate
Animate.Model('Simulation.xlsx', 'Main')
The two parameters refer to the Excel file and the name of the sheet that contains the main script.
The following libraries must be installed:
python |
≥v3.0 | python.org |
animate |
pip install py-animate | https://github.com/henkjannl/py-animate |
pandas |
pip install pandas | https://pandas.pydata.org/ |
pillow |
pip install Pillow | https://python-pillow.org/ |
ffmpeg |
https://ffmpeg.org/ |
Remarks:
- if you are using a package installer such as Anaconda, pandas and pillow may already be installed
- ffmpeg is only needed if video files need to be created
- ffmpeg must be installed such that it is accessible from the command line (i.e. added to the PATH)
The examples are provided for inspiration:
01-bulldozer demonstrates SCRIPT , IMAGE and XPOS |
|
02-bulldozer-with-table produces the same result, now using the TABLE command |
|
03-solar-system demonstrates BRINGTOFRONT and SENDTOBACK |
|
04-rotating-text demonstrates TEXT , XPOLE and YPOLE |
|
05-rotating-cloud demonstrates XPOLE , YPOLE , ROTATION and OPACITY |
|
06-bulldozer-with-bucket uses an ASSEMBLY to move the bucket and the wheel of the bulldozer. YMOVE is used together with DAMPED and ACCEL to create the bouncing cloud |
|
07-bouncing-balls demonstrates ASSEMBLY and TIMEOFFSET . All three balls are created by a single assembly. The ball is split in two to mimic the compression as it bounces on the floor. The lower half of the ball uses XSCALE and YSCALE , the upper half only XSCALE |
|
08-two-cylinders demonstrates the MASK item and some complex arithmetic in the spreadsheet to model the bubbles speeding up in the tube |
|
09-canvas demonstrates the CANVAS |
|
10-car also uses a CANVAS to draw the tire tracks, and demonstrates a TABLE driving multiple SCRIPT s, driving the car and the rear tires at the same time. |
|
11-camera demonstrates the use of an ASSEMBLY on multiple levels, one for the glass in the lower left corner, using a MASK and ROTATE |
|
12-sewing-machine is a similar example of a sewing machine. |
A SCRIPT
is a timed sequence of commands that influence properties
The columns have a predefined meaning:
Column A | Contains the time at which an event takes place |
Column B | Contains a property or a command |
Column C | Contains an item name or a value |
Column D | Contains a value, if column C contains an item name |
Example:
Remarks:
- The other columns can be used for comments or for calculations (such as columns F and G in the example above)
- If the cell in column A does not contain a number, the row is ignored by the script (such as row 1)
- The times do not have to be ordered (such as row 15 and beyond)
- By definition,
Frame0000
corresponds to t=0 s in the mainSCRIPT
- Items do not need to be explicitly created. If the item occurs for the first time in the script, Animate automatically creates a new item. Therefore, pay attention to spell the names of the items correctly; if an item name is spelled incorrectly, a second item will be created
- Animate asserts that every
Image
item has at least one image assigned. If not, an error is raised. - Commands, properties and item names are not case sensitive
- All items have most properties in common
In Example 1, the SCRIPT
command is demonstrated.
When the TABLE
command is used in a script, the name after the TABLE
refers to the sheet name in which the TABLE
is defined. A TABLE
sheet must be formatted as follows:
Column A | Specifies the time at which the event takes place | The time does not have to be ordered. Animate orders the time and interpolates between the given values. If column A does not contain a number, the row is ignored, cells can be used as comment or for internal calculations |
Row 1 | Specifies the name of the item that needs to be modified | Items cannot be created in a TABLE . Items declared in the calling SCRIPT can be modified by a TABLE If an item name is not declared in the SCRIPT that calls the table, it will be ignored by that script.Note that the same table can also be called by another script, in which the item can be declared |
Row 2 | Specifies the property of the item that needs to be modified | |
Cells | Specifies the value for the property of the item at the given time | Not every cell in a time/item combination has to have a value. If a cell has no value, the transition happens smoothly between the time/value pairs that are defined |
Remarks:
- The
TABLE
allows a more compact way to describe transitions - A number is required in column A to distiguish the row from a comment row. However, the value of the time before the TABLE command is ignored.
- The times in column A do not have to be ordered
- If values for a property are missing for certain points in time, Animate will interpolate between the values that are present
- If
FIRSTFRAME
andLASTFRAME
are not specified, the animation will run from t=0 until the last point in time specified - Between time 0 and the first specified value, the property will be constant until the first specified value
- Same for the last specified value until the end of the animation
- A script can call more than one table.
- More than one script can call the same table. If the table controls an item that is not in the calling script, the item is ignored
In Example 2, the TABLE
command is demonstrated.
The following types of items are defined:
IMAGE |
retrieves an bitmap from disk and makes it part of the animation |
TEXT |
displays text |
ASSEMBLY |
an item that is dynamically made up of other items |
CANVAS |
similar to an ASSEMBLY , but not erased between subsequent frames |
MASK |
used to hide or reveil certain parts of the items below the mask |
The IMAGE
command loads an image from file and links it to an item with a unique name.
The example below creates an item called Glass, and loads different images at 4 and 5 seconds. The image loaded at t = 3s will already be loaded as the script starts.
Example 1 demonstrates the IMAGE
item.
The TEXT
command declares a TEXT
item and immediately assigns a text value to it. The text value can be changed ad different moments in time.
In Example 4, the TEXT
item is demonstrated.
The main script can call an ASSEMBLY
, which is in fact another script which can be used as an item. Multiple levels can be cascaded. The main script can display a single ASSEMBLY
multiple times, for example with different scaling, position, rotation or mask.
In the following example, the bulldozer from example 1 is animated. This time, the bulldozer is not a static image, but the wheel and the bucket of the bulldozer can move.
Example 6 demonstrates the ASSEMBLY
item.
A CANVAS
is like an ASSEMBLY
; the difference is that the image is not erased in between frames. A CANVAS
can be useful as a drawing board, to draw text or a graph.
Example 9 demonstrates the CANVAS
item.
It is possible to work with multiple instances of an ASSEMBLY
or CANVAS
, while giving each instance a different offset in time.
For each instance, it is possible to call the TIMEOFFSET
to specify that the instance must start at a different moment in time.
The offset given can both be:
- positive: the instance starts later than the calling script, or
- negative: the instance starts earlier
As a simple reminder: if a TIMEOFFSET
of +3 seconds is specified, the called ASSEMBLY
or CANVAS
starts at 3 sec.
To let the item start later than the calling script, the offset is subtracted from the time in the calling script. In the example below, the called script starts 3 seconds later than the calling script:
Calling script |
Called script |
---|---|
0 sec | -3 sec |
1 sec | -2 sec |
2 sec | -1 sec |
3 sec | 0 sec |
4 sec | 1 sec |
5 sec | 2 sec |
This demonstrates that negative times in the called ASSEMBLY
or CANVAS
can occur. It is possible to also provide negative times in the called scripts to define the behaviour for negative values of the time.
Example 7, demonstrates the TIMEOFFSET
command.
A MASK
is used to reveil some parts of the underlying stack, or conceil others.
The MASK
accepts a filename as an argument. It works in the following way:
- At the white parts of this mask, the parts of the underlying picture will be revealed
- At the black parts of this mask, the parts of the underlying picture will become transparent
- The grey parts will partly reveal the underlying picture.
At different moments in time, a different bitmap can be loaded as MASK
.
Example 8 demonstrates the MASK
item.
The following commands are only relevant for the main script. These commands are ignored for other scripts:
FRAMESPERSECOND |
Sets the number of frames per second of the animation. This is the ratio between the frame number and the time in the simulation. |
FIRSTFRAME |
This is a property for debug purposes. If the total script takes very long to process, only a subset of the frames can be re-rendered. The value following the FIRSTFRAME command references the actual frame number, not the time to which the frame corresponds. |
LASTFRAME |
Similar to FIRSTFRAME to determine the last frame in the scene that is processed. |
SHOWTIME |
This property is also for debug purposes. Displays the time in the lower left corner of the frames |
HIDETIME |
Hides the time in the lower left corner of the frames |
ANIMATEDGIF |
Creates an animated GIF of the frames that were created, with a filename followed by the ANIMATEDGIF command |
MOVIE |
Creates an mpeg movie of the frames that were created, with a filename followed by the MOVIE command (see remarks below) |
Remarks:
- For these global commands, a number must be present in column A to prevent the row is ignored, but the value of this number is ignored
- For short animations,
ANUMATEDGIF
is conventient. - If the animation is larger, the GIF file will become very large, and
MOVIE
is more suitable - The AnimatedGIF command stores the rendered images in memory and then creates the GIF at the end. This can require much memory. Only the frames between
FIRSTFRAME
andLASTFRAME
end up in the animated GIF - The Movie command uses the frames in the
../Frames
directory. Therefore, all rendered frames are used. If going from a high to a lowFRAMERATE
, ensure to remove the frames that are no longer needed from the../Frames
directory before creating the movie - If you plan to create a movie, consider to choose a standard movie format, such as 720x576 (PAL) 1280×720 (HD720p) or 1920×1080 (HD1080p), to ensure the output is compatible with standard movie players.
- The
MOVIE
command usesffmpeg
, but there seems to be an issue. Creating an .mp4 file seems to work best, but the result cannot always be played by standard Windows Media Player. As a workaround, try opening the movie in VLC and save it as another .mp4 file using the menu optionMedia
>Convert / Save
- After the Movie or AnimatedGIF has been created, the
../Frames
directory can be removed to save disk space
- In Animate, time is specified in seconds
- By definition, the animation starts at 0 seconds and frame 0 corresponds to t=0 s
- The
FRAMERATE
command defines the ratio between frames and seconds - Rendered frames are stored in the
../Frames
subdirectory. If this directory does not exist, it will be created by Animate - By default, the last event in all script is used to determine how long the animation takes
- If a shorter animation is desired, the
LASTFRAME
command can be used to define the duration. Note that this is a frame number and not a time in seconds
- For debugging purposes, the
FIRSTFRAME
andLASTFRAME
commands can be used to render a subset of the frames - Also for debugging purposes, it can be helpful to temporatily use a lower
FRAMERATE
to test if the animation works well - With a bitmap viewer such as IrfanView, it is easy to browse though the
../Frames
directory, to check which frames need to be re-rendered. These frames can already be inspected while the rendering of the remaining frames is still running. - It is also possible to use
SHOWTIME
to display the time in each frame - To temporarily disable a row, it can be useful to type a text instead of a number in column A
WIDTH |
Sets the width of the output frames, measured in pixels |
HEIGHT |
Sets the height of the output frames |
SCRIPT |
Calls a SCRIPT in another worksheet |
TABLE |
Calls a TABLE in another worksheet |
ASSEMBLY |
Creates an ASSEMBLY item and calls the worksheet where it is defined. The worksheet that is referred to must be formatted as a SCRIPT |
CANVAS |
Creates a CANVAS item and calls the worksheet where it is defined. The worksheet that is referred to must be formatted as a SCRIPT |
TIMEOFFSET |
Applies only to ASSEMBLY and CANVAS . Determines the time difference between the time base of the calling script and the called script. This is useful if the ASSEMBLY or CANVAS are called more than once with different instances. This way, not all instances need to start at the same moment, but the same SCRIPT or TABLE can be used to define each instance. |
Remarks:
- Commands and properties are not case sensitive
All items have the following properties in common:
XPOS |
The horizontal position on which the item is positioned. The position corresponds to the position of the image as if the rotation of the image is zero and the scale is 100% in horizontal and vertical direction. Note that the origin of the coordinate system is the top left corner of the image, if XPOS =0, the left side of the item will be aligned to the left side of the output stream. |
YPOS |
The vertical position on which the item is positioned. Note that the origin of the coordinate system is the top left corner of the image, if YPOS =0, the top of the item will be aligned to the top of the output stream. |
ROTATION |
The rotation of the item in degrees. Positive angles are counterclockwise. Angles can be less than 0° or more than 360° to support multiple revolutions. Rotation and scaling is explained in more detail in this paragraph |
XSCALE |
The scale of the item in horizontal direction. A value of 1 means that the scale is not changed. See also the paragraph on the pole |
YSCALE |
The scale of the item in vertical direction. See also the paragraph on the pole |
XPOLE |
The pole around which the item is rotated and scaled |
YPOLE |
The pole around which the item is rotated and scaled |
OPACITY |
Determines the transparency of the item. A value of 0 means the item is invisible, a value of 1 means the item is opaque |
BRINGTOFRONT |
Changes the Z-order of the item list, bringing this item on top of the others. This property does not need a value. See BRINGTOFRONT and SENDTOBACK |
SENDTOBACK |
Changes the Z-order of the item list, sending this item to the bottom of the list. See BRINGTOFRONT and SENDTOBACK |
TEXTCOLOR |
Specific for text items: the color for the font of the text |
FONT |
Specific for text items: the font for the text |
Animate uses the same coordinate system conventions as bitmaps:
- the origin is in the upper left corner
- positive X-axis is to the right
- positive Y-axis is down
When scaling and rotating an item, the default pole of scaling and rotating is the origin of the item (=upper left corner). The XPOLE
and YPOLE
commands can be used to change the coordinates of the pole of rotation and scaling. The coordinates provided with XPOLE
and YPOLE
are relative to origin of the item.
In Example 4, the TEXT
, XPOLE
and YPOLE
commands are demonstrated.
Example 5 demonstrates rotation of the cloud in the original bulldozer animation.
Transitions for XPOS
, YPOS
, ROTATION
, XSCALE
, YSCALE
and OPACITY
can be made smoother by using their respective speed modifiers:
XMOVE |
The velocity profile of the movements in horizontal direction. Possible values are explained below |
YMOVE |
The velocity profile of the movements in vertical direction |
RMOVE |
The velocity profile of rotation |
SXMOVE |
The velocity profile of scaling in horizontal direction |
SYMOVE |
The velocity profile of scaling in vertical direction |
OMOVE |
The velocity profile for changing opacity |
The position, scaling, orientation and opacity modifiers can have the following values:
LINEAR |
the property changes proportional to time |
CYCLOID |
the property changes with a smooth start and finish |
SPRING |
the property moves to the other value with some dynamic overshoot |
CLICK |
the property moves with overshoot at the beginning and at the end |
ACCEL |
the property accelerates from low speed to high speed |
DAMPED |
the property starts fast and then decelerates |
SUDDEN |
the property suddenly moves at the end of the interval |
The different values can be depicted as follows:
Remarks:
- The default setting for all move modifiers is
LINEAR
SUDDEN
can be useful when switchingOPACITY
Items are ordered in a certain Z-order, meaning some items are placed in front of other items. An item can be put in front of all other items using BRINGTOFRONT
, and placed at the back using SENDTOBACK
.
Remarks:
- This changes the order of items within a
SCRIPT
,ASSEMBLY
orCANVAS
. - The
ASSEMBLY
orCANVAS
can also be placed in front of or behind other items in the script in which they are defined.
In Example 3, the BRINGTOFRONT
and SENDTOBACK
are demonstrated.
- .xlsx not yet supported, only .xls
- if
OPACITY
is less than 100% or aMASK
is not white or black, or anIMAGE
has partial transparency, a red shade may occur. This is probably something in Pillow MOVIE
is not always working well..mp4
seems to work better than.mpeg
, but in both cases the result does not seem to be reliable. VLC media player can be used to convert a buggy.mp4
into one that is accepted by other viewers such as Microsoft Powerpoint. An issue is posted at ffmpeg-pythonMOVIE
andANIMATEDGIF
do not support theFRAMERATE
- Font support is not system independent
- The
ffmpeg
library does seem to have some bugs. It produces video, but the video cannot always be displayed on all devices or it may look suboptimal. Use VLC player to convert the video to something else that does not have these flaws.
- More options for AnimatedGIF and Movie
- Consider another spreadsheet library (such as Pandas) to allow support of open document spreadsheets too
- Allow for negative scaling
- Solve why opacity turns red
- Let the user choose between 'fast' or 'pretty'
- Gather all scaling, translation and rotation transformations in one transformation to make it faster
- Make a robust Init procedure for the font directory. Use try .. except statements to check in which folder the fonts are located and which fonts are available.
- Default Zorder should be in the order in which the items are created
- Zorder as DiscreteProperty
- Zorder,
while time[index] < time
- Remember images in different phases, create the possibility to turn it off if too memory intensive
- Parse commands can be easier if commands are grouped in a few groups
- Opacity interpolates only linear. Benificial to add other options?
- Make Animate run with SVG elements instead of PNGs