[gimp-gap] added processing support for incomplete frame sequences.



commit 75e7ce26afb7e47591bf28cb6468c556915f6704
Author: Wolfgang Hofer <wolfgangh svn gnome org>
Date:   Sun Jul 21 11:40:44 2013 +0200

    added processing support for incomplete frame sequences.

 ChangeLog                        |  141 +++++++++++
 autogen.sh                       |    5 +-
 gap/Makefile.am                  |    8 +
 gap/gap_base_ops.c               |  208 +++++++++++++----
 gap/gap_image.c                  |   82 +++++--
 gap/gap_image.h                  |    5 +-
 gap/gap_lib.c                    |  478 ++++++++++++++++++++++++++++++--------
 gap/gap_lib.h                    |    4 +
 gap/gap_mod_layer.c              |   94 +++++---
 gap/gap_mov_exec.c               |  228 +++++++++++++++---
 gap/gap_mov_render.c             |   87 ++++++-
 gap/gap_mov_render.h             |    4 +-
 gap/gap_name2layer_main.c        |    3 +-
 gap/gap_navigator_dialog.c       |   34 +++-
 gap/gap_onion_base.c             |   46 +++--
 gap/gap_onion_worker.c           |   58 ++++-
 gap/gap_player_dialog.c          |  293 ++++++++++++++++++-----
 gap/gap_player_main.c            |    2 +
 gap/gap_player_main.h            |    3 +
 gap/gap_range_ops.c              |  178 ++++++++++----
 gap/gap_story_dialog.c           |   22 ++-
 gap/gap_story_main.h             |    2 +
 gap/gap_story_render_processor.c |  487 +++++++++++++++++++-------------------
 gap/gap_wr_layermode.c           |  409 ++++++++++++++++++++++++++++++++
 24 files changed, 2229 insertions(+), 652 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index ac172fd..44f4deb 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,144 @@
+2013-07-21 Wolfgang Hofer <hof gimp org>
+
+
+- Moved render framename feature to submenu.
+   from menu  <Image>/Video/Filename to Layer
+   to menu    <Image>/Video/Layer/Render/Filename to Layer
+ 
+   
+- added support for processing of incomplete frame sequences where some frame images are missing.
+  old behaviour handled this case as error condition and stopped processing.
+  new behaviour makes attempts to find the next available framenumber and continues
+  processing when a next frame image can be found.
+
+  The implemted strategy checks some (10) potential next frame numbers
+  and triggers a directory scan (that is more expensive tha a single file exists check)
+  in case when more frames are missing.
+  Example how this works:
+  
+      IMG_0050.XCF
+      IMG_0051.XCF
+      ............   (frames 52 to 59 are missing and will be checked via
+                      if (IMG_nr.XCF exists) in a loop.
+                      processing continues with IMG_0060.XCF)
+      IMG_0060.XCF
+      IMG_0061.XCF
+      IMG_0062.XCF
+      ............   (frames 62 to 89 are missing
+                      after 10 failed attempts if (IMG_nr.XCF exists)
+                      a directory scan is performed to find the next framenumber 90
+                      and processing continues with IMG_0090.XCF)
+      IMG_0090.XCF
+      
+  The following features (menu entries) were updated
+  to support the new behaviour:
+
+   Video/Go to/Next Frame
+   Video/Go to/Previous Frame
+   Video/Delete Frames
+   Video/Duplicate Frames
+   Video/Frames To Image
+   Video/Frames Flatten
+   Video/Frames Layer Delete
+ 
+   Video/Frames Convert
+   Video/Frames Resize
+   Video/Frames Crop
+   Video/Frames Scale
+   Video/Frame Sequence Shift
+   Video/Frame Sequence Reverse
+   Video/Frames Renumber
+   Video/Frames Modify
+
+   Video/VCR navigator
+     - dont show old thumbnails when corresponding image does (no longer) exits.
+     - show icons for all frames in range from first frame number up to last frame number.
+       all missing frames are shown but rendered as default icon.
+
+   Video/Onionskin/*
+     process all available frames in range but no longer stop
+     when frames are missing.
+     skip onionskin rendering whenever referenced frame 
+          (at number +n or -n) is not available.
+
+   Video/Playback   
+    implemented new preferences option to automatically skip missing frames at playback
+    OFF: missing frame images are shown as fully transparent (checker board) 
+    ON:  automatically step over missing frames
+    
+    this option is persisted as new gimprc parameter
+        "video_player_enable_auto_skip_missing_frames"
+        
+   Video/Movepath   
+    autoskip rendering of missing frames.
+    (and also skip missing frames in the moving object
+    when Frame based source stepmodes are used)
+
+
+   NOTE:
+      Missing frames in storyboard clips (with cliptype frames)
+      are still handled as ERROR.
+      .. and there are no plans to support autoskip of the missing frames there.
+         Because this would 
+         - remarkable slow down both storyboard rendering and editing.
+           To get the amount of frames included in a clip
+           this feature would require a directory scan
+           and not just a simple calculation 1 + (end_range - start_range)
+         - be much effort and makes the code more complex..
+
+
+           
+
+
+  * gap/gap_lib.c [.h]
+  * gap/gap_image.c [.h]
+  * gap/gap_base_ops.c
+  * gap/gap_range_ops.c
+  * gap/gap_mod_layer.c
+  * gap/gap_player_main.c [.h]
+  * gap/gap_player_dialog.c
+  * gap/gap_story_main.h 
+  * gap/gap_story_dialog.c 
+  * gap/gap_story_render_processor.c 
+  * gap/gap_navigator_dialog.c
+  * gap/gap_name2layer_main.c  
+  * gap/gap_onion_base.c
+  * gap/gap_onion_worker.c
+
+  * gap/gap_mov_exec.c
+  * gap/gap_mov_render.c [.h]
+
+
+
+
+   (added local features from 2013-06-02 that were not yet published until now)
+
+- workaround for winodows specific Audio Playback deadlock on short clips (only 1 frame)
+
+- added capability to set layermode in storyboard processing via filtermacro.
+   Therfore GIMP-GAP now provides a wrapper plug-in (gap_wr_layermode.c)
+   to set the layermode.
+   This wrapper plug-in can be recorded as filtermacro, and applied
+   to clips while storyboard processing via filtermacro calls.
+
+- support autogen versions 1.13 1.12 (as suggested in #699207)
+
+- Storyboard toggle unit support to display src frame number and frame count
+  as additional mode.
+
+
+
+  * autogen.sh
+  * gap/Makefile.am
+  * gap/gap_wr_layermode.c # new file
+  
+  * gap/gap_player_dialog.c
+  * gap/gap_range_ops.c
+  * gap/gap_story_render_processor.c 
+  * gap/gap_story_dialog.c
+  * gap/gap_story_main.h
+
+
 2013-02-20 Wolfgang Hofer <hof gimp org>
 
 - 2nd. bugfix for creation of storyboard from video extract plug-in.
diff --git a/autogen.sh b/autogen.sh
index 2a9097e..340b704 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -88,7 +88,10 @@ fi
 
 
 echo -n "checking for automake >= $AUTOMAKE_REQUIRED_VERSION ... "
-if (automake-1.12 --version) < /dev/null > /dev/null 2>&1; then
+if (automake-1.13 --version) < /dev/null > /dev/null 2>&1; then
+   AUTOMAKE=automake-1.13
+   ACLOCAL=aclocal-1.13
+elif (automake-1.12 --version) < /dev/null > /dev/null 2>&1; then
    AUTOMAKE=automake-1.12
    ACLOCAL=aclocal-1.12
 elif (automake-1.11 --version) < /dev/null > /dev/null 2>&1; then
diff --git a/gap/Makefile.am b/gap/Makefile.am
index 058948b..c17362c 100644
--- a/gap/Makefile.am
+++ b/gap/Makefile.am
@@ -160,6 +160,7 @@ libexec_PROGRAMS = \
        gap_wr_color_balance    \
        gap_wr_trans            \
        gap_wr_resynth          \
+       gap_wr_layermode        \
        gap_wr_opacity
 
 
@@ -461,6 +462,12 @@ gap_wr_trans_SOURCES = \
        gap_wr_trans.c  \
        gap_libgimpgap.h        
 
+gap_wr_layermode_SOURCES = \
+       gap_lastvaldesc.c       \
+       gap_lastvaldesc.h       \
+       gap_wr_layermode.c      \
+       gap_libgimpgap.h        
+
 gap_wr_color_curve_SOURCES = \
        gap_wr_color_curve.c    \
        gap_libgimpgap.h        
@@ -531,6 +538,7 @@ gap_fire_pattern_LDADD =     $(LIBGIMPGAP)  $(LIBGAPBASE) $(GIMP_LIBS)
 gap_water_pattern_LDADD =    $(LIBGIMPGAP)  $(LIBGAPBASE) $(GIMP_LIBS)
 gap_wr_opacity_LDADD =       $(LIBGIMPGAP)  $(LIBGAPBASE) $(GIMP_LIBS)
 gap_wr_trans_LDADD =         $(LIBGIMPGAP)  $(LIBGAPBASE) $(GIMP_LIBS)
+gap_wr_layermode_LDADD =     $(LIBGIMPGAP)  $(LIBGAPBASE) $(GIMP_LIBS)
 gap_wr_color_curve_LDADD =   $(LIBGIMPGAP)  $(LIBGAPBASE) $(GIMP_LIBS)
 gap_wr_color_levels_LDADD =  $(LIBGIMPGAP)  $(LIBGAPBASE) $(GIMP_LIBS)
 gap_wr_color_huesat_LDADD =  $(LIBGIMPGAP)  $(LIBGAPBASE) $(GIMP_LIBS)
diff --git a/gap/gap_base_ops.c b/gap/gap_base_ops.c
index 3b2227c..b653db4 100644
--- a/gap/gap_base_ops.c
+++ b/gap/gap_base_ops.c
@@ -431,6 +431,7 @@ static gint32
 p_del(GapAnimInfo *ainfo_ptr, long cnt)
 {
    long  l_lo, l_hi, l_curr, l_idx;
+   gboolean l_hi_frame_found;
 
    if(gap_debug) fprintf(stderr, "DEBUG  p_del\n");
 
@@ -463,19 +464,28 @@ p_del(GapAnimInfo *ainfo_ptr, long cnt)
     */
    l_lo   = l_curr;
    l_hi   = l_curr + cnt;
+   l_hi_frame_found = gap_lib_framefile_with_framenr_exists(ainfo_ptr, l_hi);
    while(l_hi <= ainfo_ptr->last_frame_nr)
    {
-     if(0 != gap_lib_rename_frame(ainfo_ptr, l_hi, l_lo))
+     l_lo = l_hi - cnt;
+     if(l_hi_frame_found)
      {
-        gchar *tmp_errtxt;
+      if(0 != gap_lib_rename_frame(ainfo_ptr, l_hi, l_lo))
+      {
+         gchar *tmp_errtxt;
 
-        tmp_errtxt = g_strdup_printf(_("Error: could not rename frame %ld to %ld") ,l_hi, l_lo);
-        gap_arr_msg_win(ainfo_ptr->run_mode, tmp_errtxt);
-        g_free(tmp_errtxt);
-        return -1;
+         tmp_errtxt = g_strdup_printf(_("Error: could not rename frame %ld to %ld") ,l_hi, l_lo);
+         gap_arr_msg_win(ainfo_ptr->run_mode, tmp_errtxt);
+         g_free(tmp_errtxt);
+         return -1;
+       }
      }
-     l_lo++;
-     l_hi++;
+     /* advance l_hi to the next available frame number 
+      * (normally to l_hi += 1; sometimes to higher number when frames are missing) 
+      */
+     l_hi = gap_lib_get_next_available_frame_number(l_hi, 1
+                           , ainfo_ptr->basename, ainfo_ptr->extension, &l_hi_frame_found);
+
    }
 
    /* calculate how much frames are left */
@@ -525,6 +535,7 @@ p_dup(GapAnimInfo *ainfo_ptr, long cnt, long range_from, long range_to)
    char  *l_dup_name;
    char  *l_curr_name;
    gdouble    l_percentage, l_percentage_step;
+   gboolean   l_lo_frame_found;
 
    if(gap_debug) fprintf(stderr, "DEBUG  p_dup fr:%d to:%d cnt:%d extension:%s: basename:%s frame_cnt:%d\n",
                          (int)range_from, (int)range_to, (int)cnt, ainfo_ptr->extension, 
ainfo_ptr->basename, (int)ainfo_ptr->frame_cnt);
@@ -596,18 +607,26 @@ p_dup(GapAnimInfo *ainfo_ptr, long cnt, long range_from, long range_to)
     */
    l_lo   = ainfo_ptr->last_frame_nr;
    l_hi   = l_lo + l_cnt2;
+   l_lo_frame_found = gap_lib_framefile_with_framenr_exists(ainfo_ptr, l_hi);
    while(l_lo > l_src_nr_max)
    {
-     if(0 != gap_lib_rename_frame(ainfo_ptr, l_lo, l_hi))
+     l_hi   = l_lo + l_cnt2;
+     if (l_lo_frame_found)
      {
-        gchar *tmp_errtxt;
-        tmp_errtxt = g_strdup_printf(_("Error: could not rename frame %ld to %ld"), l_lo, l_hi);
-        gap_arr_msg_win(ainfo_ptr->run_mode, tmp_errtxt);
-        g_free(tmp_errtxt);
-        return -1;
+      if(0 != gap_lib_rename_frame(ainfo_ptr, l_lo, l_hi))
+      {
+         gchar *tmp_errtxt;
+         tmp_errtxt = g_strdup_printf(_("Error: could not rename frame %ld to %ld"), l_lo, l_hi);
+         gap_arr_msg_win(ainfo_ptr->run_mode, tmp_errtxt);
+         g_free(tmp_errtxt);
+         return -1;
+       }
      }
-     l_lo--;
-     l_hi--;
+     /* advance l_lo to the previous available frame number 
+      * (normally to l_lo -= 1; sometimes to lower number when frames are missing) 
+      */
+     l_lo = gap_lib_get_next_available_frame_number(l_lo, -1
+               , ainfo_ptr->basename, ainfo_ptr->extension, &l_lo_frame_found);
    }
 
 
@@ -626,7 +645,10 @@ p_dup(GapAnimInfo *ainfo_ptr, long cnt, long range_from, long range_to)
       l_dup_name = gap_lib_alloc_fname(ainfo_ptr->basename, l_hi, ainfo_ptr->extension);
       if((l_dup_name != NULL) && (l_curr_name != NULL))
       {
-         gap_lib_image_file_copy(l_curr_name, l_dup_name);
+         if (g_file_test(l_curr_name, G_FILE_TEST_EXISTS))
+         {
+           gap_lib_image_file_copy(l_curr_name, l_dup_name);
+         }
          g_free(l_dup_name);
          g_free(l_curr_name);
       }
@@ -742,6 +764,7 @@ p_shift(GapAnimInfo *ainfo_ptr, long cnt, long range_from, long range_to)
    long  l_shift;
    gchar *l_curr_name;
    gchar *tmp_errtxt;
+   gboolean l_frame_found;
 
    gdouble    l_percentage, l_percentage_step;
 
@@ -787,41 +810,59 @@ p_shift(GapAnimInfo *ainfo_ptr, long cnt, long range_from, long range_to)
      gimp_progress_init( _("Renumber frame sequence..."));
    }
 
-   /* rename (renumber) all frames (using high numbers)
+   /* rename (renumber) all frames 
+    * (using higher numbers than last available frame number)
     */
 
    l_upper = ainfo_ptr->last_frame_nr +100;
    l_percentage_step = 0.5 / ((1.0 + l_lo) - l_hi);
-   for(l_curr = l_lo; l_curr <= l_hi; l_curr++)
+   l_curr = l_lo;
+   while (l_curr <= l_hi)
    {
-     if(0 != gap_lib_rename_frame(ainfo_ptr, l_curr, l_curr + l_upper))
+     l_frame_found = gap_lib_framefile_with_framenr_exists(ainfo_ptr, l_curr);
+     if (l_frame_found)
      {
-        tmp_errtxt = g_strdup_printf(_("Error: could not rename frame %ld to %ld"), l_lo, l_hi);
-        gap_arr_msg_win(ainfo_ptr->run_mode, tmp_errtxt);
-        g_free(tmp_errtxt);
-        return -1;
+       if(0 != gap_lib_rename_frame(ainfo_ptr, l_curr, l_curr + l_upper))
+       {
+         tmp_errtxt = g_strdup_printf(_("Error: could not rename frame %ld to %ld"), l_lo, l_hi);
+         gap_arr_msg_win(ainfo_ptr->run_mode, tmp_errtxt);
+         g_free(tmp_errtxt);
+         return -1;
+       }
      }
      if(ainfo_ptr->run_mode == GIMP_RUN_INTERACTIVE)
      {
        l_percentage += l_percentage_step;
        gimp_progress_update (l_percentage);
      }
+     /* advance l_curr to the next available frame number 
+      * (normally to l_curr += 1; sometimes to higher number when frames are missing) 
+      */
+     l_curr = gap_lib_get_next_available_frame_number(l_curr, 1
+                           , ainfo_ptr->basename, ainfo_ptr->extension, &l_frame_found);
    }
 
