[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: I'm having trouble with animation on Octave
From: |
Francesco Potortì |
Subject: |
Re: I'm having trouble with animation on Octave |
Date: |
Thu, 13 Oct 2016 13:20:08 +0200 |
>I have a problem with animation, using Octave 4.0.3 in Windows.
Some years ago, given lack of a standard solution which still persists,
I wrote an Octave function to create movies, which is available at
<http://fly.isti.cnr.it/pub/software/octave/movie.m>.
Here is an example usage which creates an mp4 movie with a moving square:
figure("visible","off");
movie("init","square.mp4")
n=100;
a=zeros(n,n);
a(1:20,41:60)=1;
for i=1:n;
imshow(shift(a,i));
movie("add","square.mp4");
endfor
movie("close","square.mp4",24);
close;
system("totem square.mp4")
The function uses external programs (ffmpeg, convert, png2swf) to create
the movie, depending on the chosen output format. Alternatively, it
creates a directory containing the frames as PNG images, that you can
put together by hand using your preferred program: this should work on
Windows as it is (do not create movies whose name contains spaces).
The function can be improved in several ways: currently it does not
support spaces in the movie's file name, is not tested on Windows, does
not use Octave's internal zip function, does not exploit using strings
for switch cases. Patches welcome.
--
Francesco Potortì (ricercatore) Voice: +39.050.621.3058
ISTI - Area della ricerca CNR Mobile: +39.348.8283.107
via G. Moruzzi 1, I-56124 Pisa Skype: wnlabisti
(entrance 20, 1st floor, room C71) Web: http://fly.isti.cnr.it
## Copyright (C) 2008, 2009 Francesco Potortì
## -*- texinfo -*-
## @deftypefn {Function File} {} movie (@var{action})
## @deftypefnx {Function File} {} movie (@var{action}, @var{mvf})
## @deftypefnx {Function File} {} movie (@var{action}, @var{mvf}, @var{rate})
## Create a movie from plots
##
## Example usage:
## @example
## figure("visible","off"); movie("init","square.mp4")
## n=100; a=zeros(n,n); a(1:20,41:60)=1;
## for i=1:n; imshow(shift(a,i)); movie("add","square.mp4"); endfor
## movie("close","square.mp4",24); close; system("totem square.mp4")
## @end example
##
## @var{action} takes one of three string values: @code{init},
## @code{add}, @code{close}. For each, @var{mvf} specifies the file name
## produced; the file name suffix sets the type of movie.
##
## If @var{mvf} is missing, it defaults to @file{octave_movie.mp4}. The
## suffix @file{.dir} creates a directory containing a png file per
## frame, the type @file{.zip} archives it using @command{zip}. A
## suffix of @file{.mp4}, @file{.ogg}, @file{.mov}, @file{.mjpeg},
## @file{.avi}, @file{.flv} creates a movie using @command{ffmpeg};
## @file{.mng}, @file{.gif} create a movie using @command{convert}; type
## @file{.swf} creates a movie using @command{png2swf}. You must have
## the relevant program installed when using a given extension; no
## program is required for @file{.dir}.
##
## With the @var{close} action, a third arguments specifies the frame
## rate (defaulting to 5 frames/second).
##
## @end deftypefn
## Author: Francesco Potortì <address@hidden>
## $Revision: 1.13 $
## License: GPL version 3 or later
function movie (action, mvf='octave_movie.mp4', rate=5)
verbose = false;
actions = {'init' 'add' 'close'};
# gif swf
types = {'.mp4' '.mng' '.gif' '.zip' '.ogg' '.swf' '.mov' ...
'.mjpeg' '.avi' '.flv' '.dir'};
if (nargin < 1 || !ischar(action) || !any(strcmp(action, actions)))
error("first argument must be one of:%s", sprintf(" %s",actions{:}));
endif
if (nargin >= 2 && !ischar(mvf))
error("second arg must be a string");
endif
[mpath mname mtype] = fileparts(mvf);
mdir = fullfile(mpath, [mname '.d']);
ppat = '%06d.png';
mpat = fullfile(mdir, ppat);
mglob = fullfile(mdir, strrep(sprintf(ppat,0),'0','[0-9]'));
fnof = fullfile(mdir, "+frame-number+");
switch (action)
case actions{1} # init a movie
if (isdir(mvf))
cleandir(mvf, verbose)
else
unlink(mvf);
endif
while (!([allgood msg] = mkdir(mdir)))
if (stat(fnof) && load(fnof).frameno == 0)
error("while creating dir '%s': %s", mdir, msg);
else
cleandir(mdir, verbose);
endif
endwhile
frameno = 0; save('-text',fnof,'frameno');
if (verbose) printf("Directory '%s' created.\n", mdir); endif
case actions{2} # add a frame
load(fnof);
mfile = sprintf(mpat, ++frameno);
print(mfile,'-dpng');
save('-text',fnof,'frameno');
if (verbose) printf("Frame '%s' added.\n", mfile); endif
case actions{3} # close the movie
load(fnof);
switch (mtype)
case {types{[1 5 7 8 9 10]}} # mp4, ogg, mov, mjpeg, avi, flv
cmd = sprintf("ffmpeg -y -r %d -i %s -qscale 0 %s 2>&1", rate, mpat,
mvf);
case {types{[2 3]}} # mng, gif
cmd = sprintf("convert %s -adjoin %s'[1-%d]' %s 2>&1", mglob, mpat,
frameno, mvf);
case types{4} # zip
cmd = sprintf("zip -qr9 %s %s 2>&1", mvf, mglob);
case types{6} # swf
cmd = sprintf("png2swf -z -r %d -o %s %s", rate, mvf, mglob);
case types{end} # dir
rename(mdir, mvf); return
otherwise
error("second arg must end with one of:%s", sprintf(" %s",types{:}));
endswitch
if (verbose) printf("\nExecuting %s\n", cmd); endif
[status output] = system(cmd);
if (status != 0)
error("Creation of movie '%s' containing %d frames failed:\n%s",
mvf, frameno, output);
endif
if (verbose) printf("Movie '%s' contains %d frames:\n%s",
mvf, frameno, output); endif
cleandir(mdir, verbose);
endswitch
endfunction
function cleandir(mdir, verbose)
unwind_protect
save_crr = confirm_recursive_rmdir(false);
[allgood msg] = rmdir(mdir,"s");
if (!allgood)
error("while removing dir '%s': %s", mdir, msg); endif
unwind_protect_cleanup
confirm_recursive_rmdir(save_crr);
end_unwind_protect
if (verbose) printf("Directory '%s' removed\n", mdir); endif
endfunction