changeset 17853:aacb9da13df6

imwrite: implement LoopCount option. * __magick_read__.cc (F__magick_write__): set animationIterations() when writing an image to implement the LoopCount option. * private/__imwrite__.m: input check for the new option LoopCount and set its default. Also fix bug that was using varargin rather than the param/key cell to print error message on unknown option. * imwrite.m: document new option and its problems.
author Carnë Draug <carandraug@octave.org>
date Tue, 05 Nov 2013 05:05:11 +0000
parents 4de2eeb7d790
children adb0ba0d0c13
files libinterp/dldfcn/__magick_read__.cc scripts/image/imwrite.m scripts/image/private/__imwrite__.m
diffstat 3 files changed, 60 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/dldfcn/__magick_read__.cc	Mon Jun 24 16:02:54 2013 -0500
+++ b/libinterp/dldfcn/__magick_read__.cc	Tue Nov 05 05:05:11 2013 +0000
@@ -1408,6 +1408,32 @@
         }
     }
 
+      // FIXME - LoopCount or animationIterations
+      //  How it should work:
+      //
+      // This value is only set for the first image in the sequence. Trying
+      // to set this value with the append mode should have no effect, the
+      // value used with the first image is the one that counts (that would
+      // also be Matlab compatible). Thus, the right way to do this would be
+      // to have an else block on the condition above, and set this only
+      // when creating a new file. Since Matlab does not interpret a 4D
+      // matrix as sequence of images to write, its users need to use a for
+      // loop and set LoopCount only on the first iteration (it actually
+      // throws warnings otherwise)
+      //
+      //  Why is this not done the right way:
+      //
+      // When GM saves a single image, it discards the value if there is only
+      // a single image and sets it to "no loop".  Since our default is an
+      // infinite loop, if the user tries to do it the Matlab way (setting
+      // LoopCount only on the first image) that value will go nowhere.
+      // See https://sourceforge.net/p/graphicsmagick/bugs/248/
+      // Because of this, we document to set LoopCount on every iteration
+      // (in Matlab will cause a lot of warnings), or pass a 4D matrix with
+      // all frames (won't work in Matlab at all).
+      // Note that this only needs to be set on the first frame
+      imvec[0].animationIterations (options.getfield ("loopcount").uint_value ());
+
   write_file (filename, ext, imvec);
   if (error_state)
     return retval;
--- a/scripts/image/imwrite.m	Mon Jun 24 16:02:54 2013 -0500
+++ b/scripts/image/imwrite.m	Tue Nov 05 05:05:11 2013 +0000
@@ -47,6 +47,14 @@
 ## dimension must be a singleton.  By default, image will be completely
 ## opaque.
 ##
+## @item LoopCount
+## For formats that accept animations (such as GIF), controls how many times
+## the sequence is repeated.  A value of Inf means an infinite loop (default),
+## a value of 0 or 1 that the sequence is played only once (loops zero times),
+## while a value of 2 or above loops that number of times (looping twice means
+## it plays the complete sequence 3 times).  This option is ignored when there
+## is only a single image at the end of writing the file.
+##
 ## @item Quality
 ## Set the quality of the compression.  The value should be an
 ## integer between 0 and 100, with larger values indicating higher visual
--- a/scripts/image/private/__imwrite__.m	Mon Jun 24 16:02:54 2013 -0500
+++ b/scripts/image/private/__imwrite__.m	Tue Nov 05 05:05:11 2013 +0000
@@ -43,6 +43,7 @@
   ## set default for options
   options = struct ("writemode", "overwrite",
                     "quality",   75,
+                    "loopcount", 0, ## this is actually Inf
                     "alpha",     cast ([], class (img)));
 
   for idx = 1:2:numel (param_list)
@@ -82,8 +83,32 @@
         endif
         options.quality = round (options.quality);
 
+      case "loopcount"
+        options.loopcount = param_list{idx+1};
+        if (! isscalar (options.loopcount) || ! isnumeric (options.loopcount)
+            || (! isinf (options.loopcount) && (options.loopcount < 0 ||
+                                                options.loopcount > 65535)))
+          error ("imwrite: value for %s must be Inf or between 0 and 65535",
+                 param_list{idx});
+        endif
+        ## Graphics Magick is a bit weird here. A value of 0 will be an
+        ## infinite loop, a value of 1, will really be no loop, while a
+        ## value of 2 or more will be that number of loops (checked
+        ## with GNOME image viewer). This means that there is no way
+        ## to make it loop only once. See
+        ## https://sourceforge.net/p/graphicsmagick/bugs/249/
+        ## There is also the problem of setting this when there is only
+        ## a single frame. See
+        ## https://sourceforge.net/p/graphicsmagick/bugs/248/
+        if (isinf (options.loopcount))
+          options.loopcount = 0;
+        elseif (options.loopcount == 0 || options.loopcount == 1)
+          options.loopcount++;
+        endif
+        options.loopcount = floor (options.loopcount);
+
       otherwise
-        error ("imwrite: invalid PARAMETER `%s'", varargin{idx});
+        error ("imwrite: invalid PARAMETER `%s'", param_list{idx});
 
     endswitch
   endfor