-   /* rename (renumber) all frames (using desied destination numbers)
+   /* rename (renumber) all frames (using desired destination numbers)
     */
    l_dst = l_lo + l_shift;
    if (l_dst > l_hi) { l_dst -= (l_lo -1); }
    if (l_dst < l_lo) { l_dst += ((l_hi - l_lo) +1); }
    for(l_curr = l_upper + l_lo; l_curr <= l_upper + l_hi; l_curr++)
    {
-     if (l_dst > l_hi) { l_dst = l_lo; }
-     if(0 != gap_lib_rename_frame(ainfo_ptr, l_curr, l_dst))
+     if (l_dst > l_hi) 
      {
-        tmp_errtxt = g_strdup_printf(_("Error: could not rename frame %ld to %ld"), l_lo, l_hi);
-        gap_arr_msg_win(ainfo_ptr->run_mode, tmp_errtxt);
-        g_free(tmp_errtxt);
-        return -1;
+       l_dst = l_lo; 
+     }
+     l_frame_found = gap_lib_framefile_with_framenr_exists(ainfo_ptr, l_curr);
+     if (l_frame_found)
+     {
+       if(0 != gap_lib_rename_frame(ainfo_ptr, l_curr, l_dst))
+       {
+         tmp_errtxt = g_strdup_printf(_("Error: could not rename frame %ld to %ld"), l_lo, l_hi);
+         gap_arr_msg_win(ainfo_ptr->run_mode, tmp_errtxt);
+         g_free(tmp_errtxt);
+         return -1;
+       }
      }
      if(ainfo_ptr->run_mode == GIMP_RUN_INTERACTIVE)
      {
@@ -845,10 +886,17 @@ p_shift(GapAnimInfo *ainfo_ptr, long cnt, long range_from, long range_to)
 /* ============================================================================
  * p_reverse
  *
- * all frames in the given range are renumbered in reverse order
+ * all frames in the given range are renamed to reverse the order of the frame sequence range.
+ * Note that frame numbers in the range will be the same before and after this procdure,
+ * but content of the frame images is swapped.
  *
- *  example:  range before 3, 4, 5, 6, 7
- *            range after  7, 6, 5, 4, 3
+ *  examples:
+ *      A,B,C  .... image content with FrameNumber (n)
+ *   range before A(3), B(4), C(5), D(6), E(7)
+ *   range after  E(3), D(4), C(5), B(6), A(7)
+ *
+ *   range before A(3), B(4), C(7), D(21), E(22), F(51)
+ *   range after  F(3), E(4), D(7), C(21), B(22), A(51)
  *
  * return image_id (of the new loaded frame) on success
  *        or -1 on errors
@@ -861,7 +909,6 @@ p_reverse(GapAnimInfo *ainfo_ptr, long range_from, long range_to)
    long  l_lo, l_hi, l_curr;
    long  l_swap;
    gchar *tmp_errtxt;
-
    gdouble    l_percentage;
 
    l_tmp_nr = ainfo_ptr->last_frame_nr + 4;  /* use a free frame_nr for temp name */
@@ -902,11 +949,49 @@ p_reverse(GapAnimInfo *ainfo_ptr, long range_from, long range_to)
      gimp_progress_init( _("Renumber frame sequence..."));
    }
 
-   /* swap lo with high for each of the (first half of the) frames */
-   for(l_curr = l_lo; l_curr < l_lo + ((l_hi - l_lo + 1) / 2); l_curr++)
+
+   /* swap lo with high for each of the (first half of the) frames
+    * to reverse the frame sequence.
+    */
+   l_curr = l_lo;
+   l_swap = l_hi - (l_curr - l_lo);
+   while(1)
    {
-     l_swap = l_hi - (l_curr - l_lo);
-     /* rename hi to temp */
+     gboolean l_cur_frame_found;
+     gboolean l_swap_frame_found;
+     
+     l_cur_frame_found = gap_lib_framefile_with_framenr_exists(ainfo_ptr, l_curr);
+     if(l_cur_frame_found != TRUE)
+     {
+       /* advance l_curr to the next available frame number 
+        * (normally to l_curr += 1; 
+        * sometimes to higher number when frames are missing) 
+        */
+       l_curr = gap_lib_get_next_available_frame_number(l_curr, 1
+                           , ainfo_ptr->basename, ainfo_ptr->extension, &l_cur_frame_found);
+     }
+     l_swap_frame_found = gap_lib_framefile_with_framenr_exists(ainfo_ptr, l_swap);
+     if(l_swap_frame_found != TRUE)
+     {
+       /* advance l_swap to the previous available frame number 
+        * (normally to l_swap -= 1; 
+        * sometimes to lower number when frames are missing) 
+        */
+       l_swap = gap_lib_get_next_available_frame_number(l_swap, -1
+                           , ainfo_ptr->basename, ainfo_ptr->extension, &l_swap_frame_found);
+     }
+     
+     if ((l_cur_frame_found != TRUE) 
+     ||  (l_swap_frame_found != TRUE)
+     ||  (l_swap <= l_curr))
+     {
+        /* stop when no more frames found for swapping 
+         * or all framenames in the range are already swapped.
+         */
+        break;  
+     }
+
+     /* rename hi (l_swap) to temp */
      if(0 != gap_lib_rename_frame(ainfo_ptr, l_swap, l_tmp_nr))
      {
        tmp_errtxt = g_strdup_printf(_("Error: could not rename frame %ld to %ld"), l_swap, l_tmp_nr);
@@ -928,7 +1013,7 @@ p_reverse(GapAnimInfo *ainfo_ptr, long range_from, long range_to)
        tmp_errtxt = g_strdup_printf(_("Error: could not rename frame %ld to %ld"), l_tmp_nr, 
ainfo_ptr->curr_frame_nr);
        gap_arr_msg_win(ainfo_ptr->run_mode, tmp_errtxt);
        g_free(tmp_errtxt);
-     return -1;
+       return -1;
      }
      if (ainfo_ptr->run_mode == GIMP_RUN_INTERACTIVE)
      {
@@ -936,6 +1021,8 @@ p_reverse(GapAnimInfo *ainfo_ptr, long range_from, long range_to)
        if (l_percentage > 1.0) l_percentage = 1.0;
        gimp_progress_update (l_percentage);
      }
+     l_curr++;
+     l_swap--;
    }
 
    /* load from the "new" current frame */
@@ -966,8 +1053,17 @@ gap_base_next(GimpRunMode run_mode, gint32 image_id)
   ainfo_ptr = gap_lib_alloc_ainfo(image_id, run_mode);
   if(ainfo_ptr != NULL)
   {
-    ainfo_ptr->frame_nr = ainfo_ptr->curr_frame_nr + 1;
-    rc = gap_lib_replace_image(ainfo_ptr);
+    gboolean l_frame_found;
+ 
+    ainfo_ptr->frame_nr = 
+          gap_lib_get_next_available_frame_number(ainfo_ptr->curr_frame_nr, 1
+                      , ainfo_ptr->basename, ainfo_ptr->extension
+                      , &l_frame_found
+                      );
+    if (l_frame_found)
+    {
+      rc = gap_lib_replace_image(ainfo_ptr);
+    }
 
     gap_lib_free_ainfo(&ainfo_ptr);
   }
@@ -985,8 +1081,16 @@ gap_base_prev(GimpRunMode run_mode, gint32 image_id)
   ainfo_ptr = gap_lib_alloc_ainfo(image_id, run_mode);
   if(ainfo_ptr != NULL)
   {
-    ainfo_ptr->frame_nr = ainfo_ptr->curr_frame_nr - 1;
-    rc = gap_lib_replace_image(ainfo_ptr);
+    gboolean l_frame_found;
+    ainfo_ptr->frame_nr = 
+          gap_lib_get_next_available_frame_number(ainfo_ptr->curr_frame_nr, -1
+                      , ainfo_ptr->basename, ainfo_ptr->extension
+                      , &l_frame_found
+                      );
+    if (l_frame_found)
+    {
+      rc = gap_lib_replace_image(ainfo_ptr);
+    }
 
     gap_lib_free_ainfo(&ainfo_ptr);
   }
@@ -1053,7 +1157,6 @@ gap_base_last(GimpRunMode run_mode, gint32 image_id)
  *    show dialogwindow where user can enter the destination frame Nr.
  * ============================================================================
  */
-
 gint32
 gap_base_goto(GimpRunMode run_mode, gint32 image_id, int nr)
 {
@@ -1160,12 +1263,14 @@ gap_base_del(GimpRunMode run_mode, gint32 image_id, int nr)
   GapAnimInfo *ainfo_ptr;
 
   long           l_cnt;
+  long           l_delete_to_frame_nr;
   long           l_max;
   gchar         *l_hline;
   gchar         *l_title;
   gchar         *l_tooltip;
 
   rc = -1;
+  l_cnt = -1;
   ainfo_ptr = gap_lib_alloc_ainfo(image_id, run_mode);
   if(ainfo_ptr != NULL)
   {
@@ -1194,7 +1299,7 @@ gap_base_del(GimpRunMode run_mode, gint32 image_id, int nr)
         l_tooltip = g_strdup_printf(_("Delete frames starting at current number %d "
                                       "up to this number (inclusive)")
                     , (int)ainfo_ptr->curr_frame_nr );
-        l_cnt = gap_arr_slider_dialog(l_title, l_hline
+        l_delete_to_frame_nr = gap_arr_slider_dialog(l_title, l_hline
               , _("Number:")
               , l_tooltip
               , ainfo_ptr->curr_frame_nr
@@ -1207,9 +1312,9 @@ gap_base_del(GimpRunMode run_mode, gint32 image_id, int nr)
         g_free (l_title);
         g_free (l_hline);
 
-        if(l_cnt >= 0)
+        if(l_delete_to_frame_nr >= 0)
         {
-           l_cnt = 1 + l_cnt - ainfo_ptr->curr_frame_nr;
+           l_cnt = 1 + l_delete_to_frame_nr - ainfo_ptr->curr_frame_nr;
 
            /* ask the user to confirm delete (there is no undo) */
            if(!p_delete_confirm_dialog(ainfo_ptr
@@ -2065,7 +2170,12 @@ p_renumber_frames(GapAnimInfo *ainfo_ptr, long start_frame_nr, long digits)
         l_to--;
         l_cnt++;
       }
-      l_from--;
+      /* advance l_from to the previous available frame number 
+       * (normally to l_from -= 1; sometimes to lower number when frames are missing) 
+       */
+      l_from = gap_lib_get_next_available_frame_number(l_from, -1
+               , ainfo_ptr->basename, ainfo_ptr->extension, NULL);
+
       if(ainfo_ptr->run_mode == GIMP_RUN_INTERACTIVE)
       {
         gimp_progress_update( (gdouble)(l_cnt)
diff --git a/gap/gap_image.c b/gap/gap_image.c
index 794748a..1ea1cf4 100644
--- a/gap/gap_image.c
+++ b/gap/gap_image.c
@@ -55,14 +55,14 @@ gap_image_delete_immediate (gint32 image_id)
   gboolean imageDeleteWorkaroundDefault = TRUE;
   if(gap_base_get_gimprc_gboolean_value("gap-image-delete-workaround"
          , imageDeleteWorkaroundDefault))
-  {         
+  {
     if(gap_debug)
     {
       printf("gap_image_delete_immediate: SCALED down to 2x2 id = %d (workaround for gimp_image-delete 
problem)\n"
               , (int)image_id
               );
     }
-    
+
     gimp_image_undo_disable(image_id);
 
     gimp_image_scale_full(image_id, 2, 2, 0 /*INTERPOLATION_NONE*/);
@@ -135,7 +135,7 @@ void gap_image_prevent_empty_image(gint32 image_id)
      g_free (l_layers_list);
   }
   else l_nlayers = 0;
-  
+
   if(l_nlayers == 0)
   {
      /* the resulting image has no layer, add a transparent dummy layer */
@@ -150,7 +150,7 @@ void gap_image_prevent_empty_image(gint32 image_id)
      /* add a transparent dummy layer */
      l_layer_id = gimp_layer_new(image_id, "dummy",
                                     l_width, l_height,  l_type,
-                                    0.0,       /* Opacity full transparent */     
+                                    0.0,       /* Opacity full transparent */
                                     0);        /* NORMAL */
      gimp_image_add_layer(image_id, l_layer_id, 0);
   }
@@ -162,11 +162,11 @@ void gap_image_prevent_empty_image(gint32 image_id)
 /* ============================================================================
  * gap_image_new_with_layer_of_samesize
  * ============================================================================
- * create empty image 
+ * create empty image
  *  if layer_id is NOT NULL then create one full transparent layer at full image size
  *  and return the layer_id
  */
-gint32  
+gint32
 gap_image_new_with_layer_of_samesize(gint32 old_image_id, gint32 *layer_id)
 {
   GimpImageBaseType  l_type;
@@ -176,7 +176,7 @@ gap_image_new_with_layer_of_samesize(gint32 old_image_id, gint32 *layer_id)
   gdouble     l_xresoulution, l_yresoulution;
   gint32     l_unit;
 
-  
+
   /* create empty image  */
   l_width  = gimp_image_width(old_image_id);
   l_height = gimp_image_height(old_image_id);
@@ -187,29 +187,29 @@ gap_image_new_with_layer_of_samesize(gint32 old_image_id, gint32 *layer_id)
   new_image_id = gimp_image_new(l_width, l_height,l_type);
   gimp_image_set_resolution(new_image_id, l_xresoulution, l_yresoulution);
   gimp_image_set_unit(new_image_id, l_unit);
-  
+
   if(layer_id)
   {
     l_type   = (l_type * 2); /* convert from GimpImageBaseType to GimpImageType */
     *layer_id = gimp_layer_new(new_image_id, "dummy",
                                  l_width, l_height,  l_type,
-                                 0.0,       /* Opacity full transparent */     
+                                 0.0,       /* Opacity full transparent */
                                  0);        /* NORMAL */
     gimp_image_add_layer(new_image_id, *layer_id, 0);
   }
-  
+
   return (new_image_id);
-  
+
 }  /* end gap_image_new_with_layer_of_samesize */
 
-gint32 
+gint32
 gap_image_new_of_samesize(gint32 old_image_id)
 {
   return(gap_image_new_with_layer_of_samesize(old_image_id, NULL));
 }
 
 
- 
+
 /* ------------------------------------
  * gap_image_is_alive
  * ------------------------------------
@@ -251,15 +251,15 @@ gap_image_is_alive(gint32 image_id)
   }
 
   if(gap_debug) printf("gap_image_is_alive: image_id %d is not VALID\n", (int)image_id);
- 
+
   return FALSE ;   /* INVALID image id */
 }  /* end gap_image_is_alive */
- 
- 
+
+
 /* ------------------------------------
  * gap_image_get_any_layer
  * ------------------------------------
- * return the id of the active layer 
+ * return the id of the active layer
  *   or the id of the first layer found in the image if there is no active layer
  *   or -1 if the image has no layer at all.
  */
@@ -284,7 +284,7 @@ gap_image_get_any_layer(gint32 image_id)
 }  /* end gap_image_get_any_layer */
 
 
- 
+
 /* ------------------------------------
  * gap_image_merge_to_specified_layer
  * ------------------------------------
@@ -302,7 +302,7 @@ gap_image_merge_to_specified_layer(gint32 ref_layer_id, GimpMergeType mergemode)
     gint32  l_idx;
     gint    l_nlayers;
     gint32 *l_layers_list;
-    
+
     l_layers_list = gimp_image_get_layers(l_image_id, &l_nlayers);
     if(l_layers_list != NULL)
     {
@@ -416,7 +416,7 @@ gap_image_set_selection_from_selection_or_drawable(gint32 image_id, gint32 ref_d
   gimp_selection_all(image_id);
   //l_sel_channel_id = gimp_image_get_selection(image_id);
   l_aux_channel_id = gimp_selection_save(image_id);
-  
+
   /* copy the work drawable (layer or channel) into the selection channel
    * the work layer is a grayscale copy GRAY or GRAYA of the alt_selection layer
    *  that is already scaled and resized to fit the size of the target image
@@ -456,7 +456,7 @@ gap_image_remove_invisble_layers(gint32 image_id)
   if(l_layers_list != NULL)
   {
     int ii;
-    
+
     for(ii=0; ii < l_nlayers; ii++)
     {
       if (gimp_drawable_get_visible(l_layers_list[ii]) != TRUE)
@@ -482,7 +482,7 @@ gap_image_remove_all_guides(gint32 image_id)
   {
     guide_id = 0;  /* 0 starts find at 1st guide */
     guide_id = gimp_image_find_next_guide(image_id, guide_id);
-    
+
     if (guide_id < 1)
     {
        break;
@@ -490,7 +490,7 @@ gap_image_remove_all_guides(gint32 image_id)
     gimp_image_delete_guide(image_id, guide_id);
   }
 
-  
+
 }  /* end gap_image_remove_all_guides */
 
 
@@ -517,7 +517,7 @@ gap_image_limit_layers(gint32 image_id, gint keepTopLayers,  gint keepBgLayers)
   if(l_layers_list != NULL)
   {
     int ii;
-    
+
     for(ii=0; ii < l_nlayers; ii++)
     {
       if ((ii >= keepTopLayers)
@@ -532,3 +532,37 @@ gap_image_limit_layers(gint32 image_id, gint keepTopLayers,  gint keepBgLayers)
 }  /* end gap_image_limit_layers */
 
 
+/* ----------------------------------------------------
+ * gap_image_create_unicolor_image
+ * ----------------------------------------------------
+ * - create a new image with one black filled layer
+ *   (both have the requested size)
+ *
+ * return the new created image_id
+ *   and the layer_id of the black_layer
+ */
+gint32
+gap_image_create_unicolor_image(gint32 *layer_id, gint32 width , gint32 height
+                       , gdouble r_f, gdouble g_f, gdouble b_f, gdouble a_f)
+{
+  gint32 l_empty_layer_id;
+  gint32 l_image_id;
+
+  *layer_id = -1;
+  l_image_id = gimp_image_new(width, height, GIMP_RGB);
+  if(l_image_id >= 0)
+  {
+    l_empty_layer_id = gimp_layer_new(l_image_id, "black_background",
+                          width, height,
+                          GIMP_RGBA_IMAGE,
+                          100.0,     /* Opacity full opaque */
+                          GIMP_NORMAL_MODE);
+    gimp_image_add_layer(l_image_id, l_empty_layer_id, 0);
+
+    /* clear layer to unique color */
+    gap_layer_clear_to_color(l_empty_layer_id, r_f, g_f, b_f, a_f);
+
+    *layer_id = l_empty_layer_id;
+  }
+  return(l_image_id);
+}       /* end gap_image_create_unicolor_image */
diff --git a/gap/gap_image.h b/gap/gap_image.h
index f716d5c..f90e484 100644
--- a/gap/gap_image.h
+++ b/gap/gap_image.h
@@ -34,7 +34,7 @@
 
 #include "config.h"
 
-/* SYTEM (UNIX) includes */ 
+/* SYTEM (UNIX) includes */
 #include <stdio.h>
 #include <stdlib.h>
 
@@ -57,6 +57,9 @@ void      gap_image_remove_invisble_layers(gint32 image_id);
 void      gap_image_remove_all_guides(gint32 image_id);
 void      gap_image_limit_layers(gint32 image_id, gint keepTopLayers,  gint keepBgLayers);
 
+gint32    gap_image_create_unicolor_image(gint32 *layer_id, gint32 width , gint32 height
+                       , gdouble r_f, gdouble g_f, gdouble b_f, gdouble a_f);
+
 
 #endif
 
diff --git a/gap/gap_lib.c b/gap/gap_lib.c
index 701d844..0b2cf32 100644
--- a/gap/gap_lib.c
+++ b/gap/gap_lib.c
@@ -168,7 +168,7 @@ static gint32       p_set_or_pick_active_layer_by_name(gint32 image_id
                           ,gboolean setActiveLayer
                           ,gboolean ignoreOnionLayers
                           );
-                          
+
 
 static gchar *      p_get_active_layer_name(gint32 image_id
                        ,gint32 *active_layer
@@ -194,6 +194,11 @@ static gint32       p_lib_save_named_image2(gint32 image_id, const char *sav_nam
 static char*        p_gzip (char *orig_name, char *new_name, char *zip);
 
 
+long     gap_lib_dir_find_next_frame_number(long cur_frame_nr, long stepsize,
+            char *basename, char *extension, gboolean *frame_found_ptr);
+long     gap_lib_dir_find_next_frame_number_for_imagename(long stepsize,
+            char *imagename, gboolean *frame_found_ptr);
+
 
 
 /* ------------------------------------
@@ -224,7 +229,7 @@ gap_lib_layer_tracking(gint32 image_id
                     )
 {
   gint32 l_matching_layer_id;
-  
+
   l_matching_layer_id = -1;
   if (trackByName)
   {
@@ -239,7 +244,7 @@ gap_lib_layer_tracking(gint32 image_id
       return(l_matching_layer_id);
     }
   }
-  
+
   if (trackByStackPosition)
   {
     l_matching_layer_id = p_set_or_pick_active_layer_by_pos(image_id
@@ -250,7 +255,7 @@ gap_lib_layer_tracking(gint32 image_id
   }
 
   return(l_matching_layer_id);
-  
+
 }  /* end gap_lib_layer_tracking */
 
 
@@ -308,10 +313,10 @@ p_set_or_pick_active_layer_by_pos(gint32 image_id
         l_pos++;
       }
     }
-    
+
     g_free(l_layers_list);
   }
-  
+
   if(l_matching_layer_id >= 0)
   {
     if(setActiveLayer == TRUE)
@@ -322,7 +327,7 @@ p_set_or_pick_active_layer_by_pos(gint32 image_id
     if(gap_debug)
     {
       char       *l_name;
-     
+
       l_name = gimp_drawable_get_name(l_matching_layer_id);
       if(setActiveLayer == TRUE)
       {
@@ -341,13 +346,13 @@ p_set_or_pick_active_layer_by_pos(gint32 image_id
       if(l_name)
       {
         g_free(l_name);
-      }     
+      }
     }
     return (l_matching_layer_id);
   }
-  
+
   return (-1);
-  
+
 }  /* end p_set_or_pick_active_layer_by_pos */
 
 
@@ -389,17 +394,17 @@ p_set_or_pick_active_layer_by_name(gint32 image_id
   l_pos = 0;
   l_max_score = 0;
   l_matching_layer_id = -1;
-  
+
   if(ref_layer_name == NULL)
   {
     return(p_set_or_pick_active_layer_by_pos(image_id, ref_layer_stackpos, setActiveLayer, 
ignoreOnionLayers));
   }
-  
+
   if(!g_utf8_validate(ref_layer_name, -1, NULL))
   {
     return(p_set_or_pick_active_layer_by_pos(image_id, ref_layer_stackpos, setActiveLayer, 
ignoreOnionLayers));
   }
-  
+
   l_ref_len = g_utf8_strlen(ref_layer_name, -1);
   l_layers_list = gimp_image_get_layers(image_id, &l_nlayers);
   if(l_layers_list)
@@ -428,7 +433,7 @@ p_set_or_pick_active_layer_by_name(gint32 image_id
           {
             gunichar refname_char;
             gunichar layername_char;
-            
+
             refname_char = g_utf8_get_char(uni_ref_ptr);
             layername_char = g_utf8_get_char(uni_nam_ptr);
 
@@ -468,7 +473,7 @@ p_set_or_pick_active_layer_by_name(gint32 image_id
 
         g_free(l_layer_name);
       }
-      
+
       if(l_score == l_max_score)
       {
         /* stackposition is checked as secondary criterium
@@ -483,8 +488,8 @@ p_set_or_pick_active_layer_by_name(gint32 image_id
         {
           l_is_layer_ignored = FALSE;
         }
-        
-        
+
+
         if(!l_is_layer_ignored)
         {
           if(l_pos == ref_layer_stackpos)
@@ -500,10 +505,10 @@ p_set_or_pick_active_layer_by_name(gint32 image_id
         l_max_score = l_score;
       }
     }
-    
+
     g_free(l_layers_list);
   }
-  
+
   if(l_matching_layer_id >= 0)
   {
     if (setActiveLayer == TRUE)
@@ -514,7 +519,7 @@ p_set_or_pick_active_layer_by_name(gint32 image_id
     if(gap_debug)
     {
       char       *l_name;
-     
+
       l_name = gimp_drawable_get_name(l_matching_layer_id);
       if (setActiveLayer == TRUE)
       {
@@ -533,11 +538,11 @@ p_set_or_pick_active_layer_by_name(gint32 image_id
       if(l_name)
       {
         g_free(l_name);
-      }     
+      }
     }
     return (l_matching_layer_id);
   }
-  
+
   return (-1);
 }  /* end p_set_or_pick_active_layer_by_name */
 
@@ -563,12 +568,12 @@ p_get_active_layer_name(gint32 image_id
   gint        l_pos;
   gboolean    l_is_onion;
   gint32      l_layer_id;
-  
+
   layer_name = NULL;
 
   *stack_pos = -1;
   *active_layer = gimp_image_get_active_layer(image_id);
-  
+
   if(*active_layer >= 0)
   {
     layer_name = gimp_drawable_get_name(*active_layer);
@@ -588,18 +593,18 @@ p_get_active_layer_name(gint32 image_id
           *stack_pos = l_pos;
           break;
         }
-        
+
         l_is_onion = gap_onion_base_check_is_onion_layer(l_layer_id);
         if(!l_is_onion)
         {
           l_pos++;
         }
       }
-    
+
       g_free(l_layers_list);
     }
   }
-  
+
   return (layer_name);
 }  /* end p_get_active_layer_name */
 
@@ -639,7 +644,7 @@ p_do_active_layer_tracking(gint32 image_id
       break;
   }
 }  /* end p_do_active_layer_tracking */
-                
+
 
 /* ============================================================================
  * gap_lib_file_exists
@@ -914,7 +919,7 @@ gap_lib_count_framenumber_digits(const char *imagename)
 
     l_ptr--;
   }
-  
+
   if(gap_debug)
   {
     printf("DEBUG gap_lib_count_framenumber_digits  imagename:'%s' digits_used:%d\n"
@@ -953,7 +958,7 @@ gap_lib_rename_frame(GapAnimInfo *ainfo_ptr, long from_nr, long to_nr)
    {
      return(1);
    }
-   
+
    l_digits_used = gap_lib_count_framenumber_digits(l_from_fname);
    if (l_digits_used > 0)
    {
@@ -964,11 +969,11 @@ gap_lib_rename_frame(GapAnimInfo *ainfo_ptr, long from_nr, long to_nr)
      /* this should not occur when the frame imagfile with from_nr already exists */
      l_to_fname = gap_lib_alloc_fname(ainfo_ptr->basename, to_nr, ainfo_ptr->extension);
    }
-   
-   if(l_to_fname == NULL) 
+
+   if(l_to_fname == NULL)
    {
-     g_free(l_from_fname); 
-     return(1); 
+     g_free(l_from_fname);
+     return(1);
    }
 
 
@@ -1109,7 +1114,7 @@ gap_lib_build_basename_without_ext(const char *filename)
 {
   char *basename;
   gint  idx;
-  
+
   basename = g_filename_display_basename(filename);
   idx = strlen(basename) -1;
   while(idx > 0)
@@ -1273,10 +1278,10 @@ gap_lib_alloc_fname6(char *basename, long nr, char *extension, long default_digi
             l_digits_used = 7;
             break;
          }
-         
 
 
-         
+
+
          /* check if frame is on disk with 4-digit style framenumber */
          g_snprintf(l_fname, l_len, "%s%04ld%s", basename, l_nr_chk, extension);
          if (gap_lib_file_exists(l_fname))
@@ -1422,12 +1427,12 @@ gap_lib_exists_frame_nr(GapAnimInfo *ainfo_ptr, long nr, long *l_has_digits)
         }
         break;
      }
-     
-     
-     
-     
-     
-     
+
+
+
+
+
+
      /* check if frame is on disk with 4-digit style framenumber */
      g_snprintf(l_fname, l_len, "%s%04ld%s", ainfo_ptr->basename, l_nr_chk, ainfo_ptr->extension);
      if (gap_lib_file_exists(l_fname))
@@ -1512,10 +1517,10 @@ gap_lib_exists_frame_nr(GapAnimInfo *ainfo_ptr, long nr, long *l_has_digits)
  * gap_lib_alloc_ainfo_from_name
  *
  * allocate and init an ainfo structure from the given imagename
- * (use this to get anim informations if none of the frame is not loaded
+ * (use this to get anim informations if none of the frame is loaded
  *  as image into the gimp
  *  and no image_id is available)
- * The ainfo_type is just a first guess. 
+ * The ainfo_type is just a first guess.
  *  (check for videofiles GAP_AINFO_MOVIE is not supported here,
  *   because this would require an video-api open attempt that would slow down)
  * ============================================================================
@@ -1559,6 +1564,8 @@ gap_lib_alloc_ainfo_from_name(const char *imagename, GimpRunMode run_mode)
    l_ainfo_ptr->last_frame_nr = -1;
    l_ainfo_ptr->frame_cnt = 0;
    l_ainfo_ptr->run_mode = run_mode;
+   l_ainfo_ptr->frame_nr_before_curr_frame_nr = -1;   /* -1 if no frame found before curr_frame_nr */
+   l_ainfo_ptr->frame_nr_after_curr_frame_nr = -1;    /* -1 if no frame found after curr_frame_nr */
 
 
    return(l_ainfo_ptr);
@@ -1777,11 +1784,16 @@ gap_lib_dir_ainfo(GapAnimInfo *ainfo_ptr)
                  }
 
                  if (l_nr > l_maxnr)
+                 {
                     l_maxnr = l_nr;
+                 }
                  if (l_nr < l_minnr)
+                 {
                     l_minnr = l_nr;
-                 
-                 if ((l_nr < ainfo_ptr->curr_frame_nr) && (l_nr > ainfo_ptr->frame_nr_before_curr_frame_nr))
+                 }
+
+                 if ((l_nr < ainfo_ptr->curr_frame_nr) 
+                 && (l_nr > ainfo_ptr->frame_nr_before_curr_frame_nr))
                  {
                    ainfo_ptr->frame_nr_before_curr_frame_nr = l_nr;
                  }
@@ -2045,7 +2057,7 @@ p_decide_save_as(gint32 image_id, const char *sav_name, const char *final_sav_na
   int               l_argc;
   int               l_save_as_mode;
   GimpRunMode      l_run_mode;
-    
+
 
    /* check if there are SAVE_AS_MODE settings (from privious calls within one gimp session) */
   l_save_as_mode = -1;
@@ -2305,7 +2317,7 @@ p_lib_save_jpg_non_interactive(gint32 image_id, gint32 l_drawable_id, const char
      l_rc = TRUE;
   }
   gimp_destroy_params (l_params, l_retvals);
-  
+
   return (l_rc);
 
 }  /* end p_lib_save_jpg_non_interactive */
@@ -2333,7 +2345,7 @@ p_extension_is_jpeg(const char *extension)
 
   }
   return (FALSE);
-  
+
 }
 
 /* -------------------------------------
@@ -2352,11 +2364,11 @@ p_lib_save_named_image_1(gint32 image_id, const char *sav_name, GimpRunMode run_
   GAPJpegSaveVals   *jpg_save_vals;
   gint32 l_sav_rc;
   char *l_key_save_vals_jpg;
-  
-  
+
+
   l_sav_rc = -1;
   jpg_save_vals = NULL;
-  
+
   l_key_save_vals_jpg = g_strdup_printf("GIMP_GAP_SAVE_VALS_JPG_%s%s"
                        ,l_basename
                        ,l_extension
@@ -2379,7 +2391,7 @@ p_lib_save_named_image_1(gint32 image_id, const char *sav_name, GimpRunMode run_
   if (run_mode != GIMP_RUN_INTERACTIVE)
   {
     int jpg_parsize;
-    
+
     jpg_parsize = gimp_get_data_size(l_key_save_vals_jpg);
     if(gap_debug)
     {
@@ -2425,15 +2437,15 @@ p_lib_save_named_image_1(gint32 image_id, const char *sav_name, GimpRunMode run_
     {
       const GAPJpegSaveVals   *const_jpg_save_vals;
       const_jpg_save_vals = gimp_parasite_data (jpg_save_parasite);
-      
+
       /* store the jpeg save options for the handled frame basename and extension in this session */
       gimp_set_data (l_key_save_vals_jpg, const_jpg_save_vals, sizeof(GAPJpegSaveVals));
       gimp_parasite_free (jpg_save_parasite);
     }
   }
-  
+
   g_free(l_key_save_vals_jpg);
-  
+
   return (l_sav_rc);
 }  /* end p_lib_save_named_image_1 */
 
@@ -2468,13 +2480,13 @@ p_lib_save_named_image2(gint32 image_id, const char *sav_name, GimpRunMode run_m
 
   l_drawable_id = l_layers_list[l_nlayers -1];  /* use the background layer */
 
-  if ((jpg_save_vals != NULL) 
+  if ((jpg_save_vals != NULL)
   && (run_mode != GIMP_RUN_INTERACTIVE))
   {
     /* Special case: save JPG noninteractive
      * Since GIMP-2.4.x jpeg file save plugin changed behaviour:
      * when saved in GIMP_RUN_WITH_LAST_VALS mode it acts the same way
-     * as interactive mode (e.q. opens a dialog) 
+     * as interactive mode (e.q. opens a dialog)
      * this behaviour is not acceptable when saving lots of frames.
      * therefore GAP tries to figure out the jpeg save paramters that
      * are available as parasite data, and perform a non interactive
@@ -2597,7 +2609,7 @@ gap_lib_save_named_frame(gint32 image_id, char *sav_name)
       );
     return -1;
   }
-  
+
   gimp_image_set_filename(image_id, sav_name);
 
   if(0 == strcmp(l_ext, ".xcf"))
@@ -2722,7 +2734,7 @@ gap_lib_save_named_frame(gint32 image_id, char *sav_name)
          {
            printf("DEBUG: gap_lib_save_named_frame: RENAME 2nd try\n");
          }
-         
+
          if(0 == gap_lib_file_copy(l_tmpname, sav_name))
          {
             g_remove(l_tmpname);
@@ -2895,7 +2907,7 @@ gap_lib_load_named_frame (gint32 old_image_id, char *lod_name)
   {
       return -1;
   }
-  
+
   if (gap_pdb_gimp_displays_reconnect(old_image_id, l_new_image_id))
   {
       /* deleting the old image if it is still alive
@@ -2907,7 +2919,7 @@ gap_lib_load_named_frame (gint32 old_image_id, char *lod_name)
        * GAP has no more chance of explicitly deleting the old image
        * (hope that this is already done implicitly by gimp_reconnect_displays ?)
        */
-       
+
       if(gap_image_is_alive(old_image_id))
       {
         gimp_image_delete(old_image_id);
@@ -2970,8 +2982,8 @@ gap_lib_replace_image(GapAnimInfo *ainfo_ptr)
   ref_layer_name = p_get_active_layer_name(ainfo_ptr->image_id
                                           ,&ref_active_layer
                                           ,&ref_layer_stackpos
-                                          );  
-  
+                                          );
+
   if(ainfo_ptr->new_filename != NULL)
   {
     g_free(ainfo_ptr->new_filename);
@@ -2987,7 +2999,7 @@ gap_lib_replace_image(GapAnimInfo *ainfo_ptr)
      }
      return -1;
   }
-  
+
   if(0 == gap_lib_file_exists(ainfo_ptr->new_filename ))
   {
      if(gap_debug)
@@ -3238,13 +3250,13 @@ gap_vid_edit_copy(GimpRunMode run_mode, gint32 image_id, long range_from, long r
 
   gchar *l_curr_name;
   gchar *l_fname ;
-  gchar *l_fname_copy;
   gchar *l_basename;
   gint32 l_frame_nr;
-  gint32 l_cnt_range;
   gint32 l_cnt2;
-  gint32 l_idx;
   gint32 l_tmp_image_id;
+  long   l_cur_frame_nr;
+  long   l_top_frame_nr;
+  gboolean   l_frame_found;
 
   ainfo_ptr = gap_lib_alloc_ainfo(image_id, run_mode);
   if(ainfo_ptr == NULL)
@@ -3268,37 +3280,58 @@ gap_vid_edit_copy(GimpRunMode run_mode, gint32 image_id, long range_from, long r
   l_cnt2 = gap_vid_edit_framecount();  /* count frames in the video paste buffer */
   l_frame_nr = 1 + l_cnt2;           /* start at one, or continue (append) at end +1 */
 
-  l_cnt_range = 1 + MAX(range_to, range_from) - MIN(range_to, range_from);
-  for(l_idx = 0; l_idx < l_cnt_range;  l_idx++)
+
+
+  l_top_frame_nr = MAX(range_to, range_from);
+  l_cur_frame_nr = MIN(range_to, range_from);
+  l_frame_found = TRUE;
+  while(l_frame_found == TRUE)
   {
-     if(rc < 0)
+     if((rc < 0) || (l_cur_frame_nr > l_top_frame_nr))
      {
        break;
      }
      l_fname = gap_lib_alloc_fname(ainfo_ptr->basename,
-                             MIN(range_to, range_from) + l_idx,
+                             l_cur_frame_nr,
                              ainfo_ptr->extension);
-     l_fname_copy = g_strdup_printf("%s%06ld.xcf", l_basename, (long)l_frame_nr);
-
-     if(strcmp(ainfo_ptr->extension, ".xcf") == 0)
-     {
-        rc = gap_lib_image_file_copy(l_fname, l_fname_copy);
-     }
-     else
+     if (g_file_test(l_fname, G_FILE_TEST_EXISTS))
      {
-        /* convert other fileformats to xcf before saving to video paste buffer */
-        l_tmp_image_id = gap_lib_load_image(l_fname);
-        rc = gap_lib_save_named_frame(l_tmp_image_id, l_fname_copy);
-        gimp_image_delete(l_tmp_image_id);
+       gchar *l_fname_copy;
+
+       l_fname_copy = g_strdup_printf("%s%06ld.xcf", l_basename, (long)l_frame_nr);
+
+       if(strcmp(ainfo_ptr->extension, ".xcf") == 0)
+       {
+         rc = gap_lib_image_file_copy(l_fname, l_fname_copy);
+       }
+       else
+       {
+         /* convert other fileformats to xcf before saving to video paste buffer */
+         l_tmp_image_id = gap_lib_load_image(l_fname);
+         rc = gap_lib_save_named_frame(l_tmp_image_id, l_fname_copy);
+         gimp_image_delete(l_tmp_image_id);
+       }
+       g_free(l_fname_copy);
+       l_frame_nr++;
      }
      g_free(l_fname);
-     g_free(l_fname_copy);
-     l_frame_nr++;
+
+     /* advance l_cur_frame_nr to the next available frame number
+      * (normally to l_cur_frame_nr += 1;
+      * sometimes to higher number when frames are missing)
+      */
+     l_cur_frame_nr = gap_lib_get_next_available_frame_number(l_cur_frame_nr, 1
+                                , ainfo_ptr->basename, ainfo_ptr->extension, &l_frame_found);
+
+
   }
   gap_lib_free_ainfo(&ainfo_ptr);
   return(rc);
 }       /* end gap_vid_edit_copy */
 
+
+
+
 /* ============================================================================
  * p_custom_palette_file
  *   write a gimp palette file
@@ -3360,6 +3393,7 @@ gap_vid_edit_paste(GimpRunMode run_mode, gint32 image_id, long paste_mode)
   gint32 l_tmp_image_id;
   gint       l_rc;
   GimpImageBaseType  l_orig_basetype;
+  gboolean   l_frame_found;
 
   l_cnt2 = gap_vid_edit_framecount();
   if(gap_debug)
@@ -3429,17 +3463,31 @@ gap_vid_edit_paste(GimpRunMode run_mode, gint32 image_id, long paste_mode)
 
      while(l_lo >= l_insert_frame_nr)
      {
-       if(0 != gap_lib_rename_frame(ainfo_ptr, l_lo, l_hi))
+       l_hi   = l_lo + l_cnt2;
+       l_frame_found = gap_lib_framefile_with_framenr_exists(ainfo_ptr, l_lo);
+       if (l_frame_found)
        {
-          gchar *tmp_errtxt;
-          tmp_errtxt = g_strdup_printf(_("Error: could not rename frame %ld to %ld"), (long int)l_lo, (long 
int)l_hi);
-          gap_arr_msg_win(ainfo_ptr->run_mode, tmp_errtxt);
-          g_free(tmp_errtxt);
-          return -1;
+         if(0 != gap_lib_rename_frame(ainfo_ptr, l_lo, l_hi))
+         {
+           gchar *tmp_errtxt;
+           tmp_errtxt = g_strdup_printf(_("Error: could not rename frame %ld to %ld"), (long int)l_lo, (long 
int)l_hi);
+           gap_arr_msg_win(ainfo_ptr->run_mode, tmp_errtxt);
+           g_free(tmp_errtxt);
+           return -1;
+         }
        }
-       l_lo--;
-       l_hi--;
-     }
+       /* advance l_lo to the previous available frame number
+        * (normally to l_lo -= 1;
+        * sometimes to lower number when frames are missing)
+        */
+       l_lo = gap_lib_get_next_available_frame_number(l_lo, -1
+                              , ainfo_ptr->basename, ainfo_ptr->extension, &l_frame_found);
+       if (!l_frame_found)
+       {
+         break;
+       }
+
+     }  /* end while */
   }
 
   l_basename = gap_lib_get_video_paste_name();
@@ -3587,3 +3635,243 @@ gap_vid_edit_paste(GimpRunMode run_mode, gint32 image_id, long paste_mode)
 }       /* end gap_vid_edit_paste */
 
 
+/* ---------------------------------------
+ * gap_lib_get_next_available_frame_number
+ * ---------------------------------------
+ * returns the next available frame_number in sequence
+ * (for ascending sequence use stepsize 1
+ * for descending sequence use stepsize -1)
+ * if the frame image file with the next expected frame number is not
+ * found, the number is derived from the next available frame image file.
+ *
+ * if there are no more next frame images,
+ *     *frame_found_ptr is set to FALSE (if it is not NULL)
+ *     and cur_frame_nr + stepsize is returned
+ * otherwise (when a next frame image was found)
+ *     *frame_found_ptr is set to TRUE (if it is not NULL)
+ *     and the frame number of the next matching frame image is returned.
+ */
+long
+gap_lib_get_next_available_frame_number(long cur_frame_nr, long stepsize,
+  char *basename, char *extension, gboolean *frame_found_ptr)
+{
+  long     l_next_frame_nr;
+  gint     l_idx;
+  gboolean l_frame_found;
+
+  l_next_frame_nr = cur_frame_nr + stepsize;
+  l_frame_found = FALSE;
+
+  for(l_idx=1; l_idx < 10; l_idx++)
+  {
+    char *new_filename;
+    long l_potential_next_frame_nr;
+
+    l_potential_next_frame_nr =  cur_frame_nr + (l_idx * stepsize);
+    new_filename = gap_lib_alloc_fname(basename,
+                                       l_potential_next_frame_nr,
+                                       extension);
+    if (new_filename == NULL)
+    {
+      break;
+    }
+    else
+    {
+      if(g_file_test(new_filename, G_FILE_TEST_EXISTS))
+      {
+         l_next_frame_nr = l_potential_next_frame_nr;
+         l_frame_found = TRUE;
+      }
+      g_free(new_filename);
+    }
+    if (l_frame_found)
+    {
+      break;
+    }
+  }
+
+  if (l_frame_found != TRUE)
+  {
+     l_next_frame_nr = gap_lib_dir_find_next_frame_number(cur_frame_nr
+                         , stepsize
+                         , basename
+                         , extension
+                         , &l_frame_found
+                         );
+  }
+
+
+  if (frame_found_ptr != NULL)
+  {
+    *frame_found_ptr = l_frame_found;
+  }
+  return (l_next_frame_nr);
+
+
+}  /* end gap_lib_get_next_available_frame_number */
+
+
+
+/* ----------------------------------
+ * gap_lib_dir_find_next_frame_number
+ * ----------------------------------
+ * returns the next available frame_number in sequence
+ * for the frame that is specified by basename, cur_frame_nr, extension.
+ * (for ascending sequence use stepsize 1
+ * for descending sequence use stepsize -1)
+ * if the frame image file with the next expected frame number is not
+ * found, the number is derived from the next available frame image file.
+ *
+ * NOTE that this variant performs an uncodintional directory scan
+ * of the directory that contains the specified imagename.
+ * For performance reasons gap_lib_get_next_available_frame_number
+ * should be used where possible.
+ *
+ * if there are no more next frame images,
+ *     *frame_found_ptr is set to FALSE (if it is not NULL)
+ *     and cur_frame_nr + stepsize is returned
+ * otherwise (when a next frame image was found)
+ *     *frame_found_ptr is set to TRUE (if it is not NULL)
+ *     and the frame number of the next matching frame image is returned.
+ */
+long
+gap_lib_dir_find_next_frame_number(long cur_frame_nr, long stepsize,
+  char *basename, char *extension, gboolean *frame_found_ptr)
+{
+  char        *imagename;
+  long         l_next_frame_nr;
+
+  l_next_frame_nr = cur_frame_nr + stepsize;
+
+  imagename = gap_lib_alloc_fname(basename,
+                                  cur_frame_nr,
+                                  extension);
+  l_next_frame_nr = gap_lib_dir_find_next_frame_number_for_imagename(
+                      stepsize, imagename, frame_found_ptr);
+  g_free(imagename);
+
+  return (l_next_frame_nr);
+
+}       /* end gap_lib_dir_find_next_frame_number */
+
+
+/* -----------------------------------------------
+ * gap_lib_dir_find_next_frame_number_for_imagename
+ * ------------------------------------------------
+ * returns the next available frame_number for the specified frame imganame in sequence
+ * (for ascending sequence use stepsize 1
+ * for descending sequence use stepsize -1)
+ * if the frame image file with the next expected frame number is not
+ * found, the number is derived from the next available frame image file.
+ *
+ * NOTE that this variant performs a directory scan of the directory
+ * that contains the specified imagename.
+ *
+ *
+ * if there are no more next frame images,
+ *     *frame_found_ptr is set to FALSE (if it is not NULL)
+ *     and cur_frame_nr + stepsize is returned
+ * otherwise (when a next frame image was found)
+ *     *frame_found_ptr is set to TRUE (if it is not NULL)
+ *     and the frame number of the next matching frame image is returned.
+ */
+long
+gap_lib_dir_find_next_frame_number_for_imagename(long stepsize,
+  char *imagename, gboolean *frame_found_ptr)
+{
+  GapAnimInfo *ainfo_ptr;
+  long         l_next_frame_nr;
+  gboolean     l_frame_found;
+
+  l_next_frame_nr = -1;
+  l_frame_found = FALSE;
+
+  ainfo_ptr = gap_lib_alloc_ainfo_from_name(imagename, GIMP_RUN_NONINTERACTIVE);
+  if (ainfo_ptr == NULL)
+  {
+    printf("gap_lib_dir_find_next_frame_number_for_imagename: FAILED, ainfo_ptr is null for %s\n"
+          , imagename);
+  }
+  else
+  {
+    l_next_frame_nr = ainfo_ptr->curr_frame_nr + stepsize;
+
+    if (0 == gap_lib_dir_ainfo(ainfo_ptr))
+    {
+      if (stepsize >= 0)
+      {
+        if (ainfo_ptr->frame_nr_after_curr_frame_nr >= 0)
+        {
+          l_frame_found = TRUE;
+          l_next_frame_nr = ainfo_ptr->frame_nr_after_curr_frame_nr;
+        }
+      }
+      else
+      {
+        if (ainfo_ptr->frame_nr_before_curr_frame_nr >= 0)
+        {
+          l_frame_found = TRUE;
+          l_next_frame_nr = ainfo_ptr->frame_nr_before_curr_frame_nr;
+        }
+      }
+
+    }
+
+    if(gap_debug)
+    {
+      printf("gap_lib_dir_find_next_frame_number_for_imagename: %s \n"
+           "  l_next_frame_nr:%d found:%d TRUE:%d\n"
+           "  curr_frame_nr:%d  frame_nr_after_curr_frame_nr:%d  frame_nr_before_curr_frame_nr:%d 
stepsize:%d \n"
+          , imagename
+          , (int)l_next_frame_nr
+          , (int)l_frame_found
+          , (int)TRUE
+          , (int)ainfo_ptr->curr_frame_nr
+          , (int)ainfo_ptr->frame_nr_after_curr_frame_nr
+          , (int)ainfo_ptr->frame_nr_before_curr_frame_nr
+          , (int)stepsize
+          );
+    }
+
+    gap_lib_free_ainfo(&ainfo_ptr);
+  }
+
+
+  if (frame_found_ptr != NULL)
+  {
+    *frame_found_ptr = l_frame_found;
+  }
+
+
+  return (l_next_frame_nr);
+}       /* end gap_lib_dir_find_next_frame_number_for_imagename */
+
+
+/* -------------------------------------
+ * gap_lib_framefile_with_framenr_exists
+ * -------------------------------------
+ *
+ * return FALSE ... file does not exist
+ * return TRUE  ... file exists
+ */
+gboolean
+gap_lib_framefile_with_framenr_exists(GapAnimInfo *ainfo_ptr, long frame_nr)
+{
+  char *filename;
+  gboolean l_rc;
+
+  l_rc = FALSE;
+
+  /* build the frame name */
+  filename = gap_lib_alloc_fname(ainfo_ptr->basename,
+                                 frame_nr,
+                                 ainfo_ptr->extension);
+  if(filename != NULL)
+  {
+    l_rc = g_file_test(filename, G_FILE_TEST_EXISTS);
+    g_free(filename);
+  }
+
+  return (l_rc);
+
+}       /* end gap_lib_framefile_with_framenr_exists */
diff --git a/gap/gap_lib.h b/gap/gap_lib.h
index 5f60aa5..a39511e 100644
--- a/gap/gap_lib.h
+++ b/gap/gap_lib.h
@@ -106,6 +106,10 @@ int      gap_lib_rename_frame(GapAnimInfo *ainfo_ptr, long from_nr, long to_nr);
 int      gap_lib_delete_frame(GapAnimInfo *ainfo_ptr, long nr);
 gint32   gap_lib_replace_image(GapAnimInfo *ainfo_ptr);
 
+long     gap_lib_get_next_available_frame_number(long cur_frame_nr, long stepsize,
+            char *basename, char *extension, gboolean *frame_found_ptr);
+gboolean gap_lib_framefile_with_framenr_exists(GapAnimInfo *ainfo_ptr, long frame_nr);
+
 
 #endif
 
diff --git a/gap/gap_mod_layer.c b/gap/gap_mod_layer.c
index 9fb4bbc..a95de8d 100644
--- a/gap/gap_mod_layer.c
+++ b/gap/gap_mod_layer.c
@@ -159,7 +159,7 @@ p_get_nb_layer_id(gint32 image_id, gint32 ref_layer_id, gint32 nb_ref)
   gint32        l_nb_idx;
 
   l_nb_layer_id = -1;
-  
+
   l_layers_list = gimp_image_get_layers(image_id, &l_nlayers);
   if(l_layers_list != NULL)
   {
@@ -175,7 +175,7 @@ p_get_nb_layer_id(gint32 image_id, gint32 ref_layer_id, gint32 nb_ref)
         break;
       }
     }
-  
+
     g_free (l_layers_list);
   }
 
@@ -359,7 +359,7 @@ p_selection_combine(gint32 image_id
  *       To perform the action on the master image pass -1 as master_image_id.
  *       (this shall be done deferred after processing all the other frame images)
  *
- * return TRUE if action was handled 
+ * return TRUE if action was handled
  *             (this is also TRUE if the action was skiped due to the condition
  *              image_id == master_image_id)
  * return FALSE for all other actions
@@ -391,7 +391,7 @@ p_apply_selection_action(gint32 image_id, gint32 action_mode
 
   if(action_mode == GAP_MOD_ACM_SEL_ADD)
   {
-    /* if we are processing the master image, 
+    /* if we are processing the master image,
      * no need to add selection to itself
      */
     if (image_id != master_image_id)
@@ -403,7 +403,7 @@ p_apply_selection_action(gint32 image_id, gint32 action_mode
 
   if(action_mode == GAP_MOD_ACM_SEL_SUBTRACT)
   {
-    /* if we are processing the master image, 
+    /* if we are processing the master image,
      * we must defere action until all other images are handled
      * to keep original master selection intact.
      * (subtract from itself would clear the selection)
@@ -417,7 +417,7 @@ p_apply_selection_action(gint32 image_id, gint32 action_mode
 
   if(action_mode == GAP_MOD_ACM_SEL_INTERSECT)
   {
-    /* if we are processing the master image, 
+    /* if we are processing the master image,
      * intersect with itself can be skipped, because
      * the result will be the same selection as before.
      */
@@ -448,7 +448,7 @@ p_apply_selection_action(gint32 image_id, gint32 action_mode
 
 
   return(FALSE);
-  
+
 }  /* end p_apply_selection_action */
 
 
@@ -491,7 +491,7 @@ p_apply_action(gint32 image_id,
   if(gap_debug) printf("gap: p_apply_action START\n");
 
   l_rc = 0;
-  
+
   l_merge_mode = -44; /* none of the flatten modes */
 
   if(action_mode == GAP_MOD_ACM_MERGE_EXPAND) l_merge_mode = GAP_RANGE_OPS_FLAM_MERG_EXPAND;
@@ -504,9 +504,9 @@ p_apply_action(gint32 image_id,
   {
     gint32  master_channel_id;
     gboolean action_was_applied;
-    
+
     master_channel_id = gimp_image_get_selection(master_image_id);
-    action_was_applied = p_apply_selection_action(image_id 
+    action_was_applied = p_apply_selection_action(image_id
                                                 , action_mode
                                                 , master_image_id
                                                 , master_channel_id
@@ -818,7 +818,7 @@ p_apply_action(gint32 image_id,
             gint32 l_nb_ref;
             gint32 l_fsel_layer_id;
             gint32 l_nb_had_layermask;
-            
+
             l_nb_ref = 1;
             if(action_mode == GAP_MOD_ACM_LMASK_COPY_FROM_UPPER_LMASK)
             {
@@ -838,7 +838,7 @@ p_apply_action(gint32 image_id,
                 l_nb_mask_id = gimp_layer_create_mask(l_nb_layer_id, GIMP_ADD_COPY_MASK);
                 gimp_layer_add_mask(l_nb_layer_id, l_nb_mask_id);
               }
-              
+
               if(l_nb_mask_id >= 0)
               {
                 /* the referenced neigbour layer has a layermask
@@ -848,7 +848,7 @@ p_apply_action(gint32 image_id,
                 gimp_edit_copy(l_nb_mask_id);
                 l_fsel_layer_id = gimp_edit_paste(l_layermask_id, FALSE);
                 gimp_floating_sel_anchor(l_fsel_layer_id);
-                
+
                 if(l_nb_had_layermask == FALSE)
                 {
                   /* remove the temporary created layermask in the neigbour layer */
@@ -898,7 +898,7 @@ p_apply_action(gint32 image_id,
                                                , _("_msk")   /* name suffix */
                                                );
           break;
-        case GAP_MOD_ACM_SET_MODE_NORMAL: 
+        case GAP_MOD_ACM_SET_MODE_NORMAL:
           gimp_layer_set_mode(l_layer_id, GIMP_NORMAL_MODE);
           break;
         case GAP_MOD_ACM_SET_MODE_DISSOLVE:
@@ -1003,7 +1003,7 @@ p_do_filter_dialogs(GapAnimInfo *ainfo_ptr,
   static char *canonical_proc_name;
 
   l_browser_result.accelCharacteristic = GAP_ACCEL_CHAR_LINEAR;
-  
+
   /* GAP-PDB-Browser Dialog */
   /* ---------------------- */
   if(gap_db_browser_dialog( _("Select Filter for Animated Apply on Frames"),
@@ -1025,9 +1025,9 @@ p_do_filter_dialogs(GapAnimInfo *ainfo_ptr,
   strncpy(filter_procname, canonical_proc_name, filt_len-1);
   filter_procname[filt_len-1] = '\0';
   g_free(canonical_proc_name);
-  
+
   /* invert acceleration to deceleration and vice versa
-   * (because processing runs backwards from total_frames down to 0) 
+   * (because processing runs backwards from total_frames down to 0)
    */
   *accelCharacteristic = (-1 * l_browser_result.accelCharacteristic);
 
@@ -1260,16 +1260,17 @@ gap_mod_frames_modify(GapAnimInfo *ainfo_ptr,
   gint          l_count;
   gboolean      l_operating_on_current_image;
   gboolean      l_operate_on_layermask;
-      
+  gboolean      l_frame_found;
+
 
 
 
   if(gap_debug)
-  { 
+  {
     printf("gap: gap_mod_frames_modify START, action_mode=%d  sel_mode=%d case=%d, invert=%d patt:%s:\n",
         (int)action_mode, (int)sel_mode, (int)sel_case, (int)sel_invert, sel_pattern);
   }
-  
+
   l_operate_on_layermask = FALSE;
   l_percentage = 0.0;
   if(ainfo_ptr->run_mode == GIMP_RUN_INTERACTIVE)
@@ -1335,7 +1336,10 @@ gap_mod_frames_modify(GapAnimInfo *ainfo_ptr,
                                         l_cur_frame_nr,
                                         ainfo_ptr->extension);
     if(ainfo_ptr->new_filename == NULL)
+    {
        goto error;
+    }
+
 
     if(ainfo_ptr->curr_frame_nr == l_cur_frame_nr)
     {
@@ -1345,12 +1349,19 @@ gap_mod_frames_modify(GapAnimInfo *ainfo_ptr,
     }
     else
     {
+      l_frame_found = g_file_test(ainfo_ptr->new_filename, G_FILE_TEST_EXISTS);
+      if (l_frame_found != TRUE)
+      {
+        goto modify_advance_to_next_frame;
+      }
       /* load current frame into temporary image */
       l_operating_on_current_image = FALSE;
       l_tmp_image_id = gap_lib_load_image(ainfo_ptr->new_filename);
     }
     if(l_tmp_image_id < 0)
+    {
        goto error;
+    }
 
     /* get informations (id, visible, selected) about all layers */
     l_layli_ptr = gap_mod_alloc_layli(l_tmp_image_id, &l_sel_cnt, &l_nlayers,
@@ -1362,9 +1373,9 @@ gap_mod_frames_modify(GapAnimInfo *ainfo_ptr,
        goto error;
     }
 
-    if((l_cur_frame_nr == l_begin) 
+    if((l_cur_frame_nr == l_begin)
     && ((action_mode == GAP_MOD_ACM_APPLY_FILTER) || (action_mode == GAP_MOD_ACM_APPLY_FILTER_ON_LAYERMASK)))
-    {      
+    {
       /* ------------- 1.st frame: extra dialogs for APPLY_FILTER ---------- */
 
       if(l_sel_cnt < 1)
@@ -1372,7 +1383,7 @@ gap_mod_frames_modify(GapAnimInfo *ainfo_ptr,
          g_message(_("No selected layer in start frame"));
          goto error;
       }
-      
+
       if(action_mode == GAP_MOD_ACM_APPLY_FILTER_ON_LAYERMASK)
       {
         gint l_ii;
@@ -1447,7 +1458,9 @@ gap_mod_frames_modify(GapAnimInfo *ainfo_ptr,
     }
 
     if(l_rc != 0)
+    {
       goto error;
+    }
 
     /* perform function (defined by action_mode) on selcted layer(s) */
     l_rc = p_apply_action(l_tmp_image_id,
@@ -1490,11 +1503,11 @@ gap_mod_frames_modify(GapAnimInfo *ainfo_ptr,
     && (l_plugin_iterator != NULL) && (accelCharacteristic != GAP_ACCEL_CHAR_NONE ))
     {
        gdouble accelStep;
-       
+
        l_cur_step -= 1.0;
-       
+
        accelStep = gap_calculate_current_step_with_acceleration(l_cur_step, l_total_steps, 
accelCharacteristic);
-       if(gap_debug) 
+       if(gap_debug)
        {
          printf("DEBUG: calling iterator %s  current frame:%d  accelStep:%f\n"
                                ,l_plugin_iterator
@@ -1542,6 +1555,7 @@ gap_mod_frames_modify(GapAnimInfo *ainfo_ptr,
     {
       /* destroy the tmp image */
       gimp_image_delete(l_tmp_image_id);
+      l_tmp_image_id = -1;
     }
 
     /* close display (if open) */
@@ -1553,19 +1567,19 @@ gap_mod_frames_modify(GapAnimInfo *ainfo_ptr,
 
 
     if(l_rc != 0)
+    {
       goto error;
-
-
+    }
 
     if(ainfo_ptr->run_mode == GIMP_RUN_INTERACTIVE)
     {
       l_percentage += l_percentage_step;
-     
+
       if(progress_bar != NULL)
       {
         guchar *progressText;
         progressText = g_strdup_printf("frame:%d (%d)", (int)l_cur_frame_nr, (int)l_end);
-        
+
         gtk_progress_bar_set_text(GTK_PROGRESS_BAR(progress_bar), progressText);
         gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progress_bar), l_percentage);
         g_free(progressText);
@@ -1585,10 +1599,21 @@ gap_mod_frames_modify(GapAnimInfo *ainfo_ptr,
       }
     }
 
-    /* advance to next frame */
+modify_advance_to_next_frame:
     if(l_cur_frame_nr == l_end)
+    {
+       break;
+    }
+    /* advance l_cur_frame_nr to the next available frame number
+     * (normally to l_cur_frame_nr += l_step;
+     * sometimes to higher/lower number when frames are missing)
+     */
+    l_cur_frame_nr = gap_lib_get_next_available_frame_number(l_cur_frame_nr, l_step
+                           , ainfo_ptr->basename, ainfo_ptr->extension, &l_frame_found);
+    if(l_frame_found != TRUE)
+    {
        break;
-    l_cur_frame_nr += l_step;
+    }
 
   }             /* end while(1)  loop foreach frame in range */
 
@@ -1612,7 +1637,7 @@ gap_mod_frames_modify(GapAnimInfo *ainfo_ptr,
         *  than using a copy)
         */
        master_channel_id = gimp_selection_save(ainfo_ptr->image_id);
-       p_apply_selection_action(ainfo_ptr->image_id 
+       p_apply_selection_action(ainfo_ptr->image_id
                              , action_mode
                              , -1   /* MASTER_image_id */
                              , master_channel_id
@@ -1643,7 +1668,6 @@ error:
 
 }               /* end gap_mod_frames_modify */
 
-
 /* ============================================================================
  * gap_mod_layer
  * ============================================================================
@@ -1709,7 +1733,7 @@ gint gap_mod_layer(GimpRunMode run_mode, gint32 image_id,
       if(l_rc >= 0)
       {
         gboolean run_flag;
-         
+
         run_flag = TRUE;
         /* no need to save the current image before processing
          * because the gap_mod_frames_modify procedure operates directly on the current frame
diff --git a/gap/gap_mov_exec.c b/gap/gap_mov_exec.c
index af62297..b7e91fa 100644
--- a/gap/gap_mov_exec.c
+++ b/gap/gap_mov_exec.c
@@ -81,7 +81,9 @@ extern      int gap_debug; /* ==0  ... dont print debug infos */
 static void p_add_tween_and_trace(gint32 dest_image_id, GapMovData *mov_ptr, GapMovCurrent *cur_ptr);
 static gint p_mov_call_render(GapMovData *mov_ptr, GapMovCurrent *cur_ptr, gint apv_layerstack);
 static void p_mov_advance_src_layer(GapMovCurrent *cur_ptr, GapMovValues  *pvals);
+static long p_mov_advance_src_frame_no_fetch(GapMovCurrent *cur_ptr, GapMovValues  *pvals);
 static void p_mov_advance_src_frame(GapMovCurrent *cur_ptr, GapMovValues  *pvals);
+static void p_mov_advance_src_layer_or_frame_on_autoskip(GapMovCurrent *cur_ptr, GapMovValues  *pvals, long 
autoskip_size);
 
 static void     p_log_current_render_params(GapMovData *mov_ptr, GapMovCurrent *cur_ptr);
 static void     p_printf_log_parameters(GapMovData *mov_ptr);
@@ -365,10 +367,10 @@ p_mov_call_render(GapMovData *mov_ptr, GapMovCurrent *cur_ptr, gint apv_layersta
       else
       {
         l_tmp_image_id = mov_ptr->val_ptr->dst_image_id;
-       if (l_tmp_image_id < 0)
-       {
+        if (l_tmp_image_id < 0)
+        {
           l_tmp_image_id = gimp_drawable_get_image(singleFramePtr->drawable_id);
-       }
+        }
       }
 
 
@@ -389,7 +391,7 @@ p_mov_call_render(GapMovData *mov_ptr, GapMovCurrent *cur_ptr, gint apv_layersta
           }
         }
       }
-      else 
+      else
       {
         l_rc = -1;
       }
@@ -416,7 +418,7 @@ p_mov_call_render(GapMovData *mov_ptr, GapMovCurrent *cur_ptr, gint apv_layersta
          {
            return -1;
          }
-         
+
          gimp_image_undo_disable (l_tmp_image_id);
 
          if((mov_ptr->val_ptr->apv_scalex != 100.0) || (mov_ptr->val_ptr->apv_scaley != 100.0))
@@ -510,7 +512,7 @@ p_mov_call_render(GapMovData *mov_ptr, GapMovCurrent *cur_ptr, gint apv_layersta
 
   if(singleFramePtr == NULL)
   {
-    /* destroy the tmp image 
+    /* destroy the tmp image
      * (but not in singleframes mode. Note that in singleframe mode l_tmp_image_id
      * referes to the image from where we were invoked)
      */
@@ -544,14 +546,18 @@ p_mov_advance_src_layer(GapMovCurrent *cur_ptr, GapMovValues  *pvals)
   }
   l_round = 0.0;
 
-  if(gap_debug) printf("p_mov_advance_src_layer: stepmode=%d last_layer=%d idx=%d (%.4f) speed_factor: 
%.4f\n",
+  if(gap_debug)
+  {
+    printf("p_mov_advance_src_layer: stepmode=%d last_layer=%d idx=%d (%.4f) speed_factor: %.4f\n",
                        (int)pvals->src_stepmode,
                        (int)cur_ptr->src_last_layer,
                        (int)cur_ptr->src_layer_idx,
                        (float)cur_ptr->src_layer_idx_dbl,
                        (float)l_step_speed_factor
                       );
-
+  }
+  
+  
   /* note: top layer has index 0
    *       therfore reverse loops have to count up
    *       forward loop is defined as sequence from BG to TOP layer
@@ -619,16 +625,18 @@ p_mov_advance_src_layer(GapMovCurrent *cur_ptr, GapMovValues  *pvals)
 
 
 /* ============================================================================
- * p_mov_advance_src_frame
- *   advance chached image to next source frame according to FRAME based pvals->stepmode
+ * p_mov_advance_src_frame_no_fetch
+ *   advance settings to next source frame according to FRAME based pvals->stepmode
+ *   but do not yet fetch the resulting source frame into the chached image.
  * ============================================================================
  */
-static void
-p_mov_advance_src_frame(GapMovCurrent *cur_ptr, GapMovValues  *pvals)
+static long
+p_mov_advance_src_frame_no_fetch(GapMovCurrent *cur_ptr, GapMovValues  *pvals)
 {
   static gdouble l_ping = 1;
   gdouble l_step_speed_factor;
   gdouble l_round;
+  long    l_stepsize_autoskip;
 
   /* limit step factor to number of available frames -1 */
   l_step_speed_factor = MIN(pvals->step_speed_factor, (gdouble)(pvals->cache_ainfo_ptr->frame_cnt -1));
@@ -638,6 +646,7 @@ p_mov_advance_src_frame(GapMovCurrent *cur_ptr, GapMovValues  *pvals)
     l_step_speed_factor /= (gdouble)(pvals->tween_steps +1);
   }
   l_round = 0.0;
+  l_stepsize_autoskip = 1;
 
   if(pvals->src_stepmode != GAP_STEP_FRAME_NONE)
   {
@@ -652,7 +661,9 @@ p_mov_advance_src_frame(GapMovCurrent *cur_ptr, GapMovValues  *pvals)
     }
   }
 
-  if(gap_debug) printf("p_mov_advance_src_frame: stepmode=%d frame_cnt=%d first_frame=%d last_frame=%d 
idx=%d (%.4f) speed_factor: %.4f\n",
+  if(gap_debug)
+  {
+    printf("p_mov_advance_src_frame_no_fetch: stepmode=%d frame_cnt=%d first_frame=%d last_frame=%d idx=%d 
(%.4f) speed_factor: %.4f\n",
                        (int)pvals->src_stepmode,
                        (int)pvals->cache_ainfo_ptr->frame_cnt,
                        (int)pvals->cache_ainfo_ptr->first_frame_nr,
@@ -661,12 +672,14 @@ p_mov_advance_src_frame(GapMovCurrent *cur_ptr, GapMovValues  *pvals)
                        (float)cur_ptr->src_frame_idx_dbl,
                        (float)l_step_speed_factor
                       );
+  }
 
   if((pvals->cache_ainfo_ptr->frame_cnt > 1 ) && (pvals->src_stepmode != GAP_STEP_FRAME_NONE))
   {
     switch(pvals->src_stepmode)
     {
       case GAP_STEP_FRAME_ONCE_REV:
+        l_stepsize_autoskip = -1;
         cur_ptr->src_frame_idx_dbl -= l_step_speed_factor;
         if(cur_ptr->src_frame_idx_dbl < (gdouble)pvals->cache_ainfo_ptr->first_frame_nr)
         {
@@ -674,6 +687,7 @@ p_mov_advance_src_frame(GapMovCurrent *cur_ptr, GapMovValues  *pvals)
         }
         break;
       case GAP_STEP_FRAME_ONCE:
+        l_stepsize_autoskip = 1;
         cur_ptr->src_frame_idx_dbl += l_step_speed_factor;
         if(cur_ptr->src_frame_idx_dbl > (gdouble)pvals->cache_ainfo_ptr->last_frame_nr)
         {
@@ -699,8 +713,10 @@ p_mov_advance_src_frame(GapMovCurrent *cur_ptr, GapMovValues  *pvals)
              l_ping = -1;
           }
         }
+        l_stepsize_autoskip = l_ping;
         break;
       case GAP_STEP_FRAME_LOOP_REV:
+        l_stepsize_autoskip = -1;
         cur_ptr->src_frame_idx_dbl -= l_step_speed_factor;
         if(cur_ptr->src_frame_idx_dbl < (gdouble)(pvals->cache_ainfo_ptr->first_frame_nr -0.5))
         {
@@ -710,6 +726,7 @@ p_mov_advance_src_frame(GapMovCurrent *cur_ptr, GapMovValues  *pvals)
         break;
       case GAP_STEP_FRAME_LOOP:
       default:
+        l_stepsize_autoskip = 1;
         cur_ptr->src_frame_idx_dbl += l_step_speed_factor;
         if(cur_ptr->src_frame_idx_dbl >= (gdouble)(pvals->cache_ainfo_ptr->last_frame_nr +1))
         {
@@ -722,12 +739,93 @@ p_mov_advance_src_frame(GapMovCurrent *cur_ptr, GapMovValues  *pvals)
                                   ,pvals->cache_ainfo_ptr->first_frame_nr
                                   ,pvals->cache_ainfo_ptr->last_frame_nr
                                   );
-    gap_mov_render_fetch_src_frame(pvals, cur_ptr->src_frame_idx);
+
   }
-}       /* end  p_advance_src_frame */
+  return (l_stepsize_autoskip);
+  
+}       /* end  p_mov_advance_src_frame_no_fetch */
+
 
+/* ============================================================================
+ * p_mov_advance_src_frame
+ *   advance chached image to next source frame according to FRAME based pvals->stepmode
+ * ============================================================================
+ */
+static void
+p_mov_advance_src_frame(GapMovCurrent *cur_ptr, GapMovValues  *pvals)
+{
+  gint32 l_but_got_frame_nr;
+  long    l_stepsize_autoskip;
+
+  /* prepare settings for fetching the next source frame */
+  l_stepsize_autoskip = p_mov_advance_src_frame_no_fetch(cur_ptr, pvals);
+
+  if((pvals->cache_ainfo_ptr->frame_cnt > 1 )
+  && (pvals->src_stepmode != GAP_STEP_FRAME_NONE))
+  {
+    /* advance with feed back to src_frame_idx_dbl
+     * in case fetch delivers another frame than than wanted
+     * -- autoskip feature when frames are missing --
+     */
+
+    l_but_got_frame_nr = -1;
+    gap_mov_render_fetch_src_frame_autoskip(pvals, cur_ptr->src_frame_idx
+       , &l_but_got_frame_nr, l_stepsize_autoskip);
+    if ((l_but_got_frame_nr >= 0) && (l_but_got_frame_nr != cur_ptr->src_frame_idx))
+    {
+      cur_ptr->src_frame_idx_dbl += (l_but_got_frame_nr - cur_ptr->src_frame_idx);
+    }
+  }
+}       /* end  p_mov_advance_src_frame */
+
+
+/* ============================================================================
+ * p_mov_advance_src_layer_or_frame_on_autoskip
+ *   advance source layer or chached image to next frame according to FRAME based pvals->stepmode
+ *   this is done in a loop autoskip_size times.
+ * ============================================================================
+ */
+static void
+p_mov_advance_src_layer_or_frame_on_autoskip(GapMovCurrent *cur_ptr, GapMovValues  *val_ptr, long 
autoskip_size)
+{
+  gint32 l_cnt;
+  gint32 l_tweensteps_to_go;
+
+  if((val_ptr->src_stepmode == GAP_STEP_FRAME_NONE) 
+  || (val_ptr->src_stepmode == GAP_STEP_NONE))
+  {
+    return;
+  }
+
+
+  l_tweensteps_to_go = (val_ptr->tween_steps + 1) * autoskip_size;
+
+  for(l_cnt = l_tweensteps_to_go; l_cnt > 0; l_cnt--)
+  {
+    if(val_ptr->src_stepmode < GAP_STEP_FRAME )
+    {
+       /* advance settings for next src layer */
+       p_mov_advance_src_layer(cur_ptr, val_ptr);
+    }
+    else
+    {
+      if (l_cnt == 1)
+      {
+        /* advance settings for next source frame and
+         * read this source frame merged as layer into the cache (pvals->cache_tmp_image_id)
+         */
+        p_mov_advance_src_frame(cur_ptr, val_ptr);
+      }
+      else
+      {
+        /* advance settings for next source frame (without fetching the source frame) */
+        p_mov_advance_src_frame_no_fetch(cur_ptr, val_ptr);
+      }
+    }
+  }
 
 
+}  /* end p_mov_advance_src_layer_or_frame_on_autoskip */
 
 
 
@@ -1030,7 +1128,7 @@ p_calculate_settings_for_current_FrameTween(
 
 
   currFrameTweenInSegment =
-     tweenMultiplicator * (abs (currFrameIndex - val_ptr->point[startOfSegmentIndex].keyframe)); 
+     tweenMultiplicator * (abs (currFrameIndex - val_ptr->point[startOfSegmentIndex].keyframe));
   currFrameTweenInSegment += (val_ptr->tween_steps - val_ptr->twix);
 
   /* calculate length factor respecting position in the path segment where 0 is at begin 1 at end */
@@ -1386,12 +1484,13 @@ p_log_current_render_params(GapMovData *mov_ptr, GapMovCurrent *cur_ptr)
 
     val_ptr = mov_ptr->val_ptr;
 
-    printf("\nCurrent Render Params: dst_frame_nr:%ld tweenIndex:%d src_layer_idx:%ld\n"
+    printf("\nCurrent Render Params: dst_frame_nr:%ld tweenIndex:%d src_layer_idx:%d (dbl:%f)\n"
                 "       currX:%f currY:%f\n"
                 "       Width:%f Height:%f\n"
                 "       Opacity:%f  Rotate:%f  clip_to_img:%d force_visibility:%d\n"
                 "       src_stepmode:%d handleX:%d handleY:%d currSelFeatherRadius:%f rotate_threshold:%f\n",
-                     cur_ptr->dst_frame_nr, (int)val_ptr->twix, cur_ptr->src_layer_idx,
+                     cur_ptr->dst_frame_nr, (int)val_ptr->twix, (int)cur_ptr->src_layer_idx,
+                     (float)cur_ptr->src_layer_idx_dbl,
                      (float)cur_ptr->currX,
                      (float)cur_ptr->currY,
                      (float)cur_ptr->currWidth,
@@ -1439,7 +1538,7 @@ static void
 p_printf_log_parameters(GapMovData *mov_ptr)
 {
   gint l_idx;
-  
+
   printf("apv_mlayer_image: %ld\n", (long)mov_ptr->val_ptr->apv_mlayer_image);
   printf("apv_mode: %ld\n", (long)mov_ptr->val_ptr->apv_mode);
   printf("apv_scale x: %f y:%f\n", (float)mov_ptr->val_ptr->apv_scalex, (float)mov_ptr->val_ptr->apv_scaley);
@@ -1651,26 +1750,36 @@ p_duplicate_layer(gint32 layerId)
   gimp_image_set_active_layer(imageId, layerId);
   dupLayerId = gimp_layer_copy(layerId);
   gimp_image_add_layer(imageId, dupLayerId, -1 /* -1 place above active layer */);
-  
-  return(dupLayerId);
-  
-}  /* end p_duplicate_layer */
 
+  return(dupLayerId);
 
+}  /* end p_duplicate_layer */
 
 
 /* -----------------------
  * p_mov_execute_or_query
  * -----------------------
+ * This procedure operates in render mode or query mode.
+ *
+ * RENDER MODE: (mov_query == NULL)
+ * ------------
  * Copy layer(s) from Sourceimage to given destination frame range,
  * varying koordinates and opacity and perform other transformations
  * according to controlpoint settings on the copied layer.
  * To each affected destination frame one copy of a source layer is added.
  * (more than one layer is added in case of tween processing and tracelayer processing)
  * The source layer is iterated through all layers of the sourceimage
- * according to stemmode parameter.
+ * according to multilayer image based stemmode parameter v.
+ * for the frame based stepmodes, interprete the src as frame image sequence
+ * (e.g iterate through flattened copied of src frame images instead of iterating layers)
+ *
  * For the placement the layers act as if their size is equal to their
  * Sourceimages size.
+ *
+ * QUERY MODE: (mov_query != NULL)
+ * -----------
+ * deliver calculated render settings to the caller (in *mov_query)
+ * but do not render anything.
  */
 long
 p_mov_execute_or_query(GapMovData *mov_ptr, GapMovQuery *mov_query)
@@ -1995,10 +2104,14 @@ p_mov_execute_or_query(GapMovData *mov_ptr, GapMovQuery *mov_query)
   /* frameindex loop */
   for(l_fridx = 1; l_fridx < l_cnt; l_fridx++)
   {
+     gboolean l_frame_found;
      gdouble  l_tw_cnt;   /* number of tweens (including the real frame) 1 if no tweens present */
 
-     if(gap_debug) printf("\np_mov_execute: l_fridx=%ld, l_flt_timing[l_ptidx]=%f, l_rc=%d l_ptidx=%d, 
l_prev_keyptidx=%d\n",
+     if(gap_debug)
+     {
+      printf("\np_mov_execute: l_fridx=%ld, l_flt_timing[l_ptidx]=%f, l_rc=%d l_ptidx=%d, 
l_prev_keyptidx=%d\n",
                            l_fridx, (float)l_flt_timing[l_ptidx], (int)l_rc, (int)l_ptidx, 
(int)l_prev_keyptidx);
+     }
 
      if(l_rc != 0)
      {
@@ -2008,6 +2121,47 @@ p_mov_execute_or_query(GapMovData *mov_ptr, GapMovQuery *mov_query)
       /* advance frame_nr, (1st frame was done outside this loop) */
       cur_ptr->dst_frame_nr += l_frame_step;  /* +1  or -1 */
 
+      /* check for missing frames */
+      l_frame_found = gap_lib_framefile_with_framenr_exists(mov_ptr->dst_ainfo_ptr, cur_ptr->dst_frame_nr);
+      if (!l_frame_found)
+      {
+        long l_available_frame_nr;
+
+        l_available_frame_nr = gap_lib_get_next_available_frame_number(
+                 cur_ptr->dst_frame_nr, l_frame_step,
+                 mov_ptr->dst_ainfo_ptr->basename, mov_ptr->dst_ainfo_ptr->extension,
+                 &l_frame_found);
+        if (l_frame_found)
+        {
+           long l_autoskip_size;
+           /* skip processing for all missing frames and continue with next
+            * available frame. (Note that keyframe numbers will not work correct
+            * due to this autoskip of missing frames.)
+            */
+           l_autoskip_size = abs(l_available_frame_nr - cur_ptr->dst_frame_nr);
+           l_fridx += l_autoskip_size;
+
+           if(gap_debug)
+           {
+             printf("\np_mov_execute: AUTOSKIP missing_frame:%d l_available_frame_nr:%d l_autoskip_size:%d 
l_fridx=%ld \n"
+                           , (int)cur_ptr->dst_frame_nr
+                           , (int)l_available_frame_nr
+                           , (int)l_autoskip_size
+                           , l_fridx);
+           }
+           cur_ptr->dst_frame_nr = l_available_frame_nr;
+           if(mov_query == NULL)
+           {
+             p_mov_advance_src_layer_or_frame_on_autoskip(cur_ptr, val_ptr, l_autoskip_size);
+           }
+        }
+        else
+        {
+          break;  /* stop when no next/previous frame could be found */
+        }
+      }
+
+
       if((gdouble)l_fridx > l_flt_timing[l_ptidx])
       {
          /*  fix for object jumps forth and back as reported in #607927 */
@@ -2195,7 +2349,7 @@ p_mov_execute_or_query(GapMovData *mov_ptr, GapMovQuery *mov_query)
  *
  * in case the  mov_ptr->singleFramePtr->drawable_id is NOT already part
  * of the processed frame it will be copied to the frame and
- * the transformation is done on the copy 
+ * the transformation is done on the copy
  *  -- typical secnario when called from storyboard processor --
  * Otherwise transformation is done on the original
  *  -- typical scenario when called via PDB (as filter in the modify frames feature)
@@ -2824,7 +2978,7 @@ gap_mov_exec_anim_preview(GapMovValues *pvals_orig, GapAnimInfo *ainfo_ptr, gint
         }
         break;
     }
-    
+
     if(useOneFrame)
     {
       if((l_filename != NULL)
@@ -2844,8 +2998,8 @@ gap_mov_exec_anim_preview(GapMovValues *pvals_orig, GapAnimInfo *ainfo_ptr, gint
         gimp_image_scale(l_tmp_frame_id, l_size_x, l_size_y);
       }
     }
-    
-    
+
+
     if(l_filename != NULL)
     {
       g_free(l_filename);
@@ -3864,9 +4018,9 @@ gdouble
 gap_mov_exec_get_default_rotate_threshold()
 {
   gdouble rotate_threshold;
-  
-  
-  rotate_threshold = 
+
+
+  rotate_threshold =
     gap_base_get_gimprc_gdouble_value (GAP_MOVEPATH_GIMPRC_ROTATE_THRESHOLD
                                        , GAP_MOVEPATH_DEFAULT_ROTATE_THRESHOLD
                                        , 0.0  /* gdouble min_value */
@@ -4037,7 +4191,7 @@ gap_mov_exec_move_path_singleframe(GimpRunMode run_mode, gint32 image_id
  * --------------------------------------
  * return TRUE on valid movepat xml parameterfile
  */
-gboolean 
+gboolean
 gap_mov_exec_check_valid_xml_paramfile(const char *filename)
 {
   gboolean  isXmlLoadOk;
@@ -4045,7 +4199,7 @@ gap_mov_exec_check_valid_xml_paramfile(const char *filename)
 
   isXmlLoadOk = FALSE;
   pvals = gap_mov_exec_new_GapMovValues();
-  
+
   if(filename != NULL)
   {
     if(*filename != '\0')
@@ -4092,8 +4246,8 @@ gap_mov_exec_move_path_singleframe_directcall(gint32 frame_image_id
    */
   pvals = gap_mov_exec_new_GapMovValues();
   pvals->dst_image_id = frame_image_id;
-  
-  
+
+
   singleframevals.drawable_id = drawable_id;
   singleframevals.frame_phase = frame_phase;
   singleframevals.total_frames = -1;          /* get path length (total frames) from xml paramfile */
@@ -4123,7 +4277,7 @@ gap_mov_exec_move_path_singleframe_directcall(gint32 frame_image_id
        ,(int)drawable_id
        );
   }
-  
+
   g_free(pvals);
   return (result_layer_id);
 
diff --git a/gap/gap_mov_render.c b/gap/gap_mov_render.c
index ea49cb8..ae5b253 100644
--- a/gap/gap_mov_render.c
+++ b/gap/gap_mov_render.c
@@ -996,7 +996,7 @@ gap_mov_render_render(gint32 image_id, GapMovValues *val_ptr, GapMovCurrent *cur
   }
 
 
-  if((cur_ptr->currRotation  > val_ptr->rotate_threshold) 
+  if((cur_ptr->currRotation  > val_ptr->rotate_threshold)
   || (cur_ptr->currRotation <  (0.0 - val_ptr->rotate_threshold)))
   {
     gboolean     l_interpolation;
@@ -1122,7 +1122,7 @@ gap_mov_render_render(gint32 image_id, GapMovValues *val_ptr, GapMovCurrent *cur
 
 
 /* ============================================================================
- * gap_mov_render_fetch_src_frame
+ * gap_mov_render_fetch_src_frame_autoskip
  *   fetch the requested video frame SourceImage into cache_tmp_image_id
  *   and
  *    - reduce all visible layers to one layer (cache_tmp_layer_id)
@@ -1131,17 +1131,27 @@ gap_mov_render_render(gint32 image_id, GapMovValues *val_ptr, GapMovCurrent *cur
  *      of the same source image -- for  GAP_STEP_FRAME_NONE
  *    - never load current frame number from diskfile (use duplicate of the src_image)
  *  returns 0 (OK) or -1 (on Errors)
+ *
+ *  For the frame based modes this procedure supports the autoskip feature
+ *  that will automatically advance to the next/previous availble frame
+ *  (depending on stepsize) when the specified wanted_frame_nr is not availble.
+ *
+ *  IN/OUTPUT: but_got_frame_nr will be overwritten when the frame with the wanted_frame_nr
+ *             is not availble but autoskip to the next/prev frame was successful
+ *             in this case *but_got_frame_nr contains the number of an available frame image
+ *             in all other cases *but_got_frame_nr is NOT changed by this procedure.
  * ============================================================================
  */
 gint
-gap_mov_render_fetch_src_frame(GapMovValues *pvals,  gint32 wanted_frame_nr)
+gap_mov_render_fetch_src_frame_autoskip(GapMovValues *pvals,  gint32 wanted_frame_nr
+   , gint32 *but_got_frame_nr, long stepsize)
 {
   GapAnimInfo  *l_ainfo_ptr;
   GapAnimInfo  *l_old_ainfo_ptr;
 
   if(gap_debug)
   {
-     printf("gap_mov_render_fetch_src_frame: START src_image_id: %d wanted_frame_nr:%d"
+     printf("gap_mov_render_fetch_src_frame_autoskip: START src_image_id: %d wanted_frame_nr:%d"
             " cache_src_image_id:%d cache_frame_number:%d\n"
             , (int)pvals->src_image_id
             , (int)wanted_frame_nr
@@ -1162,7 +1172,7 @@ gap_mov_render_fetch_src_frame(GapMovValues *pvals,  gint32 wanted_frame_nr)
      {
         if(gap_debug)
         {
-           printf("gap_mov_render_fetch_src_frame: DELETE cache_tmp_image_id:%d\n",
+           printf("gap_mov_render_fetch_src_frame_autoskip: DELETE cache_tmp_image_id:%d\n",
                     (int)pvals->cache_tmp_image_id);
         }
         /* destroy the cached frame image */
@@ -1195,6 +1205,7 @@ gap_mov_render_fetch_src_frame(GapMovValues *pvals,  gint32 wanted_frame_nr)
         }
      }
 
+render_fetch_wanted_src_frame:
      if ((wanted_frame_nr == pvals->cache_ainfo_ptr->curr_frame_nr)
      ||  (wanted_frame_nr < 0))
      {
@@ -1220,16 +1231,44 @@ gap_mov_render_fetch_src_frame(GapMovValues *pvals,  gint32 wanted_frame_nr)
           return -1;
        }
 
-       /* load the wanted source frame */
-       pvals->cache_tmp_image_id =  gap_lib_load_image(pvals->cache_ainfo_ptr->new_filename);
-       if(pvals->cache_tmp_image_id < 0)
+       if (g_file_test(pvals->cache_ainfo_ptr->new_filename, G_FILE_TEST_EXISTS))
        {
-          printf("gap: load error on src image %s\n", pvals->cache_ainfo_ptr->new_filename);
-          return -1;
+         /* load the wanted source frame */
+         pvals->cache_tmp_image_id =  gap_lib_load_image(pvals->cache_ainfo_ptr->new_filename);
+         if(pvals->cache_tmp_image_id < 0)
+         {
+            printf("gap: load error on src image %s\n", pvals->cache_ainfo_ptr->new_filename);
+            return -1;
+         }
        }
+       else
+       {
+         long    l_available_frame_nr;
+         gboolean l_frame_found;
+
+         l_available_frame_nr = gap_lib_get_next_available_frame_number(
+               wanted_frame_nr, stepsize
+             , pvals->cache_ainfo_ptr->basename, pvals->cache_ainfo_ptr->extension
+             , &l_frame_found);
+         if (l_frame_found)
+         {
+           /* autoskip to next or previous available frame number */
+           *but_got_frame_nr = l_available_frame_nr;
+           wanted_frame_nr = l_available_frame_nr;
+           goto render_fetch_wanted_src_frame;
+         }
+         else
+         {
+            printf("gap: missing frame number error on src image %s\n", 
pvals->cache_ainfo_ptr->new_filename);
+            return -1;
+         }
 
+       }
      }
 
+
+     /* frame fetch done at this point */
+
      gimp_image_undo_disable (pvals->cache_tmp_image_id);
 
      pvals->cache_tmp_layer_id = gap_image_merge_visible_layers(pvals->cache_tmp_image_id, 
GIMP_EXPAND_AS_NECESSARY);
@@ -1245,7 +1284,7 @@ gap_mov_render_fetch_src_frame(GapMovValues *pvals,  gint32 wanted_frame_nr)
 
        if(gap_debug)
        {
-          printf("gap_mov_render_fetch_src_frame: Scale for Animpreview apv_scalex %f apv_scaley %f\n"
+          printf("gap_mov_render_fetch_src_frame_autoskip: Scale for Animpreview apv_scalex %f apv_scaley 
%f\n"
                  , (float)pvals->apv_scalex, (float)pvals->apv_scaley );
        }
 
@@ -1280,9 +1319,33 @@ gap_mov_render_fetch_src_frame(GapMovValues *pvals,  gint32 wanted_frame_nr)
 
   }
 
+  return 0; /* OK */
+
+}       /* end gap_mov_render_fetch_src_frame_autoskip */
 
 
-  return 0; /* OK */
+/* ============================================================================
+ * gap_mov_render_fetch_src_frame
+ *   fetch the requested video frame SourceImage into cache_tmp_image_id
+ *   and
+ *    - reduce all visible layers to one layer (cache_tmp_layer_id)
+ *    - (scale to animated preview size if called for AnimPreview )
+ *    - reuse cached image (for subsequent calls for the same framenumber
+ *      of the same source image -- for  GAP_STEP_FRAME_NONE
+ *    - never load current frame number from diskfile (use duplicate of the src_image)
+ *  returns 0 (OK) or -1 (on Errors)
+ * ============================================================================
+ */
+gint
+gap_mov_render_fetch_src_frame(GapMovValues *pvals,  gint32 wanted_frame_nr)
+{
+  gint32 l_but_got_frame_nr;
+  gint   l_rc;
+
+  l_rc = gap_mov_render_fetch_src_frame_autoskip(pvals
+                    ,  wanted_frame_nr, &l_but_got_frame_nr, 1);
+  return (l_rc);
+
 }       /* end gap_mov_render_fetch_src_frame */
 
 
diff --git a/gap/gap_mov_render.h b/gap/gap_mov_render.h
index b330e97..98d3c44 100644
--- a/gap/gap_mov_render.h
+++ b/gap/gap_mov_render.h
@@ -31,11 +31,13 @@
  * gimp    1.3.20d; 2003/10/15  hof: sourcecode cleanup
  * gimp    1.3.14a; 2003/05/24  hof: created (splitted off from gap_mov_dialog)
  */
- 
+
 
 #include "gap_mov_dialog.h"
 
 gint   gap_mov_render_render(gint32 image_id, GapMovValues *val_ptr, GapMovCurrent *cur_ptr);
+gint   gap_mov_render_fetch_src_frame_autoskip(GapMovValues *pvals,  gint32 wanted_frame_nr
+            , gint32 *but_got_frame_nr, long stepsize);
 gint   gap_mov_render_fetch_src_frame(GapMovValues *pvals,  gint32 wanted_frame_nr);
 void   gap_mov_render_create_or_replace_tempsel_image(gint32 channel_id, GapMovValues *val_ptr, gboolean 
all_empty);
 
diff --git a/gap/gap_name2layer_main.c b/gap/gap_name2layer_main.c
index 050e108..3b32733 100644
--- a/gap/gap_name2layer_main.c
+++ b/gap/gap_name2layer_main.c
@@ -173,8 +173,7 @@ static void query (void)
                           in_args,
                           out_args);
 
-  // gimp_plugin_menu_branch_register("<Image>", "Video");
-  gimp_plugin_menu_register (PLUG_IN_NAME, N_("<Image>/Video/"));
+  gimp_plugin_menu_register (PLUG_IN_NAME, N_("<Image>/Video/Layer/Render/"));
 }  /* end query */
 
 static void
diff --git a/gap/gap_navigator_dialog.c b/gap/gap_navigator_dialog.c
index cf53c5a..da66356 100644
--- a/gap/gap_navigator_dialog.c
+++ b/gap/gap_navigator_dialog.c
@@ -405,6 +405,7 @@ static void       p_acl_tracking_off_callback(GtkWidget *widget, NaviDialog *nav
 static void       p_acl_tracking_by_name_callback(GtkWidget *widget, NaviDialog *naviD);
 static void       p_acl_tracking_by_pos_callback(GtkWidget *widget, NaviDialog *naviD);
 
+static gint32     p_get_number_of_frames(GapAnimInfo *ainfo_ptr);
 
 
 /* -----------------------
@@ -548,7 +549,6 @@ query ()
                          GIMP_PLUGIN,
                          G_N_ELEMENTS (args_navigator), nreturn_vals,
                          args_navigator, return_vals);
-  // gimp_plugin_menu_branch_register("<Image>", "Video");
   gimp_plugin_menu_register (PLUGIN_NAME, N_("<Image>/Video/"));
 }       /* end query */
 
@@ -2515,13 +2515,16 @@ navi_render_preview (FrameWidget *fw)
      struct stat  l_stat;
      gchar       *l_frame_filename;
      gboolean     l_can_use_cached_thumbnail;
+     gboolean     l_referenced_frame_exists;
 
      l_can_use_cached_thumbnail = FALSE;
+     l_referenced_frame_exists = FALSE;
      l_frame_filename = gap_lib_alloc_fname(naviD->ainfo_ptr->basename, fw->frame_nr, 
naviD->ainfo_ptr->extension);
      if(l_frame_filename)
      {
        if (0 == g_stat(l_frame_filename, &l_stat))
        {
+         l_referenced_frame_exists = TRUE;
          if(fw->frame_filename)
          {
            if(gap_debug)
@@ -2587,7 +2590,8 @@ navi_render_preview (FrameWidget *fw)
      {
        /* fetch l_th_data from thumbnail_file */
        if(gap_debug) printf("navi_render_preview: fetching THUMBNAILFILE for: %s\n", l_frame_filename);
-       if(l_frame_filename)
+       if((l_frame_filename)
+       && (l_referenced_frame_exists))
        {
          /* init preferred width and height
           * (as hint for the thumbnail loader to decide
@@ -3654,7 +3658,7 @@ navi_dyn_adj_set_limits(void)
   if(naviD == NULL) { return; }
   if(naviD->dyn_adj == NULL) { return; }
 
-  frame_cnt_zoomed = naviD->ainfo_ptr->frame_cnt / naviD->vin_ptr->timezoom;
+  frame_cnt_zoomed = p_get_number_of_frames(naviD->ainfo_ptr) / naviD->vin_ptr->timezoom;
   if(naviD->vin_ptr->timezoom > 1)
   {
     /* if there is a rest add 1 to make the last frame,
@@ -4342,7 +4346,7 @@ navi_dialog_create (GtkWidget* shell, gint32 image_id)
     gdouble upper_max;
     gdouble initial_val;
 
-    upper_max = naviD->ainfo_ptr->frame_cnt;
+    upper_max = p_get_number_of_frames(naviD->ainfo_ptr);
     initial_val = 1 + ((naviD->ainfo_ptr->curr_frame_nr - naviD->ainfo_ptr->first_frame_nr) / 
naviD->vin_ptr->timezoom);
 
     naviD->dyn_adj = gtk_adjustment_new (initial_val
@@ -4620,4 +4624,24 @@ ops_button_extended_callback (GtkWidget *widget,
 }
 /* ---------------------------------------  end copy of gimp-1.1.14/app/ops_buttons.c */
 
-
+/* -------------------------------
+ * p_get_number_of_frames
+ * -------------------------------
+ * calculate the number of frames from first and last frame number.
+ * the calculated value may not match the real number of available frame image files
+ * (ainfo_ptr->frame_cnt) in case some frame images are missing.
+ * Note that the current VCR navigator implemetation renders a default icon
+ * for each missing frame.
+ */
+static gint32
+p_get_number_of_frames(GapAnimInfo *ainfo_ptr)
+{
+  gint32 numFrames;
+  
+  numFrames = 1;
+  if (ainfo_ptr != NULL)
+  {
+    numFrames += abs(ainfo_ptr->last_frame_nr - ainfo_ptr->first_frame_nr);
+  }
+  return (numFrames);
+}
diff --git a/gap/gap_onion_base.c b/gap/gap_onion_base.c
index c710b56..ce8ae84 100644
--- a/gap/gap_onion_base.c
+++ b/gap/gap_onion_base.c
@@ -269,7 +269,7 @@ gap_onion_base_onionskin_apply(gpointer gpp
 {
   gint32        l_nr;
   gint32        l_sign;
-  
+
   gint32        l_onr;
   gint32        l_ign;
   gint32        l_idx;
@@ -327,7 +327,7 @@ gap_onion_base_onionskin_apply(gpointer gpp
       l_active_layer = -1;
     }
   }
-  
+
   /* delete onion layers (if there are old ones) */
   gap_onion_base_onionskin_delete(image_id);
 
@@ -361,7 +361,7 @@ gap_onion_base_onionskin_apply(gpointer gpp
        /* process near neigbours first to give them the highest configured opacity value */
        l_nr = l_onr;
     }
- 
+
     /* find out reference frame number */
     switch(vin_ptr->ref_mode)
     {
@@ -377,7 +377,7 @@ gap_onion_base_onionskin_apply(gpointer gpp
       default:
         break;
     }
- 
+
     l_frame_nr = ainfo_curr_frame_nr + (l_sign * (vin_ptr->ref_delta * l_nr));
 
 
@@ -434,11 +434,23 @@ gap_onion_base_onionskin_apply(gpointer gpp
       l_new_filename = gap_lib_alloc_fname(ainfo_basename,
                                           l_frame_nr,
                                           ainfo_extension);
-      /* load referenced frame */
-      l_tmp_image_id = gap_lib_load_image(l_new_filename);
-      if(l_tmp_image_id < 0)
-         return -1;
-
+      if(g_file_test(l_new_filename, G_FILE_TEST_EXISTS))
+      {
+        /* load referenced frame */
+        l_tmp_image_id = gap_lib_load_image(l_new_filename);
+        if(l_tmp_image_id < 0)
+        {
+          g_free(l_new_filename);
+          return -1;
+           }
+      }
+      else
+      {
+        /* refered frame image is not available, ignore it */
+        g_free(l_new_filename);
+        l_new_filename = NULL;
+        continue;
+      }
       /* dont waste time and memory for undo in noninteracive processing
        * of the src frames
        */
@@ -647,7 +659,7 @@ gap_onion_image_has_oinonlayers(gint32 image_id, gboolean only_visible)
         }
       }
     }
-    
+
     g_free(l_layers_list);
   }
   return (l_has_onion);
@@ -658,14 +670,14 @@ gap_onion_image_has_oinonlayers(gint32 image_id, gboolean only_visible)
 /* ---------------------------------
  * gap_onion_base_image_duplicate
  * ---------------------------------
- * duplicate the image 
- * and mark onionskin layers in the copy 
+ * duplicate the image
+ * and mark onionskin layers in the copy
  */
 gint32
 gap_onion_base_image_duplicate(gint32 image_id)
 {
   gint32 dup_image_id;
-  
+
   dup_image_id = gimp_image_duplicate(image_id);
   if(dup_image_id >= 0)
   {
@@ -677,11 +689,11 @@ gap_onion_base_image_duplicate(gint32 image_id)
     gint        l_is_onion;
     gint32      l_layer_id;
     gboolean    l_has_onion;
-    
+
     l_layers_list = gimp_image_get_layers(image_id, &l_nlayers);
     l_dup_layers_list = gimp_image_get_layers(dup_image_id, &l_dup_nlayers);
 
-    if((l_layers_list) 
+    if((l_layers_list)
     && (l_dup_layers_list))
     {
       for(l_idx=0;l_idx < MIN(l_nlayers, l_dup_nlayers);l_idx++)
@@ -698,8 +710,8 @@ gap_onion_base_image_duplicate(gint32 image_id)
       g_free(l_layers_list);
       g_free(l_dup_layers_list);
     }
-    
+
   }
-  
+
   return(dup_image_id);
 }  /* end gap_onion_base_image_duplicate */
diff --git a/gap/gap_onion_worker.c b/gap/gap_onion_worker.c
index baea1bc..4a3ebcd 100644
--- a/gap/gap_onion_worker.c
+++ b/gap/gap_onion_worker.c
@@ -49,7 +49,7 @@ p_find_frame_in_img_cache(void *gpp_void
   gint32 l_idx;
   *image_id = -1;
   *layer_id = -1;
-  
+
   gpp = (GapOnionMainGlobalParams *)gpp_void;
 
   for(l_idx = 0; l_idx < MIN(gpp->cache.count, GAP_ONION_CACHE_SIZE); l_idx++)
@@ -207,7 +207,7 @@ gap_onion_worker_plug_in_gap_get_animinfo(gint32 image_ID, GapOnionMainAinfo *ai
      printf("Error: PDB call of %s failed, image_ID: %d\n", l_called_proc, (int)image_ID);
    }
    gimp_destroy_params(return_vals, nreturn_vals);
-   
+
 }       /* end gap_onion_worker_plug_in_gap_get_animinfo */
 
 
@@ -217,7 +217,7 @@ gint
 gap_onion_worker_set_data_onion_cfg(GapOnionMainGlobalParams *gpp, char *key)
 {
   if(gap_debug) printf("gap_onion_worker_set_data_onion_cfg: START\n");
-  
+
   return (gap_vin_set_common_onion(&gpp->vin, &gpp->ainfo.basename[0]));
 }
 
@@ -225,8 +225,8 @@ gint
 gap_onion_worker_get_data_onion_cfg(GapOnionMainGlobalParams *gpp)
 {
   GapVinVideoInfo *l_vin;
-  
-  
+
+
   if(gap_debug) printf("gap_onion_worker_get_data_onion_cfg: START\n");
 
   /* try to read configuration params */
@@ -338,6 +338,7 @@ gap_onion_worker_onion_range(GapOnionMainGlobalParams *gpp)
   gint32 l_curr_frame_nr;
   gdouble    l_percentage, l_percentage_step;
   gchar  *l_new_filename;
+  gboolean l_frame_found;
 
 
   l_percentage = 0.0;
@@ -376,7 +377,9 @@ gap_onion_worker_onion_range(GapOnionMainGlobalParams *gpp)
   l_new_filename = gimp_image_get_filename(l_current_image_id);
   l_rc = gap_lib_save_named_frame(gpp->image_ID, l_new_filename);
   if(l_rc < 0)
-     return -1;
+  {
+    return -1;
+  }
 
   l_curr_frame_nr = gpp->ainfo.curr_frame_nr;
   l_frame_nr = l_begin;
@@ -400,11 +403,22 @@ gap_onion_worker_onion_range(GapOnionMainGlobalParams *gpp)
       l_new_filename = gap_lib_alloc_fname(gpp->ainfo.basename,
                                           l_frame_nr,
                                           gpp->ainfo.extension);
-      /* load frame */
-      gpp->image_ID =  gap_lib_load_image(l_new_filename);
-      if(gpp->image_ID < 0)
-         return -1;
-
+      if(g_file_test(l_new_filename, G_FILE_TEST_EXISTS))
+      {
+        /* load frame */
+        gpp->image_ID =  gap_lib_load_image(l_new_filename);
+        if(gpp->image_ID < 0)
+        {
+          g_free(l_new_filename);
+          return -1;
+        }
+      }
+      else
+      {
+        g_free(l_new_filename);
+        l_new_filename = NULL;
+        goto continue_with_next_frame;
+      }
       /* add image to cache */
       p_add_img_to_cache(gpp, l_frame_nr, gpp->image_ID, -1);
     }
@@ -424,7 +438,17 @@ gap_onion_worker_onion_range(GapOnionMainGlobalParams *gpp)
 
     l_rc = gap_lib_save_named_frame(gpp->image_ID, l_new_filename);
     if(l_rc < 0)
+    {
+       g_free(l_new_filename);
        return -1;
+    }
+
+continue_with_next_frame:
+    if(l_new_filename != NULL)
+    {
+      g_free(l_new_filename);
+      l_new_filename = NULL;
+    }
 
     if(gpp->run_mode == GIMP_RUN_INTERACTIVE)
     {
@@ -436,7 +460,17 @@ gap_onion_worker_onion_range(GapOnionMainGlobalParams *gpp)
     {
       break;
     }
-    l_frame_nr += l_step;
+    /* advance l_frame_nr to the next/previous available frame number
+     * (normally to l_frame_nr += l_step
+     * sometimes to higher/lower number when frames are missing)
+     */
+    l_frame_nr =
+       gap_lib_get_next_available_frame_number(l_frame_nr, l_step,
+           gpp->ainfo.basename, gpp->ainfo.extension, &l_frame_found);
+    if (!l_frame_found)
+    {
+      break;
+    }
   }
 
   /* clean up the cache (delete all cached temp images) */
diff --git a/gap/gap_player_dialog.c b/gap/gap_player_dialog.c
index 319d3d9..eac9c53 100644
--- a/gap/gap_player_dialog.c
+++ b/gap/gap_player_dialog.c
@@ -158,6 +158,12 @@ unsigned long env_AUDIOLCK = 0;                 /* Default compiled in locking s
 #define FRAMENR_BUTTON_BEGIN 0
 #define FRAMENR_BUTTON_END   1
 
+#define GIMPRC_VIDEO_PLAYER_SHOW_GO_BUTTONS                 "video_player_show_go_buttons"
+#define GIMPRC_VIDEO_PLAYER_SHOW_POSITION_SCALE             "video_player_show_position_scale"
+#define GIMPRC_VIDEO_PLAYER_ENABLE_DETAIL_TRACKING          "video_player_enable_detail_tracking"
+#define GIMPRC_VIDEO_PLAYER_CACHE_NTILES                    "video_player_cache_ntiles"
+#define GIMPRC_VIDEO_PLAYER_ENABLE_AUTO_SKIP_MISSING_FRAMES "video_player_enable_auto_skip_missing_frames"
+
 
 typedef struct t_gobutton
 {
@@ -258,6 +264,8 @@ static void   on_show_gobuttons_checkbutton_toggled  (GtkToggleButton *togglebut
                                                       GapPlayerMainGlobalParams *gpp);
 static void   on_show_positionscale_checkbutton_toggled (GtkToggleButton *togglebutton,
                                                       GapPlayerMainGlobalParams *gpp);
+static void   on_auto_skip_missing_checkbutton_toggled (GtkToggleButton *togglebutton,
+                                                      GapPlayerMainGlobalParams *gpp);
 
 static void   on_play_button_clicked                (GtkButton       *button,
                                                      GdkEventButton  *bevent,
@@ -792,8 +800,8 @@ p_get_audio_relevant_FrameNr(GapPlayerMainGlobalParams *gpp, gint32 framenr)
 {
   GapStoryLocateRet *stb_ret;
   gint32 localFrameNr;
-  
-  /* prepare standard behaviour 
+
+  /* prepare standard behaviour
    *
    */
   localFrameNr = framenr - gpp->ainfo_ptr->first_frame_nr;
@@ -835,7 +843,7 @@ p_get_audio_relevant_FrameNr(GapPlayerMainGlobalParams *gpp, gint32 framenr)
   }
 
   return (localFrameNr);
-  
+
 }  /* end p_get_audio_relevant_FrameNr */
 
 /* -----------------------------------------
@@ -864,7 +872,7 @@ p_build_otone_audiofilename(const char *videofilename, gint32 atrack, const char
 {
   char *l_audiofilename;
   FILE *l_fp;
-  
+
   if (suffix == NULL)
   {
     l_audiofilename = g_strdup_printf("%s.%d.wav", videofilename, atrack);
@@ -873,13 +881,13 @@ p_build_otone_audiofilename(const char *videofilename, gint32 atrack, const char
   {
     l_audiofilename = g_strdup_printf("%s%s.%d.wav", videofilename, suffix, atrack);
   }
-  
+
   if(g_file_test(l_audiofilename, G_FILE_TEST_EXISTS))
   {
     return(l_audiofilename);
   }
-  
-  
+
+
   /* test creation of l_audiofilename is possible */
   l_fp = fopen(l_audiofilename, "w");
   if (l_fp)
@@ -893,8 +901,8 @@ p_build_otone_audiofilename(const char *videofilename, gint32 atrack, const char
   }
 
   l_audiofilename = g_strdup(p_get_default_tmp_otone_audiofilename());
-  return(l_audiofilename);  
-  
+  return(l_audiofilename);
+
 }  /* end p_build_otone_audiofilename */
 
 
@@ -919,7 +927,7 @@ p_check_otone_workfile_up_to_date(const char *videofilename, const char *audiofi
   {
     return(FALSE);
   }
-  
+
   l_audiofilename = p_build_otone_audiofilename(videofilename
                                , l_extract_audiotrack
                                , NULL  /* no suffix used */
@@ -963,7 +971,7 @@ p_audio_start_play(GapPlayerMainGlobalParams *gpp)
   gint32 l_samplerate;
   gint32 l_samples;
   gdouble l_referedClipSpeed;
-    
+
 
   /* if (gap_debug) printf("p_audio_start_play\n"); */
 
@@ -975,6 +983,30 @@ p_audio_start_play(GapPlayerMainGlobalParams *gpp)
   if(gpp->play_backward)                        { return; }
   if(gpp->ainfo_ptr == NULL)                    { return; }
 
+
+  if(gap_debug)
+  {
+    printf("p_audio_start_play play_current_framenr:%d  last_frame_nr:%d begin_frame:%d end_frame:%d\n"
+       , (int)gpp->play_current_framenr
+       , (int)gpp->ainfo_ptr->last_frame_nr
+       , (int)gpp->begin_frame
+       , (int)gpp->end_frame
+       );
+
+  }
+
+
+  /* Workarond: do not start audio when there is just one frame to play
+   * Note that short audioplayback of only one frame caused deadlock
+   * in tests on windows7, but caused no problem in linux environment.
+   */
+  if((gpp->begin_frame == gpp->end_frame)
+  || (gpp->play_current_framenr == gpp->end_frame))
+  {
+    return;
+  }
+
+
   l_samples = gpp->audio_samples;
   l_samplerate = gpp->audio_samplerate;
   l_referedClipSpeed = gpp->original_speed;
@@ -989,9 +1021,9 @@ p_audio_start_play(GapPlayerMainGlobalParams *gpp)
       l_samplerate = gpp->gvahand->samplerate;
     }
 #endif
-    
+
     localFramenr = p_get_audio_relevant_FrameNr(gpp, gpp->play_current_framenr);
-    
+
     offset_start_sec = ( localFramenr
                      + gpp->audio_frame_offset
                      ) / MAX(1, l_referedClipSpeed);
@@ -1005,7 +1037,7 @@ p_audio_start_play(GapPlayerMainGlobalParams *gpp)
   }
 
   offset_start_samples = offset_start_sec * l_samplerate;
-  
+
 #ifdef GAP_ENABLE_VIDEOAPI_SUPPORT
   if(gap_debug)
   {
@@ -1020,8 +1052,8 @@ p_audio_start_play(GapPlayerMainGlobalParams *gpp)
       );
   }
 #endif
-  
-  
+
+
   if(l_referedClipSpeed > 0)
   {
     /* use moidfied samplerate if video is not played at original speed
@@ -1076,15 +1108,15 @@ p_audio_start_play(GapPlayerMainGlobalParams *gpp)
  *
  * In case newer audiosupport  is availabel just enable the relevant GUI widgets
  *
- * In case audiosupport is NOT available 
+ * In case audiosupport is NOT available
  *
  */
 static void
 p_audio_startup_server(GapPlayerMainGlobalParams *gpp)
 {
   gboolean l_audio_enable = FALSE;
-  
-    
+
+
 #ifdef GAP_ENABLE_AUDIO_SUPPORT_WAVPLAY
   const char *cp;
   gboolean wavplay_server_found;
@@ -1279,7 +1311,7 @@ p_conditional_detail_tracking(GapPlayerMainGlobalParams *gpp, gint32 image_id)
  * ------------------------------
  * check if there is a valid current videoreference.
  * if yes attach the reference as (temporary) videoreference parasite
- * to the specified drawable_id 
+ * to the specified drawable_id
  * (that is typically the layer in the mtrace image)
  */
 static void
@@ -1305,7 +1337,7 @@ p_conditional_attach_dvref(GapPlayerMainGlobalParams *gpp
         gap_dvref_assign_videoref_parasites(gpp->dvref_ptr, drawable_id);
       }
     }
-  } 
+  }
 }  /* end p_conditional_attach_dvref */
 
 /* ------------------------------
@@ -1763,7 +1795,7 @@ p_reload_ainfo_ptr(GapPlayerMainGlobalParams *gpp, gint32 image_id)
 
   gpp->image_id = image_id;
   l_hasImagename = FALSE;
-  
+
   if(gpp->stb_ptr)    { return; }
   if(gpp->ainfo_ptr)  { gap_lib_free_ainfo(&gpp->ainfo_ptr); }
 
@@ -1860,7 +1892,7 @@ p_reload_ainfo_ptr(GapPlayerMainGlobalParams *gpp, gint32 image_id)
       gpp->ainfo_ptr->first_frame_nr = 1;
       gpp->ainfo_ptr->last_frame_nr = 1;
       gpp->original_speed = 24.0;
-      
+
     }
   }
 
@@ -2492,7 +2524,7 @@ on_audio_otone_extract_button_clicked (GtkButton       *button,
     l_dbl_total_frames = (gdouble)gpp->gvahand->total_frames;
 
     p_msg_progress_bar_audio(gpp, _("extracting audio"));
- 
+
     if(g_file_test(l_audiofilename, G_FILE_TEST_EXISTS))
     {
       g_remove(l_audiofilename);
@@ -2504,7 +2536,7 @@ on_audio_otone_extract_button_clicked (GtkButton       *button,
 
     gpp->cancel_video_api = FALSE;
     gpp->request_cancel_video_api = FALSE;
-   
+
     /* extract audio segment (in full length) to otone workfile */
     gap_audio_extract_from_videofile(gpp->gva_videofile
                          , l_audiofilename
@@ -2539,7 +2571,7 @@ on_audio_otone_extract_button_clicked (GtkButton       *button,
     else
     {
       gint32 l_audiofile_size;
-      
+
       l_audiofile_size = gap_file_get_filesize(l_audiofilename);
       if (l_audiofile_size < 1)
       {
@@ -2547,7 +2579,7 @@ on_audio_otone_extract_button_clicked (GtkButton       *button,
         g_message(_("Extract of audiotrack failed on videofile: %s"), gpp->gva_videofile);
         goto cleanup;
       }
-      
+
       if (gpp->cancel_video_api == TRUE)
       {
         /* due to cancel the extracted audiofile is not complete
@@ -2563,7 +2595,7 @@ on_audio_otone_extract_button_clicked (GtkButton       *button,
       }
     }
   }
-  
+
 
   gpp->audio_auto_offset_by_framenr = TRUE;
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (gpp->audio_auto_offset_by_framenr_checkbutton),
@@ -2840,7 +2872,7 @@ p_open_videofile(GapPlayerMainGlobalParams *gpp
                                              );
       }
     }
-    
+
     if(gpp->gvahand->vindex)
     {
       if(gpp->gvahand->vindex->total_frames > 0)
@@ -2931,7 +2963,7 @@ p_open_videofile(GapPlayerMainGlobalParams *gpp
   }
 /* printf("PLAYER: open END\n"); */
 #endif
-  
+
 }  /* end p_open_videofile */
 
 
@@ -2957,7 +2989,7 @@ p_fetch_videoframe(GapPlayerMainGlobalParams *gpp
 {
   guchar *th_data;
   static gint32 funcId = -1;
-  
+
   GAP_TIMM_GET_FUNCTION_ID(funcId, "playerDialog.p_fetch_videoframe");
 
 
@@ -3079,7 +3111,7 @@ p_fetch_videoframe(GapPlayerMainGlobalParams *gpp
     }
     else if (gpp->dvref_ptr != NULL)
     {
-      /* refresh current videofile reference 
+      /* refresh current videofile reference
        * Note: the  dvref_ptr->videofile gets no COPY but only a rference to the current videofilename
        *       this pointer can be reset to NULL any time (at p_display_frame)
        *       but MUST NOT free up the refered name.
@@ -3143,16 +3175,16 @@ p_init_tile_cache(GapPlayerMainGlobalParams *gpp)
 
   gpp->cache_ntiles = GAP_PLAYER_MAIN_DEFAULT_CACHE_NTILES;
 
-  value_string = gimp_gimprc_query("video_player_cache_ntiles");
+  value_string = gimp_gimprc_query(GIMPRC_VIDEO_PLAYER_CACHE_NTILES);
   if(value_string)
   {
     gpp->cache_ntiles = MAX(0, atol(value_string));
-    
+
     g_free(value_string);
   }
 
   gimp_tile_cache_ntiles(gpp->cache_ntiles);
-  
+
 }  /* end p_init_tile_cache */
 
 /* -----------------------------
@@ -3178,7 +3210,7 @@ p_init_layout_options(GapPlayerMainGlobalParams *gpp)
   gpp->show_go_buttons = TRUE;
   gpp->show_position_scale = TRUE;
 
-  value_string = gimp_gimprc_query("video_player_show_go_buttons");
+  value_string = gimp_gimprc_query(GIMPRC_VIDEO_PLAYER_SHOW_GO_BUTTONS);
   if(value_string)
   {
     if ((*value_string == 'Y') || (*value_string == 'y'))
@@ -3193,7 +3225,7 @@ p_init_layout_options(GapPlayerMainGlobalParams *gpp)
     g_free(value_string);
   }
 
-  value_string = gimp_gimprc_query("video_player_show_position_scale");
+  value_string = gimp_gimprc_query(GIMPRC_VIDEO_PLAYER_SHOW_POSITION_SCALE);
   if(value_string)
   {
     if ((*value_string == 'Y') || (*value_string == 'y'))
@@ -3209,7 +3241,7 @@ p_init_layout_options(GapPlayerMainGlobalParams *gpp)
   }
 
 
-  value_string = gimp_gimprc_query("video_player_enable_detail_tracking");
+  value_string = gimp_gimprc_query(GIMPRC_VIDEO_PLAYER_ENABLE_DETAIL_TRACKING);
   if(value_string)
   {
     if ((*value_string == 'Y') || (*value_string == 'y'))
@@ -3223,6 +3255,22 @@ p_init_layout_options(GapPlayerMainGlobalParams *gpp)
 
     g_free(value_string);
   }
+
+
+  value_string = gimp_gimprc_query(GIMPRC_VIDEO_PLAYER_ENABLE_AUTO_SKIP_MISSING_FRAMES);
+  if(value_string)
+  {
+    if ((*value_string == 'Y') || (*value_string == 'y'))
+    {
+      gpp->enableAutoSkipMissingFrames = TRUE;
+    }
+    else
+    {
+      gpp->enableAutoSkipMissingFrames = FALSE;
+    }
+
+    g_free(value_string);
+  }
 }  /* end p_init_layout_options */
 
 
@@ -3554,7 +3602,7 @@ p_fetch_display_th_data_from_storyboard(GapPlayerMainGlobalParams *gpp
   GapStoryLocateRet *stb_ret;
   guchar *l_th_data;
   static gint32 funcId = -1;
-  
+
   GAP_TIMM_GET_FUNCTION_ID(funcId, "playerDialog.p_fetch_display_th_data_from_storyboard");
   GAP_TIMM_START_FUNCTION(funcId);
 
@@ -3577,7 +3625,7 @@ p_fetch_display_th_data_from_storyboard(GapPlayerMainGlobalParams *gpp
          if(*filename_pptr)
          {
            gboolean isBackwards;
-           
+
            if(gpp->use_thumbnails)
            {
              /* fetch does already scale down to current preview size */
@@ -3855,10 +3903,14 @@ p_render_display_free_image_id(GapPlayerMainGlobalParams *gpp
 }  /* end p_render_display_free_image_id */
 
 
-
 /* ------------------------------------------
  * p_render_display_from_active_image_or_file
  * ------------------------------------------
+ * the active image is rendered by duplicating the the already loaded gimp image
+ * to reflect current (possibly not yet saved) representation.
+ * other frame images must be rendered from disc.
+ * (do not check if img_filename exists here again,
+ * because this was typically already done when called by the p_display_frame procedure.)
  */
 static void
 p_render_display_from_active_image_or_file(GapPlayerMainGlobalParams *gpp
@@ -3894,7 +3946,7 @@ p_render_display_from_active_image_or_file(GapPlayerMainGlobalParams *gpp
     if (l_image_id < 0)
     {
       /* could not read the image
-       * one reason could be, that frames were deleted while this plugin is active
+       * one reason could be, that frames were damged or deleted while this plugin is active
        * so we stop playback,
        * and try to reload informations about all frames
        */
@@ -3918,7 +3970,6 @@ p_render_display_from_active_image_or_file(GapPlayerMainGlobalParams *gpp
     gap_thumb_cond_gimp_file_save_thumbnail(l_image_id, img_filename);
   }
 
-
   p_render_display_free_image_id(gpp
      , l_image_id
      , flip_request
@@ -3969,7 +4020,7 @@ p_display_frame(GapPlayerMainGlobalParams *gpp, gint32 framenr)
   GdkPixbuf *pixbuf;
   gchar *ckey;
   static gint32 funcId = -1;
-  
+
   GAP_TIMM_GET_FUNCTION_ID(funcId, "playerDialog.p_display_frame");
 
   /*if(gap_debug) printf("p_display_frame START: framenr:%d\n", (int)framenr);*/
@@ -4052,7 +4103,7 @@ p_display_frame(GapPlayerMainGlobalParams *gpp, gint32 framenr)
     if(gpp->ainfo_ptr->ainfo_type == GAP_AINFO_MOVIE)
     {
       gboolean isBackwards;
-      
+
       /* playback of a single videoclip */
       if(gpp->use_thumbnails)
       {
@@ -4150,7 +4201,7 @@ p_display_frame(GapPlayerMainGlobalParams *gpp, gint32 framenr)
   && (l_composite_image_id < 0))
   {
     /* frame not available, create black fully transparent buffer
-     * ( renders as empty checkerboard)
+     * (renders as empty checkerboard)
      */
     l_th_bpp = 4;
     l_th_width = gpp->pv_width;
@@ -4255,6 +4306,26 @@ p_display_frame(GapPlayerMainGlobalParams *gpp, gint32 framenr)
                        );
       }
 
+      if (l_th_data == NULL)
+      {
+        /* got no thumbnail data until now,
+         * check if the (full sized) image exists, e.g and can be used for rendering
+         */
+           if(!g_file_test(l_filename, G_FILE_TEST_EXISTS))
+           {
+                     /* frame image file not available, create black fully transparent buffer
+                      * (renders as empty checkerboard)
+                      */
+                     l_th_bpp = 4;
+                     l_th_width = gpp->pv_width;
+                     l_th_height = gpp->pv_height;
+                     l_th_data_count = l_th_width * l_th_height * l_th_bpp;
+                     l_th_data = g_malloc0(l_th_data_count);
+               }
+         }
+
+
+
       if (l_th_data)
       {
          p_render_display_free_thdata(gpp
@@ -4269,7 +4340,7 @@ p_display_frame(GapPlayerMainGlobalParams *gpp, gint32 framenr)
       }
       else
       {
-        /* got no thumbnail data, must use the full image */
+        /* still got no thumbnail data, must use the full image */
         p_render_display_from_active_image_or_file(gpp
             , l_filename
             , framenr_is_the_active_image
@@ -4302,6 +4373,45 @@ p_display_frame(GapPlayerMainGlobalParams *gpp, gint32 framenr)
 
 }  /* end p_display_frame */
 
+/* -----------------------------
+ * p_get_available_frame_number
+ * -----------------------------
+ * this procedure validates the specified framenumber
+ * for frame images (e.g. ainfo_type == GAP_AINFO_FRAMES)
+ * in case framenr refers to a missing frame image filename (that does not exist)
+ * the next (or previous for negative stepsize) available framenumber is returned
+ * 
+ * in case the frame image is found (e.g. ainfo_type != GAP_AINFO_FRAMES)
+ * return the unchanged framenr
+ */
+static gint32
+p_get_available_frame_number(GapPlayerMainGlobalParams *gpp, gint32  framenr, gint stepsize)
+{
+  gint32 available_framenr;
+  
+  available_framenr = framenr;
+  
+  if (gpp->ainfo_ptr->ainfo_type == GAP_AINFO_FRAMES)
+  {
+    gboolean l_cur_frame_found;
+
+    l_cur_frame_found = gap_lib_framefile_with_framenr_exists(gpp->ainfo_ptr, framenr);
+    if((l_cur_frame_found != TRUE)
+    && (gpp->enableAutoSkipMissingFrames))
+    {
+      /* advance l_curr to the next available frame number
+       * (normally to framenr += stepsize);
+       * sometimes to higher number when frames are missing)
+       */
+      available_framenr = gap_lib_get_next_available_frame_number(framenr, stepsize
+                         , gpp->ainfo_ptr->basename, gpp->ainfo_ptr->extension, &l_cur_frame_found);
+    }
+  }
+  return (available_framenr);
+  
+}  /* p_get_available_frame_number */
+
+
 /* ------------------------------
  * p_get_next_framenr_in_sequence /2
  * ------------------------------
@@ -4311,7 +4421,8 @@ p_get_next_framenr_in_sequence2(GapPlayerMainGlobalParams *gpp)
 {
   gint32 l_first;
   gint32 l_last;
-
+  gint   l_stepsize;
+  
   l_first = gpp->ainfo_ptr->first_frame_nr;
   l_last  = gpp->ainfo_ptr->last_frame_nr;
   if(gpp->play_selection_only)
@@ -4398,6 +4509,20 @@ p_get_next_framenr_in_sequence2(GapPlayerMainGlobalParams *gpp)
     }
   }
 
+  if (gpp->play_backward)
+  {
+    l_stepsize = -1;
+  }
+  else
+  {
+    l_stepsize = 1;
+  }
+
+  gpp->play_current_framenr =
+     p_get_available_frame_number(gpp, gpp->play_current_framenr, l_stepsize);
+
+
+
   gpp->play_current_framenr = CLAMP(gpp->play_current_framenr, l_first, l_last);
   return (gpp->play_current_framenr);
 }  /* end p_get_next_framenr_in_sequence2 */
@@ -4472,6 +4597,8 @@ p_step_frame(GapPlayerMainGlobalParams *gpp, gint stepsize)
   framenr = gpp->play_current_framenr + stepsize;
   if(gpp->ainfo_ptr)
   {
+
+    framenr = p_get_available_frame_number(gpp, framenr, stepsize);
     framenr = CLAMP(framenr
                    , gpp->ainfo_ptr->first_frame_nr
                    , gpp->ainfo_ptr->last_frame_nr
@@ -4561,7 +4688,7 @@ on_timer_playback(GapPlayerMainGlobalParams *gpp)
        gint ii;
        gint ii_max;
        gint32 l_prev_framenr;
-       gint32 l_framenr = -1;
+       gint32 l_framenr;
        gboolean l_frame_dropped;
        gdouble  l_delay;
 
@@ -5936,6 +6063,31 @@ on_show_positionscale_checkbutton_toggled(GtkToggleButton *togglebutton,
 }  /* end on_show_positionscale_checkbutton_toggled */
 
 
+
+/* -----------------------------------------
+ * on_auto_skip_missing_checkbutton_toggled
+ * -----------------------------------------
+ */
+static void
+on_auto_skip_missing_checkbutton_toggled(GtkToggleButton *togglebutton,
+                                        GapPlayerMainGlobalParams *gpp)
+{
+  if(gpp == NULL)
+  {
+    return;
+  }
+
+  if (togglebutton->active)
+  {
+       gpp->enableAutoSkipMissingFrames = TRUE;
+  }
+  else
+  {
+       gpp->enableAutoSkipMissingFrames = FALSE;
+  }
+
+}  /* end on_auto_skip_missing_checkbutton_toggled */
+
 /* ---------------------------------------------
  * on_enable_detail_tracking_checkbutton_toggled
  * ---------------------------------------------
@@ -5982,7 +6134,7 @@ on_detail_tracking_button_clicked (GtkButton       *button,
 
   dtailTrackingOk =
     gap_detail_tracking_dialog_cfg_set_vals(gpp->mtrace_image_id);
-  
+
   if(dtailTrackingOk)
   {
     gpp->enableDetailTracking = TRUE;
@@ -6455,7 +6607,7 @@ on_audio_create_copy_button_clicked (GtkButton       *button,
 
       g_free(l_cmd);
       g_free(l_resample_params);
-      
+
 
       /* if the external converter created the wavfile
        * then use the newly created wavfile
@@ -6490,7 +6642,7 @@ on_audio_filename_entry_changed (GtkWidget     *widget,
                                  GapPlayerMainGlobalParams *gpp)
 {
   gboolean has_changed;
-  
+
   if(gpp == NULL)
   {
     return;
@@ -6506,7 +6658,7 @@ on_audio_filename_entry_changed (GtkWidget     *widget,
        printf(" ()) gtk_entry_get_text:%s\n"
             , gtk_entry_get_text(GTK_ENTRY(gpp->audio_filename_entry)));
      }
-     
+
     if (gtk_entry_get_text(GTK_ENTRY(gpp->audio_filename_entry)) != NULL)
     {
       if (strcmp(gpp->audio_filename, gtk_entry_get_text(GTK_ENTRY(gpp->audio_filename_entry))) == 0)
@@ -6515,7 +6667,7 @@ on_audio_filename_entry_changed (GtkWidget     *widget,
       }
     }
   }
-  
+
   g_snprintf(gpp->audio_filename, sizeof(gpp->audio_filename), "%s"
             , gtk_entry_get_text(GTK_ENTRY(gpp->audio_filename_entry))
              );
@@ -7195,24 +7347,26 @@ on_prefs_save_gimprc_button_clicked (GtkButton       *button,
                                GapPlayerMainGlobalParams *gpp)
 {
   gchar *valueAsString;
-  
+
   if(gpp == NULL)
   {
     return;
   }
   gap_player_cache_set_gimprc_bytesize(gpp->max_player_cache);
 
-  p_gimprc_save_boolean_option("video_player_show_go_buttons"
+  p_gimprc_save_boolean_option(GIMPRC_VIDEO_PLAYER_SHOW_GO_BUTTONS
                              ,gpp->show_go_buttons);
-  p_gimprc_save_boolean_option("video_player_show_position_scale"
+  p_gimprc_save_boolean_option(GIMPRC_VIDEO_PLAYER_SHOW_POSITION_SCALE
                              ,gpp->show_position_scale);
-  p_gimprc_save_boolean_option("video_player_enable_detail_tracking"
+  p_gimprc_save_boolean_option(GIMPRC_VIDEO_PLAYER_ENABLE_DETAIL_TRACKING
                              ,gpp->enableDetailTracking);
+  p_gimprc_save_boolean_option(GIMPRC_VIDEO_PLAYER_ENABLE_AUTO_SKIP_MISSING_FRAMES
+                             ,gpp->enableAutoSkipMissingFrames);
 
   valueAsString = g_strdup_printf("%ld", (long)gpp->cache_ntiles);
-  gimp_gimprc_set("video_player_cache_ntiles", valueAsString);
+  gimp_gimprc_set(GIMPRC_VIDEO_PLAYER_CACHE_NTILES, valueAsString);
   g_free(valueAsString);
-  
+
 
 }  /* end on_prefs_save_gimprc_button_clicked */
 
@@ -7404,7 +7558,24 @@ p_new_configframe(GapPlayerMainGlobalParams *gpp)
 
   row++;
 
+  /* Auto skip missing frames */
+  checkbutton = gtk_check_button_new_with_label (_("Auto Skip Missing Frames"));
+  gpp->autoSkipMissingFrames_checkbutton = checkbutton;
+  gtk_widget_show (checkbutton);
+  gtk_table_attach (GTK_TABLE (table1), checkbutton, 1, 3, row, row+1,
+                    (GtkAttachOptions) (GTK_FILL),
+                    (GtkAttachOptions) (0), 0, 0);
+  gimp_help_set_help_data (checkbutton, _("ON: Automatically skip missing frames on playback.\n"
+                                          "OFF: Show missing frames as empty (transparent) image."), NULL);
+  if(gpp->enableAutoSkipMissingFrames)
+  {
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (checkbutton), TRUE);
+  }
+  g_signal_connect (G_OBJECT (checkbutton), "toggled",
+                      G_CALLBACK (on_auto_skip_missing_checkbutton_toggled),
+                      gpp);
 
+  row++;
 
 
 
@@ -8837,7 +9008,7 @@ gap_player_dlg_create(GapPlayerMainGlobalParams *gpp)
   gpp->audio_frame_offset = 0;
   gpp->audio_filesel = NULL;
   gpp->audio_tmp_dialog_is_open = FALSE;
-  
+
   gpp->audio_otone_atrack = 1;
   gpp->audio_enable_checkbutton = NULL;
   gpp->audio_auto_offset_by_framenr_checkbutton = NULL;
diff --git a/gap/gap_player_main.c b/gap/gap_player_main.c
index 1ef9809..7aed9a1 100644
--- a/gap/gap_player_main.c
+++ b/gap/gap_player_main.c
@@ -227,6 +227,8 @@ static GapPlayerMainGlobalParams global_params =
 , GAP_PLAYER_MAIN_DEFAULT_CACHE_NTILES  /* gulong cache_ntiles */
 , NULL                /* GtkObject *cache_ntiles_spinbutton_adj */
 , NULL                /* GtkWidget   *detail_tracking_checkbutton */
+, TRUE                /* gboolean     enableAutoSkipMissingFrames */
+, NULL                /* GtkWidget   *autoSkipMissingFrames_checkbutton */
 };
 
 
diff --git a/gap/gap_player_main.h b/gap/gap_player_main.h
index 3514526..ff31d4e 100644
--- a/gap/gap_player_main.h
+++ b/gap/gap_player_main.h
@@ -262,6 +262,9 @@ typedef struct GapPlayerMainGlobalParams {
   gulong       cache_ntiles;                 /* gimp tile cache size for the player process */
   GtkObject   *cache_ntiles_spinbutton_adj;
   GtkWidget   *detail_tracking_checkbutton;
+
+  gboolean     enableAutoSkipMissingFrames;
+  GtkWidget   *autoSkipMissingFrames_checkbutton;
   
 } GapPlayerMainGlobalParams;
 
diff --git a/gap/gap_range_ops.c b/gap/gap_range_ops.c
index fdded21..5675417 100644
--- a/gap/gap_range_ops.c
+++ b/gap/gap_range_ops.c
@@ -899,11 +899,11 @@ p_frames_to_multilayer(GapAnimInfo *ainfo_ptr,
   gint32 calling_frame_nr;
   gdouble    l_xresoulution, l_yresoulution;
   gint32     l_unit;
+  gboolean   l_frame_found;
 
   calling_image_id = ainfo_ptr->image_id;
   calling_frame_nr = ainfo_ptr->curr_frame_nr;
 
-
   l_percentage = 0.0;
   l_nlayers_result = 0;
   if(ainfo_ptr->run_mode == GIMP_RUN_INTERACTIVE)
@@ -991,7 +991,8 @@ p_frames_to_multilayer(GapAnimInfo *ainfo_ptr,
 
 
   l_cur_frame_nr = l_begin;
-  while(1)
+  l_frame_found = TRUE;
+  while(l_frame_found == TRUE)
   {
     /* build the frame name */
     if(ainfo_ptr->new_filename != NULL) g_free(ainfo_ptr->new_filename);
@@ -1008,8 +1009,15 @@ p_frames_to_multilayer(GapAnimInfo *ainfo_ptr,
     }
     else
     {
-      /* load current frame into temporary image */
-      l_tmp_image_id = gap_lib_load_image(ainfo_ptr->new_filename);
+      if (g_file_test(ainfo_ptr->new_filename, G_FILE_TEST_EXISTS))
+      {
+        /* load current frame into temporary image */
+        l_tmp_image_id = gap_lib_load_image(ainfo_ptr->new_filename);
+      }
+      else
+      {
+         goto frames_to_multilayer_advance_to_next_frame;
+      }
     }
     if(l_tmp_image_id < 0)
        goto error;
@@ -1139,6 +1147,7 @@ p_frames_to_multilayer(GapAnimInfo *ainfo_ptr,
     /* destroy the tmp image */
     gimp_image_delete(l_tmp_image_id);
 
+frames_to_multilayer_advance_to_next_frame:
     if(ainfo_ptr->run_mode == GIMP_RUN_INTERACTIVE)
     {
       l_percentage += l_percentage_step;
@@ -1147,10 +1156,21 @@ p_frames_to_multilayer(GapAnimInfo *ainfo_ptr,
 
     /* advance to next frame */
     if(l_cur_frame_nr == l_end)
-       break;
-    l_cur_frame_nr += l_step;
+    {
+      break;
+    }
 
-  }
+     /* advance l_hi to the next available frame number 
+      * (normally to l_cur_frame_nr += l_step;
+      * sometimes to higher/lower number when frames are missing) 
+      */
+    l_cur_frame_nr = gap_lib_get_next_available_frame_number(l_cur_frame_nr, l_step
+                           , ainfo_ptr->basename, ainfo_ptr->extension, &l_frame_found);
+    if (l_frame_found != TRUE)
+    {
+      break;
+    }
+  }  /* end while */
 
   gap_image_prevent_empty_image(l_new_image_id);
 
@@ -1402,17 +1422,30 @@ p_frames_convert(GapAnimInfo *ainfo_ptr,
   while(l_rc >= 0)
   {
     /* build the frame name */
-    if(ainfo_ptr->new_filename != NULL) g_free(ainfo_ptr->new_filename);
+    if(ainfo_ptr->new_filename != NULL)
+    {
+      g_free(ainfo_ptr->new_filename);
+    }
+    
     ainfo_ptr->new_filename = gap_lib_alloc_fname(ainfo_ptr->basename,
                                         l_cur_frame_nr,
                                         ainfo_ptr->extension);
     if(ainfo_ptr->new_filename == NULL)
-       return -1;
+    {
+       goto check_end_or_advance_to_next_frame;
+    }
 
+    if(1 != gap_lib_file_exists(ainfo_ptr->new_filename)) 
+    {
+       goto check_end_or_advance_to_next_frame;
+    }
+    
     /* load current frame */
     l_tmp_image_id = gap_lib_load_image(ainfo_ptr->new_filename);
     if(l_tmp_image_id < 0)
+    {
        return -1;
+    }
 
     l_img_already_flat = FALSE; /* an image without any layer is considered as not flattend */
     l_layers_list = gimp_image_get_layers(l_tmp_image_id, &l_nlayers);
@@ -1566,6 +1599,8 @@ p_frames_convert(GapAnimInfo *ainfo_ptr,
       break;
     }
 
+check_end_or_advance_to_next_frame:
+
     /* break at last handled frame */
     if(l_cur_frame_nr == l_end)
     {
@@ -1581,11 +1616,12 @@ p_frames_convert(GapAnimInfo *ainfo_ptr,
     }
 
     /* advance to next frame */
-    l_cur_frame_nr += l_step;
+    l_cur_frame_nr = gap_lib_get_next_available_frame_number(l_cur_frame_nr
+                      , l_step, ainfo_ptr->basename, ainfo_ptr->extension, NULL);
   }
 
-
   return l_rc;
+
 }       /* end p_frames_convert */
 
 
@@ -1654,6 +1690,7 @@ p_anim_sizechange(GapAnimInfo *ainfo_ptr,
   gdouble    l_percentage, l_percentage_step;
   GimpParam     *l_params;
   int         l_rc;
+  gboolean    l_frame_found;
 
   l_rc = 0;
   l_params = NULL;
@@ -1691,7 +1728,8 @@ p_anim_sizechange(GapAnimInfo *ainfo_ptr,
 
   l_cur_frame_nr = l_begin;
 
-  while(1)
+  l_frame_found = TRUE;
+  while(l_frame_found == TRUE)
   {
     /* build the frame name */
     if(ainfo_ptr->new_filename != NULL) g_free(ainfo_ptr->new_filename);
@@ -1699,23 +1737,37 @@ p_anim_sizechange(GapAnimInfo *ainfo_ptr,
                                         l_cur_frame_nr,
                                         ainfo_ptr->extension);
     if(ainfo_ptr->new_filename == NULL)
+    {
        return -1;
+    }
 
-    /* load current frame into temporary image */
-    l_tmp_image_id = gap_lib_load_image(ainfo_ptr->new_filename);
-    if(l_tmp_image_id < 0)
-       return -1;
+    if (g_file_test(ainfo_ptr->new_filename, G_FILE_TEST_EXISTS))
+    {
+      /* load current frame into temporary image */
+      l_tmp_image_id = gap_lib_load_image(ainfo_ptr->new_filename);
+      if(l_tmp_image_id < 0)
+      {
+         return -1;
+      }
 
-    l_rc = p_image_sizechange(l_tmp_image_id, asiz_mode,
+      l_rc = p_image_sizechange(l_tmp_image_id, asiz_mode,
                               size_x, size_y, offs_x, offs_y);
-    if(l_rc < 0) break;
+      if(l_rc < 0)
+      {
+        break;
+      }
+
+      /* save back the current frame with same name */
+      l_rc = gap_lib_save_named_frame(l_tmp_image_id, ainfo_ptr->new_filename);
+      if(l_rc < 0)
+      {
+        break;
+      }
 
-    /* save back the current frame with same name */
-    l_rc = gap_lib_save_named_frame(l_tmp_image_id, ainfo_ptr->new_filename);
-    if(l_rc < 0) break;
+      /* destroy the tmp image */
+      gimp_image_delete(l_tmp_image_id);
+    }
 
-    /* destroy the tmp image */
-    gimp_image_delete(l_tmp_image_id);
 
     if(ainfo_ptr->run_mode == GIMP_RUN_INTERACTIVE)
     {
@@ -1725,8 +1777,16 @@ p_anim_sizechange(GapAnimInfo *ainfo_ptr,
 
     /* advance to next frame */
     if(l_cur_frame_nr == l_end)
+    {
        break;
-    l_cur_frame_nr += l_step;
+    }
+
+    /* advance l_cur_frame_nr to the next available frame number 
+     * (normally to l_cur_frame_nr += l_step; 
+     * sometimes to higher number when frames are missing) 
+     */
+    l_cur_frame_nr = gap_lib_get_next_available_frame_number(l_cur_frame_nr, l_step
+                           , ainfo_ptr->basename, ainfo_ptr->extension, &l_frame_found);
 
   }   /* end while loop over all frames*/
 
@@ -1822,6 +1882,7 @@ p_frames_layer_del(GapAnimInfo *ainfo_ptr,
   gdouble    l_percentage, l_percentage_step;
   gchar     *l_buff;
   int        l_rc;
+  gboolean   l_frame_found;
 
 
   l_rc = 0;
@@ -1866,7 +1927,8 @@ p_frames_layer_del(GapAnimInfo *ainfo_ptr,
 
 
   l_cur_frame_nr = l_begin;
-  while(1)
+  l_frame_found = TRUE;
+  while(l_frame_found == TRUE)
   {
     /* build the frame name */
     if(ainfo_ptr->new_filename != NULL) g_free(ainfo_ptr->new_filename);
@@ -1874,37 +1936,44 @@ p_frames_layer_del(GapAnimInfo *ainfo_ptr,
                                         l_cur_frame_nr,
                                         ainfo_ptr->extension);
     if(ainfo_ptr->new_filename == NULL)
+    {
        return -1;
-
-    /* load current frame */
-    l_tmp_image_id = gap_lib_load_image(ainfo_ptr->new_filename);
-    if(l_tmp_image_id < 0)
-       return -1;
-
-    /* remove layer[position] */
-    l_layers_list = gimp_image_get_layers(l_tmp_image_id, &l_nlayers);
-    if(l_layers_list != NULL)
+    }
+   
+    if (g_file_test(ainfo_ptr->new_filename, G_FILE_TEST_EXISTS))
     {
-      /* findout layer id of the requestetd position within layerstack */
-      if(position < l_nlayers) l_tmp_layer_id = l_layers_list[position];
-      else                     l_tmp_layer_id = l_layers_list[l_nlayers -1];
-
-      g_free (l_layers_list);
+      /* load current frame */
+      l_tmp_image_id = gap_lib_load_image(ainfo_ptr->new_filename);
+      if(l_tmp_image_id < 0)
+      {
+        return -1;
+      }
 
-      /* check for last layer (MUST NOT be deleted !) */
-      if(l_nlayers > 1)
+      /* remove layer[position] */
+      l_layers_list = gimp_image_get_layers(l_tmp_image_id, &l_nlayers);
+      if(l_layers_list != NULL)
       {
-        /* remove and delete requested layer */
-        gimp_image_remove_layer(l_tmp_image_id, l_tmp_layer_id);
+        /* findout layer id of the requestetd position within layerstack */
+        if(position < l_nlayers) l_tmp_layer_id = l_layers_list[position];
+        else                     l_tmp_layer_id = l_layers_list[l_nlayers -1];
 
-        /* save current frame */
-        l_rc = gap_lib_save_named_frame(l_tmp_image_id, ainfo_ptr->new_filename);
-      }
-    }
+        g_free (l_layers_list);
 
-    /* destroy the tmp image */
-    gimp_image_delete(l_tmp_image_id);
+        /* check for last layer (MUST NOT be deleted !) */
+        if(l_nlayers > 1)
+        {
+          /* remove and delete requested layer */
+          gimp_image_remove_layer(l_tmp_image_id, l_tmp_layer_id);
+
+          /* save current frame */
+          l_rc = gap_lib_save_named_frame(l_tmp_image_id, ainfo_ptr->new_filename);
+        }
+      }
 
+      /* destroy the tmp image */
+      gimp_image_delete(l_tmp_image_id);
+    }
+    
     if(ainfo_ptr->run_mode == GIMP_RUN_INTERACTIVE)
     {
       l_percentage += l_percentage_step;
@@ -1913,13 +1982,20 @@ p_frames_layer_del(GapAnimInfo *ainfo_ptr,
 
     /* advance to next frame */
     if((l_cur_frame_nr == l_end) || (l_rc < 0))
+    {
        break;
-    l_cur_frame_nr += l_step;
+    }
 
+    /* advance l_cur_frame_nr to the next available frame number 
+     * (normally to l_cur_frame_nr += l_step; 
+     * sometimes to higher number when frames are missing) 
+     */
+    l_cur_frame_nr = gap_lib_get_next_available_frame_number(l_cur_frame_nr, l_step
+                           , ainfo_ptr->basename, ainfo_ptr->extension, &l_frame_found);
   }
 
-
   return l_rc;
+
 }       /* end p_frames_layer_del */
 
 
diff --git a/gap/gap_story_dialog.c b/gap/gap_story_dialog.c
index 8e43765..54e842f 100644
--- a/gap/gap_story_dialog.c
+++ b/gap/gap_story_dialog.c
@@ -1301,6 +1301,19 @@ p_frame_widget_render (GapStbFrameWidget *fw)
      {
        switch(tabw->edmode)
        {
+        case GAP_STB_EDMO_SRC_FRAME_NUMBER_AND_COUNT:
+           if((fw->stb_refptr) && (fw->stb_elem_refptr))
+           {
+             gint l_src_framenr;
+             gint l_frame_count;
+             
+             l_src_framenr = fw->stb_elem_refptr->from_frame;
+             l_frame_count = fw->stb_elem_refptr->nframes;
+             l_txt = g_strdup_printf(":%d#%d", (int)l_src_framenr, (int)l_frame_count);
+             gtk_label_set_text ( GTK_LABEL(fw->val_label), l_txt);
+             g_free(l_txt);
+             break;
+           }
         case GAP_STB_EDMO_FRAME_NUMBER:
            if(fw->stb_refptr)
            {
@@ -5658,7 +5671,7 @@ p_menu_win_render_properties_cb (GtkWidget *widget, GapStbMainGlobalParams *sgpp
   if(l_rc == TRUE)
   {
     gboolean isFFMpegEncoderMultiprocessorSupport;
-
+ 
     sgpp->stb_max_open_videofile         = argv[l_stb_max_open_videofile_idx].int_ret;
     sgpp->stb_fcache_size_per_videofile  = argv[l_stb_fcache_size_per_videofile_idx].int_ret;
     sgpp->ffetch_max_img_cache_elements  = argv[l_ffetch_max_img_cache_elements_idx].int_ret;
@@ -5829,6 +5842,7 @@ p_menu_cll_add_att_elem_cb (GtkWidget *widget, GapStbMainGlobalParams *sgpp)
   p_tabw_add_att_elem(sgpp->cll_widgets, sgpp, sgpp->cll);
 }  /* end p_menu_cll_add_att_elem_cb */
 
+
 /* -----------------------------
  * p_menu_cll_toggle_edmode
  * -----------------------------
@@ -5848,6 +5862,9 @@ p_menu_cll_toggle_edmode (GtkWidget *widget, GapStbMainGlobalParams *sgpp)
       case GAP_STB_EDMO_FRAME_NUMBER:
         sgpp->cll_widgets->edmode = GAP_STB_EDMO_TIMECODE;
         break;
+      case GAP_STB_EDMO_TIMECODE:
+        sgpp->cll_widgets->edmode = GAP_STB_EDMO_SRC_FRAME_NUMBER_AND_COUNT;
+        break;
       default:
         sgpp->cll_widgets->edmode = GAP_STB_EDMO_SEQUENCE_NUMBER;
         break;
@@ -6106,6 +6123,9 @@ p_menu_stb_toggle_edmode (GtkWidget *widget, GapStbMainGlobalParams *sgpp)
       case GAP_STB_EDMO_FRAME_NUMBER:
         sgpp->stb_widgets->edmode = GAP_STB_EDMO_TIMECODE;
         break;
+      case GAP_STB_EDMO_TIMECODE:
+        sgpp->stb_widgets->edmode = GAP_STB_EDMO_SRC_FRAME_NUMBER_AND_COUNT;
+        break;
       default:
         sgpp->stb_widgets->edmode = GAP_STB_EDMO_SEQUENCE_NUMBER;
         break;
diff --git a/gap/gap_story_main.h b/gap/gap_story_main.h
index b25af4e..dfdb968 100644
--- a/gap/gap_story_main.h
+++ b/gap/gap_story_main.h
@@ -57,6 +57,7 @@ typedef gpointer t_GVA_Handle;
 #endif
 
 #define GAP_GIMPRC_ENABLE_STORYBOARD_DEBUG_FEATURES "video-enable-storyboard-debug-features"
+#define GAP_VIDEO_STORYBOARD_PROCESSOR_FAIL_ON_IMAGE_LOAD_ERRORS 
"video-storyboard-processor-fail-on-image-load-errors"
 
 
 #define GAP_STB_ATT_GFX_ARRAY_MAX 2
@@ -70,6 +71,7 @@ typedef enum
      GAP_STB_EDMO_SEQUENCE_NUMBER
     ,GAP_STB_EDMO_FRAME_NUMBER
     ,GAP_STB_EDMO_TIMECODE
+    ,GAP_STB_EDMO_SRC_FRAME_NUMBER_AND_COUNT
   } GapStoryElemDisplayMode;
 
 typedef enum
diff --git a/gap/gap_story_render_processor.c b/gap/gap_story_render_processor.c
index bbf6440..aa04426 100644
--- a/gap/gap_story_render_processor.c
+++ b/gap/gap_story_render_processor.c
@@ -74,10 +74,12 @@
 #include "gap_audio_wav.h"
 #include "gap_story_file.h"
 #include "gap_layer_copy.h"
+#include "gap_story_main.h"
 #include "gap_story_render_audio.h"
 #include "gap_story_render_processor.h"
 #include "gap_fmac_name.h"
 #include "gap_frame_fetcher.h"
+#include "gap_image.h"
 #include "gap_accel_char.h"
 #include "gap_mov_exec.h"
 
@@ -122,8 +124,8 @@ typedef struct GapStbFetchData {   /* nick: gfd */
 }  GapStbFetchData;
 
 
-/* data for video frame prefetch using multiple threads 
- * (used optional depending on gimprc configuration) 
+/* data for video frame prefetch using multiple threads
+ * (used optional depending on gimprc configuration)
  */
 typedef struct VideoPrefetchData   /* vpre */
 {
@@ -146,7 +148,7 @@ typedef struct VideoPrefetchData   /* vpre */
  * To aviod those type of CRASH a workaround was implemented that puts unused mutex
  * in a mutex pool for reuse instead of removing the mutex,
  * to aviod the call to g_mutex_free and to avoid allocating too many mutex resources.
- * 
+ *
  *
  * GThread-ERROR **: file gthread-posix.c: line 171 (g_mutex_free_posix_impl):
  *   error 'Das Ger�t oder die Ressource ist belegt' during 'pthread_mutex_destroy ((pthread_mutex_t *) 
mutex)'
@@ -172,7 +174,7 @@ typedef struct StbMutexPool   /* mutxp */
  * With smaller fcache the prefetched frames are often overwritten by the prefetch thread
  * before the main thread can read them from the fcache. This triggers many unwanted seek operations
  * with significant loss of performance when multithreaded processing is activated.
- *  
+ *
  */
 #define SMALL_FCACHE_SIZE_AT_FORWARD_READ  (MULTITHREAD_PREFETCH_AMOUNT + 2)
 
@@ -405,6 +407,7 @@ static void       p_transform_postprocessing(gint32 new_layer_id
                          , GapStoryRenderVidHandle *vidhand
                          , gdouble opacity
                          , gint32 local_stepcount
+                         , gint32 layermode
                          );
 static gint32     p_transform_and_add_layer( gint32 comp_image_id
                          , gint32 tmp_image_id
@@ -426,8 +429,6 @@ static gint32     p_transform_and_add_layer( gint32 comp_image_id
                          , const char *movepath_file_xml
                          , gdouble movepath_framePhase
                          );
-static gint32     p_create_unicolor_image(gint32 *layer_id, gint32 width , gint32 height
-                       , gdouble r_f, gdouble g_f, gdouble b_f, gdouble a_f);
 static gint32     p_prepare_RGB_image(gint32 image_id);
 
 static void       p_limit_open_videohandles(GapStoryRenderVidHandle *vidhand
@@ -576,7 +577,7 @@ p_pooled_g_mutex_new()
 {
   GMutex       *mutex;
   StbMutexPool *mutexp;
-  
+
   for(mutexp = mutexPool; mutexp != NULL; mutexp=mutexp->next)
   {
     if(mutexp->isFree == TRUE)
@@ -591,7 +592,7 @@ p_pooled_g_mutex_new()
       return(mutexp->mutex);
     }
   }
-  
+
   mutexp  = g_new(StbMutexPool, 1);
   mutexp->isFree = FALSE;
   mutexp->mutex = g_mutex_new();
@@ -606,7 +607,7 @@ p_pooled_g_mutex_new()
   }
 
   return(mutexp->mutex);
-  
+
 }  /* end p_pooled_g_mutex_new */
 
 /* --------------------------
@@ -617,7 +618,7 @@ static void
 p_pooled_g_mutex_free(GMutex       *mutex)
 {
   StbMutexPool *mutexp;
-  
+
   for(mutexp = mutexPool; mutexp != NULL; mutexp=mutexp->next)
   {
     if(mutexp->mutex == mutex)
@@ -1556,7 +1557,7 @@ p_fetch_framename(GapStoryRenderFrameRangeElem *frn_list
                                     , frn_elem->move_y_accel
                                     );
 
-         /* movepath transition handling */                                   
+         /* movepath transition handling */
          if(frn_elem->movepath_file_xml != NULL)
          {
            gint32  l_steps_since_transition_start;
@@ -1564,13 +1565,13 @@ p_fetch_framename(GapStoryRenderFrameRangeElem *frn_list
 
            l_steps_since_transition_start = frn_elem->movepath_frames_done + l_step;
            phase = 1.0;
-           
-           
+
+
            if (l_steps_since_transition_start < frn_elem->movepath_dur)
            {
              gint32 duration;
              gint   accel;
-             
+
              accel = 0;
              duration = abs(frn_elem->movepath_to - frn_elem->movepath_from);
              gfd->movepath_file_xml = frn_elem->movepath_file_xml;
@@ -1592,7 +1593,7 @@ p_fetch_framename(GapStoryRenderFrameRangeElem *frn_list
                , (float)phase
                );
            }
-           
+
          }
 
 
@@ -1792,17 +1793,17 @@ p_new_framerange_element(GapStoryRenderFrameType  frn_type
   frn_elem->seltrack           = seltrack;
   frn_elem->exact_seek         = exact_seek;
   frn_elem->delace             = delace;
-  
+
   frn_elem->movepath_from      = 0.0;
   frn_elem->movepath_to        = 0.0;
   frn_elem->movepath_frames_done = 0;
   frn_elem->movepath_dur         = 0;
   frn_elem->movepath_file_xml    = NULL;
 
-  
+
   frn_elem->next               = NULL;
-  
-  
+
+
 
 
   if(ext)
@@ -2577,7 +2578,7 @@ p_clear_vattr_array(GapStoryRenderVTrackArray *vtarr)
     vtarr->attr[l_idx].move_y_dur           = 0;
     vtarr->attr[l_idx].move_y_accel         = 0;
     vtarr->attr[l_idx].move_y_frames_done   = 0;
-    
+
     vtarr->attr[l_idx].movepath_from        = 0.0;
     vtarr->attr[l_idx].movepath_to          = 0.0;
     vtarr->attr[l_idx].movepath_dur         = 0;
@@ -2927,7 +2928,7 @@ p_storyboard_analyze(GapStoryBoard *stb
                     vtarr->attr[l_track].movepath_frames_done = 0;
                     /* no need to strdup for the vattr table here.
                      * becaue we use the reference to the original data in this table
-                     * (therefore dont g_free 
+                     * (therefore dont g_free
                      * the g_strdup is done later when the movepath_file_xml is
                      * set in the individual GapStoryRenderFrameRangeElem frn_elem
                      * (see p_set_vtrack_attributes)
@@ -2938,7 +2939,7 @@ p_storyboard_analyze(GapStoryBoard *stb
                       if(stb_elem->att_movepath_file_xml[0] != '\0')
                       {
                         gboolean is_valid;
-                        
+
                         is_valid = gap_mov_exec_check_valid_xml_paramfile(stb_elem->att_movepath_file_xml);
                         if (is_valid)
                         {
@@ -4134,7 +4135,7 @@ p_open_video_handle_private(    gboolean ignore_audio
     vidhand->isLogResourceUsage = TRUE;
   }
   p_initOptionalMulitprocessorSupport(vidhand);
-  
+
   vidhand->frn_list = NULL;
   vidhand->preferred_decoder = NULL;
   vidhand->master_insert_alpha_format = NULL;
@@ -4156,7 +4157,7 @@ p_open_video_handle_private(    gboolean ignore_audio
   vidhand->util_sox          = NULL;
   vidhand->util_sox_options  = NULL;
   gap_story_render_set_audio_resampling_program(vidhand, util_sox, util_sox_options);
-  
+
   vidhand->ignore_audio      = ignore_audio;
   vidhand->ignore_video      = ignore_video;
   vidhand->create_audio_tmp_files = create_audio_tmp_files;
@@ -4696,7 +4697,7 @@ p_exec_filtermacro(gint32 image_id, gint32 layer_id, const char *filtermacro_fil
   gint          l_nlayers;
   gint32       *l_layers_list;
   static gint32 funcId = -1;
-  
+
   GAP_TIMM_GET_FUNCTION_ID(funcId, "p_exec_filtermacro");
   GAP_TIMM_START_FUNCTION(funcId);
 
@@ -4784,7 +4785,7 @@ p_exec_filtermacro(gint32 image_id, gint32 layer_id, const char *filtermacro_fil
 
     }
   }
-  
+
   if(gap_debug)
   {
     if(l_rc_layer_id != layer_id)
@@ -4793,7 +4794,7 @@ p_exec_filtermacro(gint32 image_id, gint32 layer_id, const char *filtermacro_fil
         ,(int)layer_id
         ,(int)l_rc_layer_id
         );
-        
+
     }
   }
 
@@ -4890,13 +4891,13 @@ p_transform_rotate_layer_at(gint32 image_id, gint32 layer_id, gdouble rotate
   l_angle_deg = rotate;
   while(l_angle_deg >= 360.0)
   {
-    l_angle_deg -=360; 
+    l_angle_deg -=360;
   }
   while(l_angle_deg <= -360.0)
   {
-    l_angle_deg +=360; 
+    l_angle_deg +=360;
   }
-  
+
   if ((l_angle_deg < 0.05) && (l_angle_deg > -0.05))
   {
     /* ignore very small rotations */
@@ -4978,7 +4979,7 @@ p_transform_rotate_layer_at(gint32 image_id, gint32 layer_id, gdouble rotate
  *
  * return the new created layer id in the comp_image_id
  *   (that is already added to the composte image on top of layerstack
- *    and is already transformed 
+ *    and is already transformed
  *    -- except postprocessing for mask anchor master and opacity )
  */
 static gint32
@@ -5007,14 +5008,14 @@ p_transform_with_movepath_processing( gint32 comp_image_id
   gint32 l_movepath_layer_id;
   gint32 l_tmp_movpath_image_id;
   gint32 l_empty_layer_id;
-  
+
   gint   l_base_offset_x;
   gint   l_base_offset_y;
   gint   l_mov_dx;
   gint   l_mov_dy;
   gint   result_width;
   gint   result_height;
-    
+
   GapStoryCalcAttr  calculate_attributes;
   GapStoryCalcAttr  *calculated;
 
@@ -5027,14 +5028,14 @@ p_transform_with_movepath_processing( gint32 comp_image_id
       , (int)tmp_image_id
       , (int)comp_image_id
       );
-    if(frn_elem != NULL) 
+    if(frn_elem != NULL)
     {
-      gap_story_render_debug_print_frame_elem(frn_elem, -77); 
+      gap_story_render_debug_print_frame_elem(frn_elem, -77);
     }
   }
 
   l_tmp_movpath_image_id = -1;
-  
+
 
   vid_width = gimp_image_width(comp_image_id);
   vid_height = gimp_image_height(comp_image_id);
@@ -5069,8 +5070,8 @@ p_transform_with_movepath_processing( gint32 comp_image_id
    */
   l_tmp_movpath_image_id = gimp_image_new(vid_width, vid_height, GIMP_RGB);
   gimp_image_undo_disable(l_tmp_movpath_image_id);
-  
-  
+
+
   l_empty_layer_id = gimp_layer_new(l_tmp_movpath_image_id, "empty",
                         vid_width, vid_height,
                         GIMP_RGBA_IMAGE,
@@ -5099,7 +5100,7 @@ p_transform_with_movepath_processing( gint32 comp_image_id
    * note that fit size flags were already handled in the movepath transformation.
    *
    * further processing continues with the result of movepath processing
-   * (the image l_tmp_movpath_image_id) 
+   * (the image l_tmp_movpath_image_id)
    * note that the resulting layer (l_movepath_layer_id) may be oversized,
    * e.g may overlap image boudaries due to the movepath transformations
    * (when the clip to image flag was not active in movepath processing)
@@ -5115,7 +5116,7 @@ p_transform_with_movepath_processing( gint32 comp_image_id
 
   /* findout the offsets of the  layer within the Image */
   gimp_drawable_offsets(l_movepath_layer_id, &l_base_offset_x, &l_base_offset_y );
-  
+
   /* handle movement */
   l_mov_dx = rint((gdouble)vid_width * move_x);
   l_mov_dy = rint((gdouble)vid_height * move_y);
@@ -5140,7 +5141,7 @@ p_transform_with_movepath_processing( gint32 comp_image_id
   /* handle scaling */
   result_width  = MAX(1, rint(((gdouble)vid_width  * scale_x)));
   result_height = MAX(1, rint(((gdouble)vid_height * scale_y)));
-  
+
   if((result_width != vid_width)
   || (result_height != vid_height))
   {
@@ -5196,7 +5197,7 @@ p_transform_with_movepath_processing( gint32 comp_image_id
 
       /* resize image canvas back to coposite videoframe size */
       gimp_image_resize(l_tmp_movpath_image_id, vid_width, vid_height, offs_x, offs_y);
-    
+
     }
     else if ((result_width < vid_width)
     && (result_height >= vid_height))
@@ -5215,11 +5216,11 @@ p_transform_with_movepath_processing( gint32 comp_image_id
 
       /* resize image canvas back to coposite videoframe size */
       gimp_image_resize(l_tmp_movpath_image_id, vid_width, vid_height, offs_x, offs_y);
-    
+
     }
 
 
-  
+
   }
 
   /* trim resulting layer to imagesize after all transformations
@@ -5230,7 +5231,7 @@ p_transform_with_movepath_processing( gint32 comp_image_id
 
   /* make 1:1 copy of the l_movepath_layer_id (that has already same size as
    * the composite image and is already transformed)
-   * and add to the composite image (at top) 
+   * and add to the composite image (at top)
    */
   l_new_layer_id = gimp_layer_new_from_drawable(l_movepath_layer_id, comp_image_id);
   if(l_new_layer_id >= 0)
@@ -5243,7 +5244,7 @@ p_transform_with_movepath_processing( gint32 comp_image_id
     gimp_image_add_layer(comp_image_id, l_new_layer_id, 0);
     gimp_layer_set_offsets(l_new_layer_id, 0, 0);
   }
-  
+
 //p_debug_dup_image(l_tmp_movpath_image_id);
 
 
@@ -5253,7 +5254,7 @@ p_transform_with_movepath_processing( gint32 comp_image_id
   }
 
   return(l_new_layer_id);
-  
+
 }   /* end p_transform_with_movepath_processing */
 
 
@@ -5262,7 +5263,7 @@ p_transform_with_movepath_processing( gint32 comp_image_id
  * ----------------------------------
  * perform the final processing steps on the transformed
  * layer. This includes applying mask (but only in case mask is anchored to master)
- * and setting the opacity.
+ * and setting the opacity and layermode.
  */
 static void
 p_transform_postprocessing(gint32 new_layer_id
@@ -5270,9 +5271,9 @@ p_transform_postprocessing(gint32 new_layer_id
   , GapStoryRenderVidHandle *vidhand
   , gdouble opacity
   , gint32 local_stepcount
+  , gint32 fmacLayermode    /* layermode after (optional) filtermacro execution */
   )
 {
-
   if((frn_elem->mask_name != NULL)
   && (frn_elem->mask_anchor == GAP_MSK_ANCHOR_MASTER))
   {
@@ -5287,6 +5288,18 @@ p_transform_postprocessing(gint32 new_layer_id
   }
 
   gimp_layer_set_opacity(new_layer_id, opacity);
+  if (fmacLayermode != GIMP_NORMAL_MODE)
+  {
+    /* apply the layermode as established via filtermacro call
+     * ... but only in case when there was no other transformation
+     *     (such as move path) that has already set
+     *     another layermode than GIMP_NORMAL_MODE
+     */
+    if (gimp_layer_get_mode(new_layer_id) == GIMP_NORMAL_MODE)
+    {
+      gimp_layer_set_mode(new_layer_id, fmacLayermode);
+    }
+  }
 
 }  /* end p_transform_postprocessing */
 
@@ -5333,7 +5346,8 @@ p_transform_and_add_layer( gint32 comp_image_id
   gint32 l_fmac_layer_id;
   gint32 l_movepath_layer_id;
   gint32 l_tmp_image_id;
-    
+  gint32 l_layermode;
+
   GapStoryCalcAttr  calculate_attributes;
   GapStoryCalcAttr  *calculated;
 
@@ -5344,7 +5358,7 @@ p_transform_and_add_layer( gint32 comp_image_id
   static gint32 funcIdRotate = -1;
   static gint32 funcIdClipped = -1;
   static gint32 funcIdClipScale = -1;
-  
+
   GAP_TIMM_GET_FUNCTION_ID(funcId,          "p_transform_and_add_layer");
   GAP_TIMM_GET_FUNCTION_ID(funcIdPath,      "p_transform_and_add_layer.PathFullsize");
   GAP_TIMM_GET_FUNCTION_ID(funcIdFull,      "p_transform_and_add_layer.Fullsize");
@@ -5352,7 +5366,7 @@ p_transform_and_add_layer( gint32 comp_image_id
   GAP_TIMM_GET_FUNCTION_ID(funcIdRotate,    "p_transform_and_add_layer.RotateFullsize");
   GAP_TIMM_GET_FUNCTION_ID(funcIdClipped,   "p_transform_and_add_layer.Clippedsize");
   GAP_TIMM_GET_FUNCTION_ID(funcIdClipScale, "p_transform_and_add_layer.ScaleClippedsize");
-  
+
   GAP_TIMM_START_FUNCTION(funcId);
 
 
@@ -5366,7 +5380,7 @@ p_transform_and_add_layer( gint32 comp_image_id
   }
 
   l_tmp_image_id = tmp_image_id;
-  
+
   /* execute input track specific  filtermacro (optional if supplied)
    * local_stepcount  (usually delivered by procedure p_fetch_framename)
    *  is used to define fmac_current_step
@@ -5380,6 +5394,10 @@ p_transform_and_add_layer( gint32 comp_image_id
                       , frn_elem->fmac_total_steps
                       , frn_elem->fmac_accel
                     );
+  /* the filtermacro may have set another layermode than GIMP_NORMAL_MODE ..
+   * .. therfore save to l_layermode and apply to final resulting layer postprocessing
+   */
+  l_layermode = gimp_layer_get_mode(l_fmac_layer_id);
 
   if(gap_debug)
   {
@@ -5400,7 +5418,7 @@ p_transform_and_add_layer( gint32 comp_image_id
   if(movepath_file_xml != NULL)
   {
     GAP_TIMM_START_FUNCTION(funcIdPath);
-    
+
     l_new_layer_id = p_transform_with_movepath_processing(comp_image_id
                             , tmp_image_id
                             , layer_id
@@ -5431,7 +5449,7 @@ p_transform_and_add_layer( gint32 comp_image_id
 
     /* expand layer to tmp image size (before applying any scaling) */
     gimp_layer_resize_to_image_size(layer_id);
-  
+
     /* calculate scaling, offsets and opacity  according to current attributes */
     gap_story_file_calculate_render_attributes(&calculate_attributes
       , vid_width
@@ -5683,6 +5701,7 @@ p_transform_and_add_layer( gint32 comp_image_id
      , vidhand
      , calculated->opacity
      , local_stepcount
+     , l_layermode
      );
 
 
@@ -5717,7 +5736,7 @@ gap_story_render_transform_with_movepath_processing(gint32 comp_image_id
                          )
 {
   gint32 l_new_layer_id;
-  
+
   l_new_layer_id = p_transform_with_movepath_processing(comp_image_id
                             , tmp_image_id
                             , layer_id
@@ -5743,41 +5762,6 @@ gap_story_render_transform_with_movepath_processing(gint32 comp_image_id
 
 
 /* ----------------------------------------------------
- * p_create_unicolor_image
- * ----------------------------------------------------
- * - create a new image with one black filled layer
- *   (both have the requested size)
- *
- * return the new created image_id
- *   and the layer_id of the black_layer
- */
-static gint32
-p_create_unicolor_image(gint32 *layer_id, gint32 width , gint32 height
-                       , gdouble r_f, gdouble g_f, gdouble b_f, gdouble a_f)
-{
-  gint32 l_empty_layer_id;
-  gint32 l_image_id;
-
-  *layer_id = -1;
-  l_image_id = gimp_image_new(width, height, GIMP_RGB);
-  if(l_image_id >= 0)
-  {
-    l_empty_layer_id = gimp_layer_new(l_image_id, "black_background",
-                          width, height,
-                          GIMP_RGBA_IMAGE,
-                          100.0,     /* Opacity full opaque */
-                          GIMP_NORMAL_MODE);
-    gimp_image_add_layer(l_image_id, l_empty_layer_id, 0);
-
-    /* clear layer to unique color */
-    gap_layer_clear_to_color(l_empty_layer_id, r_f, g_f, b_f, a_f);
-
-    *layer_id = l_empty_layer_id;
-  }
-  return(l_image_id);
-}       /* end p_create_unicolor_image */
-
-/* ----------------------------------------------------
  * p_prepare_RGB_image
  * ----------------------------------------------------
  * prepare image for encoding
@@ -5889,16 +5873,16 @@ p_limit_open_videohandles(GapStoryRenderVidHandle *vidhand
          p_call_GVA_close(frn_elem->gvahand);
          frn_elem->gvahand = NULL;
          l_count_open_videohandles--;
-  
+
          if (l_count_open_videohandles < max_open_videohandles)
          {
            return;
          }
-  
+
       }
     }
   }
-  
+
   /* at this point there are still too many GVA video handles open
    * (this may occure if videos are used as masks, therefore try to close
    * mask video handles too.)
@@ -5906,7 +5890,7 @@ p_limit_open_videohandles(GapStoryRenderVidHandle *vidhand
   if(vidhand->is_mask_handle != TRUE)
   {
     GapStoryRenderMaskDefElem *maskdef_elem;
-    
+
     maskdef_elem = vidhand->maskdef_elem;
     if(maskdef_elem != NULL)
     {
@@ -5934,7 +5918,7 @@ p_limit_open_videohandles(GapStoryRenderVidHandle *vidhand
  *
  * return rank
  *    5 .. videoFrameNrToBeReadNext is available in fcache and curent position >= videoFrameNrToBeReadNext 
same track
- *    4 .. videoFrameNrToBeReadNext is available in fcache and curent position >= videoFrameNrToBeReadNext) 
+ *    4 .. videoFrameNrToBeReadNext is available in fcache and curent position >= videoFrameNrToBeReadNext)
  *    3 .. videoFrameNrToBeReadNext is reachable with a few sequential read operaton same track
  *    2 .. videoFrameNrToBeReadNext is reachable with a few sequential read operaton)
  *    1 .. videoFrameNrToBeReadNext requires forward seek operaton
@@ -5972,7 +5956,7 @@ p_calculateGvahandHolderRank(GapStoryRenderFrameRangeElem *frn_elem
       return(GVAHAND_HOLDER_RANK_3);
     }
     return(GVAHAND_HOLDER_RANK_2);
-    
+
   }
 
   if (gvahand->current_seek_nr <= videoFrameNrToBeReadNext)
@@ -6028,7 +6012,7 @@ p_try_to_steal_gvahand(GapStoryRenderVidHandle *vidhand
                                                         , 2
                                                         , 100
                                                         );
-  
+
   for(section = vidhand->section_list; section != NULL; section = section->next)
   {
     for (frn_elem = section->frn_list; frn_elem != NULL; frn_elem = (GapStoryRenderFrameRangeElem 
*)frn_elem->next)
@@ -6057,7 +6041,7 @@ p_try_to_steal_gvahand(GapStoryRenderVidHandle *vidhand
               break;
             }
           }
-          
+
          }
       }
     }
@@ -6072,7 +6056,7 @@ p_try_to_steal_gvahand(GapStoryRenderVidHandle *vidhand
   && (gvahandHolderRank <=  GVAHAND_HOLDER_RANK_NO_BENEFIT_LEVEL))
   {
     GapStoryRenderMaskDefElem *maskdef_elem;
-    
+
     for(maskdef_elem = vidhand->maskdef_elem; maskdef_elem != NULL;  maskdef_elem = maskdef_elem->next)
     {
       if(maskdef_elem->mask_vidhand)
@@ -6117,7 +6101,7 @@ p_try_to_steal_gvahand(GapStoryRenderVidHandle *vidhand
       return(gvahand);
     }
   }
- 
+
 
   p_limit_open_videohandles(vidhand, master_frame_nr, l_count_open_videohandles, l_max_open_videohandles);
 #endif
@@ -6324,28 +6308,28 @@ p_dump_stb_resources_gvahand(GapStoryRenderVidHandle *vidhand
                                                         );
 
   l_count_open_videohandles = 0;
-  
-  
-  
+
+
+
   for(section = vidhand->section_list; section != NULL; section = section->next)
   {
     char                  *section_name;
-    
+
     section_name = section->section_name;
     if (section_name == NULL)
     {
       section_name = "MAIN";
     }
-    
+
     for (frn_elem = section->frn_list; frn_elem != NULL; frn_elem = (GapStoryRenderFrameRangeElem 
*)frn_elem->next)
     {
       if (frn_elem->gvahand != NULL)
       {
         t_GVA_Handle *gvahand;
-        
+
         l_count_open_videohandles++;
         gvahand = frn_elem->gvahand;
-        
+
         printf("STB Section:%s GVA_handle: %s  master_frame_nr:%d currFrameNr:%d fcache elemSize:%d 
byteSize:%d\n"
           , section_name
           , gvahand->filename
@@ -6358,14 +6342,14 @@ p_dump_stb_resources_gvahand(GapStoryRenderVidHandle *vidhand
     }
 
   }
-  
-  
+
+
   printf("STB at master_frame_nr:%d currently_open GVA_handles:%d (limit 
video-storyboard-max-open-videofiles:%d)\n"
     ,(int)master_frame_nr
     ,(int)l_count_open_videohandles
     ,(int)l_max_open_videohandles
     );
-  
+
 #endif
 }  /* end p_dump_stb_resources_gvahand */
 
@@ -6410,7 +6394,7 @@ p_story_render_fetch_composite_image_or_buffer(GapStoryRenderVidHandle *vidhand
                  )
 {
   gint32 image_id;
-  
+
   image_id = p_story_render_fetch_composite_image_private(vidhand
                                                   ,master_frame_nr
                                                   ,vid_width
@@ -6439,8 +6423,8 @@ p_story_render_fetch_composite_image_or_buffer(GapStoryRenderVidHandle *vidhand
       p_dump_stb_resources_gvahand(vidhand, master_frame_nr);
     }
   }
-  
-  
+
+
   return (image_id);
 
 }  /* end p_story_render_fetch_composite_image_or_buffer */
@@ -6483,7 +6467,7 @@ gap_story_render_fetch_composite_image(GapStoryRenderVidHandle *vidhand
                  )
 {
   gint32 image_id;
-  
+
   image_id = p_story_render_fetch_composite_image_or_buffer(vidhand
                                                   ,master_frame_nr
                                                   ,vid_width
@@ -6641,15 +6625,15 @@ p_is_larger_image_variant_expected(GapStbFetchData *gfdCurrent
   gfd = &gapStbFetchData;
   p_init_gfd(gfd);
   calculated = &calculate_attributes;
-  
+
   foundLargerVariant = FALSE;
-  
+
   /* check upto 500 further frames for usage of the same image
    * to findout maximum required prescale size in the near rendering future..
    * (note that in practice it is typical that one of the break conditions
    * occurs much earlier before the 500 checks are done)
    */
-  for(lookForwardMasterFframeNr = master_frame_nr + 1; 
+  for(lookForwardMasterFframeNr = master_frame_nr + 1;
       lookForwardMasterFframeNr < master_frame_nr + 500;
       lookForwardMasterFframeNr++)
   {
@@ -6662,7 +6646,7 @@ p_is_larger_image_variant_expected(GapStbFetchData *gfdCurrent
     {
       printf("  o lookForwardMasterFframeNr:%d\n", lookForwardMasterFframeNr);
     }
-    
+
     for(l_track = vidhand->maxVidTrack; l_track >= vidhand->minVidTrack; l_track--)
     {
       gfd->framename = p_fetch_framename(vidhand->frn_list
@@ -6702,7 +6686,7 @@ p_is_larger_image_variant_expected(GapStbFetchData *gfdCurrent
                foundLargerVariant = TRUE;
              }
 
-  
+
           }
         }
 
@@ -6772,7 +6756,7 @@ p_prescale_image_size_handling(GapStbFetchData *gfdCurrent
     /* failed to fetch image */
     return (l_fetched_image_id);
   }
-  
+
   calculated = &calculate_attributes;
 
   /* calculate scaling, offsets and opacity  according to current attributes
@@ -6794,7 +6778,7 @@ p_prescale_image_size_handling(GapStbFetchData *gfdCurrent
       , gfd->move_x
       , gfd->move_y
       );
-    
+
   currentPrescaleWidth = calculated->width;
   currentPrescaleHeight = calculated->height;
   maxPrescaleWidth = currentPrescaleWidth;
@@ -6832,7 +6816,7 @@ p_prescale_image_size_handling(GapStbFetchData *gfdCurrent
     }
     return (l_fetched_image_id);
   }
-  
+
   if ((gimp_image_width(l_fetched_image_id) < originalWidth)
   ||  (gimp_image_height(l_fetched_image_id) < originalHeight))
   {
@@ -6840,11 +6824,11 @@ p_prescale_image_size_handling(GapStbFetchData *gfdCurrent
      &&  (gimp_image_height(l_fetched_image_id) >= currentPrescaleHeight))
      {
        /* fetched image is already down scaled.
-        * optional check for further (chained) downscale 
+        * optional check for further (chained) downscale
         */
        gboolean  foundLargerVariant = FALSE;
        gboolean  prescaleEnabledDownscaleChainDefault = TRUE;
-       
+
        if(gap_base_get_gimprc_gboolean_value(GAP_VIDEO_STORYBOARD_PRESCALE_ENABLE_DOWNSCALE_CHAIN
          , prescaleEnabledDownscaleChainDefault))
        {
@@ -6903,7 +6887,7 @@ p_prescale_image_size_handling(GapStbFetchData *gfdCurrent
            );
          }
        }
-       
+
        return (l_fetched_image_id);
      }
   }
@@ -6911,16 +6895,16 @@ p_prescale_image_size_handling(GapStbFetchData *gfdCurrent
 
   gfd = &gapStbFetchData;
   p_init_gfd(gfd);
-  
+
   foundSmallerVariant = FALSE;
   foundTooLargeVariant = FALSE;
-  
+
   /* check upto 500 further frames for usage of the same image
    * to findout maximum required prescale size in the near rendering future..
    * (note that in practice it is typical that one of the break conditions
    * occurs much earlier before the 500 checks are done)
    */
-  for(lookForwardMasterFframeNr = master_frame_nr + 1; 
+  for(lookForwardMasterFframeNr = master_frame_nr + 1;
       lookForwardMasterFframeNr < master_frame_nr + 500;
       lookForwardMasterFframeNr++)
   {
@@ -6932,7 +6916,7 @@ p_prescale_image_size_handling(GapStbFetchData *gfdCurrent
     {
       printf("  lookForwardMasterFframeNr:%d\n", lookForwardMasterFframeNr);
     }
-    
+
     nextCompositeFrameIncludesSameImage = FALSE;
     nextCompositeFrameIncludesSameImageAtSamePrescaleSize = FALSE;
     for(l_track = vidhand->maxVidTrack; l_track >= vidhand->minVidTrack; l_track--)
@@ -6951,7 +6935,7 @@ p_prescale_image_size_handling(GapStbFetchData *gfdCurrent
           if (strcmp(gfd->framename, gfdCurrent->framename) == 0)
           {
             nextCompositeFrameIncludesSameImage = TRUE;
-            
+
             gap_story_file_calculate_render_attributes(&calculate_attributes
                   , vid_width
                   , vid_height
@@ -6985,7 +6969,7 @@ p_prescale_image_size_handling(GapStbFetchData *gfdCurrent
              {
                foundSmallerVariant = TRUE;
              }
-             
+
              if (calculated->width > originalWidth)
              {
                foundTooLargeVariant = TRUE;
@@ -6999,7 +6983,7 @@ p_prescale_image_size_handling(GapStbFetchData *gfdCurrent
                }
              }
 
-  
+
           }
         }
 
@@ -7014,7 +6998,7 @@ p_prescale_image_size_handling(GapStbFetchData *gfdCurrent
       /* stop looking forward when:
        * o) next frame does not refere to same image
        * o) or refers to same image at exact same prescale size
-       * o) or refers to smaller representation 
+       * o) or refers to smaller representation
        *    (assume zoom out where usage of larger variant is NOT expected in near future)
        * o) or refers to much larger variant > 150 %
        */
@@ -7022,7 +7006,7 @@ p_prescale_image_size_handling(GapStbFetchData *gfdCurrent
     }
   }
 
-  /* the 2nd fetch call (with prescale size != 0) triggers prescaling */ 
+  /* the 2nd fetch call (with prescale size != 0) triggers prescaling */
   l_fetched_image_id = gap_frame_fetch_prescaled_image(vidhand->ffetch_user_id
                         , gfdCurrent->framename            /* full filename of the image */
                         , TRUE /*  enable caching */
@@ -7088,10 +7072,10 @@ p_stb_render_image_or_animimage(GapStbFetchData *gfd
          );
     }
     /* prescale handling */
-    l_orig_image_id = 
+    l_orig_image_id =
        p_prescale_image_size_handling(gfd, vidhand, master_frame_nr, vid_width, vid_height);
   }
-  else 
+  else
   {
     if(gap_debug)
     {
@@ -7140,7 +7124,7 @@ p_stb_render_image_or_animimage(GapStbFetchData *gfd
         );
     }
 
-    gfd->tmp_image_id = p_create_unicolor_image(&gfd->layer_id
+    gfd->tmp_image_id = gap_image_create_unicolor_image(&gfd->layer_id
                                             , gimp_image_width(l_orig_image_id)
                                             , gimp_image_height(l_orig_image_id)
                                             , 0.0, 0.0, 0.0, 0.0);
@@ -7191,7 +7175,7 @@ static gboolean
 p_is_another_clip_playing_the_same_video_backwards(GapStoryRenderFrameRangeElem *frn_elem_ref)
 {
   GapStoryRenderFrameRangeElem *frn_elem;
-  
+
   for (frn_elem = frn_elem_ref->next; frn_elem != NULL; frn_elem = (GapStoryRenderFrameRangeElem 
*)frn_elem->next)
   {
       if(frn_elem->frn_type == GAP_FRN_MOVIE)
@@ -7224,7 +7208,7 @@ p_is_another_clip_playing_the_same_video_backwards(GapStoryRenderFrameRangeElem
  * (because it saves a lot of slow seek operations)
  * therfore the configured fcache size is only set in case the videoclip
  * is played backwards (in this or future clips refering the same videofile)
- * 
+ *
  * returns the actual picked size of the frame cache
  */
 static void
@@ -7244,9 +7228,9 @@ p_check_and_open_video_handle(GapStoryRenderFrameRangeElem *frn_elem
   {
     isPlayingBackwards = FALSE;
   }
-  
+
 #ifdef GAP_ENABLE_VIDEOAPI_SUPPORT
-  
+
   if(frn_elem->gvahand == NULL)
   {
      /* before we open a new GVA videohandle, lets check
@@ -7278,13 +7262,13 @@ p_check_and_open_video_handle(GapStoryRenderFrameRangeElem *frn_elem
        if(frn_elem->gvahand)
        {
          gint32   fcacheSize;
-         
+
          fcacheSize = gap_base_get_gimprc_int_value(GAP_GIMPRC_VIDEO_STORYBOARD_FCACHE_SIZE_PER_VIDEOFILE
                                                      , GAP_STB_RENDER_GVA_FRAMES_TO_KEEP_CACHED  /* default 
*/
                                                      , 2   /* min */
                                                      , 250 /* max */
                                                    );
-                                                     
+
          if(!isPlayingBackwards)
          {
            if(FALSE == p_is_another_clip_playing_the_same_video_backwards(frn_elem))
@@ -7304,7 +7288,7 @@ p_check_and_open_video_handle(GapStoryRenderFrameRangeElem *frn_elem
        }
      }
   }
-#endif  
+#endif
 }  /* end p_check_and_open_video_handle */
 
 
@@ -7316,14 +7300,14 @@ p_get_PrefetchThreadPool()
   {
     gint    maxThreads;
     GError *error = NULL;
-    
-      
+
+
     maxThreads = gap_base_get_gimprc_int_value(GAP_GIMPRC_VIDEO_STORYBOARD_MAX_OPEN_VIDEOFILES
                                                 , GAP_STB_DEFAULT_MAX_OPEN_VIDEOFILES
                                                 , 2
                                                 , 100
                                                 );
-      
+
     prefetchThreadPool = g_thread_pool_new((GFunc)p_videoPrefetchWorkerThreadFunction
                                          ,NULL        /* user data */
                                          ,maxThreads  /* max_threads */
@@ -7335,15 +7319,15 @@ p_get_PrefetchThreadPool()
       printf("** ERROR could not create prefetchThreadPool\n");
     }
   }
-  
+
   return (prefetchThreadPool);
 }
 
 
 /* -------------------------------------------
- * p_initOptionalMulitprocessorSupport 
+ * p_initOptionalMulitprocessorSupport
  * -------------------------------------------
- * this procedure creates a thread pool in case 
+ * this procedure creates a thread pool in case
  * the gimprc parameters are configured for multiprocessor support.
  * further the vidhand->isMultithreadEnabled is set accordingly.
  * Note that gimprc configuration is ignored in case
@@ -7353,7 +7337,7 @@ static void
 p_initOptionalMulitprocessorSupport(GapStoryRenderVidHandle *vidhand)
 {
   vidhand->isMultithreadEnabled = FALSE;
-  
+
 #ifdef GAP_ENABLE_VIDEOAPI_SUPPORT
   vidhand->isMultithreadEnabled = gap_story_isMultiprocessorSupportEnabled();
   if (vidhand->isMultithreadEnabled)
@@ -7361,7 +7345,7 @@ p_initOptionalMulitprocessorSupport(GapStoryRenderVidHandle *vidhand)
     /* check and init thread system */
     vidhand->isMultithreadEnabled = gap_base_thread_init();
   }
-  
+
   if (vidhand->isMultithreadEnabled)
   {
     p_get_PrefetchThreadPool();
@@ -7381,7 +7365,7 @@ p_initOptionalMulitprocessorSupport(GapStoryRenderVidHandle *vidhand)
  * finally clode the GVA video handle.
  */
 #ifdef GAP_ENABLE_VIDEOAPI_SUPPORT
-static void  
+static void
 p_call_GVA_close(t_GVA_Handle *gvahand)
 {
   if(gap_debug)
@@ -7402,16 +7386,16 @@ p_call_GVA_close(t_GVA_Handle *gvahand)
     if(gvahand->user_data)
     {
       VideoPrefetchData *vpre;
-      
+
       vpre = (VideoPrefetchData *)gvahand->user_data;
       if(vpre)
       {
         GMutex            *mutex;
         gint retryCount = 0;
-        
+
         mutex = vpre->mutex;
 
-RETRY:        
+RETRY:
         GVA_fcache_mutex_lock (vpre->gvahand);
 
         if((vpre->isPrefetchThreadRunning == TRUE)
@@ -7427,7 +7411,7 @@ RETRY:
                   );
           }
           g_cond_wait (vpre->prefetchDoneCond, vpre->mutex);
-          
+
           if(gap_debug)
           {
             printf("call_GVA_close WAKE-UP prefetch worker thread finished (closing video %s) mutex:%d\n"
@@ -7461,12 +7445,12 @@ RETRY:
         gvahand->user_data = NULL;
         g_mutex_unlock(mutex);
 
-  
+
         /* dispose the fcache mutex */
         //g_mutex_free (mutex);               // TODO: g_mutex_free sometimes leads to CRASH
         p_pooled_g_mutex_free(mutex);         // As workaround keep mutex alive in a pool for reuse...
         g_cond_free (vpre->prefetchDoneCond);
-        
+
         vpre->prefetchDoneCond = NULL;
 
       }
@@ -7502,7 +7486,7 @@ p_call_GVA_search_fcache_and_get_frame_as_gimp_layer_or_rgb888(t_GVA_Handle *gva
       ,caller
       );
   }
-  
+
   GVA_search_fcache_and_get_frame_as_gimp_layer_or_rgb888(gvahand
                  , framenumber
                  , deinterlace
@@ -7524,7 +7508,7 @@ p_call_GVA_search_fcache_and_get_frame_as_gimp_layer_or_rgb888(t_GVA_Handle *gva
       ,(int)fcacheFetchResult->isFrameAvailable
       );
   }
-                 
+
 }  /* end p_call_GVA_search_fcache_and_get_frame_as_gimp_layer_or_rgb888 */
 
 
@@ -7582,7 +7566,7 @@ p_stb_render_movie_single_processor(GapStbFetchData *gfd
 
   fcacheFetchResult.isRgb888Result = FALSE;  /* configure fcache for standard fetch as gimp layer */
   fcacheFetchResult.rgbBuffer.data = NULL;
-  
+
   if(gfd->gapStoryFetchResult != NULL)
   {
     fcacheFetchResult.isRgb888Result = gfd->isRgb888Result;
@@ -7633,7 +7617,7 @@ p_stb_render_movie_single_processor(GapStbFetchData *gfd
          else
          {
            gboolean isPlayingBackwards;
-           
+
            if(gfd->frn_elem->frame_from > gfd->frn_elem->frame_to)
            {
              isPlayingBackwards = TRUE;
@@ -7642,12 +7626,12 @@ p_stb_render_movie_single_processor(GapStbFetchData *gfd
            {
              isPlayingBackwards = FALSE;
            }
-           
+
            if(vidhand->do_gimp_progress)
            {
               gimp_progress_init(_("Seek Inputvideoframe..."));
            }
-           
+
            /* for backwards playing clip seek before the wanted position
             * and read some frames until wanted position is reaced to fill the fcache
             * (this shall speed up the next few backwards reads that can be fetched from fcache)
@@ -7656,8 +7640,8 @@ p_stb_render_movie_single_processor(GapStbFetchData *gfd
            {
              gdouble seekFrameNumber;
              gdouble delta;
-           
-           
+
+
              delta = GVA_get_fcache_size_in_elements(gfd->frn_elem->gvahand) -1;
              seekFrameNumber = MAX((gdouble)gfd->localframe_index - delta, 2);
              GVA_seek_frame(gfd->frn_elem->gvahand, seekFrameNumber, GVA_UPOS_FRAMES);
@@ -7696,7 +7680,7 @@ p_stb_render_movie_single_processor(GapStbFetchData *gfd
                  );
        }
      }
-     
+
      if (fcacheFetchResult.isFrameAvailable == TRUE)
      {
        p_get_gapStoryFetchResult_from_fcacheFetchResult(gfd, &fcacheFetchResult);
@@ -7706,7 +7690,7 @@ p_stb_render_movie_single_processor(GapStbFetchData *gfd
        gfd->tmp_image_id = -1;
      }
   }
-  
+
 
   GAP_TIMM_STOP_FUNCTION(funcId);
 
@@ -7735,7 +7719,7 @@ p_call_GVA_get_next_frame_andSendReadySignal(VideoPrefetchData *vpre, gint32 tar
       , (int)vpre->gvahand->current_seek_nr
       );
   }
-  
+
   GVA_get_next_frame(vpre->gvahand);
   GVA_fcache_mutex_lock (vpre->gvahand);
   if (vpre->gvahand->current_frame_nr == targetFrameNumber)
@@ -7750,9 +7734,9 @@ p_call_GVA_get_next_frame_andSendReadySignal(VideoPrefetchData *vpre, gint32 tar
     }
     g_cond_signal  (vpre->targetFrameReadyCond);
   }
-  
+
   GVA_fcache_mutex_unlock (vpre->gvahand);
-  
+
 }  /* end p_call_GVA_get_next_frame_andSendReadySignal */
 #endif
 
@@ -7780,7 +7764,7 @@ p_videoPrefetchWorkerThreadFunction (VideoPrefetchData *vpre)
   gint32               prefetchFrameNumber;
   gint32               targetFrameNumber;
   gboolean             isPlayingBackwards;
-           
+
   if(gap_debug)
   {
     printf("p_videoPrefetchWorkerThreadFunction START (before mutex lock) TID:%lld gvahand:%d  
targetFrameNumber:%d\n"
@@ -7789,7 +7773,7 @@ p_videoPrefetchWorkerThreadFunction (VideoPrefetchData *vpre)
          ,(int)vpre->targetFrameNumber
          );
   }
-  
+
   GVA_fcache_mutex_lock (vpre->gvahand);
 
   prefetchFrameNumber = vpre->prefetchFrameNumber;
@@ -7803,7 +7787,7 @@ p_videoPrefetchWorkerThreadFunction (VideoPrefetchData *vpre)
   {
     isPlayingBackwards = FALSE;
   }
-  
+
   GVA_fcache_mutex_unlock (vpre->gvahand);
 
   if(targetFrameNumber >= 0)
@@ -7840,7 +7824,7 @@ p_videoPrefetchWorkerThreadFunction (VideoPrefetchData *vpre)
       {
         gdouble seekFrameNumber;
         gdouble delta;
-        
+
         if(gap_debug)
         {
           printf("p_videoPrefetchWorkerThreadFunction TID:%lld gvahand:%d BACKWARD READ 
targetFrameNumber:%d\n"
@@ -7849,7 +7833,7 @@ p_videoPrefetchWorkerThreadFunction (VideoPrefetchData *vpre)
              ,(int)targetFrameNumber
              );
         }
-        
+
         delta = GVA_get_fcache_size_in_elements(vpre->gvahand) -1;
         seekFrameNumber = MAX((gdouble)targetFrameNumber - delta, 2);
         GVA_seek_frame(vpre->gvahand, seekFrameNumber, GVA_UPOS_FRAMES);
@@ -7885,7 +7869,7 @@ p_videoPrefetchWorkerThreadFunction (VideoPrefetchData *vpre)
       }
     }
   }
-  
+
 
   GVA_fcache_mutex_lock (vpre->gvahand);
   vpre->isPrefetchThreadRunning = FALSE;
@@ -7923,8 +7907,8 @@ static gint32
 p_getPredictedNextFramenr(gint32 targetFrameNr, GapStoryRenderFrameRangeElem *frn_elem)
 {
   gint32 predictedFrameNr;
-  
-  
+
+
   if (frn_elem->frame_from > frn_elem->frame_to)
   {
     /* Backward Read */
@@ -7943,10 +7927,10 @@ p_getPredictedNextFramenr(gint32 targetFrameNr, GapStoryRenderFrameRangeElem *fr
     gint32 fcacheSize;
     gint32 prefetchAmount;
     gint32 highestReferedFrameNr;
-    
+
     fcacheSize = GVA_get_fcache_size_in_elements(frn_elem->gvahand);
     prefetchAmount = MIN(MULTITHREAD_PREFETCH_AMOUNT, fcacheSize -1);
-    
+
     highestReferedFrameNr = frn_elem->frame_to;
 //     if(frn_elem->gvahand->all_frames_counted == TRUE)
 //     {
@@ -7971,7 +7955,7 @@ p_getPredictedNextFramenr(gint32 targetFrameNr, GapStoryRenderFrameRangeElem *fr
   }
 
   return (predictedFrameNr);
-  
+
 }  /* end  p_getPredictedNextFramenr */
 #endif
 
@@ -7983,7 +7967,7 @@ p_getPredictedNextFramenr(gint32 targetFrameNr, GapStoryRenderFrameRangeElem *fr
  * multithread environment.
  * It reads the required target frame from the GVA api fcache,
  * and trigers a parallel prefetch thread.
- * The parallel running prefetch thread fills up the GVA api fcache 
+ * The parallel running prefetch thread fills up the GVA api fcache
  * by reading (more than one) frame from the videofile in advance.
  * to increase fcache hit chance at the next call.
  *
@@ -8007,7 +7991,7 @@ p_stb_render_movie_multiprocessor(GapStbFetchData *gfd
   gint32             predictedNextFrameNr;
   gint32             targetFrameNumber;
   gint32             numProcessors;
-  
+
   GVA_fcache_fetch_result fcacheFetchResult;
   GError *error;
 
@@ -8022,17 +8006,17 @@ p_stb_render_movie_multiprocessor(GapStbFetchData *gfd
   error = NULL;
   targetFrameNumber = gfd->localframe_index; /* this framenumber is required now for processing */
   numProcessors = gap_base_get_numProcessors();
-  
+
   fcacheFetchResult.isRgb888Result = FALSE;  /* configure fcache for standard fetch as gimp layer */
   fcacheFetchResult.rgbBuffer.data = NULL;
-  
+
   if(gfd->gapStoryFetchResult != NULL)
   {
     fcacheFetchResult.isRgb888Result = gfd->isRgb888Result;
     fcacheFetchResult.rgbBuffer.data = gfd->gapStoryFetchResult->raw_rgb_data;
   }
-  
- 
+
+
  /* split delace value: integer part is deinterlace mode, rest is threshold */
   p_split_delace_value(gfd->frn_elem->delace
              , gfd->localframe_tween_rest
@@ -8060,7 +8044,7 @@ p_stb_render_movie_multiprocessor(GapStbFetchData *gfd
       vpre->isPlayingBackwards = TRUE;
     }
     gfd->frn_elem->gvahand->user_data = vpre;
-    
+
     /* Let the GVA api know about the mutex.
      * This triggers g_mutex_lock / g_mutex_unlock calls in API internal functions
      * dealing with the fcache access.
@@ -8086,7 +8070,7 @@ p_stb_render_movie_multiprocessor(GapStbFetchData *gfd
       /* fcache hit */
       gboolean triggerMorePrefetch;
       gint32   fnr;
-      
+
       if(gap_debug)
       {
         printf("FCACHE-HIT gvahand:%d framenr:%d predictedFrameNr:%d retryCount:%d\n"
@@ -8142,7 +8126,7 @@ p_stb_render_movie_multiprocessor(GapStbFetchData *gfd
     {
       /* frame is NOT (yet) in fcache */
       GVA_fcache_mutex_lock (vpre->gvahand);
-      
+
       if(vpre->isPrefetchThreadRunning != TRUE)
       {
         vpre->prefetchFrameNumber = predictedNextFrameNr;
@@ -8157,7 +8141,7 @@ p_stb_render_movie_multiprocessor(GapStbFetchData *gfd
               , (int)retryCount
               );
         }
- 
+
         vpre->isPrefetchThreadRunning = TRUE;
         /* (re)activate a worker thread for next prefetch that fills fcache upto prefetchFrameNumber */
         g_thread_pool_push (p_get_PrefetchThreadPool()
@@ -8166,7 +8150,7 @@ p_stb_render_movie_multiprocessor(GapStbFetchData *gfd
                          );
 
       }
-      
+
       if(gap_debug)
       {
         printf("WAIT  gvahand:%d until prefetch worker thread has fetched target framenr:%d 
predictedFrameNr:%d retryCount:%d\n"
@@ -8179,10 +8163,10 @@ p_stb_render_movie_multiprocessor(GapStbFetchData *gfd
 
       GAP_TIMM_START_FUNCTION(funcIdWait);
 
-      /* wait until next frame s fetched 
-       * g_cond_wait Waits until this thread is woken up on targetFrameReadyCond. 
-       * The mutex is unlocked before falling asleep and locked again before resuming. 
-       */ 
+      /* wait until next frame s fetched
+       * g_cond_wait Waits until this thread is woken up on targetFrameReadyCond.
+       * The mutex is unlocked before falling asleep and locked again before resuming.
+       */
       g_cond_wait (vpre->targetFrameReadyCond, vpre->mutex);
 
 
@@ -8198,7 +8182,7 @@ p_stb_render_movie_multiprocessor(GapStbFetchData *gfd
           );
       }
       GVA_fcache_mutex_unlock (vpre->gvahand);
-  
+
       /* retry another attempt to get the frame from the fcache (that shall be filled by the worker thread */
     }
   }
@@ -8241,7 +8225,7 @@ p_stb_render_movie_multiprocessor(GapStbFetchData *gfd
 
 
 /* -------------------------------------------
- * p_stb_render_movie (GAP_FRN_MOVIE) 
+ * p_stb_render_movie (GAP_FRN_MOVIE)
  * -------------------------------------------
  * fetch frame from a videofile (gfd->framename contains the videofile name)
  * on success the fetched imageId is set in the  gfd->tmp_image_id
@@ -8349,12 +8333,12 @@ p_check_next_composite_frame_includes_same_image(GapStbFetchData *gfdCurrent
   gboolean nextCompositeFrameIncludesSameImage;
   GapStbFetchData gapStbFetchData;
   GapStbFetchData *gfd;
-  
+
   nextCompositeFrameIncludesSameImage = FALSE;
-  
+
   gfd = &gapStbFetchData;
   p_init_gfd(gfd);
-  
+
   for(l_track = vidhand->maxVidTrack; l_track >= vidhand->minVidTrack; l_track--)
   {
     gfd->framename = p_fetch_framename(vidhand->frn_list
@@ -8377,7 +8361,7 @@ p_check_next_composite_frame_includes_same_image(GapStbFetchData *gfdCurrent
       g_free(gfd->framename);
     }
   }
-    
+
   return (nextCompositeFrameIncludesSameImage);
 }
 
@@ -8404,7 +8388,7 @@ p_stb_render_frame_images(GapStbFetchData *gfd, GapStoryRenderVidHandle *vidhand
   gint32   prescaleHeight;
   GapStoryCalcAttr  calculate_attributes;
   GapStoryCalcAttr  *calculated;
-  
+
   if(gap_debug)
   {
     printf("FRAME fetch gfd->framename: %s\n    ===> master:%d  from: %d to: %d\n"
@@ -8415,6 +8399,13 @@ p_stb_render_frame_images(GapStbFetchData *gfd, GapStoryRenderVidHandle *vidhand
       );
   }
 
+  if (!g_file_test(gfd->framename, G_FILE_TEST_EXISTS))
+  {
+    gfd->tmp_image_id = -1;
+    return;
+  }
+
+
   nextCompositeFrameIncludesSameImage =
      p_check_next_composite_frame_includes_same_image(gfd, vidhand, master_frame_nr);
 
@@ -8449,14 +8440,14 @@ p_stb_render_frame_images(GapStbFetchData *gfd, GapStoryRenderVidHandle *vidhand
       , gfd->move_x
       , gfd->move_y
       );
-    
+
   prescaleWidth = calculated->width;
   prescaleHeight = calculated->height;
 
   if (gap_frame_fetch_is_image_in_cache(l_fetched_image_id))
   {
     gboolean fetchedImageUsable;
-    
+
     fetchedImageUsable = FALSE;
     if ((gimp_image_width(l_fetched_image_id) >= prescaleWidth)
     &&  (gimp_image_height(l_fetched_image_id) >= prescaleHeight))
@@ -8471,8 +8462,8 @@ p_stb_render_frame_images(GapStbFetchData *gfd, GapStoryRenderVidHandle *vidhand
         fetchedImageUsable = TRUE;
       }
     }
-    
-    
+
+
     if(fetchedImageUsable == TRUE)
     {
       if(gap_debug)
@@ -8499,7 +8490,7 @@ p_stb_render_frame_images(GapStbFetchData *gfd, GapStoryRenderVidHandle *vidhand
            );
       }
       /* the cached image is downscaled and smaller than required size.
-       * in this case load again from file (at original size to ensure 
+       * in this case load again from file (at original size to ensure
        * best possible render quality)
        */
       gfd->tmp_image_id = gap_lib_load_image(gfd->framename);
@@ -8524,7 +8515,7 @@ p_stb_render_frame_images(GapStbFetchData *gfd, GapStoryRenderVidHandle *vidhand
 
 
 }  /* end p_stb_render_frame_images */
-  
+
 
 /* -------------------------------------------
  * p_stb_render_composite_image_postprocessing
@@ -8554,7 +8545,7 @@ p_stb_render_composite_image_postprocessing(GapStbFetchData *gfd
     /* none of the tracks had a frame image on this master_frame_nr position
      * create a blank image (VID_SILENNCE)
      */
-    gfd->comp_image_id = p_create_unicolor_image(&gfd->layer_id
+    gfd->comp_image_id = gap_image_create_unicolor_image(&gfd->layer_id
                          , vid_width
                          , vid_height
                          , 0.0
@@ -8808,7 +8799,7 @@ p_do_insert_area_processing(GapStbFetchData *gfd
   char *logo_imagename;
 
   logo_imagename = p_get_insert_area_filename(gfd, vidhand);
-  
+
   if(g_file_test(logo_imagename, G_FILE_TEST_EXISTS))
   {
     gint32 logo_image_id;
@@ -8830,7 +8821,7 @@ p_do_insert_area_processing(GapStbFetchData *gfd
     if(logo_image_id < 0)
     {
       printf("p_do_insert_area_processing: ERROR could not load logo_imagename:%s\n", logo_imagename);
-      
+
       g_free(logo_imagename);
       return;
     }
@@ -8913,7 +8904,7 @@ p_prepare_GRAY_image(gint32 image_id)
   }
 
   return(l_layer_id);
-  
+
 } /* end p_prepare_GRAY_image */
 
 
@@ -8975,11 +8966,11 @@ p_get_insert_alpha_filename(GapStbFetchData *gfd
         , alpha_imagename
         );
   }
-  
+
   g_free(videofilename_without_path);
-  
+
   return(alpha_imagename);
-  
+
 }  /* end p_get_insert_alpha_filename */
 
 /* -------------------------------------
@@ -9073,7 +9064,7 @@ p_do_insert_alpha_processing(GapStbFetchData *gfd
 }  /* end p_do_insert_alpha_processing */
 
 /* --------------------------------------------
- * p_isFiltermacroActive  
+ * p_isFiltermacroActive
  * --------------------------------------------
  */
 static gboolean
@@ -9083,11 +9074,11 @@ p_isFiltermacroActive(const char *filtermacro_file)
   {
      if(*filtermacro_file != '\0')
      {
-       return(TRUE);  
+       return(TRUE);
      }
   }
-  return(FALSE); 
-  
+  return(FALSE);
+
 }  /* end p_isFiltermacroActive */
 
 
@@ -9097,7 +9088,7 @@ p_isFiltermacroActive(const char *filtermacro_file)
  * this procedure checks if the current frame can be directly fetched as rgb888 buffer
  * form a videoclip without the need to convert to gimp drawable and rendering transitions.
  * (this can speed up viedeoencoders that can handle rgb888 data)
- * 
+ *
  * if an rgb888 fetch is possible for the current master_frame_nr
  * the fetch is performed and TRUE will be returned.
  * otherwise FALSE is returned.
@@ -9122,7 +9113,7 @@ p_story_render_bypass_where_possible(GapStoryRenderVidHandle *vidhand
   gfd = &gapStbFetchData;
   gfdMovie = NULL;
   videofileName = NULL;
-  
+
   if(gap_debug)
   {
     printf("p_story_render_bypass_where_possible START master_frame_nr:%d minVidTrack:%d maxVidTrack:%d 
enable_rgb888_flag:%d\n"
@@ -9160,7 +9151,7 @@ p_story_render_bypass_where_possible(GapStoryRenderVidHandle *vidhand
         );
     }
 
-    
+
     if(gfd->framename)
     {
       if(gfd->frn_type == GAP_FRN_MOVIE)
@@ -9184,9 +9175,9 @@ p_story_render_bypass_where_possible(GapStoryRenderVidHandle *vidhand
           )
           {
             gboolean isAutoInsertActive;
-            
+
             isAutoInsertActive = FALSE;
-            
+
             if(vidhand->master_insert_alpha_format != NULL)
             {
               char *alpha_imagename;
@@ -9211,23 +9202,23 @@ p_story_render_bypass_where_possible(GapStoryRenderVidHandle *vidhand
               }
               g_free(logo_imagename);
             }
-            
+
             if (isAutoInsertActive != TRUE)
             {
               gfdMovie = gfd;
               videofileName = g_strdup(gfd->framename);
             }
           }
-        
+
       }
       g_free(gfd->framename);
     }
-    
+
     if(gfdMovie != NULL)
     {
       break;
     }
-    
+
     if(gfd->frn_type != GAP_FRN_SILENCE)
     {
       if(gfd->opacity != 0.0)
@@ -9235,14 +9226,14 @@ p_story_render_bypass_where_possible(GapStoryRenderVidHandle *vidhand
         break;
       }
     }
-    
+
     /* at this point we detected that current layer is fully transparent
      * therefore we can continue checking the next track (e.g. lower layerstack position)
      */
-     
+
   }       /* end for loop over all video tracks */
-  
-  
+
+
 
 
   if((gfdMovie != NULL)
@@ -9294,16 +9285,16 @@ p_story_render_bypass_where_possible(GapStoryRenderVidHandle *vidhand
          }
        }
      }
-     
+
   }
-  
+
   if(videofileName != NULL)
   {
     g_free(videofileName);
   }
-  
+
   return(isByPassRenderEngine);
-  
+
 }  /* end p_story_render_bypass_where_possible  */
 
 
@@ -9345,7 +9336,7 @@ p_story_render_fetch_composite_image_private(GapStoryRenderVidHandle *vidhand
   static gint32 funcId = -1;
   static gint32 funcIdDirect = -1;
   static gint32 funcIdDirectScale = -1;
-  
+
   GAP_TIMM_GET_FUNCTION_ID(funcId, "p_story_render_fetch_composite_image_private");
   GAP_TIMM_GET_FUNCTION_ID(funcIdDirect, "p_story_render_fetch_composite_image_private.Direct");
   GAP_TIMM_GET_FUNCTION_ID(funcIdDirectScale, "p_story_render_fetch_composite_image_private.Direct.Scale");
@@ -9355,7 +9346,7 @@ p_story_render_fetch_composite_image_private(GapStoryRenderVidHandle *vidhand
 
   gfd = &gapStbFetchData;
   p_init_gfd(gfd);
-  
+
   *layer_id         = -1;
 
 
@@ -9402,15 +9393,15 @@ p_story_render_fetch_composite_image_private(GapStoryRenderVidHandle *vidhand
   && (p_isFiltermacroActive(filtermacro_file) != TRUE))
   {
     gboolean isByPassRenderEngine;
-    
+
     isByPassRenderEngine = p_story_render_bypass_where_possible(vidhand
-                    , master_frame_nr 
+                    , master_frame_nr
                     , vid_width
                     , vid_height
                     , enable_rgb888_flag
                     , gapStoryFetchResult
                     );
-    
+
     if (isByPassRenderEngine == TRUE)
     {
       if(gap_debug)
@@ -9444,7 +9435,7 @@ p_story_render_fetch_composite_image_private(GapStoryRenderVidHandle *vidhand
      {
        if(gfd->frn_type == GAP_FRN_COLOR)
        {
-           gfd->tmp_image_id = p_create_unicolor_image(&gfd->layer_id
+           gfd->tmp_image_id = gap_image_create_unicolor_image(&gfd->layer_id
                                                 , vid_width
                                                 , vid_height
                                                 , gfd->red_f
@@ -9556,7 +9547,7 @@ p_story_render_fetch_composite_image_private(GapStoryRenderVidHandle *vidhand
            ||  (gimp_image_height(gfd->comp_image_id) != vid_height) )
            {
               GAP_TIMM_START_FUNCTION(funcIdDirectScale);
-              
+
               if(gap_debug)
               {
                 printf("DEBUG: p_story_render_fetch_composite_image_private scaling composite image\n");
@@ -9571,7 +9562,7 @@ p_story_render_fetch_composite_image_private(GapStoryRenderVidHandle *vidhand
          {
            /* create empty backgound */
            gint32 l_empty_layer_id;
-           gfd->comp_image_id = p_create_unicolor_image(&l_empty_layer_id
+           gfd->comp_image_id = gap_image_create_unicolor_image(&l_empty_layer_id
                                 , vid_width
                                 , vid_height
                                 , 0.0
diff --git a/gap/gap_wr_layermode.c b/gap/gap_wr_layermode.c
new file mode 100644
index 0000000..ad33a7f
--- /dev/null
+++ b/gap/gap_wr_layermode.c
@@ -0,0 +1,409 @@
+/*  gap_wr_layermode.c
+ *    wrapper plugin to set Layermode by Wolfgang Hofer.
+ *  2013/05/02
+ */
+
+/* The GIMP -- an image manipulation program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* Revision history
+ *  (2013/05/02)  v1.0       hof: created
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <gtk/gtk.h>
+#include <libgimp/gimp.h>
+#include <libgimp/gimpui.h>
+
+#include "gap_lastvaldesc.h"
+
+#include "gap-intl.h"
+
+/* Defines */
+#define PLUG_IN_NAME        "plug-in-wr-set-layermode"
+#define PLUG_IN_BINARY      "wr_layermode"
+#define PLUG_IN_PRINT_NAME  "Set Layermode"
+#define PLUG_IN_IMAGE_TYPES "RGB*, INDEXED*, GRAY*"
+#define PLUG_IN_AUTHOR      "Wolfgang Hofer (hof gimp org)"
+#define PLUG_IN_COPYRIGHT   "Wolfgang Hofer"
+
+int gap_debug = 0;  /* 1 == print debug infos , 0 dont print debug infos */
+
+
+typedef struct {
+  gint32  mode;
+} LayermodeValues;
+
+
+
+static LayermodeValues glob_vals =
+{
+  0           /* 0..GIMP_NORMAL_MODE */
+};
+
+
+static void  query (void);
+static void  run (const gchar *name,          /* name of plugin */
+     gint nparams,               /* number of in-paramters */
+     const GimpParam * param,    /* in-parameters */
+     gint *nreturn_vals,         /* number of out-parameters */
+     GimpParam ** return_vals);  /* out-parameters */
+
+static gint  p_layermode_run (gint32 image_id, gint32 drawable_id);
+static gint  p_layermode_dialog (void);
+
+
+/* Global Variables */
+GimpPlugInInfo PLUG_IN_INFO =
+{
+  NULL,   /* init_proc  */
+  NULL,   /* quit_proc  */
+  query,  /* query_proc */
+  run     /* run_proc   */
+};
+
+static GimpParamDef in_args[] = {
+                  { GIMP_PDB_INT32,    "run_mode", "Interactive, non-interactive"},
+                  { GIMP_PDB_IMAGE,    "image", "Input image" },
+                  { GIMP_PDB_DRAWABLE, "drawable", "Input drawable (must be a layer)"},
+                  { GIMP_PDB_INT32,    "mode", "The new layer combination mode { NORMAL-MODE (0), 
DISSOLVE-MODE (1), BEHIND-MODE (2), MULTIPLY-MODE (3), SCREEN-MODE (4), OVERLAY-MODE (5), DIFFERENCE-MODE 
(6), ADDITION-MODE (7), SUBTRACT-MODE (8), DARKEN-ONLY-MODE (9), LIGHTEN-ONLY-MODE (10), HUE-MODE (11), 
SATURATION-MODE (12), COLOR-MODE (13), VALUE-MODE (14), DIVIDE-MODE (15), DODGE-MODE (16), BURN-MODE (17), 
HARDLIGHT-MODE (18), SOFTLIGHT-MODE (19), GRAIN-EXTRACT-MODE (20), GRAIN-MERGE-MODE (21), COLOR-ERASE-MODE 
(22), ERASE-MODE (23), REPLACE-MODE (24), ANTI-ERASE-MODE (25) }"},
+  };
+
+static GimpParamDef return_vals[] = {
+    { GIMP_PDB_DRAWABLE, "the_drawable", "the handled drawable" }
+};
+
+static gint global_number_in_args = G_N_ELEMENTS (in_args);
+static gint global_number_out_args = G_N_ELEMENTS (return_vals);
+
+
+/* Functions */
+
+MAIN ()
+
+static void query (void)
+{
+  static GimpLastvalDef lastvals[] =
+  {
+    GIMP_LASTVALDEF_GINT32          (GIMP_ITER_FALSE,  glob_vals.mode,     "mode"),
+  };
+
+
+
+  gimp_plugin_domain_register (GETTEXT_PACKAGE, LOCALEDIR);
+
+  /* registration for last values buffer structure (useful for animated filter apply) */
+  gimp_lastval_desc_register(PLUG_IN_NAME,
+                             &glob_vals,
+                             sizeof(glob_vals),
+                             G_N_ELEMENTS (lastvals),
+                             lastvals);
+
+  /* the actual installation of the plugin */
+  gimp_install_procedure (PLUG_IN_NAME,
+                          "Set Layer combination mode",
+                          "This plug-in is a wrapper for gimp_layer_set_mode functionality, "
+                          "and provides the typical PDB interface for calling it as "
+                          "filter for the use with GIMP-GAP filtermacro and Video Frame manipulation",
+                          PLUG_IN_AUTHOR,
+                          PLUG_IN_COPYRIGHT,
+                          GAP_VERSION_WITH_DATE,
+                          N_("Set Layer Mode..."),
+                          PLUG_IN_IMAGE_TYPES,
+                          GIMP_PLUGIN,
+                          global_number_in_args,
+                          global_number_out_args,
+                          in_args,
+                          return_vals);
+  {
+    /* Menu names */
+    const char *menupath_image_video_layer_attr = N_("<Image>/Video/Layer/Attributes/");
+
+    gimp_plugin_menu_register (PLUG_IN_NAME, menupath_image_video_layer_attr);
+  }
+
+}  /* end query */
+
+static void
+run (const gchar *name,          /* name of plugin */
+     gint nparams,               /* number of in-paramters */
+     const GimpParam * param,    /* in-parameters */
+     gint *nreturn_vals,         /* number of out-parameters */
+     GimpParam ** return_vals)   /* out-parameters */
+{
+  const gchar *l_env;
+  gint32       image_id = -1;
+
+
+  /* Get the runmode from the in-parameters */
+  GimpRunMode run_mode = param[0].data.d_int32;
+
+  /* status variable, use it to check for errors in invocation usualy only
+     during non-interactive calling */
+  GimpPDBStatusType status = GIMP_PDB_SUCCESS;
+
+  /* always return at least the status to the caller. */
+  static GimpParam values[2];
+
+  INIT_I18N();
+
+  l_env = g_getenv("GAP_DEBUG");
+  if(l_env != NULL)
+  {
+    if((*l_env != 'n') && (*l_env != 'N')) gap_debug = 1;
+  }
+
+  if(gap_debug) printf("\n\nDEBUG: run %s\n", name);
+
+  /* initialize the return of the status */
+  values[0].type = GIMP_PDB_STATUS;
+  values[0].data.d_status = status;
+  values[1].type = GIMP_PDB_DRAWABLE;
+  values[1].data.d_drawable = -1;
+  *nreturn_vals = 2;
+  *return_vals = values;
+
+
+  /* get image and drawable */
+  image_id = param[1].data.d_int32;
+
+
+  /* how are we running today? */
+  switch (run_mode)
+  {
+    case GIMP_RUN_INTERACTIVE:
+      /* Possibly retrieve data from a previous run */
+      gimp_get_data (PLUG_IN_NAME, &glob_vals);
+
+      /* Get information from the dialog */
+      if (!p_layermode_dialog())
+      {
+        return;
+      }
+      break;
+
+    case GIMP_RUN_NONINTERACTIVE:
+      /* check to see if invoked with the correct number of parameters */
+      if (nparams == global_number_in_args)
+      {
+          glob_vals.mode        = (gint32)  param[3].data.d_int32;
+      }
+      else
+      {
+        status = GIMP_PDB_CALLING_ERROR;
+      }
+
+      break;
+
+    case GIMP_RUN_WITH_LAST_VALS:
+      /* Possibly retrieve data from a previous run */
+      gimp_get_data (PLUG_IN_NAME, &glob_vals);
+
+      break;
+
+    default:
+      break;
+  }
+
+  if (status == GIMP_PDB_SUCCESS)
+  {
+    /* Run the main function */
+    values[1].data.d_drawable = p_layermode_run(image_id, param[2].data.d_drawable);
+    if (values[1].data.d_drawable < 0)
+    {
+       status = GIMP_PDB_CALLING_ERROR;
+    }
+
+    /* If run mode is interactive, flush displays, else (script) don't
+       do it, as the screen updates would make the scripts slow */
+    if (run_mode != GIMP_RUN_NONINTERACTIVE)
+      gimp_displays_flush ();
+
+    /* Store variable states for next run */
+    if (run_mode == GIMP_RUN_INTERACTIVE)
+      gimp_set_data (PLUG_IN_NAME, &glob_vals, sizeof (LayermodeValues));
+  }
+  values[0].data.d_status = status;
+}       /* end run */
+
+
+
+/* ============================================================================
+ * p_layermode_run
+ *        The main function
+ * ============================================================================
+ */
+static gint32
+p_layermode_run (gint32 image_id, gint32 drawable_id)
+{
+  if(gap_debug)
+  {
+    printf("mode: %d\n", (int)glob_vals.mode);
+  }
+
+  gimp_layer_set_mode(drawable_id, glob_vals.mode);
+
+  return (drawable_id);
+}       /* end p_layermode_run */
+
+
+
+
+/* ------------- Dialog stuff --------------- */
+
+
+
+static void
+p_layermode_menu_callback (GtkWidget *widget,  void *dataPtr)
+{
+  gint value;
+
+  gimp_int_combo_box_get_active (GIMP_INT_COMBO_BOX (widget), &value);
+
+  glob_vals.mode = value;
+}
+
+/* ------------------
+ * p_layermode_dialog
+ * ------------------
+ *   return  TRUE (OK, run the processing)
+ *           FALSE (in case of Error or cancel)
+ */
+static gboolean
+p_layermode_dialog(void)
+{
+  GtkWidget *dialog;
+  GtkWidget *main_vbox;
+  GtkWidget *frame;
+  GtkWidget *table;
+  GtkWidget *label;
+  GtkWidget *combo;
+  gboolean   run;
+  gint       rc;
+
+  gimp_ui_init (PLUG_IN_BINARY, FALSE);
+
+  dialog = gimp_dialog_new (_("LAYERMODE"), PLUG_IN_BINARY,
+                            NULL, 0,
+                            gimp_standard_help_func, PLUG_IN_NAME,
+
+                            GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+                            GTK_STOCK_OK,     GTK_RESPONSE_OK,
+
+                            NULL);
+
+  gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
+                                           GTK_RESPONSE_OK,
+                                           GTK_RESPONSE_CANCEL,
+                                           -1);
+
+  gimp_window_set_transient (GTK_WINDOW (dialog));
+
+  /*  The main vbox  */
+  main_vbox = gtk_vbox_new (FALSE, 12);
+  gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12);
+  gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), main_vbox);
+  gtk_widget_show (main_vbox);
+
+  /*  Options section  */
+  frame = gimp_frame_new ( _("Options"));
+  gtk_widget_show (frame);
+  gtk_box_pack_start (GTK_BOX (main_vbox), frame, FALSE, FALSE, 0);
+
+  /* The table to hold the frame of options */
+  table = gtk_table_new (2, 2, FALSE);
+  gtk_table_set_col_spacings (GTK_TABLE (table), 12);
+  gtk_table_set_row_spacings (GTK_TABLE (table), 12);
+  gtk_container_add (GTK_CONTAINER (frame), table);
+ 
+
+  /* Paintmode combo (menu) */
+
+  label = gtk_label_new( _("Mode:"));
+  gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
+  gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, GTK_FILL, 0, 4, 0);
+  gtk_widget_show(label);
+
+  combo = gimp_int_combo_box_new (_("Normal"),         GIMP_NORMAL_MODE,
+                                   _("Dissolve"),       GIMP_DISSOLVE_MODE,
+                                   _("Behind"),         GIMP_BEHIND_MODE,
+                                   _("Multiply"),       GIMP_MULTIPLY_MODE,
+                                   _("Divide"),         GIMP_DIVIDE_MODE,
+                                   _("Screen"),         GIMP_SCREEN_MODE,
+                                   _("Overlay"),        GIMP_OVERLAY_MODE,
+                                   _("Dodge"),          GIMP_DODGE_MODE,
+                                   _("Burn"),           GIMP_BURN_MODE,
+                                   _("Hard Light"),     GIMP_HARDLIGHT_MODE,
+                                   _("Soft Light"),     GIMP_SOFTLIGHT_MODE,
+                                   _("Grain Extract"),  GIMP_GRAIN_EXTRACT_MODE,
+                                   _("Grain Merge"),    GIMP_GRAIN_MERGE_MODE,
+                                   _("Difference"),     GIMP_DIFFERENCE_MODE,
+                                   _("Addition"),       GIMP_ADDITION_MODE,
+                                   _("Subtract"),       GIMP_SUBTRACT_MODE,
+                                   _("Darken Only"),    GIMP_DARKEN_ONLY_MODE,
+                                   _("Lighten Only"),   GIMP_LIGHTEN_ONLY_MODE,
+                                   _("Hue"),            GIMP_HUE_MODE,
+                                   _("Saturation"),     GIMP_SATURATION_MODE,
+                                   _("Color"),          GIMP_COLOR_MODE,
+                                   _("Color Erase"),    GIMP_COLOR_ERASE_MODE,
+                                   _("Value"),          GIMP_VALUE_MODE,
+                                   NULL);
+
+  {
+    gint initialValue;
+    initialValue = GIMP_NORMAL_MODE;
+
+
+    gimp_int_combo_box_connect (GIMP_INT_COMBO_BOX (combo),
+                              initialValue,
+                              G_CALLBACK (p_layermode_menu_callback),
+                              NULL);
+
+  }
+
+  gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 0, 1,
+                   GTK_EXPAND | GTK_FILL, 0, 0, 0);
+  gimp_help_set_help_data(combo,
+                       _("Paintmode")
+                       , NULL);
+  gtk_widget_show(combo);
+
+
+
+  gtk_widget_show (frame);
+  gtk_widget_show (table);
+  gtk_widget_show (dialog);
+
+  rc = gimp_dialog_run (GIMP_DIALOG (dialog));
+  
+  if(gap_debug)
+  {
+    printf("rc:%d GTK_RESPONSE_OK:%d\n", (int)rc, (int)GTK_RESPONSE_OK);
+  }
+  
+  run = (rc == GTK_RESPONSE_OK);
+
+  gtk_widget_destroy (dialog);
+
+  return run;
+}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]