help-octave
[Top][All Lists]
Advanced

[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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]