Mercurial > octave
changeset 26212:2be1833a93a5
movie.m: New function (patch #9363)
* NEWS: Announce new function.
* scripts/image/movie.m: New function file.
* scripts/image/module.mk: Add movie.m to build system.
* getframe.m: Add movie to seealso links.
* image.txi: Add movie DOCSTRING. Reorganize part of "Representing Images"
section.
author | Pantxo Diribarne <pantxo.diribarne@gmail.com> |
---|---|
date | Sun, 28 May 2017 13:42:02 +0200 |
parents | 69bd0cfbd123 |
children | ff0eadb417ec |
files | NEWS doc/interpreter/image.txi scripts/image/getframe.m scripts/image/module.mk scripts/image/movie.m |
diffstat | 5 files changed, 236 insertions(+), 3 deletions(-) [+] |
line wrap: on
line diff
--- a/NEWS Wed Dec 12 15:01:21 2018 -0800 +++ b/NEWS Sun May 28 13:42:02 2017 +0200 @@ -164,6 +164,7 @@ matlab.lang.makeUniqueStrings matlab.lang.makeValidName movegui + movie openfig ordeig savefig
--- a/doc/interpreter/image.txi Wed Dec 12 15:01:21 2018 -0800 +++ b/doc/interpreter/image.txi Sun May 28 13:42:02 2017 +0200 @@ -140,9 +140,10 @@ an RGB color. The color map must be of class @code{double} with values between 0 and 1. -@DOCSTRING(im2double) +The following convenience functions are available for conversion between image +formats. -@DOCSTRING(iscolormap) +@DOCSTRING(im2double) @DOCSTRING(gray2ind) @@ -152,14 +153,27 @@ @DOCSTRING(ind2rgb) +Octave also provides tools to produce and work with movie frame structures. +Those structures encapsulate the image data (@qcode{"cdata"} field) together +with the corresponding colormap (@qcode{"colormap"} field). + @DOCSTRING(getframe) +@DOCSTRING(movie) + @DOCSTRING(frame2im) @DOCSTRING(im2frame) +The @code{colormap} function is used to change the colormap of the current axes or figure. + @DOCSTRING(colormap) +@DOCSTRING(iscolormap) + +The following functions return predefined colormaps, the same that can be +requested by name using the @code{colormap} function. + @DOCSTRING(rgbplot) @DOCSTRING(autumn)
--- a/scripts/image/getframe.m Wed Dec 12 15:01:21 2018 -0800 +++ b/scripts/image/getframe.m Sun May 28 13:42:02 2017 +0200 @@ -41,7 +41,7 @@ ## the figure to be captured. Regardless of the figure @qcode{"units"} ## property, @var{rect} must be defined in @strong{pixels}. ## -## @seealso{im2frame, frame2im} +## @seealso{im2frame, frame2im, movie} ## @end deftypefn function frame = getframe (h = [], rect = [])
--- a/scripts/image/module.mk Wed Dec 12 15:01:21 2018 -0800 +++ b/scripts/image/module.mk Sun May 28 13:42:02 2017 +0200 @@ -46,6 +46,7 @@ %reldir%/iscolormap.m \ %reldir%/jet.m \ %reldir%/lines.m \ + %reldir%/movie.m \ %reldir%/ocean.m \ %reldir%/pink.m \ %reldir%/prism.m \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/image/movie.m Sun May 28 13:42:02 2017 +0200 @@ -0,0 +1,217 @@ +## Copyright (C) 2017 Pantxo Diribarne +## +## This file is part of Octave. +## +## Octave is free software: you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation, either version 3 of the License, or +## (at your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## <https://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## @deftypefn {} {} movie (@var{mov}) +## @deftypefnx {} {} movie (@var{mov}, @var{n}) +## @deftypefnx {} {} movie (@var{mov}, @var{n}, @var{fps}) +## @deftypefnx {} {} movie (@var{h}, @dots{}) +## Play a movie defined by an array of frame structures. +## +## The movie @var{mov} must be a struct array of frames with fields +## @qcode{"cdata"} and @qcode{"colormap"}, as returned by the @code{getframe} +## function. By default all images are displayed once, at 12 fps, in the +## current axes. +## +## The optional argument @var{n} is a scalar or vector of integers that +## controls the number of times the movie is displayed and which particular +## frames are shown: +## +## @table @asis +## @item First element: +## +## @table @asis +## @item @var{n}(1) > 0 +## Play the movie @var{n}(1) times. +## +## @item @var{n}(1) < 0 +## Play the movie @code{abs (@var{n}(1)} times alternatively in forward and +## backward order. +## @end table +## +## @item Other elements (if any): +## Indices of the frames in @var{mov} that will be displayed. +## @end table +## +## If the first argument is a handle to a figure or axes @var{h}, the movie is +## played in that figure or axes instead of the current axes. +## +## @seealso{getframe, im2frame, frame2im} +## @end deftypefn + +function movie (varargin) + + if (nargin == 0) + print_usage (); + endif + + ## Extract possible handle argument + hax = []; + if (isaxes (varargin{1})) + hax = varargin{1}; + varargin(1) = []; + elseif (isfigure (varargin{1})) + hax = get (varargin{1}, "currentaxes"); + if (isempty (hax)) + hax = axes ("parent", varargin{1}); + endif + varargin(1) = []; + endif + + ## Extract other arguments + n = 1; + fps = 12; + idx = []; + nargs = numel (varargin); + if (nargs == 0) + print_usage (); + elseif (nargs >= 1) + mov = varargin{1}; + if (! isfield (mov, "cdata") || ! isfield (mov, "colormap")) + error ("movie: MOV must be a frame struct array"); + endif + + if (nargs >= 2) + n = varargin{2}; + if (! isindex (abs (n(1)))) + error ("movie: N must be a non-zero integer"); + elseif (! isscalar (n)) + idx = n(2:end)(:)'; + n = n(1); + if (! isindex (idx, numel (mov))) + error (["movie: All elements N(2:end) must be valid indices ", ... + "into the MOV struct array"]); + + endif + endif + + if (nargs >= 3) + fps = varargin{3}; + if (! (isnumeric (fps) && isscalar (fps) && fps > 0)) + error ("movie: FPS must be a numeric scalar > 0"); + endif + endif + endif + endif + + if (isempty (hax)) + hax = gca (); + endif + + ## Build the list of frames to be displayed + if (isempty (idx)) + idx = (1:numel (mov)); + endif + + if (n > 0) + idx = repmat (idx, 1, n); + else + n = -n; + tmp = repmat ([idx fliplr(idx)], 1, fix (n/2)); + if (fix (n/2) != n/2) + idx = [tmp, idx]; + else + idx = tmp; + endif + endif + + tau = 1/fps; + set (hax, "ydir", "reverse", "visible", "off"); + tic (); + him = image ("parent", hax, "cdata", mov(1).cdata); + for ii = idx + pause (tau - toc ()); + tic (); + if (! isempty (mov(ii).colormap)) + set (hax, "colormap", mov(ii).colormap) + endif + set (him, "cdata", mov(ii).cdata); + endfor + +endfunction + + +%!demo +%! nframes = 20; +%! colors = jet (nframes); +%! baseim = ones (20, 20, 3, "uint8"); +%! mov(nframes) = struct ("cdata", [], "colormap", []); +%! for ii = 1:nframes +%! im = baseim * 255; +%! im(:,ii,1) = colors(ii,1) * 255; +%! im(:,ii,2) = colors(ii,2) * 255; +%! im(:,ii,3) = colors(ii,3) * 255; +%! mov(ii).cdata = im; +%! endfor +%! clf (); +%! title "Play movie forward 2 times" +%! movie (mov, 2); + +%!demo +%! nframes = 20; +%! colors = jet (nframes); +%! baseim = ones (20, 20, 3, "uint8"); +%! mov(nframes) = struct ("cdata", [], "colormap", []); +%! for ii = 1:nframes +%! im = baseim * 255; +%! im(:,ii,1) = colors(ii,1) * 255; +%! im(:,ii,2) = colors(ii,2) * 255; +%! im(:,ii,3) = colors(ii,3) * 255; +%! mov(ii).cdata = im; +%! endfor +%! clf (); +%! title "Play movie forward and backward 5 times at 25 fps" +%! movie (mov, -5, 25); + +%!demo +%! nframes = 20; +%! colors = jet (nframes); +%! baseim = ones (20, 20, 3, "uint8"); +%! mov(nframes) = struct ("cdata", [], "colormap", []); +%! for ii = 1:nframes +%! im = baseim * 255; +%! im(:,ii,1) = colors(ii,1) * 255; +%! im(:,ii,2) = colors(ii,2) * 255; +%! im(:,ii,3) = colors(ii,3) * 255; +%! mov(ii).cdata = im; +%! endfor +%! clf (); +%! title "Play downsampled movie 5 times" +%! movie (mov, [5 1:3:nframes]); + +%!demo +%! clf (); +%! z = sombrero (); +%! hs = surf (z); +%! axis manual +%! nframes = 50; +%! mov(nframes) = struct ("cdata", [], "colormap", []); +%! for ii = 1:nframes +%! set (hs, "zdata", z * sin (2*pi*ii/nframes)); +%! mov(ii) = getframe (); +%! endfor +%! clf (); +%! movie (mov, 5, 25); + +## Test input validation +%!error movie () +%!error <MOV must be a frame struct array> movie ({2}) +%!error <N must be a non-zero integer> +%! movie (struct ("cdata", [], "colormap", []), 2.3); +%!error <N must be a non-zero integer> +%! movie (struct ("cdata", [], "colormap", []), [2.3 -6]);