[gimp-gap/gap-2-8] merged latest features from master to gap-2-8 branch + fixed some deprecated calls.
- From: Wolfgang Hofer <wolfgangh src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp-gap/gap-2-8] merged latest features from master to gap-2-8 branch + fixed some deprecated calls.
- Date: Mon, 9 Sep 2013 18:15:09 +0000 (UTC)
commit 9d051c8e57691aa786b23d833f0eff802773b457
Author: Wolfgang Hofer <wolfgangh svn gnome org>
Date: Mon Sep 9 20:05:52 2013 +0200
merged latest features from master to gap-2-8 branch + fixed some deprecated calls.
ChangeLog | 170 +++++++++++++
autogen.sh | 5 +-
configure.in | 4 +-
gap/Makefile.am | 8 +
gap/gap_base_ops.c | 208 ++++++++++++----
gap/gap_detail_align_exec.c | 10 +-
gap/gap_edge_detection.c | 2 +-
gap/gap_fg_matting_exec.c | 4 +-
gap/gap_image.c | 84 +++++--
gap/gap_image.h | 5 +-
gap/gap_layer_copy.c | 19 +-
gap/gap_lib.c | 478 +++++++++++++++++++++++++++++--------
gap/gap_lib.h | 4 +
gap/gap_mod_layer.c | 98 +++++---
gap/gap_mov_exec.c | 228 +++++++++++++++---
gap/gap_mov_render.c | 98 ++++++--
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_pdb_calls.c | 9 +-
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_file.c | 17 +-
gap/gap_story_main.h | 2 +
gap/gap_story_render_processor.c | 496 +++++++++++++++++++-------------------
gap/gap_wr_layermode.c | 409 +++++++++++++++++++++++++++++++
gap/gap_wr_resynth.c | 2 +-
gap/gap_wr_trans.c | 37 ++--
33 files changed, 2321 insertions(+), 719 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index ac172fd..389b80b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,173 @@
+2013-09-09 Wolfgang Hofer <hof gimp org>
+
+- Replaced some deprecated calls by gimp-2.8 compatible pendants.
+ (this task is not yet finished, but current GAP should now run
+ both with GIMP-2.8 and GIMP-2.9 git master with remarkable less annoying deprection warning pop up windows)
+
+ Handled so far:
+ gimp_selection_load ==> gimp_image_select_item
+ gimp_drawable_transform_* ==> gimp_item_transform_*
+ gimp_image_add_layer ==> gimp_image_insert_layer (was already done at creation of branch gap-2-8)
+
+ gap-2-8 branch now requires at least gimp-2.8.0 version.
+
+ * configure.in
+ * gap/gap_fg_matting_exec.c
+ * gap/gap_image.c
+ * gap/gap_mod_layer.c
+ * gap/gap_mov_render.c
+ * gap/gap_wr_resynth.c
+ * gap/gap_wr_trans.c
+
+ * gap/gap_layer_copy.c
+ * gap/gap_pdb_calls.c
+ * gap/gap_story_file.c
+ * gap/gap_story_render_processor.c
+
+ * gap/gap_detail_align_exec.c
+ * gap/gap_mov_render.c
+
+ (2013-07-21) merged latest features from master to gap-2-8 branch
+
+
+- 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/configure.in b/configure.in
index b977c35..6e46b80 100644
--- a/configure.in
+++ b/configure.in
@@ -9,7 +9,7 @@ GAP_MINOR_VERSION=7
GAP_MICRO_VERSION=0
GAP_VERSION=$GAP_MAJOR_VERSION.$GAP_MINOR_VERSION.$GAP_MICRO_VERSION
VERSION=$GAP_VERSION
-GAP_VERSION_WITH_DATE="$GAP_VERSION; 2009/05/20"
+GAP_VERSION_WITH_DATE="$GAP_VERSION; 2013/09/07"
AC_SUBST(GAP_MAJOR_VERSION)
AC_SUBST(GAP_MINOR_VERSION)
@@ -51,7 +51,7 @@ AC_CHECK_HEADERS(unistd.h)
AC_CHECK_FUNCS(bind_textdomain_codeset)
-PKG_CHECK_MODULES(GIMP, gimp-2.0 >= 2.6.0 gimpui-2.0 >= 2.6.0 gimpthumb-2.0)
+PKG_CHECK_MODULES(GIMP, gimp-2.0 >= 2.8.0 gimpui-2.0 >= 2.8.0 gimpthumb-2.0)
GIMP_DATA_DIR=`$PKG_CONFIG gimp-2.0 --variable=gimpdatadir`
GIMP_PLUGIN_DIR=`$PKG_CONFIG gimp-2.0 --variable=gimplibdir`
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_detail_align_exec.c b/gap/gap_detail_align_exec.c
index 17f233f..3c7efb5 100644
--- a/gap/gap_detail_align_exec.c
+++ b/gap/gap_detail_align_exec.c
@@ -463,7 +463,10 @@ p_exact_align_drawable(gint32 activeDrawableId, AlingCoords *alingCoords)
scaleXY = len1 / len2;
}
- transformedDrawableId = gimp_drawable_transform_2d(activeDrawableId
+ gimp_context_set_defaults();
+ gimp_context_set_transform_resize(GIMP_TRANSFORM_RESIZE_ADJUST); /* do NOT clip */
+ gimp_context_set_transform_direction(GIMP_TRANSFORM_FORWARD);
+ transformedDrawableId = gimp_item_transform_2d(activeDrawableId
, px3
, py3
, scaleXY
@@ -471,11 +474,6 @@ p_exact_align_drawable(gint32 activeDrawableId, AlingCoords *alingCoords)
, angleRad
, px1
, py1
- , 0 /* FORWARD (0), TRANSFORM-BACKWARD (1) */
- , 2 /* INTERPOLATION-CUBIC (2) */
- , TRUE /* supersample */
- , 1 /* Maximum recursion level used for supersampling */
- , 0 /* TRANSFORM-RESIZE-ADJUST (0) TRANSFORM-RESIZE-CLIP (1) */
);
if(gap_debug)
diff --git a/gap/gap_edge_detection.c b/gap/gap_edge_detection.c
index 0cf62ae..188b5db 100644
--- a/gap/gap_edge_detection.c
+++ b/gap/gap_edge_detection.c
@@ -768,7 +768,7 @@ gint32 gap_edgeDetection(gint32 refDrawableId
blurDrawable = NULL;
// blurLayerId = gimp_layer_copy(edgeLayerId);
-// gimp_image_add_layer (imageId, blurLayerId, 0, 0 /* stackposition */ );
+// gimp_image_insert_layer (imageId, blurLayerId, 0, 0 /* stackposition */ );
// blurDrawable = gimp_drawable_get(blurLayerId);
p_subtract_ref_layer(imageId, edgeDrawable, refDrawable, threshold, shift, invert);
diff --git a/gap/gap_fg_matting_exec.c b/gap/gap_fg_matting_exec.c
index 6e355d3..6085412 100644
--- a/gap/gap_fg_matting_exec.c
+++ b/gap/gap_fg_matting_exec.c
@@ -656,7 +656,7 @@ gap_fg_from_selection_exec_apply_run (gint32 image_id, gint32 drawable_id
gimp_context_set_background (&color);
gimp_edit_fill(trimap, GIMP_BACKGROUND_FILL);
- gimp_selection_load(activeSelection);
+ gimp_image_select_item(image_id, GIMP_CHANNEL_OP_REPLACE, activeSelection);
gimp_selection_sharpen(image_id);
if (fsValPtr->outerRadius > 0)
{
@@ -698,7 +698,7 @@ gap_fg_from_selection_exec_apply_run (gint32 image_id, gint32 drawable_id
/* restore original selection */
if (hadSelection == TRUE)
{
- gimp_selection_load(activeSelection);
+ gimp_image_select_item(image_id, GIMP_CHANNEL_OP_REPLACE, activeSelection);
}
gimp_image_undo_group_end(image_id);
diff --git a/gap/gap_image.c b/gap/gap_image.c
index 5bc9747..b5a63dc 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_insert_layer(image_id, l_layer_id, 0, 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_insert_layer(new_image_id, *layer_id, 0, 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
@@ -433,7 +433,7 @@ gap_image_set_selection_from_selection_or_drawable(gint32 image_id, gint32 ref_d
, FALSE /* gboolean shadow */
);
- gimp_selection_load(l_aux_channel_id);
+ gimp_image_select_item(image_id, GIMP_CHANNEL_OP_REPLACE, l_aux_channel_id);
gimp_image_remove_channel(image_id, l_aux_channel_id);
gap_image_delete_immediate(dup_image_id);
@@ -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_insert_layer(l_image_id, l_empty_layer_id, 0, 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_layer_copy.c b/gap/gap_layer_copy.c
index 1156b13..383cfb9 100644
--- a/gap/gap_layer_copy.c
+++ b/gap/gap_layer_copy.c
@@ -636,37 +636,40 @@ gap_layer_flip(gint32 layer_id, gint32 flip_request)
gint32 center_y;
gdouble axis;
-
+
switch(flip_request)
{
case GAP_STB_FLIP_HOR:
+ gimp_context_set_defaults();
+ gimp_context_set_transform_resize(GIMP_TRANSFORM_RESIZE_CLIP); /* enable clipping */
axis = (gdouble)(gimp_drawable_width(layer_id)) / 2.0;
- layer_id = gimp_drawable_transform_flip_simple(layer_id
+ layer_id = gimp_item_transform_flip_simple(layer_id
,GIMP_ORIENTATION_HORIZONTAL
,TRUE /* auto_center */
,axis
- ,TRUE /* clip_result */
);
break;
case GAP_STB_FLIP_VER:
+ gimp_context_set_defaults();
+ gimp_context_set_transform_resize(GIMP_TRANSFORM_RESIZE_CLIP); /* enable clipping */
axis = (gdouble)(gimp_drawable_height(layer_id)) / 2.0;
- layer_id = gimp_drawable_transform_flip_simple(layer_id
+ layer_id = gimp_item_transform_flip_simple(layer_id
,GIMP_ORIENTATION_VERTICAL
,TRUE /* auto_center */
,axis
- ,TRUE /* clip_result */
);
break;
case GAP_STB_FLIP_BOTH:
+ gimp_context_set_defaults();
+ gimp_context_set_transform_resize(GIMP_TRANSFORM_RESIZE_CLIP); /* enable clipping */
center_x = gimp_drawable_width(layer_id) / 2;
center_y = gimp_drawable_height(layer_id) / 2;
- layer_id = gimp_drawable_transform_rotate_simple(layer_id
+ layer_id = gimp_item_transform_rotate_simple(layer_id
,GIMP_ROTATE_180
,TRUE /* auto_center */
,center_x
,center_y
- ,TRUE /* clip_result */
);
break;
default:
@@ -831,8 +834,6 @@ gap_layer_create_layer_from_layermask(gint32 src_layer_id
, gint32 image_id
, const char *name_prefix, const char *name_suffix)
{
- gboolean l_has_already_layermask;
- gint32 l_layermask_id;
gint32 l_new_layer_id;
gint32 l_new_layermask_id;
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..0ab1a1f 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
@@ -628,7 +628,7 @@ p_apply_action(gint32 image_id,
break;
case GAP_MOD_ACM_DUPLICATE:
l_new_layer_id = gimp_layer_copy(l_layer_id);
- gimp_image_add_layer (image_id, l_new_layer_id, -1);
+ gimp_image_insert_layer (image_id, l_new_layer_id, 0, -1);
if (!gap_match_string_is_empty (new_layername))
{
gap_match_substitute_framenr(&l_name_buff[0], sizeof(l_name_buff),
@@ -689,7 +689,7 @@ p_apply_action(gint32 image_id,
{
if(strcmp(l_channelname,&l_name_buff[0] ) == 0)
{
- gimp_selection_load(l_channels[l_ii]);
+ gimp_image_select_item(image_id, GIMP_CHANNEL_OP_REPLACE, l_channels[l_ii]);
g_free(l_channelname);
break;
}
@@ -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 600143f..9c8bc3f 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_insert_layer(imageId, dupLayerId, 0, -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 3c99d4a..4518aba 100644
--- a/gap/gap_mov_render.c
+++ b/gap/gap_mov_render.c
@@ -160,7 +160,7 @@ p_mov_selection_handling(gint32 orig_layer_id
,FALSE /* shadow */
);
- gimp_selection_load(val_ptr->tmpsel_channel_id);
+ gimp_image_select_item(val_ptr->tmpsel_image_id, GIMP_CHANNEL_OP_REPLACE, val_ptr->tmpsel_channel_id);
if(cur_ptr->currSelFeatherRadius > 0.001)
@@ -332,7 +332,10 @@ p_mov_transform_perspective(gint32 layer_id
);
}
- gimp_drawable_transform_perspective_default (layer_id,
+
+ gimp_context_set_defaults();
+ gimp_context_set_transform_resize(GIMP_TRANSFORM_RESIZE_ADJUST); /* do NOT clip */
+ gimp_item_transform_perspective(layer_id,
x0,
y0,
x1,
@@ -340,9 +343,7 @@ p_mov_transform_perspective(gint32 layer_id
x2,
y2,
x3,
- y3,
- TRUE, /* whether to use interpolation and supersampling for good quality */
- FALSE /* whether to clip results */
+ y3
);
*resized_flag = 1;
@@ -996,7 +997,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 +1123,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 +1132,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 +1173,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 +1206,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 +1232,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 +1285,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 +1320,33 @@ gap_mov_render_fetch_src_frame(GapMovValues *pvals, gint32 wanted_frame_nr)
}
+ return 0; /* OK */
+} /* end gap_mov_render_fetch_src_frame_autoskip */
+
+
+/* ============================================================================
+ * 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);
- return 0; /* OK */
} /* 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 680e93b..7c25d94 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_pdb_calls.c b/gap/gap_pdb_calls.c
index 0bb3a40..c132a2f 100644
--- a/gap/gap_pdb_calls.c
+++ b/gap/gap_pdb_calls.c
@@ -194,8 +194,9 @@ gap_pdb_procedure_available(char *proc_name)
/* ============================================================================
* gap_pdb_gimp_rotate_degree
- * PDB call of 'gimp_rotate'
* ============================================================================
+ * wrapper to call rotate transformation by degrees.
+ * (the gimp core requires radians)
*/
gint32
@@ -204,14 +205,14 @@ gap_pdb_gimp_rotate_degree(gint32 drawable_id, gboolean interpolation, gdouble a
gdouble l_angle_rad;
l_angle_rad = (angle_deg * G_PI) / 180.0;
+ gimp_context_set_defaults();
+ gimp_context_set_transform_resize(GIMP_TRANSFORM_RESIZE_ADJUST); /* do NOT clip */
- return(gimp_drawable_transform_rotate_default(drawable_id
+ return(gimp_item_transform_rotate(drawable_id
, l_angle_rad
, FALSE /* auto_center */
, 0 /* center_x */
, 0 /* center_y */
- , interpolation
- , FALSE /* clip_results */
));
diff --git a/gap/gap_player_dialog.c b/gap/gap_player_dialog.c
index 4b0f5a6..01acc3f 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 */
/* ------------------------------
@@ -1765,7 +1797,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); }
@@ -1862,7 +1894,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;
-
+
}
}
@@ -2494,7 +2526,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);
@@ -2506,7 +2538,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
@@ -2541,7 +2573,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)
{
@@ -2549,7 +2581,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
@@ -2565,7 +2597,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),
@@ -2842,7 +2874,7 @@ p_open_videofile(GapPlayerMainGlobalParams *gpp
);
}
}
-
+
if(gpp->gvahand->vindex)
{
if(gpp->gvahand->vindex->total_frames > 0)
@@ -2933,7 +2965,7 @@ p_open_videofile(GapPlayerMainGlobalParams *gpp
}
/* printf("PLAYER: open END\n"); */
#endif
-
+
} /* end p_open_videofile */
@@ -2959,7 +2991,7 @@ p_fetch_videoframe(GapPlayerMainGlobalParams *gpp
{
guchar *th_data;
static gint32 funcId = -1;
-
+
GAP_TIMM_GET_FUNCTION_ID(funcId, "playerDialog.p_fetch_videoframe");
@@ -3081,7 +3113,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.
@@ -3145,16 +3177,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 */
/* -----------------------------
@@ -3180,7 +3212,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'))
@@ -3195,7 +3227,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'))
@@ -3211,7 +3243,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'))
@@ -3225,6 +3257,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 */
@@ -3556,7 +3604,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);
@@ -3579,7 +3627,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 */
@@ -3857,10 +3905,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
@@ -3896,7 +3948,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
*/
@@ -3920,7 +3972,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
@@ -3971,7 +4022,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);*/
@@ -4054,7 +4105,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)
{
@@ -4152,7 +4203,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;
@@ -4257,6 +4308,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
@@ -4271,7 +4342,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
@@ -4304,6 +4375,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
* ------------------------------
@@ -4313,7 +4423,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)
@@ -4400,6 +4511,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 */
@@ -4474,6 +4599,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
@@ -4563,7 +4690,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;
@@ -5938,6 +6065,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
* ---------------------------------------------
@@ -5984,7 +6136,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;
@@ -6457,7 +6609,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
@@ -6492,7 +6644,7 @@ on_audio_filename_entry_changed (GtkWidget *widget,
GapPlayerMainGlobalParams *gpp)
{
gboolean has_changed;
-
+
if(gpp == NULL)
{
return;
@@ -6508,7 +6660,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)
@@ -6517,7 +6669,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))
);
@@ -7197,24 +7349,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 */
@@ -7406,7 +7560,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++;
@@ -8839,7 +9010,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 a46cddc..d0a1365 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_file.c b/gap/gap_story_file.c
index d72f89e..3780274 100644
--- a/gap/gap_story_file.c
+++ b/gap/gap_story_file.c
@@ -9955,15 +9955,16 @@ gap_story_transform_rotate_layer(gint32 image_id, gint32 layer_id, gdouble rotat
l_center_x = gimp_drawable_width(layer_id) / 2.0;
l_center_y = gimp_drawable_height(layer_id) / 2.0;
+ gimp_context_set_defaults();
+ gimp_context_set_transform_resize(GIMP_TRANSFORM_RESIZE_ADJUST); /* do NOT clip transformation results
*/
+
/* have to rotate the layer (rotation also changes size as needed) */
- gimp_drawable_transform_rotate_default(layer_id
- , l_angle_rad
- , TRUE /* auto_center */
- , l_center_x
- , l_center_y
- , TRUE /* interpolation */
- , FALSE /* clip_results */
- );
+ gimp_item_transform_rotate(layer_id
+ , l_angle_rad
+ , TRUE /* auto_center */
+ , l_center_x
+ , l_center_y
+ );
} /* end gap_story_transform_rotate_layer */
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 1f69c47..fc0fb2b 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,10 +148,10 @@ 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)'
+ * error 'Device or Ressource is busy' during 'pthread_mutex_destroy ((pthread_mutex_t *) mutex)'
*/
typedef struct StbMutexPool /* mutxp */
{
@@ -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 */
@@ -4945,15 +4946,16 @@ p_transform_rotate_layer_at(gint32 image_id, gint32 layer_id, gdouble rotate
);
}
+ gimp_context_set_defaults();
+ gimp_context_set_transform_resize(GIMP_TRANSFORM_RESIZE_ADJUST); /* do NOT clip transformation results
*/
+
/* perform rotation of the layer (rotation also changes size as needed) */
- gimp_drawable_transform_rotate_default(layer_id
+ gimp_item_transform_rotate(layer_id
, l_angle_rad
, FALSE /* auto_center */
, l_center_x
, l_center_y
- , TRUE /* interpolation */
- , FALSE /* clip_results */
);
@@ -4978,7 +4980,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 +5009,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 +5029,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 +5071,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 +5101,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 +5117,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 +5142,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 +5198,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 +5217,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 +5232,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 +5245,7 @@ p_transform_with_movepath_processing( gint32 comp_image_id
gimp_image_insert_layer(comp_image_id, l_new_layer_id, 0, 0);
gimp_layer_set_offsets(l_new_layer_id, 0, 0);
}
-
+
//p_debug_dup_image(l_tmp_movpath_image_id);
@@ -5253,7 +5255,7 @@ p_transform_with_movepath_processing( gint32 comp_image_id
}
return(l_new_layer_id);
-
+
} /* end p_transform_with_movepath_processing */
@@ -5262,7 +5264,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 +5272,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 +5289,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 +5347,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 +5359,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 +5367,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 +5381,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 +5395,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 +5419,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 +5450,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 +5702,7 @@ p_transform_and_add_layer( gint32 comp_image_id
, vidhand
, calculated->opacity
, local_stepcount
+ , l_layermode
);
@@ -5717,7 +5737,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 +5763,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_insert_layer(l_image_id, l_empty_layer_id, 0, 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 +5874,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 +5891,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 +5919,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 +5957,7 @@ p_calculateGvahandHolderRank(GapStoryRenderFrameRangeElem *frn_elem
return(GVAHAND_HOLDER_RANK_3);
}
return(GVAHAND_HOLDER_RANK_2);
-
+
}
if (gvahand->current_seek_nr <= videoFrameNrToBeReadNext)
@@ -6028,7 +6013,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 +6042,7 @@ p_try_to_steal_gvahand(GapStoryRenderVidHandle *vidhand
break;
}
}
-
+
}
}
}
@@ -6072,7 +6057,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 +6102,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 +6309,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 +6343,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 +6395,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 +6424,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 +6468,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 +6626,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 +6647,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 +6687,7 @@ p_is_larger_image_variant_expected(GapStbFetchData *gfdCurrent
foundLargerVariant = TRUE;
}
-
+
}
}
@@ -6772,7 +6757,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 +6779,7 @@ p_prescale_image_size_handling(GapStbFetchData *gfdCurrent
, gfd->move_x
, gfd->move_y
);
-
+
currentPrescaleWidth = calculated->width;
currentPrescaleHeight = calculated->height;
maxPrescaleWidth = currentPrescaleWidth;
@@ -6832,7 +6817,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 +6825,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 +6888,7 @@ p_prescale_image_size_handling(GapStbFetchData *gfdCurrent
);
}
}
-
+
return (l_fetched_image_id);
}
}
@@ -6911,16 +6896,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 +6917,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 +6936,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 +6970,7 @@ p_prescale_image_size_handling(GapStbFetchData *gfdCurrent
{
foundSmallerVariant = TRUE;
}
-
+
if (calculated->width > originalWidth)
{
foundTooLargeVariant = TRUE;
@@ -6999,7 +6984,7 @@ p_prescale_image_size_handling(GapStbFetchData *gfdCurrent
}
}
-
+
}
}
@@ -7014,7 +6999,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 +7007,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 +7073,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 +7125,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 +7176,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 +7209,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 +7229,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 +7263,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 +7289,7 @@ p_check_and_open_video_handle(GapStoryRenderFrameRangeElem *frn_elem
}
}
}
-#endif
+#endif
} /* end p_check_and_open_video_handle */
@@ -7316,14 +7301,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 +7320,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 +7338,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 +7346,7 @@ p_initOptionalMulitprocessorSupport(GapStoryRenderVidHandle *vidhand)
/* check and init thread system */
vidhand->isMultithreadEnabled = gap_base_thread_init();
}
-
+
if (vidhand->isMultithreadEnabled)
{
p_get_PrefetchThreadPool();
@@ -7381,7 +7366,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 +7387,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 +7412,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 +7446,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 +7487,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 +7509,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 +7567,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 +7618,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 +7627,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 +7641,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 +7681,7 @@ p_stb_render_movie_single_processor(GapStbFetchData *gfd
);
}
}
-
+
if (fcacheFetchResult.isFrameAvailable == TRUE)
{
p_get_gapStoryFetchResult_from_fcacheFetchResult(gfd, &fcacheFetchResult);
@@ -7706,7 +7691,7 @@ p_stb_render_movie_single_processor(GapStbFetchData *gfd
gfd->tmp_image_id = -1;
}
}
-
+
GAP_TIMM_STOP_FUNCTION(funcId);
@@ -7735,7 +7720,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 +7735,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 +7765,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 +7774,7 @@ p_videoPrefetchWorkerThreadFunction (VideoPrefetchData *vpre)
,(int)vpre->targetFrameNumber
);
}
-
+
GVA_fcache_mutex_lock (vpre->gvahand);
prefetchFrameNumber = vpre->prefetchFrameNumber;
@@ -7803,7 +7788,7 @@ p_videoPrefetchWorkerThreadFunction (VideoPrefetchData *vpre)
{
isPlayingBackwards = FALSE;
}
-
+
GVA_fcache_mutex_unlock (vpre->gvahand);
if(targetFrameNumber >= 0)
@@ -7840,7 +7825,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 +7834,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 +7870,7 @@ p_videoPrefetchWorkerThreadFunction (VideoPrefetchData *vpre)
}
}
}
-
+
GVA_fcache_mutex_lock (vpre->gvahand);
vpre->isPrefetchThreadRunning = FALSE;
@@ -7923,8 +7908,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 +7928,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 +7956,7 @@ p_getPredictedNextFramenr(gint32 targetFrameNr, GapStoryRenderFrameRangeElem *fr
}
return (predictedFrameNr);
-
+
} /* end p_getPredictedNextFramenr */
#endif
@@ -7983,7 +7968,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 +7992,7 @@ p_stb_render_movie_multiprocessor(GapStbFetchData *gfd
gint32 predictedNextFrameNr;
gint32 targetFrameNumber;
gint32 numProcessors;
-
+
GVA_fcache_fetch_result fcacheFetchResult;
GError *error;
@@ -8022,17 +8007,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 +8045,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 +8071,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 +8127,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 +8142,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 +8151,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 +8164,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 +8183,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 +8226,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 +8334,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 +8362,7 @@ p_check_next_composite_frame_includes_same_image(GapStbFetchData *gfdCurrent
g_free(gfd->framename);
}
}
-
+
return (nextCompositeFrameIncludesSameImage);
}
@@ -8404,7 +8389,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 +8400,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 +8441,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 +8463,8 @@ p_stb_render_frame_images(GapStbFetchData *gfd, GapStoryRenderVidHandle *vidhand
fetchedImageUsable = TRUE;
}
}
-
-
+
+
if(fetchedImageUsable == TRUE)
{
if(gap_debug)
@@ -8499,7 +8491,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 +8516,7 @@ p_stb_render_frame_images(GapStbFetchData *gfd, GapStoryRenderVidHandle *vidhand
} /* end p_stb_render_frame_images */
-
+
/* -------------------------------------------
* p_stb_render_composite_image_postprocessing
@@ -8554,7 +8546,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 +8800,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 +8822,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 +8905,7 @@ p_prepare_GRAY_image(gint32 image_id)
}
return(l_layer_id);
-
+
} /* end p_prepare_GRAY_image */
@@ -8975,11 +8967,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 +9065,7 @@ p_do_insert_alpha_processing(GapStbFetchData *gfd
} /* end p_do_insert_alpha_processing */
/* --------------------------------------------
- * p_isFiltermacroActive
+ * p_isFiltermacroActive
* --------------------------------------------
*/
static gboolean
@@ -9083,11 +9075,11 @@ p_isFiltermacroActive(const char *filtermacro_file)
{
if(*filtermacro_file != '\0')
{
- return(TRUE);
+ return(TRUE);
}
}
- return(FALSE);
-
+ return(FALSE);
+
} /* end p_isFiltermacroActive */
@@ -9097,7 +9089,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 +9114,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 +9152,7 @@ p_story_render_bypass_where_possible(GapStoryRenderVidHandle *vidhand
);
}
-
+
if(gfd->framename)
{
if(gfd->frn_type == GAP_FRN_MOVIE)
@@ -9184,9 +9176,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 +9203,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 +9227,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 +9286,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 +9337,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 +9347,7 @@ p_story_render_fetch_composite_image_private(GapStoryRenderVidHandle *vidhand
gfd = &gapStbFetchData;
p_init_gfd(gfd);
-
+
*layer_id = -1;
@@ -9402,15 +9394,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 +9436,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 +9548,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 +9563,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;
+}
diff --git a/gap/gap_wr_resynth.c b/gap/gap_wr_resynth.c
index 9b35233..7770b31 100644
--- a/gap/gap_wr_resynth.c
+++ b/gap/gap_wr_resynth.c
@@ -658,7 +658,7 @@ p_create_corpus_layer(gint32 image_id, gint32 drawable_id, TransValues *val_ptr)
gimp_context_get_background(&bck_color);
channel_2_id = gimp_selection_save(dup_image_id);
- gimp_selection_load(channel_id);
+ gimp_image_select_item(dup_image_id, GIMP_CHANNEL_OP_REPLACE, channel_id);
gimp_rgba_set_uchar (&white_opaque_color, 255, 255, 255, 255);
gimp_context_set_background(&white_opaque_color);
diff --git a/gap/gap_wr_trans.c b/gap/gap_wr_trans.c
index 8ed993b..f21d5f8 100644
--- a/gap/gap_wr_trans.c
+++ b/gap/gap_wr_trans.c
@@ -477,7 +477,6 @@ static gint32
p_transform_layer(gint32 image_id, gint32 drawable_id, GapTransLayerMode trans_mode, TransValues *val_ptr)
{
gboolean auto_center;
- gboolean clip_result;
gdouble axis;
gboolean has_selection;
gboolean non_empty;
@@ -502,75 +501,68 @@ p_transform_layer(gint32 image_id, gint32 drawable_id, GapTransLayerMode trans_m
trans_drawable_id = -1;
auto_center = TRUE;
- clip_result = TRUE;
+ gimp_context_set_defaults();
/* here the action starts, we transform the drawable */
switch(trans_mode)
{
case GAP_TRANS_FLIP_HOR:
- clip_result = TRUE;
+ gimp_context_set_transform_resize(GIMP_TRANSFORM_RESIZE_CLIP); /* enable clipping */
axis = (gdouble)(gimp_drawable_width(drawable_id)) / 2.0;
- trans_drawable_id = gimp_drawable_transform_flip_simple(drawable_id
+ trans_drawable_id = gimp_item_transform_flip_simple(drawable_id
,GIMP_ORIENTATION_HORIZONTAL
,auto_center
,axis
- ,clip_result
);
break;
case GAP_TRANS_FLIP_VER:
- clip_result = TRUE;
+ gimp_context_set_transform_resize(GIMP_TRANSFORM_RESIZE_CLIP); /* enable clipping */
axis = (gdouble)(gimp_drawable_height(drawable_id)) / 2.0;
- trans_drawable_id = gimp_drawable_transform_flip_simple(drawable_id
+ trans_drawable_id = gimp_item_transform_flip_simple(drawable_id
,GIMP_ORIENTATION_VERTICAL
,auto_center
,axis
- ,clip_result
);
break;
case GAP_TRANS_ROT_90:
- clip_result = FALSE;
- trans_drawable_id = gimp_drawable_transform_rotate_simple(drawable_id
+ gimp_context_set_transform_resize(GIMP_TRANSFORM_RESIZE_ADJUST); /* do NOT clip */
+ trans_drawable_id = gimp_item_transform_rotate_simple(drawable_id
,GIMP_ROTATE_90
,auto_center
,center_x
,center_y
- ,clip_result
);
break;
case GAP_TRANS_ROT_180:
- clip_result = FALSE;
- trans_drawable_id = gimp_drawable_transform_rotate_simple(drawable_id
+ gimp_context_set_transform_resize(GIMP_TRANSFORM_RESIZE_ADJUST); /* do NOT clip */
+ trans_drawable_id = gimp_item_transform_rotate_simple(drawable_id
,GIMP_ROTATE_180
,auto_center
,center_x
,center_y
- ,clip_result
);
break;
case GAP_TRANS_ROT_270:
- clip_result = FALSE;
- trans_drawable_id = gimp_drawable_transform_rotate_simple(drawable_id
+ gimp_context_set_transform_resize(GIMP_TRANSFORM_RESIZE_ADJUST); /* do NOT clip */
+ trans_drawable_id = gimp_item_transform_rotate_simple(drawable_id
,GIMP_ROTATE_270
,auto_center
,center_x
,center_y
- ,clip_result
);
break;
case GAP_TRANS_ROT_ANY:
{
gdouble l_angle_rad;
- clip_result = FALSE;
l_angle_rad = (val_ptr->angle_deg * G_PI) / 180.0;
+ gimp_context_set_transform_resize(GIMP_TRANSFORM_RESIZE_ADJUST); /* do NOT clip */
- trans_drawable_id = gimp_drawable_transform_rotate_default(drawable_id
+ trans_drawable_id = gimp_item_transform_rotate(drawable_id
, l_angle_rad
, FALSE /* auto_center */
, center_x
, center_y
- , TRUE /* interpolation (TRUE use default
interpolation) */
- , clip_result
);
@@ -597,7 +589,8 @@ p_transform_layer(gint32 image_id, gint32 drawable_id, GapTransLayerMode trans_m
gimp_floating_sel_anchor (gimp_image_get_floating_sel (image_id));
- gimp_selection_load(sav_selection_id);
+ // gimp_selection_load(sav_selection_id); // OLD
+ gimp_image_select_item(image_id, GIMP_CHANNEL_OP_REPLACE, sav_selection_id); // NEW
gimp_image_remove_channel(image_id, sav_selection_id);
//gimp_drawable_delete(sav_selection_id);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]