-distort SRT provides simple but high-quality animation.
For video and animations, we often want to digitally pan and zoom. Successive frames might show different views of the same static image, or different views of a sequence of video frames perhaps to stabilise a hand-held video, or to give the impression of a hand-held camera even though the camera was on a tripod. Importantly, the pan and zoom must be smooth, and not limited to integer pixel coordinates.
Generally, the input image should be large enough that we can pan and zoom while remaining within the image boundaries.
GIF is a poor format for animating photographs. I use it here only for convenience of display on the Web.
The -distort SRT operation takes between two and seven arguments. See the official Command-line Options documentation.
This page will use the six-argument form of SRT. The arguments are:
X,Y | A coordinate within the input image. |
Scale | Scale.
1: no change. >1: magnifies (zooms in) |
Angle | Angle of rotation. |
NewX,NewY | Corresponding coordinate within the output image. |
The arguments can be floating-point, and IM correctly uses them. The arguments can also be %[fx:...] expressions.
With those six arguments, SRT effectively does the following operations:
Internally, I suppose IM does this in a single operation. But the effect is as if these four separate operations were performed.
"-distort SRT" applies the transformation, putting the required result in the top-left of the canvas. We could crop it from there. However, it is faster to use "-define distort:viewport" before the SRT. The results are identical. If the input is much larger than the output, a viewport is much faster than a crop. (I suppose IM works by looping through every output pixel, calculating the source location. Setting a viewport reduces the required looping.) Annoyingly, -define distort:viewport cannot accept fx expressions.
For example: suppose we have an image that includes a foot, with the big toe at coordinate 3134,4241. We want the output to be 600x400, with the big toe at 200,266.67. We want to rotate the image by 32.5° clockwise., and scale by 0.75.
set SRC=%PICTLIB%20130713\AGA_1372.JPG %IMG7%magick ^ %SRC% ^ -define distort:viewport=600x400+0+0 ^ -distort SRT 3134,4241,0.75,32.5,200,266.67 ^ as_ex1.png |
For convenience, I put these eight values into variables. These values will be the ones used in the first frame (frame zero) of the animation.
OUT_WI
OUT_HT |
Required output width and height. |
IN_X
IN_Y |
Coords in the input image. |
OUT_X
OUT_Y |
Corresponding coords in the output image. |
SCALE | Initial scale. |
ANGLE | Initial angle of rotation. |
set OUT_WI=600 set OUT_HT=400 set IN_X=3134 set IN_Y=4241 set OUT_X=200 set OUT_Y=266.67 set SCALE=0.75 set ANGLE=32.5
Animating the output width and height can't be done within the convert command, and we don't usually want this, so I don't show that here. We can easily animate the other six values.
I use six variables, each being the amount of change per frame.
D_IN_X
D_IN_Y |
Pan across the input image, before applying scale and rotate.
Positive pans right/down (moves image left/up). |
D_OUT_X
D_OUT_Y |
Pan across the output, after applying scale and rotate.
Positive pans right/down (moves image left/up). |
D_SCALE | Multiplier for scale. |
D_ANGLE | Additional angle of rotation, degrees clockwise. |
For no movement:
set D_IN_X=0 set D_IN_Y=0 set D_OUT_X=0 set D_OUT_Y=0 set D_SCALE=1 set D_ANGLE=0
The formulae to calculate the SRT parameters are:
X = IN_X + D_IN_X * FNUM
Y = IN_Y + D_IN_Y * FNUM
NewX = OUT_X + D_OUT_X * FNUM
NewY = OUT_Y + D_OUT_Y * FNUM
Scale = SCALE * D_SCALEFNUM
Angle = ANGLE + D_ANGLE * FNUM
... where FNUM is the frame number, starting from zero.
If we have a small animation, we can process it entirely within a single convert command by duplicating the image and using t as the frame number.
Translate the input before scale/rotate. set D_IN_X=3 set D_IN_Y=0 %IMG7%magick ^ -loop 0 -delay 20 ^ %SRC% ^ -duplicate 4 ^ -define distort:viewport=%OUT_WI%x%OUT_HT%+0+0 ^ -distort SRT ^ %%[fx:%IN_X%+%D_IN_X%*t],^ %%[fx:%IN_Y%+%D_IN_Y%*t],^ %%[fx:%SCALE%*pow(%D_SCALE%,t)],^ %%[fx:%ANGLE%+%D_ANGLE%*t],^ %%[fx:%OUT_X%-%D_OUT_X%*t],^ %%[fx:%OUT_Y%-%D_OUT_Y%*t] ^ as_g1.gif set D_IN_X=0 set D_IN_Y=0 |
|
Translate the output after scale/rotate. set D_OUT_X=3 set D_OUT_Y=1.5 %IMG7%magick ^ -loop 0 -delay 20 ^ %SRC% ^ -duplicate 4 ^ -define distort:viewport=%OUT_WI%x%OUT_HT%+0+0 ^ -distort SRT ^ %%[fx:%IN_X%+%D_IN_X%*t],^ %%[fx:%IN_Y%+%D_IN_Y%*t],^ %%[fx:%SCALE%*pow(%D_SCALE%,t)],^ %%[fx:%ANGLE%+%D_ANGLE%*t],^ %%[fx:%OUT_X%-%D_OUT_X%*t],^ %%[fx:%OUT_Y%-%D_OUT_Y%*t] ^ as_g2.gif set D_OUT_X=0 set D_OUT_Y=0 |
|
Start zoomed out, and continue zooming out. set SCALE=0.9 set D_SCALE=0.99 %IMG7%magick ^ -loop 0 -delay 20 ^ %SRC% ^ -duplicate 4 ^ -define distort:viewport=%OUT_WI%x%OUT_HT%+0+0 ^ -distort SRT ^ %%[fx:%IN_X%+%D_IN_X%*t],^ %%[fx:%IN_Y%+%D_IN_Y%*t],^ %%[fx:%SCALE%*pow(%D_SCALE%,t)],^ %%[fx:%ANGLE%+%D_ANGLE%*t],^ %%[fx:%OUT_X%-%D_OUT_X%*t],^ %%[fx:%OUT_Y%-%D_OUT_Y%*t] ^ as_g3.gif set D_SCALE=1 set SCALE=1 |
Larger animations may not fit into memory. The frames can be processed in a loop, one frame per convert. They can be assembled with gifsicle or ffmpeg.
My convention for frame file names is to use six digits with leading zeros. (Five digits is too few for 60 minutes of video.)
Zoom out and rotate. set SCALE=0.9 set D_SCALE=0.99 set D_ANGLE=1 set LAST_FR=4 del as_fra_*.png >nul for /L %%I in (0,1,%LAST_FR%) do ( set LZ=000000%%I set LZ=!LZ:~-6! echo !LZ! %IMG7%magick ^ %SRC% ^ -define distort:viewport=%OUT_WI%x%OUT_HT%+0+0 ^ -distort SRT ^ %%[fx:%IN_X%+%D_IN_X%*t],^ %%[fx:%IN_Y%+%D_IN_Y%*t],^ %%[fx:%SCALE%*pow^(%D_SCALE%,%%I^)],^ %%[fx:%ANGLE%+%D_ANGLE%*%%I],^ %%[fx:%OUT_X%-%D_OUT_X%*%%I],^ %%[fx:%OUT_Y%-%D_OUT_Y%*%%I] ^ as_fra_!LZ!.gif ) %IMG7%ffmpeg -y -i as_fra_%%06d.gif as_fra.mpg gifsicle -O2 --delay 20 --loopcount=forever as_fra_*.gif >as_fra.gif del as_fra_*.gif set D_ANGLE=0 set D_SCALE=1 set SCALE=1 |
as_fra.gif: |
The commands shown above implement simple animation of static images, creating pan, zoom and rotate effects. More sophisticated expressions can be used, for example to give the effect a smooth start or finish.
All images on this page were created by the commands shown, using:
%IMG7%magick -version
Version: ImageMagick 7.1.0-42 Q16-HDRI x64 396d87c:20220709 https://imagemagick.org Copyright: (C) 1999 ImageMagick Studio LLC License: https://imagemagick.org/script/license.php Features: Cipher DPC HDRI OpenCL Delegates (built-in): bzlib cairo freetype gslib heic jng jp2 jpeg jxl lcms lqr lzma openexr pangocairo png ps raqm raw rsvg tiff webp xml zip zlib Compiler: Visual Studio 2022 (193231332)
gifsicle --version
LCDF Gifsicle 1.87 Copyright (C) 1997-2014 Eddie Kohler This is free software; see the source for copying conditions. There is NO warranty, not even for merchantability or fitness for a particular purpose.
To improve internet download speeds, some images may have been automatically converted (by ImageMagick, of course) from PNG or TIFF or MIFF to JPG.
Source file for this web page is animsrt.h1. To re-create this web page, run "procH1 animsrt".
This page, including the images, is my copyright. Anyone is permitted to use or adapt any of the code, scripts or images for any purpose, including commercial use.
Anyone is permitted to re-publish this page, but only for non-commercial use.
Anyone is permitted to link to this page, including for commercial use.
Page version v1.0 29-September-2015.
Page created 25-Aug-2022 21:10:23.
Copyright © 2022 Alan Gibson.