[gimp-gap] added foreground extract, ffmpeg based encoder presets and build fixes
- From: Wolfgang Hofer <wolfgangh src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp-gap] added foreground extract, ffmpeg based encoder presets and build fixes
- Date: Sat, 12 Nov 2011 09:25:54 +0000 (UTC)
commit 1fb668abd5d0cc142df3a44f3454d7c93c8833db
Author: Wolfgang Hofer <wolfgangh svn gnome org>
Date: Sat Nov 12 10:23:32 2011 +0100
added foreground extract, ffmpeg based encoder presets and build fixes
ChangeLog | 86 ++
NEWS | 12 +-
docs/reference/txt/INTRODUCTION.txt | 6 +-
docs/reference/txt/Makefile.am | 1 +
docs/reference/txt/gap_gimprc_params.txt | 7 +
.../txt/plug-in-foreground-extract-matting.txt | 104 ++
extern_libs/configure_options_ffmpeg.txt | 2 +-
extern_libs/configure_options_ffmpeg_win32.txt | 2 +-
gap/Makefile.am | 16 +
gap/gap_fg_matting.c | 1546 ++++++++++++++++++++
gap/gap_fg_matting.h | 81 +
gap/gap_fg_matting_dialog.c | 636 ++++++++
gap/gap_fg_matting_dialog.h | 41 +
gap/gap_fg_matting_exec.c | 572 ++++++++
gap/gap_fg_matting_exec.h | 46 +
gap/gap_fg_matting_main.c | 312 ++++
gap/gap_fg_matting_main.h | 61 +
gap/gap_fg_regions.c | 472 ++++++
gap/gap_fg_regions.h | 50 +
gap/gap_fg_tile_manager.h | 334 +++++
gap/gap_layer_copy.c | 86 +-
gap/gap_lib.c | 190 ++-
gap/gap_lib.h | 13 +-
po/POTFILES.in | 5 +
vid_common/gap_cme_callbacks.c | 34 +-
vid_common/gap_cme_gui.c | 9 +-
vid_common/gap_cme_main.h | 7 +-
vid_enc_ffmpeg/Makefile.am | 19 +-
vid_enc_ffmpeg/ff_divx_hq.preset | 191 +++
vid_enc_ffmpeg/ff_divx_low.preset | 191 +++
vid_enc_ffmpeg/ff_divx_standard.preset | 191 +++
vid_enc_ffmpeg/ff_divx_win.preset | 191 +++
vid_enc_ffmpeg/ff_mpeg1_hq.preset | 191 +++
vid_enc_ffmpeg/ff_mpeg1_vcd.preset | 195 +++
vid_enc_ffmpeg/ff_mpeg2_dvd.preset | 195 +++
vid_enc_ffmpeg/ff_mpeg2_svcd.preset | 195 +++
vid_enc_ffmpeg/ff_real_standard.preset | 191 +++
vid_enc_ffmpeg/ff_x264_hq.preset | 191 +++
vid_enc_ffmpeg/gap_enc_ffmpeg_callbacks.c | 133 ++-
vid_enc_ffmpeg/gap_enc_ffmpeg_callbacks.h | 2 +
vid_enc_ffmpeg/gap_enc_ffmpeg_gui.c | 286 +++--
vid_enc_ffmpeg/gap_enc_ffmpeg_main.c | 173 ++-
vid_enc_ffmpeg/gap_enc_ffmpeg_main.h | 34 +-
vid_enc_ffmpeg/gap_enc_ffmpeg_par.c | 318 ++++-
44 files changed, 7316 insertions(+), 302 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 0e0f677..ada53e4 100755
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,89 @@
+2011-11-12 Wolfgang Hofer <hof gimp org>
+
+- added implementation of the foreground extraction via alpha matting algorithm
+ as plug-in.
+ The code is a modificated copy of the implementation as
+ GIMP-tool originally done by Jan Ruegg.
+ (you can find the original at the un-official GIT repository:
+ https://github.com/rggjan/Gimp-Matting
+ IMPORTANT: be sure to check out the "new_layer" branch...)
+
+ The quality of the alpha matting results are more promising than the
+ offical GIMP foreground extraction ( based on the SIOX algorthm)
+ and may be a base for future GAP features to add
+ transparency for video frames.
+
+- using --disable-vaapi option to configure ffmpeg
+ to avoid linking problems on platforms where libva
+ based video acceleration is installd.
+ (thanks to AndrzejL PCLinuxOS gmx com for pointig out
+ this kind of problems on the PCLinuxOS platform)
+ Note that gimp-gap and the FFmpeg project, does not support VA-API,
+ but libavcodec (also part of the FFmpeg project) does contain code
+ that other applications use to support hardware accelerated decoding, including VA API."
+
+- added HD video sizes entries to the combo box
+ in the master video encoder dialog.
+
+- ffmpeg encoder parameter dialog hides the complex settings by default
+ and shows only the presets, aspect and comment that is sufficient for
+ the most users.
+
+- keep title,author,copyright an comment when load / select another preset.
+
+- added video encoder preset for HD video encoding with the x264 codec.
+ the ffmpeg based encoder now checks for preset in the systemwide gimp_data_diretory
+ and the user specific gimp_directory
+
+- disabled all hardcoded presets and installed same presets as preset file.
+
+
+ NOTE: presets that refere to invalid codecs are no longer shown in the dialog.
+ e.g. the new HD x264 preset is not shown in case GIMP-GAP is compiled without
+ libx64 support for the ffmpeg encode engine.
+
+ * NEWS
+ * po/POTFILES.in
+
+ * gap/Makefile.am
+ * gap/gap_fg_matting_main.c [.h] # new files
+ * gap/gap_fg_matting_exec.c [.h] # new files
+ * gap/gap_fg_matting.c [.h] # new files
+ * gap/gap_fg_matting_dialog.c [.h] # new files
+ * gap/gap_fg_regions.c [.h] # new files
+ * gap/gap_fg_tile_manager.h # new file
+
+ * vid_enc_ffmpeg/Makefile.am
+ * vid_enc_ffmpeg/gap_enc_ffmpeg_main.c [.h]
+ * vid_enc_ffmpeg/gap_enc_ffmpeg_par.c
+ * vid_enc_ffmpeg/gap_enc_ffmpeg_gui.c
+ * vid_enc_ffmpeg/gap_enc_ffmpeg_callbacks.c [.h]
+ * vid_enc_ffmpeg/ff_divx_hq.preset # new file
+ * vid_enc_ffmpeg/ff_divx_low.preset # new file
+ * vid_enc_ffmpeg/ff_divx_standard.preset # new file
+ * vid_enc_ffmpeg/ff_divx_win.preset # new file
+ * vid_enc_ffmpeg/ff_mpeg1_hq.preset # new file
+ * vid_enc_ffmpeg/ff_mpeg1_vcd.preset # new file
+ * vid_enc_ffmpeg/ff_mpeg2_dvd.preset # new file
+ * vid_enc_ffmpeg/ff_mpeg2_svcd.preset # new file
+ * vid_enc_ffmpeg/ff_real_standard.preset # new file
+ * vid_enc_ffmpeg/ff_x264_hq.preset # new file
+ * vid_common/gap_cme_main.h
+ * vid_common/gap_cme_gui.c
+ * vid_common/gap_cme_callbacks.c
+ * extern_libs/configure_options_ffmpeg_win32.txt
+ * extern_libs/configure_options_ffmpeg.txt
+
+
+ * gap/gap_lib.c [.h]
+ * gap/gap_layer_copy.c
+ * docs/reference/txt/Makefile.am
+ * docs/reference/txt/INTRODUCTION.txt
+ * docs/reference/txt/gap_gimprc_params.txt
+ * docs/reference/txt/plug-in-foreground-extract-matting.txt #new file
+
+
+
2011-10-12 Wolfgang Hofer <hof gimp org>
diff --git a/NEWS b/NEWS
index fe02224..ca7dfb3 100644
--- a/NEWS
+++ b/NEWS
@@ -9,12 +9,18 @@ Here is a short overview whats new in GIMP-GAP-2.7.0:
- New colormask plug-in added
The colormask filter can apply transparency for pixels matching the colormask image.
intended for processing frames where moving objects can be isolated
- from the non-moving constant background by aplying the constant background
+ from the non-moving constant background by applying the constant background
as colormask on all frames.
the colormask feature is also available as new mask anchor mode
when processing stroyboard clips.
(anchor modes are: ClipColormask, Clip, Master)
+ - Foreground Extraction based on the alpha matting algorithm.
+ This plug-in uses a tri-map provided by the user
+ where pixels are marked as FORGROUND, BACKGROUND or UNDEFINED
+ and renders transpareny and color for all UNDEFINED pixels.
+
+
- support to run gimp_color_balance tool as animated filter
(added wrapper plug-in).
@@ -23,6 +29,7 @@ Here is a short overview whats new in GIMP-GAP-2.7.0:
in a "process one frame per call" style, intended to be called as filter
with the modify frames feature.
+
- GIMP-GAP now supports speed control of movements and other transitions
via Acceleration characteristic presets. Those presets are available
- in the MovePath tool
@@ -71,6 +78,9 @@ Here is a short overview whats new in GIMP-GAP-2.7.0:
.. see ChangeLog for details,
+- added preset for HD video encoding with H264 codec.
+ (GIMP-GAP must be built with libx264 to use that preset)
+
- better performance for ffmpeg based video encoder
on single and multiprocessor machines.
diff --git a/docs/reference/txt/INTRODUCTION.txt b/docs/reference/txt/INTRODUCTION.txt
index 8195f41..2099e04 100644
--- a/docs/reference/txt/INTRODUCTION.txt
+++ b/docs/reference/txt/INTRODUCTION.txt
@@ -1,4 +1,4 @@
-Project gap "GIMP Animation Package" 08. Dec. 2004 (pre)release 2.1.0
+Project gap "GIMP Animation Package" 10. Oct. 2011 (pre)release 2.6.1
--------------------------------------------------------------------
Introduction
@@ -77,7 +77,7 @@ Input from videofile:
- mplayer
- xanim
those players are capable to extract frames from
- common videofiel formats (avi, mpeg, quicktime, ....) .
+ common videofile formats (avi, mpeg, quicktime, ....) .
Please note that xanim is old unmaintained software.
The frontend for xanim is still there and may even work if
you still have xanim exporting edition.
@@ -321,7 +321,7 @@ Internal PDB names and menu names of GIMP-GAP plug-ins
plug_in_gap_videoframes_player "<Image>/Video/Playback"
plug-in-layer-set-alpha-by-colormask "<Image>/Video/Layer/Attributes/"
-
+ plug-in-foreground-extract-matting "<Image>/Video/Layer/Attributes/"
plug-in-gap-vid-encode-master "<Image>/Video/Encode/Master Videoencoder"
plug_in_gap_mpeg2encode "<Image>/Video/Encode/MPEG2 (mpeg2encode)"
diff --git a/docs/reference/txt/Makefile.am b/docs/reference/txt/Makefile.am
index 553987a..5bcf983 100644
--- a/docs/reference/txt/Makefile.am
+++ b/docs/reference/txt/Makefile.am
@@ -9,6 +9,7 @@ EXTRA_DIST = \
plug-in-plug-in-colormask.txt.txt \
plug-in-filter-macro.txt \
plug-in-firepattern.txt \
+ plug-in-foreground-extract-matting.txt \
plug-in-gap-anim-crop.txt \
plug-in-gap-anim-resize.txt \
plug-in-gap-anim-scale.txt \
diff --git a/docs/reference/txt/gap_gimprc_params.txt b/docs/reference/txt/gap_gimprc_params.txt
index 5fb6b2a..5eaebb4 100644
--- a/docs/reference/txt/gap_gimprc_params.txt
+++ b/docs/reference/txt/gap_gimprc_params.txt
@@ -231,6 +231,13 @@ If you edit gimprc files by hand, you must do this before you startup GIMP.
# in case num-processors is configured with value 1 the default is "no" (otherwise "yes")
(video-enoder-ffmpeg-multiprocessor-enable "no")
+
+# the boolean parameter video-enoder-ffmpeg-show-expert-settings
+# defines the initial mode of the FFMPEG based videoencoder Parameter dialog window.
+# where value "no" hides all notebook tabs with details video encoder
+# parameters. In this mode the user can set the parameters
+# by selecting one of the preset names via a combo box.
+(video-enoder-ffmpeg-show-expert-settings "no")
diff --git a/docs/reference/txt/plug-in-foreground-extract-matting.txt b/docs/reference/txt/plug-in-foreground-extract-matting.txt
new file mode 100644
index 0000000..60db8f2
--- /dev/null
+++ b/docs/reference/txt/plug-in-foreground-extract-matting.txt
@@ -0,0 +1,104 @@
+"plug-in-foreground-extract-matting"
+
+Foreground Extract Filter
+
+ Start from Menu:
+ <Image>/Layer/Transparency/Foreground Extract
+ ## <Image>/Video/Layer/Attributes/Foreground Extract ##
+
+How to use:
+
+ Have a image with a forground object loaded in GIMP
+ (for instance a person) that shall be
+ separated from the background.
+ The image shall be of RGB color
+
+ Add a layermask to the layer that shall be processed
+ and fill the layermask whith a medium Gray color
+ now the complete layer looks semi-transparent.
+
+ Paint on the layermask with WHITE color to mark foreground areas.
+ the painted areas appear fully opaque.
+
+ Paint on the layermask with BLACK color to mark backround areas.
+ the painted areas disappear, e.g get fully transparent.
+
+ Take care that you DO NOT mark background areas as foreground
+ and vice versa. (e.g. your brush strokes
+ shall not overlap the borders of the forground object.
+
+ When finished with that (rough) selection call the
+ Foreground Extract Filter
+ select "Layermask" in the TRI.MAP combo box
+
+ use unchecked state for the checkbuttons
+ Create Layermask and Lock Colors
+
+ This will create a new layer as copy of your input layer
+ with calculated transparency for the UNDEFINED areas.
+ This copy is placed above your input layer.
+
+ Set your original layer invisible
+ to check the result.
+ (click the Eye-Icon in the GIMP Layers dialog
+ to toggle visibility)
+
+
+
+ Note that the quality of the result depends on the provided TRI-MAP.
+ In many cases you can improve the results by tuning the TRI-MAP
+ on those areas where the filter algorithm did not deliver acceptable results
+ and run the filter again.
+
+ For good results approximately 70% of the area shall be marked
+ as either FORGROUND or BACKGROUND. Further note that processing time
+ depends on the size of the UNDEFINED areas.
+
+
+Options:
+
+ Create Layermask
+ ON: Render opacity by creating a new layer mask for the resulting layer
+ OFF: Apply rendered opacity to the alpha channel
+
+ Lock Colors
+ ON: Keep RGB channels of the input layer
+ OFF: Allow Background color removal in processed undefined regions
+
+
+How it Works:
+
+ The foreground extract filter calculates opacity and color based on a TRI-MAP.
+ The TRI-MAP is a special kind of user selection where the user marks areas as FOREGROUND (white)
+ BACKGROUND (black) and UNDEFINED (gray). The filter can calculate opacity and modify color for the
+ UNDEFINED areas in the corresponding layer.
+ Typically a layermask will be used as TRI-MAP.
+ Optionally you may select another layer (with same size) as TRI-MAP input.
+ Note that RGB TR-MAP input is implicite converted to GRAYSCALE representation
+ where values >= 240 are considered as FOREGROUND, value 0 marks BACKGROUND and all other
+ values are considered as UNDEFINED.
+
+ In case the processed layer already has an alpha channel, fully transparent
+ areas are also marked as BACKGROUND. (e.g. fully transparent pixels keep their transparency
+ and overrule the value in the corresponding TRI-MAP pixel
+ (even if the TRI-MAP marks those pixels as foreground)
+
+
+ The foreground extraction is based on the alpha matting algorithm.
+ (http://www.alphamatting.com/eval_25.php)
+
+
+
+ Whats the difference to the foreground extraction tool?
+ The old algorithm, implemented after an older paper (http://www.siox.org/),
+ has the main problem that it generates only a binary alpha matte.
+ The problems with that is that you can have severe "color bleeding" of the background color
+ into the foreground at borders. For example, fine black hair on a green background gets darkish green.
+ Also, you don't have any transparancy or antialiasing at borders, each pixel is either foreground or background.
+
+ The new algorithm, on the other hand, tries to find out the foreground AND the background color of each pixel,
+ and with that, it can calculate a semitransparent alpha value.
+ This also means that the background color can be removed from the final extracted pixel,
+ what gives, in general, much better results.
+
+
diff --git a/extern_libs/configure_options_ffmpeg.txt b/extern_libs/configure_options_ffmpeg.txt
index adccdde..6fa8162 100644
--- a/extern_libs/configure_options_ffmpeg.txt
+++ b/extern_libs/configure_options_ffmpeg.txt
@@ -1,4 +1,4 @@
---disable-shared --enable-static --enable-gpl --enable-mmx --enable-mmx2
+--disable-shared --enable-static --enable-gpl --enable-mmx --enable-mmx2 --disable-vaapi
#
# This file provides configuration options for ffmpeg
# and is included while GIMP-GAP configure script runs the ffmpeg configuration.
diff --git a/extern_libs/configure_options_ffmpeg_win32.txt b/extern_libs/configure_options_ffmpeg_win32.txt
index e2b137c..1287434 100644
--- a/extern_libs/configure_options_ffmpeg_win32.txt
+++ b/extern_libs/configure_options_ffmpeg_win32.txt
@@ -1,4 +1,4 @@
---disable-shared --enable-static --enable-gpl --enable-mmx --enable-mmx2 --disable-devices --disable-pthreads --disable-altivec --disable-sse --disable-neon
+--disable-shared --enable-static --enable-gpl --enable-mmx --enable-mmx2 --disable-vaapi --disable-devices --disable-pthreads --disable-altivec --disable-sse --disable-neon
#
# This file provides configuration options for ffmpeg
# and is included while GIMP-GAP configure scriptruns the ffmpeg configuration on Windows environment.
diff --git a/gap/Makefile.am b/gap/Makefile.am
index 0ff839b..eb4d2be 100644
--- a/gap/Makefile.am
+++ b/gap/Makefile.am
@@ -137,6 +137,7 @@ libexec_PROGRAMS = \
gap_storyboard \
$(GAP_VIDEO_EXTRACT) \
$(GAP_VIDEO_INDEX) \
+ gap_fg_matting \
gap_fire_pattern \
gap_water_pattern \
gap_wr_color_curve \
@@ -386,6 +387,20 @@ gap_video_index_SOURCES = \
gap_libgapstory.h \
gap_libgimpgap.h
+gap_fg_matting_SOURCES = \
+ gap_fg_matting_main.c \
+ gap_fg_matting_main.h \
+ gap_fg_matting_exec.c \
+ gap_fg_matting_exec.h \
+ gap_fg_matting.c \
+ gap_fg_matting.h \
+ gap_fg_matting_dialog.c \
+ gap_fg_matting_dialog.h \
+ gap_fg_regions.c \
+ gap_fg_regions.h \
+ gap_fg_tile_manager.h
+
+
gap_fire_pattern_SOURCES = \
gap_lastvaldesc.c \
gap_lastvaldesc.h \
@@ -472,6 +487,7 @@ gap_onion_LDADD = $(LIBGIMPGAP) $(LIBGAPBASE) $(GIMP_LIBS)
gap_storyboard_LDADD = $(GAPVIDEOAPI) $(WAVPLAYCLIENT) ${LIBGAPSTORY} $(LIBGAPBASE) $(GIMP_LIBS)
gap_video_extract_LDADD = $(GAPVIDEOAPI) $(WAVPLAYCLIENT) ${LIBGAPSTORY} $(LIBGAPBASE) $(GIMP_LIBS)
gap_video_index_LDADD = $(GAPVIDEOAPI) $(LIBGAPSTORY) $(LIBGAPBASE) $(GIMP_LIBS)
+gap_fg_matting_LDADD = $(LIBGIMPGAP) $(LIBGAPBASE) $(GIMP_LIBS) -lm
gap_fire_pattern_LDADD = $(LIBGIMPGAP) $(LIBGAPBASE) $(GIMP_LIBS)
gap_water_pattern_LDADD = $(LIBGIMPGAP) $(LIBGAPBASE) $(GIMP_LIBS)
gap_wr_opacity_LDADD = $(LIBGIMPGAP) $(LIBGAPBASE) $(GIMP_LIBS)
diff --git a/gap/gap_fg_matting.c b/gap/gap_fg_matting.c
new file mode 100644
index 0000000..b0c1c65
--- /dev/null
+++ b/gap/gap_fg_matting.c
@@ -0,0 +1,1546 @@
+/* gap_fg_matting.h
+ * This module is a modified copy of the alpha matting
+ * forground extraction.
+ * The modifications allow the code to run as plug-in
+ * usable with official GIMP-releases (2.6.x and later)
+ * The original implemantation was done
+ * by Jan Ruegg as gimp core tool in the unofficial repository
+ * https://github.com/rggjan/Gimp-Matting in the "new_layer" branch.
+ *
+ * modifications:
+ * - use emulation of tiles and tile manager calls (prefixed names with gapp_)
+ * - allow input layer that already has an alpha channel (allow bpp 3 or 4 not just 3)
+ *
+ *
+ */
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * Matting
+ * Copyright (C) 2011 Jan Ruegg <rggjan gmail com>
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <glib-object.h>
+#include <glib-2.0/glib/gprintf.h>
+
+#include "libgimpmath/gimpmath.h"
+
+//////////#include "core/core-types.h"
+//////////#include "pixel-region.h"
+
+#include "gap_fg_tile_manager.h"
+#include "gap_fg_matting.h"
+
+//#define IMAGE_DEBUG_PPM
+
+// Stop after certain phase
+#define DEBUG_PHASE 4
+
+
+#define CAN_USE_ORIGINAL_COLORS
+//#define HIGH_WEIGHT_FG_BG
+
+#ifdef IMAGE_DEBUG_PPM
+#include "stdio.h"
+#include "stdlib.h"
+#endif
+
+// TODO move slider before painting doesn't work!
+
+#define LAMBDA (10)
+#define SEARCH_RADIUS (10)
+#define MATTING_SQUARED_COLOR_DISTANCE (25)
+
+// fspecial('gaussian', 13, sqrt((100/(9*pi))))
+const gfloat gauss[13][13] =
+{
+ {1.7101814497842592e-06, 8.0985727252839541e-06, 2.8905528202266243e-05, 7.7760574635269639e-05, 1.5766821136856327e-04, 2.4095444850519678e-04, 2.7754402650812860e-04, 2.4095444850519678e-04, 1.5766821136856327e-04, 7.7760574635269639e-05, 2.8905528202266243e-05, 8.0985727252839541e-06, 1.7101814497842592e-06},
+ {8.0985727252839541e-06, 3.8350831249506833e-05, 1.3688227195911312e-04, 3.6823558630170203e-04, 7.4663859580211824e-04, 1.1410409842453801e-03, 1.3143111120915069e-03, 1.1410409842453801e-03, 7.4663859580211824e-04, 3.6823558630170203e-04, 1.3688227195911312e-04, 3.8350831249506833e-05, 8.0985727252839541e-06},
+ {2.8905528202266243e-05, 1.3688227195911312e-04, 4.8856193637079371e-04, 1.3143111120915069e-03, 2.6649119196619805e-03, 4.0726179129162605e-03, 4.6910558447545393e-03, 4.0726179129162605e-03, 2.6649119196619805e-03, 1.3143111120915069e-03, 4.8856193637079371e-04, 1.3688227195911312e-04, 2.8905528202266243e-05},
+ {7.7760574635269639e-05, 3.6823558630170203e-04, 1.3143111120915069e-03, 3.5357107682171015e-03, 7.1690467226628403e-03, 1.0956004919274648e-02, 1.2619703593780167e-02, 1.0956004919274648e-02, 7.1690467226628403e-03, 3.5357107682171015e-03, 1.3143111120915069e-03, 3.6823558630170203e-04, 7.7760574635269639e-05},
+ {1.5766821136856327e-04, 7.4663859580211824e-04, 2.6649119196619805e-03, 7.1690467226628403e-03, 1.4536039365470805e-02, 2.2214518185719723e-02, 2.5587852237016186e-02, 2.2214518185719723e-02, 1.4536039365470805e-02, 7.1690467226628403e-03, 2.6649119196619805e-03, 7.4663859580211824e-04, 1.5766821136856327e-04},
+ {2.4095444850519678e-04, 1.1410409842453801e-03, 4.0726179129162605e-03, 1.0956004919274648e-02, 2.2214518185719723e-02, 3.3949056260531733e-02, 3.9104311330013700e-02, 3.3949056260531733e-02, 2.2214518185719723e-02, 1.0956004919274648e-02, 4.0726179129162605e-03, 1.1410409842453801e-03, 2.4095444850519678e-04},
+ {2.7754402650812860e-04, 1.3143111120915069e-03, 4.6910558447545393e-03, 1.2619703593780167e-02, 2.5587852237016186e-02, 3.9104311330013700e-02, 4.5042405681608985e-02, 3.9104311330013700e-02, 2.5587852237016186e-02, 1.2619703593780167e-02, 4.6910558447545393e-03, 1.3143111120915069e-03, 2.7754402650812860e-04},
+ {2.4095444850519678e-04, 1.1410409842453801e-03, 4.0726179129162605e-03, 1.0956004919274648e-02, 2.2214518185719723e-02, 3.3949056260531733e-02, 3.9104311330013700e-02, 3.3949056260531733e-02, 2.2214518185719723e-02, 1.0956004919274648e-02, 4.0726179129162605e-03, 1.1410409842453801e-03, 2.4095444850519678e-04},
+ {1.5766821136856327e-04, 7.4663859580211824e-04, 2.6649119196619805e-03, 7.1690467226628403e-03, 1.4536039365470805e-02, 2.2214518185719723e-02, 2.5587852237016186e-02, 2.2214518185719723e-02, 1.4536039365470805e-02, 7.1690467226628403e-03, 2.6649119196619805e-03, 7.4663859580211824e-04, 1.5766821136856327e-04},
+ {7.7760574635269639e-05, 3.6823558630170203e-04, 1.3143111120915069e-03, 3.5357107682171015e-03, 7.1690467226628403e-03, 1.0956004919274648e-02, 1.2619703593780167e-02, 1.0956004919274648e-02, 7.1690467226628403e-03, 3.5357107682171015e-03, 1.3143111120915069e-03, 3.6823558630170203e-04, 7.7760574635269639e-05},
+ {2.8905528202266243e-05, 1.3688227195911312e-04, 4.8856193637079371e-04, 1.3143111120915069e-03, 2.6649119196619805e-03, 4.0726179129162605e-03, 4.6910558447545393e-03, 4.0726179129162605e-03, 2.6649119196619805e-03, 1.3143111120915069e-03, 4.8856193637079371e-04, 1.3688227195911312e-04, 2.8905528202266243e-05},
+ {8.0985727252839541e-06, 3.8350831249506833e-05, 1.3688227195911312e-04, 3.6823558630170203e-04, 7.4663859580211824e-04, 1.1410409842453801e-03, 1.3143111120915069e-03, 1.1410409842453801e-03, 7.4663859580211824e-04, 3.6823558630170203e-04, 1.3688227195911312e-04, 3.8350831249506833e-05, 8.0985727252839541e-06},
+ {1.7101814497842592e-06, 8.0985727252839541e-06, 2.8905528202266243e-05, 7.7760574635269639e-05, 1.5766821136856327e-04, 2.4095444850519678e-04, 2.7754402650812860e-04, 2.4095444850519678e-04, 1.5766821136856327e-04, 7.7760574635269639e-05, 2.8905528202266243e-05, 8.0985727252839541e-06, 1.7101814497842592e-06},
+};
+
+#define GAUSS(x, y) (gauss[x+6][y+6])
+
+typedef union
+{
+ //guint32 value;
+ struct
+ {
+ guint16 x; // TODO assert x not bigger than this!
+ guint16 y;
+ } coords;
+} HashAddress;
+
+struct HashEntry_;
+
+struct HashEntry_
+{
+ guchar color[3];
+
+ guchar foreground[3];
+ guchar background[3];
+
+ guchar foreground_refined[3];
+ guchar background_refined[3];
+
+ guchar alpha;
+ guchar alpha_refined;
+
+ gfloat sigma_f_squared;
+ gfloat sigma_b_squared;
+
+ gfloat confidence;
+
+ gboolean valid;
+
+ HashAddress this;
+ struct HashEntry_ *next;
+};
+
+typedef struct HashEntry_ HashEntry;
+
+// TODO should be 300*6/64, actually...
+#define BIG_CACHE_CHANNELS 4
+#define BIG_CACHE_RADIUS 6
+#define BIG_CACHE_SIZE ((BIG_CACHE_RADIUS*2+1)*64)
+#define GET_PIXEL(big_cache, x, y, color) (big_cache[BIG_CACHE_RADIUS*64+y][BIG_CACHE_RADIUS*64+x][color])
+typedef guchar BigCache[BIG_CACHE_SIZE][BIG_CACHE_SIZE][BIG_CACHE_CHANNELS];
+
+#define HASH_CACHE_EXTRA 14
+#define HASH_CACHE_SIZE (64+HASH_CACHE_EXTRA*2)
+#define GET_ENTRY(hash_cache, x, y) (hash_cache[HASH_CACHE_EXTRA+y][HASH_CACHE_EXTRA+x])
+typedef HashEntry* HashCache[HASH_CACHE_SIZE][HASH_CACHE_SIZE];
+
+/* A struct that holds the MATTING current state */
+struct _GappMattingState
+{
+ GappTileManager *pixels;
+ GappTileManager *result_layer;
+ GappTileManager *mask;
+
+ gboolean enough_pixels;
+
+ BigCache big_cache;
+ HashCache hash_cache;
+
+ gint x1, y1, x2, y2;
+ gint tx, ty;
+
+ gint width, height;
+};
+
+/* Progressbar update callback */
+static inline void
+matting_progress_update (MattingProgressFunc progress_callback,
+ gpointer progress_data,
+ gdouble value)
+{
+ if (progress_data)
+ progress_callback (progress_data, value);
+}
+
+#ifdef IMAGE_DEBUG_PPM
+static void
+debug_image (const char* filename, int dimx, int dimy, guchar *data, int padding, int num_colors)
+{
+ int i, j;
+ FILE *fp = fopen (filename, "wb"); /* b - binary mode */
+
+ if (num_colors == 3)
+ {
+ fprintf (fp, "P6\n%d %d\n255\n", dimx, dimy);
+ }
+ else if (num_colors == 1)
+ {
+ fprintf (fp, "P5\n%d %d\n255\n", dimx, dimy);
+ }
+ else
+ {
+ printf ("Problem!\n");
+ exit (1);
+ }
+
+ {
+ guchar* current = data;
+
+ for (j = 0; j < dimy; ++j)
+ {
+ for (i = 0; i < dimx; ++i)
+ {
+ if (num_colors == 3)
+ {
+ static unsigned char color[3];
+ color[0] = current[0];
+ color[1] = current[1];
+ color[2] = current[2];
+ (void) fwrite (color, 1, 3, fp);
+ }
+ else
+ {
+ static unsigned char color;
+ color = current[0];
+ (void) fwrite (&color, 1, 1, fp);
+ }
+
+ current += padding;
+ }
+ }
+ }
+ fclose (fp);
+}
+
+static void debug_cache (const char* filename, BigCache cache, int radius)
+{
+ static char filename_alpha[100];
+ static char filename_rgb[100];
+ const int size = (radius * 2 + 1) * 64;
+
+ FILE *f_color, *f_alpha;
+
+ snprintf (filename_alpha, 100, "%s_alpha.ppm", filename);
+ snprintf (filename_rgb, 100, "%s.ppm", filename);
+
+ f_color = fopen (filename_rgb, "wb"); /* b - binary mode */
+ f_alpha = fopen (filename_alpha, "wb"); /* b - binary mode */
+
+ fprintf (f_color, "P6\n%d %d\n255\n", size, size);
+ fprintf (f_alpha, "P5\n%d %d\n255\n", size, size);
+ {
+ int x, y;
+ for (y = -radius * 64; y < (radius + 1) * 64; y++)
+ {
+ for (x = -radius * 64; x < (radius + 1) * 64; x++)
+ {
+ fwrite (&GET_PIXEL(cache, x, y, 0), 1, 3, f_color);
+ fwrite (&GET_PIXEL(cache, x, y, 3), 1, 1, f_alpha);
+ }
+ }
+ }
+ fclose (f_color);
+ fclose (f_alpha);
+}
+#endif
+
+GappMattingState *
+matting_init (GappTileManager *pixels,
+ const guchar *colormap,
+ gint offset_x,
+ gint offset_y,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
+{
+ GappMattingState *state;
+
+ g_return_val_if_fail (pixels != NULL, NULL);
+ state = g_slice_new (GappMattingState);
+
+ state->pixels = pixels;
+ state->enough_pixels = FALSE;
+
+ return state;
+}
+
+static void
+load_big_cache (GappTileManager *source, GappTileManager *mask, BigCache big_cache,
+ gint tx, gint ty, gint radius)
+{
+ gint xdiff;
+ gint ydiff;
+ gint x, y;
+ gint bx, by;
+ gint width_tile, height_tile;
+
+ GappTile *src_tile = NULL;
+ GappTile *mask_tile = NULL;
+ guchar *src_pointer = NULL;
+ guchar *mask_pointer = NULL;
+
+ guchar src_bpp = gapp_tile_manager_bpp(source);
+ guchar mask_bpp = gapp_tile_manager_bpp(mask);
+
+ g_return_if_fail ((gapp_tile_manager_bpp(source) == 4) ||
+ (gapp_tile_manager_bpp(source) == 3 && mask != NULL));
+
+ for (ydiff = -radius; ydiff <= radius; ydiff++)
+ {
+ for (xdiff = -radius; xdiff <= radius; xdiff++)
+ {
+ src_tile = gapp_tile_manager_get_at (source, tx + xdiff, ty + ydiff, TRUE, FALSE);
+ if (mask)
+ mask_tile = gapp_tile_manager_get_at (mask, tx + xdiff, ty + ydiff, TRUE, FALSE);
+
+ width_tile = 0;
+ height_tile = 0;
+
+ if (src_tile)
+ {
+ src_pointer = gapp_tile_data_pointer (src_tile, 0, 0);
+ if (mask)
+ {
+ g_return_if_fail(mask_tile);
+
+ mask_pointer = gapp_tile_data_pointer (mask_tile, 0, 0);
+ }
+
+ width_tile = gapp_tile_ewidth (src_tile);
+ height_tile = gapp_tile_eheight (src_tile);
+
+ for (y = 0; y < height_tile; y++)
+ {
+ by = ydiff * 64 + y;
+ for (x = 0; x < width_tile; x++)
+ {
+ bx = xdiff * 64 + x;
+
+ GET_PIXEL(big_cache, bx, by, 0) = src_pointer[0];
+ GET_PIXEL(big_cache, bx, by, 1) = src_pointer[1];
+ GET_PIXEL(big_cache, bx, by, 2) = src_pointer[2];
+ if (mask)
+ GET_PIXEL(big_cache, bx, by, 3) = mask_pointer[mask_bpp-1];
+ else
+ GET_PIXEL(big_cache, bx, by, 3) = src_pointer[3];
+
+ if (mask)
+ {
+ src_pointer += src_bpp;
+ mask_pointer += mask_bpp;
+ }
+ else
+ {
+ src_pointer += src_bpp;
+ }
+ }
+ }
+
+ gapp_tile_release (src_tile, FALSE);
+ if (mask)
+ gapp_tile_release (mask_tile, FALSE);
+ }
+
+ for (y = 0; y < 64; y++)
+ {
+ by = ydiff * 64 + y;
+ for (x = width_tile; x < 64; x++)
+ {
+ bx = xdiff * 64 + x;
+
+ //GET_PIXEL(big_cache, bx, by, 0) = 0;
+ //GET_PIXEL(big_cache, bx, by, 1) = 0;
+ //GET_PIXEL(big_cache, bx, by, 2) = 0;
+ GET_PIXEL(big_cache, bx, by, 3) = 128;
+ }
+ }
+
+ for (y = height_tile; y < 64; y++)
+ {
+ by = ydiff * 64 + y;
+ for (x = 0; x < width_tile; x++)
+ {
+ bx = xdiff * 64 + x;
+
+ //GET_PIXEL(big_cache, bx, by, 0) = 0;
+ //GET_PIXEL(big_cache, bx, by, 1) = 0;
+ //GET_PIXEL(big_cache, bx, by, 2) = 0;
+ GET_PIXEL(big_cache, bx, by, 3) = 128;
+ }
+ }
+ }
+ }
+}
+
+typedef struct
+{
+ guchar color[3];
+ gboolean found;
+ gint distance;
+ gint x;
+ gint y;
+} SearchStructure;
+
+// Project the Point P onto the line from B-A.
+// alpha_pointer receives the calculated alpha value between 0 and 1
+// where (0=B, 1=A)
+// returns the squared distance of the best projected point to P
+static inline gfloat projection (guchar B[3], guchar A[3], guchar P[3], float* alpha_pointer)
+{
+ gint ABx = B[0] - A[0];
+ gint ABy = B[1] - A[1];
+ gint ABz = B[2] - A[2];
+
+ gint APx = P[0] - A[0];
+ gint APy = P[1] - A[1];
+ gint APz = P[2] - A[2];
+
+ gint dot_AB = ABx * ABx + ABy * ABy + ABz * ABz;
+ gfloat alpha = (float)(ABx * APx + ABy * APy + ABz * APz) / dot_AB;
+
+ gfloat PPx, PPy, PPz;
+
+ PPx = P[0] - (A[0] + alpha * ABx);
+ PPy = P[1] - (A[1] + alpha * ABy);
+ PPz = P[2] - (A[2] + alpha * ABz);
+
+ alpha = alpha > 1 ? 1 : (alpha < 0 ? 0 : alpha);
+
+ if (alpha_pointer)
+ *alpha_pointer = alpha;
+
+ // Normalize, so that it is in the unit cube of colors
+ return (PPx * PPx + PPy * PPy + PPz * PPz) / (255. * 255.);
+}
+
+// evaluate the energy function for found color fg/bg for pixel situated at x/y
+static inline float
+objective_function (SearchStructure *fg,
+ SearchStructure *bg,
+ gint x, gint xmin, gint xmax,
+ gint y, gint ymin, gint ymax,
+ float* best_alpha,
+ float pfp,
+ GappMattingState *state)
+{
+ gint xi, yi;
+ float ap;
+ float finalAlpha;
+ float Np = projection (fg->color, bg->color,
+ &GET_PIXEL (state->big_cache, x, y, 0),
+ &finalAlpha);
+
+ for (yi = ymin; yi <= ymax; yi++)
+ {
+ for (xi = xmin; xi <= ymax; xi++)
+ {
+ guchar *P = &(GET_PIXEL (state->big_cache, x + xi, y + yi, 0));
+
+ if (xi != 0 || yi != 0)
+ {
+ Np += projection (fg->color, bg->color, P, NULL);
+ }
+ }
+ }
+
+ ap = pfp + (1 - 2 * pfp) * finalAlpha;
+
+ *best_alpha = finalAlpha;
+ return pow(Np, 3) * pow(bg->distance, 4) * pow(fg->distance, 1) * pow(ap, 2);
+}
+
+// searches for known regions for a given unknown pixel in a hash table
+
+static inline gfloat dist_squared(guchar x1, guchar y1, guchar z1, guchar x2, guchar y2, guchar z2)
+{
+ gint diff_x = (gint)x1 - (gint)x2;
+ gint diff_y = (gint)y1 - (gint)y2;
+ gint diff_z = (gint)z1 - (gint)z2;
+
+ return (gfloat) (diff_x * diff_x + diff_y * diff_y + diff_z * diff_z);
+}
+
+static gfloat calculate_variance (guchar P[3], gint x, gint y, GappMattingState *state)
+{
+ gint yi;
+ gint xi;
+ guchar my_alpha = GET_PIXEL (state->big_cache, x, y, 3);
+
+ gfloat sum = 0;
+ gint num_found = 0;
+
+ for (yi = -2; yi <= 2; yi++)
+ {
+ for (xi = -2; xi <= 2; xi++)
+ {
+ if (GET_PIXEL (state->big_cache, x + xi, y + yi, 3) == my_alpha &&
+ state->tx * 64 + x + xi < state->width && state->tx * 64 + x >= 0 &&
+ state->ty * 64 + y + yi < state->height && state->ty * 64 + y >= 0)
+ {
+ sum += dist_squared(GET_PIXEL (state->big_cache, x + xi, y + yi, 0),
+ GET_PIXEL (state->big_cache, x + xi, y + yi, 1),
+ GET_PIXEL (state->big_cache, x + xi, y + yi, 2),
+ P[0],
+ P[1],
+ P[2]);
+
+ num_found++;
+ }
+ }
+ }
+
+ if (num_found == 0)
+ {
+ g_return_val_if_reached(0);
+ }
+ else
+ {
+ return sum / num_found;
+ }
+}
+
+typedef struct
+{
+ gint x;
+ gint y;
+ gfloat diff;
+} TopColor;
+
+static void inline load_hash_cache (GHashTable* unknown_hash, HashCache hash_cache,
+ gint tx, gint ty, gint bordersize)
+{
+
+ gint x, y;
+ gint xoff = tx * 64;
+ gint yoff = ty * 64;
+
+ for (y = -bordersize; y < bordersize + 64; y++)
+ {
+ for (x = -bordersize; x < bordersize + 64; x++)
+ {
+ HashAddress address;
+ address.coords.x = x + xoff;
+ address.coords.y = y + yoff;
+
+ GET_ENTRY(hash_cache, x, y) = g_hash_table_lookup (unknown_hash, &address);
+ }
+ }
+}
+
+static void inline
+compare_neighborhood (HashEntry* entry, GHashTable* unknown_hash,
+ GappMattingState *state)
+{
+ gint pos_x, pos_y;
+ gint tx, ty;
+
+ gint xdiff, ydiff;
+ gint num;
+ gint matches = 0;
+
+ HashEntry *current;
+ TopColor top3[3];
+
+ // Load coordinates from entry
+ pos_x = entry->this.coords.x;
+ pos_y = entry->this.coords.y;
+
+ tx = pos_x / 64;
+ ty = pos_y / 64;
+
+ pos_x = pos_x - 64 * tx;
+ pos_y = pos_y - 64 * ty;
+
+ if (state->tx != tx || state->ty != ty)
+ {
+ load_hash_cache (unknown_hash, state->hash_cache, tx, ty, HASH_CACHE_EXTRA);
+
+ state->tx = tx;
+ state->ty = ty;
+ }
+
+ for (num = 0; num < 3; num++)
+ {
+ top3[num].diff = INFINITY;
+ }
+
+ // TODO: change this to radius! (not square)
+ for (ydiff = -HASH_CACHE_EXTRA; ydiff <= HASH_CACHE_EXTRA; ydiff++)
+ {
+ for (xdiff = -HASH_CACHE_EXTRA; xdiff <= HASH_CACHE_EXTRA; xdiff++)
+ {
+ current = GET_ENTRY(state->hash_cache, pos_x + xdiff, pos_y + ydiff);
+
+ if (current && current->valid)
+ {
+ gfloat temp = projection (current->foreground,
+ current->background,
+ entry->color,
+ NULL);
+
+ // check if color is better than least best of colors, add the color and sort the list
+ if (temp < top3[2].diff)
+ {
+ gint i = 2;
+ for (num = 1; num >= 0; num--)
+ {
+ if (temp < top3[num].diff)
+ {
+ i = num;
+ }
+ }
+ for (num = 2; num > i; num--)
+ {
+ top3[num] = top3[num-1];
+ }
+ top3[i].diff = temp;
+ top3[i].x = pos_x + xdiff;
+ top3[i].y = pos_y + ydiff;
+ matches++;
+ }
+ }
+ }
+ }
+
+ if (matches >= 1)
+ {
+ gfloat colordiff, current_alpha;
+
+ guchar new_fg[3] = {0, 0, 0};
+ guchar new_bg[3] = {0, 0, 0};
+ gfloat new_sigma_f_squared = 0;
+ gfloat new_sigma_b_squared = 0;
+
+ gint index;
+
+ matches = matches > 3 ? 3 : matches;
+
+ for (num = 0; num < matches; num++)
+ {
+ current = GET_ENTRY(state->hash_cache, top3[num].x, top3[num].y);
+ for (index = 0; index < 3; index++)
+ {
+ // TODO: check if we should use ints here!
+ new_fg[index] += floor(current->foreground[index] / matches);
+ new_bg[index] += floor(current->background[index] / matches);
+ }
+
+ new_sigma_f_squared += current->sigma_f_squared / matches;
+ new_sigma_b_squared += current->sigma_b_squared / matches;
+ }
+
+ colordiff = dist_squared(entry->color[0],
+ entry->color[1],
+ entry->color[2],
+ new_fg[0],
+ new_fg[1],
+ new_fg[2]);
+
+ if (colordiff > new_sigma_f_squared)
+ {
+ for (index = 0; index < 3; index++)
+ {
+ entry->foreground_refined[index] = new_fg[index];
+ }
+ }
+ else
+ {
+ for (index = 0; index < 3; index++)
+ {
+#ifdef CAN_USE_ORIGINAL_COLORS
+ entry->foreground_refined[index] = entry->color[index];
+#else
+ entry->foreground_refined[index] = new_fg[index];
+#endif
+ }
+ }
+
+ colordiff = dist_squared(entry->color[0],
+ entry->color[1],
+ entry->color[2],
+ new_bg[0],
+ new_bg[1],
+ new_bg[2]);
+
+ if (colordiff > new_sigma_b_squared)
+ {
+ for (index = 0; index < 3; index++)
+ {
+ entry->background_refined[index] = new_bg[index];
+ }
+ }
+ else
+ {
+ for (index = 0; index < 3; index++)
+ {
+#ifdef CAN_USE_ORIGINAL_COLORS
+ entry->background_refined[index] = entry->color[index];
+#else
+ entry->background_refined[index] = new_bg[index];
+#endif
+ }
+ }
+
+ {
+ gfloat mp;
+ gint i;
+ gboolean same = TRUE;
+
+ mp = projection (new_fg,
+ new_bg,
+ entry->color,
+ ¤t_alpha);
+
+ entry->alpha_refined = current_alpha * 255;
+
+ for (i = 0; i < 3; i++)
+ {
+ if (entry->foreground_refined[i] != entry->background_refined[i])
+ {
+ same = FALSE;
+ break;
+ }
+ }
+
+ if (same)
+ {
+ entry->confidence = 1e-8;
+ }
+ else
+ {
+ mp = projection (entry->foreground_refined,
+ entry->background_refined,
+ entry->color,
+ NULL);
+
+ entry->confidence = exp(-LAMBDA * sqrt(mp));
+ }
+ }
+ entry->valid = TRUE;
+ }
+}
+
+static void inline
+calculate_final_colors (gfloat gauss, gint x, gint y, gfloat alpha_orig,
+ gdouble fq[3], gdouble *fd, gdouble bq[3], gdouble *bd,
+ gdouble *meandiff_q, gdouble *meandiff_d,
+ gdouble *low_freq_alpha_q, gdouble *low_freq_alpha_d,
+ gboolean is_middle, GappMattingState *state)
+{
+ guchar *fg, *bg;
+ gint i;
+ gfloat alpha, confidence;
+ gdouble weight;
+ HashEntry* current;
+
+ current = GET_ENTRY(state->hash_cache, x, y);
+ if(current == NULL || !current->valid)
+ {
+ alpha = GET_PIXEL (state->big_cache, x, y, 3);
+ if (alpha != 255 && alpha != 0) // We are outside of the image!
+ confidence = 0;
+ else
+ confidence = 1;
+
+ if (current)
+ alpha = 0.5;
+ else
+ alpha = (alpha == 255 ? 1 : 0);
+
+ fg = &GET_PIXEL (state->big_cache, x, y, 0);
+ bg = fg;
+ }
+ else
+ {
+ gfloat diff_weight;
+
+ g_return_if_fail (GET_PIXEL (state->big_cache, x, y, 3) == 128);
+
+ fg = current->foreground_refined;
+ bg = current->background_refined;
+
+ alpha = current->alpha_refined / 255.;
+ confidence = current->confidence;
+
+ diff_weight = alpha * (1 - alpha) * confidence;
+ *meandiff_d += diff_weight;
+ *meandiff_q += diff_weight * sqrt(dist_squared(
+ current->foreground_refined[0],
+ current->foreground_refined[1],
+ current->foreground_refined[2],
+ current->background_refined[0],
+ current->background_refined[1],
+ current->background_refined[2]));
+ }
+
+ // Special Case for original pixel
+ if (is_middle)
+ {
+ weight = gauss * confidence;
+ }
+ else
+ {
+ gfloat diff = alpha_orig - alpha;
+ if (diff < 0)
+ diff = -diff;
+
+ weight = gauss * confidence * diff;
+ }
+
+ for (i = 0; i < 3; i++)
+ {
+
+ fq[i] += weight * alpha * fg[i];
+ bq[i] += weight * (1 - alpha) * bg[i];
+ }
+ {
+ gdouble low_freq_weight = confidence * gauss;
+#ifdef HIGH_WEIGHT_FG_BG
+ low_freq_weight += (current == NULL && confidence == 1);
+#endif
+
+ *bd += weight * (1 - alpha);
+ *fd += weight * alpha;
+
+ *low_freq_alpha_q += low_freq_weight * alpha;
+ *low_freq_alpha_d += low_freq_weight;
+ }
+}
+
+static void inline
+local_smoothing (HashEntry* entry, GHashTable* unknown_hash, GappMattingState *state)
+{
+ gint pos_x, pos_y;
+ gint tx, ty;
+ gint i;
+
+ gint xdiff, ydiff;
+ gdouble fq[3] = {0, 0, 0};
+ gdouble fd = 0;
+ gdouble bq[3] = {0, 0, 0};
+ gdouble bd = 0;
+
+ gdouble meandiff_q = 0;
+ gdouble meandiff_d = 0;
+
+ gdouble low_freq_alpha_q = 0;
+ gdouble low_freq_alpha_d = 0;
+
+ // Load coordinates from entry
+ pos_x = entry->this.coords.x;
+ pos_y = entry->this.coords.y;
+
+ tx = pos_x / 64;
+ ty = pos_y / 64;
+
+ pos_x = pos_x - 64 * tx;
+ pos_y = pos_y - 64 * ty;
+
+ if (state->tx != tx || state->ty != ty)
+ {
+ load_hash_cache (unknown_hash, state->hash_cache, tx, ty, 6);
+ load_big_cache (state->pixels, state->result_layer, state->big_cache, tx, ty, 1);
+
+ state->tx = tx;
+ state->ty = ty;
+ }
+
+ for (ydiff = -6; ydiff <= 6; ydiff++)
+ {
+ for (xdiff = -6; xdiff <= 6; xdiff++)
+ {
+ calculate_final_colors (GAUSS(xdiff, ydiff),
+ pos_x + xdiff, pos_y + ydiff,
+ entry->alpha_refined / 255.,
+ fq, &fd, bq, &bd,
+ &meandiff_q, &meandiff_d,
+ &low_freq_alpha_q, &low_freq_alpha_d,
+ xdiff == 0 && ydiff == 0,
+ state);
+ }
+ }
+
+ for (i = 0; i < 3; i++)
+ {
+ if (fd != 0)
+ entry->foreground[i] = fq[i] / fd;
+ if (bd != 0)
+ entry->background[i] = bq[i] / bd;
+ }
+
+ {
+ gfloat current_alpha, mp;
+ gdouble low_freq_alpha = low_freq_alpha_q / low_freq_alpha_d;
+ gdouble meandiff;
+
+ gdouble final_confidence = sqrt(dist_squared(
+ entry->foreground[0],
+ entry->foreground[1],
+ entry->foreground[2],
+ entry->background[0],
+ entry->background[1],
+ entry->background[2]));
+
+ if (meandiff_d == 0)
+ meandiff_d = 1;
+
+ meandiff = meandiff_q / meandiff_d;
+ final_confidence /= meandiff;
+
+ if (final_confidence > 1)
+ final_confidence = 1;
+
+ mp = projection (entry->foreground,
+ entry->background,
+ entry->color,
+ ¤t_alpha);
+ final_confidence *= exp(-LAMBDA * sqrt(mp));
+
+ if (!(final_confidence <= 1 || final_confidence >= 0))
+ g_printf("Problem!: final_confidence: %f\n", final_confidence);
+
+ entry->alpha = (final_confidence * current_alpha + (1 - final_confidence) * low_freq_alpha) * 255;
+ //entry->alpha = low_freq_alpha * 255;
+ }
+}
+
+static void inline
+search_neighborhood (HashEntry* entry, GappMattingState *state)
+{
+ gint pos_x, pos_y;
+ gint orig_pos_x, orig_pos_y;
+ gint tx, ty;
+ gint xdiff, ydiff;
+ gfloat min_gradients[2] = {INFINITY, INFINITY};
+ gfloat gradients[4] = {0, 0, 0, 0};
+
+ gint direction, toggle, distance;
+
+ SearchStructure found[2][4];
+
+ guchar prevval[4][3] =
+ {
+ {0}
+ };
+ double angle;
+ gint permutation[4];
+
+ for (toggle = 0; toggle < 2; toggle++)
+ {
+ for (direction = 0; direction < 4; direction++)
+ {
+ found[toggle][direction].found = FALSE;
+ }
+ }
+
+ // Load coordinates from entry
+ orig_pos_x = entry->this.coords.x;
+ orig_pos_y = entry->this.coords.y;
+
+ tx = orig_pos_x / 64;
+ ty = orig_pos_y / 64;
+
+ pos_x = orig_pos_x - 64 * tx;
+ pos_y = orig_pos_y - 64 * ty;
+
+ if (state->tx != tx || state->ty != ty)
+ {
+ load_big_cache (state->pixels, state->result_layer, state->big_cache, tx, ty, 6);
+
+#ifdef IMAGE_DEBUG_PPM
+ {
+ static char buffer[100];
+
+ snprintf (buffer, 100, "pixels_result_%i_%i", tx, ty);
+ debug_cache (buffer, state->big_cache, 3);
+ }
+#endif
+
+ state->tx = tx;
+ state->ty = ty;
+ }
+
+ // in a 9x9 window, we want to have values in a 90Â window
+ angle = ((orig_pos_x % 3) + (orig_pos_y % 3) * 3) * 2.*G_PI / 9. / 4.;
+
+ for (distance = 6; distance < 6 * 64; distance += 6)
+ {
+ // TODO precalculate these!
+ xdiff = cos (angle) * distance;
+ ydiff = sin (angle) * distance;
+
+ permutation[0] = xdiff;
+ permutation[1] = ydiff;
+ permutation[2] = -xdiff;
+ permutation[3] = -ydiff;
+
+ for (direction = 0; direction < 4; direction++)
+ {
+ if (found[0][direction].found && found[1][direction].found)
+ {
+ continue;
+ }
+ else
+ {
+ guchar r, g, b, a;
+
+ gint xtmp = permutation[direction] + pos_x;
+ gint ytmp = permutation[(direction + 1) % 4] + pos_y;
+
+ r = GET_PIXEL (state->big_cache, xtmp, ytmp, 0);
+ g = GET_PIXEL (state->big_cache, xtmp, ytmp, 1);
+ b = GET_PIXEL (state->big_cache, xtmp, ytmp, 2);
+ a = GET_PIXEL (state->big_cache, xtmp, ytmp, 3);
+
+ gradients[direction] += sqrt(dist_squared(prevval[direction][0],
+ prevval[direction][1],
+ prevval[direction][2],
+ r, g, b));
+
+ prevval[direction][0] = r;
+ prevval[direction][1] = g;
+ prevval[direction][2] = b;
+
+ // check if it's foreground or background, depending on alpha
+ // toggle = 0 equals foreground
+ for (toggle = 0; toggle < 2; toggle++)
+ {
+ if (a == (toggle == 0 ? 255 : 0) &&
+ !found[toggle][direction].found)
+ {
+ if (gradients[direction] < min_gradients[toggle])
+ min_gradients[toggle] = gradients[direction];
+
+ found[toggle][direction].color[0] = r;
+ found[toggle][direction].color[1] = g;
+ found[toggle][direction].color[2] = b;
+ found[toggle][direction].distance = distance;
+ found[toggle][direction].found = TRUE;
+ found[toggle][direction].x = xtmp;
+ found[toggle][direction].y = ytmp;
+ }
+ }
+ }
+ }
+ }
+
+ {
+ gfloat min = INFINITY;
+ gint minindexf = -1;
+ gint minindexb = -1;
+
+ gint foreground_direction, background_direction;
+
+ gfloat best_alpha = -1;
+ gfloat pfp = 0.5;
+ if (min_gradients[1] > 0 || min_gradients[0] > 0)
+ pfp = min_gradients[1] / (min_gradients[0] + min_gradients[1]);
+
+ // calculate energy function for every fg/bg pair
+ for (foreground_direction = 0; foreground_direction < 4; foreground_direction++)
+ {
+ if (found[0][foreground_direction].found)
+ {
+ for (background_direction = 0; background_direction < 4; background_direction++)
+ {
+ if (found[1][background_direction].found)
+ {
+ float current_alpha, cost;
+ gint xmin = -1, ymin = -1, xmax = 1, ymax = 1;
+
+ if (orig_pos_x <= 0)
+ xmin++;
+ else if (orig_pos_x >= state->width - 1)
+ xmax--;
+ if (orig_pos_y <= 0)
+ ymin++;
+ else if (orig_pos_y >= state->height - 1)
+ ymax++;
+
+ cost = objective_function (&(found[0][foreground_direction]),
+ &(found[1][background_direction]),
+ pos_x, xmin, xmax,
+ pos_y, ymin, ymax,
+ ¤t_alpha,
+ pfp,
+ state);
+ if (cost < min)
+ {
+ best_alpha = current_alpha;
+ min = cost;
+ minindexf = foreground_direction;
+ minindexb = background_direction;
+ }
+ }
+
+ }
+ }
+ }
+
+ if (min != INFINITY)
+ {
+ SearchStructure best_foreground = found[0][minindexf];
+ SearchStructure best_background = found[1][minindexb];
+
+ // test: do combination of best match
+ // should return a very similar image as before
+ entry->foreground[0] = best_foreground.color[0];
+ entry->foreground[1] = best_foreground.color[1];
+ entry->foreground[2] = best_foreground.color[2];
+
+ entry->background[0] = best_background.color[0];
+ entry->background[1] = best_background.color[1];
+ entry->background[2] = best_background.color[2];
+
+ entry->alpha = best_alpha * 255;
+ entry->valid = TRUE;
+
+ entry->sigma_b_squared = calculate_variance (best_background.color, best_background.x, best_background.y, state);
+ entry->sigma_f_squared = calculate_variance (best_foreground.color, best_foreground.x, best_foreground.y, state);
+ }
+
+ //printf("values: %i %i %i | %i %i %i | %i %i %i | %i %i %i\n", values[0], values[1], values[2], values[3], values[4], values[5], values[6], values[7], values[8], values[9], values[10], values[11]);
+ }
+}
+
+// static gfloat
+// mask_percent_unknown (GappTileManager* mask_layer,
+// GappMattingState* state)
+// {
+// PixelRegion mask;
+// PixelRegionIterator *pr;
+// gint row, col;
+// gint pixels_unknown = 0;
+// guint width = state->x2 - state->x1;
+// guint height = state->y2 - state->y1;
+// guint pixels_total = width * height;
+//
+// pixel_region_init (&mask, mask_layer, state->x1, state->y1, width, height, TRUE);
+//
+// if (mask.bytes != 1)
+// return 1;
+//
+// for (pr = pixel_regions_register (1, &mask);
+// pr != NULL;
+// pr = pixel_regions_process (pr))
+// {
+// guchar *mask_data = mask.data;
+//
+// for (row = 0; row < mask.h; row++)
+// {
+// guchar *m = mask_data;
+//
+// for (col = 0; col < mask.w; col++, ++m)
+// {
+// if (m[0] != MATTING_USER_FOREGROUND && m[0] != MATTING_USER_BACKGROUND)
+// {
+// pixels_unknown++;
+// }
+// }
+//
+// mask_data += mask.rowstride;
+// }
+// }
+// return (gfloat) pixels_unknown / pixels_total;
+// }
+
+
+// static void
+// update_mask (GappTileManager* result_layer,
+// GappTileManager* mask_layer,
+// GappMattingState *state)
+// {
+// PixelRegion result, mask;
+// PixelRegionIterator *pr;
+// gint row, col;
+// gint width, height;
+//
+// width = state->x2 - state->x1;
+// height = state->y2 - state->y1; // TODO give this as argument
+//
+// pixel_region_init (&result, result_layer, state->x1, state->y1, width, height, FALSE);
+// pixel_region_init (&mask, mask_layer, state->x1, state->y1, width, height, TRUE);
+//
+// g_return_if_fail (result.bytes == 4 && mask.bytes == 1); // TODO check if indexed etc...
+//
+// for (pr = pixel_regions_register (2, &result, &mask);
+// pr != NULL;
+// pr = pixel_regions_process (pr))
+// {
+// const guchar *result_data = result.data;
+// guchar *mask_data = mask.data;
+//
+// for (row = 0; row < result.h; row++)
+// {
+// const guchar *r = result_data;
+// guchar *m = mask_data;
+//
+// for (col = 0; col < result.w; col++, r += result.bytes, ++m) // TODO check if 4 is ok
+// {
+// guchar mask;
+// mask = m[0];
+// if (mask != MATTING_USER_FOREGROUND &&
+// mask != MATTING_USER_BACKGROUND)
+// {
+// guchar result = r[3];
+// if (result == MATTING_USER_FOREGROUND)
+// result--;
+// if (result == MATTING_USER_BACKGROUND)
+// result++;
+// m[0] = result;
+// }
+// }
+//
+// result_data += result.rowstride;
+// mask_data += mask.rowstride;
+// }
+// }
+// }
+
+static inline gboolean
+check_closeness (guchar color[3], BigCache big_cache, gint x, gint y, guchar* result)
+{
+ guchar value;
+
+ value = GET_PIXEL (big_cache, x, y, 3);
+
+ if (value == MATTING_USER_FOREGROUND || value == MATTING_USER_BACKGROUND)
+ {
+ gint color_distance_sum;
+ gint color_distance;
+ gint i;
+ color_distance_sum = 0;
+ for (i = 0; i < 3; i++)
+ {
+ color_distance = (gint)color[i] - GET_PIXEL (big_cache, x, y, i);
+ color_distance_sum += color_distance * color_distance;
+ }
+
+ if (color_distance_sum < MATTING_SQUARED_COLOR_DISTANCE)
+ {
+ if (value == MATTING_USER_FOREGROUND)
+ *result = 255;
+ else
+ *result = 0;
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+static inline guchar
+search_for_neighbours (gint x, gint y, guchar* color, GappMattingState *state)
+{
+ gint radius, n;
+ guchar alpha;
+
+ alpha = GET_PIXEL (state->big_cache, x, y, 3);
+
+ if (alpha == MATTING_USER_BACKGROUND)
+ {
+ return 0;
+ }
+
+ if (alpha == MATTING_USER_FOREGROUND)
+ {
+ return 255;
+ }
+
+ for (radius = 0; radius <= SEARCH_RADIUS; radius++)
+ {
+ for (n = -radius; n < radius; n++)
+ {
+ if (check_closeness (color, state->big_cache, x + radius, y + n, &alpha))
+ return alpha;
+
+ if (check_closeness (color, state->big_cache, x - radius, y + n, &alpha))
+ return alpha;
+
+ if (check_closeness (color, state->big_cache, x + n, y + radius, &alpha))
+ return alpha;
+
+ if (check_closeness (color, state->big_cache, x + n, y - radius, &alpha))
+ return alpha;
+ }
+ }
+ return 128;
+}
+
+void
+matting_foreground_extract (GappMattingState *state,
+ GappTileManager *mask,
+ gint x1,
+ gint y1,
+ gint x2,
+ gint y2,
+ gfloat start_percentage,
+ MattingProgressFunc progress_callback,
+ gpointer progress_data,
+ GappTileManager *result_layer)
+{
+ GappTile *tile;
+
+ gint tx, ty, x, y;
+ guchar *pointer;
+
+ gint hash_size, hash_step;
+
+ HashEntry *first_entry = NULL;
+ HashEntry *previous_entry = NULL;
+
+ static GHashTable *unknown_hash = NULL;
+
+ state->width = gapp_tile_manager_width (mask);
+ state->height = gapp_tile_manager_height (mask);
+
+ g_return_if_fail (state != NULL);
+ g_return_if_fail (mask != NULL && gapp_tile_manager_bpp (mask) == 1);
+ g_return_if_fail (x1 >= 0);
+ g_return_if_fail (x2 > x1 && x2 <= state->width);
+ g_return_if_fail (y1 >= 0);
+ g_return_if_fail (y2 > y1 && y2 <= state->height);
+ g_return_if_fail (start_percentage >= 0 && start_percentage <= 1);
+ g_return_if_fail (progress_data == NULL || progress_callback != NULL);
+
+ g_return_if_fail (gapp_tile_manager_bpp (state->pixels) == 3 || gapp_tile_manager_bpp (state->pixels) == 4);
+ g_return_if_fail (gapp_tile_manager_bpp (result_layer) == 4);
+
+ state->x1 = x1;
+ state->y1 = y1;
+ state->x2 = x2;
+ state->y2 = y2;
+
+ state->result_layer = result_layer;
+ state->mask = mask;
+
+// if (!state->enough_pixels)
+// {
+// gfloat unknown_percent = mask_percent_unknown (mask, state);
+//
+// //g_printf("Unknown pixels: %f (%f)\n", unknown_percent, start_percentage);
+// if (unknown_percent > (1 - start_percentage))
+// {
+// return;
+// }
+// state->enough_pixels = TRUE;
+// }
+
+ unknown_hash = g_hash_table_new(g_int_hash, g_int_equal); // TODO assert int = int32
+
+ for (ty = y1 / 64; ty <= (y2-1) / 64; ty++)
+ {
+ for (tx = x1 / 64; tx <= (x2-1) / 64; tx++)
+ {
+ guint height_tile;
+ guint width_tile;
+
+ load_big_cache (state->pixels, mask, state->big_cache, tx, ty, 1);
+
+#ifdef IMAGE_DEBUG_PPM
+ {
+ static char buffer[100];
+
+ snprintf (buffer, 100, "pixels_mask_%i_%i", tx, ty);
+ debug_cache (buffer, state->big_cache, 1);
+ }
+#endif
+
+ tile = gapp_tile_manager_get_at (result_layer, tx, ty, TRUE, TRUE);
+
+ pointer = gapp_tile_data_pointer (tile, 0, 0);
+
+ width_tile = gapp_tile_ewidth (tile);
+ height_tile = gapp_tile_eheight (tile);
+
+ for (y = 0; y < height_tile; y++)
+ {
+ for (x = 0; x < width_tile; x++, pointer += 4)
+ {
+ guchar alpha;
+
+ pointer[0] = GET_PIXEL (state->big_cache, x, y, 0);
+ pointer[1] = GET_PIXEL (state->big_cache, x, y, 1);
+ pointer[2] = GET_PIXEL (state->big_cache, x, y, 2);
+ alpha = search_for_neighbours (x, y, pointer, state);
+ pointer[3] = alpha;
+
+ if (alpha == 128)
+ {
+ HashEntry *entry = g_slice_new (HashEntry);
+ // TODO: free this memory
+
+ // TODO: check if this can really be uncomented
+ //entry->foreground[0] = 255;
+ //entry->foreground[1] = 0;
+ //entry->foreground[2] = 0;
+ //entry->alpha = 255;
+ entry->valid = FALSE;
+ entry->this.coords.x = tx * 64 + x;
+ entry->this.coords.y = ty * 64 + y;
+
+ // TODO maybe look this up in image, instead of
+ // saving it redundantly in cache
+ entry->color[0] = pointer[0];
+ entry->color[1] = pointer[1];
+ entry->color[2] = pointer[2];
+ // TODO remove color from entry
+
+ // Linked list creation
+ if(first_entry == NULL)
+ first_entry = entry;
+ if (previous_entry != NULL)
+ previous_entry->next = entry;
+ previous_entry = entry;
+
+ g_hash_table_insert (unknown_hash, &(entry->this), entry);
+ }
+ }
+ }
+
+ gapp_tile_release (tile, TRUE);
+ }
+ }
+
+ g_return_if_fail(previous_entry != NULL);
+
+ // End the list with a null pointer
+ previous_entry->next = NULL;
+ hash_size = g_hash_table_size(unknown_hash);
+ hash_step = hash_size / 33;
+
+ if (DEBUG_PHASE > 1)
+ {
+ // Phase 2, loop over values in hash and fill them in
+ {
+ HashEntry *current = first_entry;
+ gint counter = 0;
+
+ state->tx = -1;
+ state->ty = -1;
+
+ while (current != NULL)
+ {
+ counter++;
+ search_neighborhood (current, state);
+ current = current->next;
+
+ if (counter % hash_step == 0)
+ matting_progress_update(progress_callback, progress_data, (float)counter / hash_size * 0.33);
+ }
+ }
+
+ if (DEBUG_PHASE > 2)
+ {
+ // Phase 3, get better values from neighbours
+ {
+ HashEntry *current = first_entry;
+ gint counter = 0;
+
+ state->tx = -1;
+ state->ty = -1;
+
+ while (current != NULL)
+ {
+ counter++;
+ compare_neighborhood (current, unknown_hash, state);
+ current = current->next;
+
+ if (counter % hash_step == 0)
+ matting_progress_update(progress_callback, progress_data, (float)counter / hash_size * 0.33 + 0.33);
+ }
+ }
+
+ if (DEBUG_PHASE > 3)
+ // Phase 4, get final color values
+ {
+ HashEntry *current = first_entry;
+ gint counter = 0;
+
+ state->tx = -1;
+ state->ty = -1;
+
+ while (current != NULL)
+ {
+ counter++;
+ if (current->valid)
+ local_smoothing (current, unknown_hash, state);
+
+ current = current->next;
+
+ if (counter % hash_step == 0)
+ matting_progress_update(progress_callback, progress_data, (float)counter / hash_size * 0.33 + 0.66);
+ }
+ }
+ }
+ }
+
+ // Last phase, fill values from hash back into result layer
+ {
+ HashEntry *current = first_entry;
+ HashEntry *tmp;
+ GappTile *tile = NULL;
+ gint current_tx = -1;
+ gint current_ty = -1;
+ gint tx, ty, pos_x, pos_y;
+ gint i;
+
+ while (current != NULL)
+ {
+ if (current->valid)
+ {
+ tx = current->this.coords.x / 64;
+ ty = current->this.coords.y / 64;
+
+ pos_x = current->this.coords.x - 64 * tx;
+ pos_y = current->this.coords.y - 64 * ty;
+
+ if (current_tx != tx || current_ty != ty)
+ {
+ if (tile != NULL)
+ gapp_tile_release(tile, TRUE);
+
+ tile = gapp_tile_manager_get_at (result_layer, tx, ty, TRUE, TRUE);
+
+ current_tx = tx;
+ current_ty = ty;
+ }
+
+ pointer = gapp_tile_data_pointer (tile, pos_x, pos_y);
+
+ for (i = 0; i < 3; i++)
+ {
+ if (DEBUG_PHASE == 3)
+ pointer[i] = current->foreground_refined[i];
+ else
+ pointer[i] = current->foreground[i];
+ }
+ if (DEBUG_PHASE == 3)
+ pointer[3] = current->alpha_refined;
+ else
+ pointer[3] = current->alpha;
+ }
+
+ tmp = current->next;
+ g_slice_free(HashEntry, current);
+ current = tmp;
+ }
+
+ if (tile != NULL)
+ gapp_tile_release(tile, TRUE);
+ }
+
+ g_hash_table_destroy(unknown_hash);
+
+ matting_progress_update(progress_callback, progress_data, 1);
+ //update_mask (result_layer, mask, state);
+}
+
+void
+matting_done (GappMattingState * state)
+{
+ g_return_if_fail (state != NULL);
+
+ g_slice_free (GappMattingState, state);
+}
diff --git a/gap/gap_fg_matting.h b/gap/gap_fg_matting.h
new file mode 100644
index 0000000..0a4afa8
--- /dev/null
+++ b/gap/gap_fg_matting.h
@@ -0,0 +1,81 @@
+/* gap_fg_matting.h
+ * This module is a modified copy of the alpha matting
+ * forground extraction.
+ * The modifications allow the code to run as plug-in
+ * usable with official GIMP-releases (2.6.x and later)
+ * The original implemantation was done
+ * by Jan Ruegg as gimp core tool in the unofficial repository
+ * https://github.com/rggjan/Gimp-Matting in the "new_layer" branch.
+ *
+ */
+/*
+ * matting: Simple Interactive Object Extraction
+ *
+ * For algorithm documentation refer to:
+ * G. Friedland, K. Jantz, L. Knipping, R. Rojas:
+ * "Image Segmentation by Uniform Color Clustering
+ * -- Approach and Benchmark Results",
+ * Technical Report B-05-07, Department of Computer Science,
+ * Freie Universitaet Berlin, June 2005.
+ * http://www.inf.fu-berlin.de/inst/pubs/tr-b-05-07.pdf
+ *
+ * See http://www.matting.org/ for more information.
+ *
+ * Algorithm idea by Gerald Friedland.
+ * This implementation is Copyright (C) 2005
+ * by Gerald Friedland <fland inf fu-berlin de>
+ * and Kristian Jantz <jantz inf fu-berlin de>.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef __GAP_MATTING_H__
+#define __GAP_MATTING_H__
+
+#include "gap_fg_tile_manager.h"
+
+
+#define MATTING_USER_FOREGROUND 240
+#define MATTING_ALGO_FOREGROUND 200
+#define MATTING_ALGO_UNDEFINED 128
+#define MATTING_USER_BACKGROUND 0
+#define MATTING_ALGO_BACKGROUND 20
+
+typedef void (* MattingProgressFunc) (gpointer progress_data,
+ gdouble fraction);
+
+GappMattingState *matting_init (GappTileManager *pixels,
+ const guchar *colormap,
+ gint offset_x,
+ gint offset_y,
+ gint x,
+ gint y,
+ gint width,
+ gint height);
+
+void matting_foreground_extract (GappMattingState *state,
+ GappTileManager *mask,
+ gint x1,
+ gint y1,
+ gint x2,
+ gint y2,
+ gfloat start_percentage,
+ MattingProgressFunc progress_callback,
+ gpointer progress_data,
+ GappTileManager *result_layer);
+
+void matting_done (GappMattingState *state);
+
+#endif /* __GAP_MATTING_H__ */
diff --git a/gap/gap_fg_matting_dialog.c b/gap/gap_fg_matting_dialog.c
new file mode 100644
index 0000000..a3914c5
--- /dev/null
+++ b/gap/gap_fg_matting_dialog.c
@@ -0,0 +1,636 @@
+/* gap_fg_matting_dialog.c
+ * 2011.10.05 hof (Wolfgang Hofer)
+ *
+ * GAP ... Gimp Animation Plugins
+ *
+ * This Module contains:
+ * - stuff for the GUI dialog
+ * of the foreground selection via alpha matting plug-in.
+ *
+ */
+/* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#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_fg_matting_main.h"
+#include "gap_fg_matting_dialog.h"
+
+#include "gap-intl.h"
+
+
+#define GAP_FOREGROUND_EXTRACT_RESPONSE_RESET 1
+#define GAP_FG_USE_LAYER_MASK -44
+
+extern int gap_debug;
+#define GAP_DEBUG_DECLARED 1
+
+typedef struct _FgExtractDialogGuiStuff FgExtractDialogGuiStuff;
+
+struct _FgExtractDialogGuiStuff
+{
+ gint run;
+ gint32 drawable_id;
+ gint countTriMapCanidates;
+
+ GtkWidget *shell;
+
+ GtkObject *colordiff_threshold_spinbutton_adj;
+ GtkWidget *colordiff_threshold_spinbutton;
+
+ GtkWidget *triMapCombo;
+ GtkWidget *triMapLabel;
+ GtkWidget *create_resultCheckbutton;
+ GtkWidget *lock_colorCheckbutton;
+ GtkWidget *create_layermaskCheckbutton;
+
+
+ GapFgExtractValues *vals;
+};
+
+
+
+
+/* --------------------------------------
+ * p_update_widget_sensitivity
+ * --------------------------------------
+ */
+static void
+p_update_widget_sensitivity (FgExtractDialogGuiStuff *guiStuffPtr)
+{
+ gtk_widget_set_sensitive(guiStuffPtr->triMapCombo , TRUE);
+
+} /* end p_update_widget_sensitivity */
+
+
+/* --------------------------------------
+ * p_init_widget_values
+ * --------------------------------------
+ * update GUI widgets to reflect the current values.
+ */
+static void
+p_init_widget_values(FgExtractDialogGuiStuff *guiStuffPtr)
+{
+ gint comboInitalValue;
+
+ comboInitalValue = -1;
+
+ if(guiStuffPtr == NULL)
+ {
+ return;
+ }
+ if(guiStuffPtr->vals == NULL)
+ {
+ return;
+ }
+
+ /* init spnbuttons */
+ gtk_adjustment_set_value(GTK_ADJUSTMENT(guiStuffPtr->colordiff_threshold_spinbutton_adj)
+ , (gfloat)guiStuffPtr->vals->colordiff_threshold);
+
+
+ /* init checkbuttons */
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (guiStuffPtr->create_resultCheckbutton)
+ , guiStuffPtr->vals->create_result);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (guiStuffPtr->lock_colorCheckbutton)
+ , guiStuffPtr->vals->lock_color);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (guiStuffPtr->create_layermaskCheckbutton)
+ , guiStuffPtr->vals->create_layermask);
+
+ if (guiStuffPtr->vals->tri_map_drawable_id == GAP_FG_USE_LAYER_MASK)
+ {
+ comboInitalValue = GAP_FG_USE_LAYER_MASK;
+ }
+ else if(gimp_drawable_is_valid(guiStuffPtr->vals->tri_map_drawable_id))
+ {
+ comboInitalValue = guiStuffPtr->vals->tri_map_drawable_id;
+ }
+
+ if (comboInitalValue != -1)
+ {
+ gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (guiStuffPtr->triMapCombo), comboInitalValue);
+ }
+
+
+} /* end p_init_widget_values */
+
+
+/* --------------------------------------
+ * on_gboolean_button_update
+ * --------------------------------------
+ */
+static void
+on_gboolean_button_update (GtkWidget *widget,
+ gpointer data)
+{
+ FgExtractDialogGuiStuff *guiStuffPtr;
+ gint *toggle_val = (gint *) data;
+
+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)))
+ {
+ *toggle_val = TRUE;
+ }
+ else
+ {
+ *toggle_val = FALSE;
+ }
+ gimp_toggle_button_sensitive_update (GTK_TOGGLE_BUTTON (widget));
+
+ guiStuffPtr = (FgExtractDialogGuiStuff *) g_object_get_data (G_OBJECT (widget), "guiStuffPtr");
+ if(guiStuffPtr != NULL)
+ {
+ p_update_widget_sensitivity (guiStuffPtr);
+ }
+}
+
+
+/* ---------------------------------
+ * p_fg_extract_response
+ * ---------------------------------
+ */
+static void
+p_fg_extract_response (GtkWidget *widget,
+ gint response_id,
+ FgExtractDialogGuiStuff *guiStuffPtr)
+{
+ GtkWidget *dialog;
+
+ switch (response_id)
+ {
+ case GAP_FOREGROUND_EXTRACT_RESPONSE_RESET:
+ if(guiStuffPtr)
+ {
+ /* rset default values */
+ gap_fg_matting_init_default_vals(guiStuffPtr->vals);
+ p_init_widget_values(guiStuffPtr);
+ p_update_widget_sensitivity (guiStuffPtr);
+ }
+ break;
+
+ case GTK_RESPONSE_OK:
+ if(guiStuffPtr)
+ {
+ if (GTK_WIDGET_VISIBLE (guiStuffPtr->shell))
+ {
+ gtk_widget_hide (guiStuffPtr->shell);
+ }
+ guiStuffPtr->run = TRUE;
+ }
+
+ default:
+ dialog = NULL;
+ if(guiStuffPtr)
+ {
+ dialog = guiStuffPtr->shell;
+ if(dialog)
+ {
+ guiStuffPtr->shell = NULL;
+ gtk_widget_destroy (dialog);
+ }
+ }
+ gtk_main_quit ();
+ break;
+ }
+} /* end p_fg_extract_response */
+
+
+
+
+/* ------------------------------
+ * p_tri_map_menu_callback
+ * ------------------------------
+ *
+ */
+static void
+p_tri_map_menu_callback(GtkWidget *widget, gint32 *layerId)
+{
+ gint value;
+
+ gimp_int_combo_box_get_active (GIMP_INT_COMBO_BOX (widget), &value);
+
+ if(gap_debug)
+ {
+ printf("p_tri_map_menu_callback: LayerAddr:%d value:%d\n"
+ ,(int)layerId
+ ,(int)value
+ );
+ }
+
+ if(layerId != NULL)
+ {
+ if (value == GAP_FG_USE_LAYER_MASK)
+ {
+ *layerId = GAP_FG_USE_LAYER_MASK;
+ }
+ else
+ {
+ *layerId = value;
+ }
+ }
+
+
+} /* end p_tri_map_menu_callback */
+
+
+/* ------------------------------
+ * p_tri_map_combo_constrain
+ * ------------------------------
+ * cecks available layers to be potential tri-map candiates
+ * INDEXED layers and the input drawable are exluded
+ */
+static gint
+p_tri_map_combo_constrain(gint32 image_id, gint32 drawable_id, FgExtractDialogGuiStuff *guiStuffPtr)
+{
+ gint32 processedImageId;
+
+ if(gap_debug)
+ {
+ printf("p_tri_map_combo_constrain PROCEDURE image_id:%d drawable_id:%d guiStuffPtr:%d\n"
+ ,(int)image_id
+ ,(int)drawable_id
+ ,(int)guiStuffPtr
+ );
+ }
+
+ if(drawable_id < 0)
+ {
+ /* gimp 1.1 makes a first call of the constraint procedure
+ * with drawable_id = -1, and skips the whole image if FALSE is returned
+ */
+ return(TRUE);
+ }
+
+ if(gimp_drawable_is_valid(drawable_id) != TRUE)
+ {
+ if(gap_debug)
+ {
+ printf("-- drawable_id:%d gimp_drawable_is_valid --\n", (int)drawable_id);
+ }
+ return(FALSE);
+ }
+
+ processedImageId = gimp_drawable_get_image(guiStuffPtr->drawable_id);
+
+ if(image_id != processedImageId)
+ {
+ if ((gimp_drawable_width(drawable_id) != gimp_drawable_width(guiStuffPtr->drawable_id))
+ || (gimp_drawable_height(drawable_id) != gimp_drawable_height(guiStuffPtr->drawable_id)))
+ {
+ printf("-- drawable_id:%d has different size --\n", (int)drawable_id);
+ return (FALSE);
+ }
+ }
+
+ if(drawable_id == guiStuffPtr->drawable_id)
+ {
+ /* disable selection of the input drawable in the tri-mask combo box
+ */
+ printf("-- drawable_id:%d is the input drawable --\n", (int)drawable_id);
+ return(FALSE);
+ }
+
+ if(!gimp_drawable_is_rgb(drawable_id))
+ {
+ if(!gimp_drawable_is_gray(drawable_id))
+ {
+ if(gap_debug)
+ {
+ printf("-- drawable_id:%d is NOT (RGB or GRAY) --\n", (int)drawable_id);
+ }
+ /* disable indexed layers */
+ return (FALSE);
+ }
+ }
+
+ if(gap_debug)
+ {
+ printf("++ drawable_id:%d is ACCEPTABLE as tri map --\n", (int)drawable_id);
+ }
+ guiStuffPtr->countTriMapCanidates++;
+
+ return(TRUE);
+
+} /* end p_tri_map_combo_constrain */
+
+
+/* ------------------------------
+ * do_dialog
+ * ------------------------------
+ * create and show the dialog window
+ */
+static void
+do_dialog (FgExtractDialogGuiStuff *guiStuffPtr, GapFgExtractValues *cuvals)
+{
+ GtkWidget *vbox;
+
+ GtkWidget *dialog1;
+ GtkWidget *dialog_vbox1;
+ GtkWidget *frame1;
+ GtkWidget *vbox1;
+ GtkWidget *label;
+ GtkWidget *table1;
+ GtkObject *spinbutton_adj;
+ GtkWidget *spinbutton;
+ GtkWidget *dialog_action_area1;
+ GtkWidget *checkbutton;
+ GtkWidget *combo;
+ gint row;
+
+
+ /* Init UI */
+ gimp_ui_init ("Forground Extract", FALSE);
+
+
+ /* The dialog1 */
+ guiStuffPtr->run = FALSE;
+ guiStuffPtr->vals = cuvals;
+
+
+ /* The dialog1 and main vbox */
+ dialog1 = gimp_dialog_new (_("Foreground-Extract"), "foreground_extract",
+ NULL, 0,
+ gimp_standard_help_func, PLUG_IN_HELP_ID,
+
+ GIMP_STOCK_RESET, GAP_FOREGROUND_EXTRACT_RESPONSE_RESET,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_OK, GTK_RESPONSE_OK,
+ NULL);
+
+ guiStuffPtr->shell = dialog1;
+
+
+ /*
+ * g_object_set_data (G_OBJECT (dialog1), "dialog1", dialog1);
+ * gtk_window_set_title (GTK_WINDOW (dialog1), _("dialog1"));
+ */
+
+
+ g_signal_connect (G_OBJECT (dialog1), "response",
+ G_CALLBACK (p_fg_extract_response),
+ guiStuffPtr);
+
+ /* the vbox */
+ vbox = gtk_vbox_new (FALSE, 2);
+ gtk_container_set_border_width (GTK_CONTAINER (vbox), 2);
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog1)->vbox), vbox,
+ TRUE, TRUE, 0);
+ gtk_widget_show (vbox);
+
+ dialog_vbox1 = GTK_DIALOG (dialog1)->vbox;
+ g_object_set_data (G_OBJECT (dialog1), "dialog_vbox1", dialog_vbox1);
+ gtk_widget_show (dialog_vbox1);
+
+
+
+ /* the frame */
+ frame1 = gimp_frame_new (_("Options"));
+
+ gtk_widget_show (frame1);
+ gtk_box_pack_start (GTK_BOX (dialog_vbox1), frame1, TRUE, TRUE, 0);
+ gtk_container_set_border_width (GTK_CONTAINER (frame1), 2);
+
+ vbox1 = gtk_vbox_new (FALSE, 0);
+ gtk_container_add (GTK_CONTAINER (frame1), vbox1);
+ gtk_widget_show (vbox1);
+
+
+ /* table1 for ... */
+ table1 = gtk_table_new (4, 2, FALSE);
+ gtk_widget_show (table1);
+ gtk_box_pack_start (GTK_BOX (vbox1), table1, TRUE, TRUE, 0);
+ gtk_container_set_border_width (GTK_CONTAINER (table1), 4);
+
+
+ row = 0;
+
+ /* the tri-map drawable selection combo box */
+ label = gtk_label_new (_("Tri-Map:"));
+ guiStuffPtr->triMapLabel = label;
+ gtk_widget_show (label);
+ gtk_table_attach (GTK_TABLE (table1), label, 0, 1, row, row+1,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
+
+ combo = gimp_layer_combo_box_new (p_tri_map_combo_constrain, guiStuffPtr);
+ guiStuffPtr->triMapCombo = combo;
+ gtk_table_attach(GTK_TABLE(table1), combo, 1, 4, row, row+1,
+ GTK_EXPAND | GTK_FILL, 0, 0, 0);
+
+ gimp_help_set_help_data(combo,
+ _("Select the tri_map layer (or layermask). "
+ " the tri-map shall be of same size as the input layer and "
+ " provides a rough user selection "
+ " where WHITE pixels in the tri map defines FOREGROUND (eg. opaque result) "
+ " BLACK pixels define BACKGROUND (eg. transparent result)"
+ " GRAY pixels (value 1 upto 240) ar marked as Undefined "
+ " (eg. opacity to be processed by this filter.) )")
+ , NULL);
+
+ /* "Layermask" combo entry (is added in case the input drawable has a layermask that can be used as tri-mask) */
+ {
+ gint32 layerMaskId;
+ gint comboInitalValue;
+
+ comboInitalValue = -1;
+ if(gimp_drawable_is_valid(guiStuffPtr->vals->tri_map_drawable_id))
+ {
+ comboInitalValue = guiStuffPtr->vals->tri_map_drawable_id;
+ }
+ layerMaskId = gimp_layer_get_mask(guiStuffPtr->drawable_id);
+ if (layerMaskId >= 0)
+ {
+ gimp_int_combo_box_prepend (GIMP_INT_COMBO_BOX (combo),
+ GIMP_INT_STORE_VALUE, GAP_FG_USE_LAYER_MASK,
+ GIMP_INT_STORE_LABEL, _("Layermask"),
+ GIMP_INT_STORE_STOCK_ID, GIMP_STOCK_LAYER_MASK,
+ -1);
+ if (comboInitalValue == -1)
+ {
+ comboInitalValue = GAP_FG_USE_LAYER_MASK;
+ }
+ guiStuffPtr->countTriMapCanidates++;
+ }
+
+
+ gimp_int_combo_box_connect (GIMP_INT_COMBO_BOX (combo),
+ comboInitalValue,
+ G_CALLBACK (p_tri_map_menu_callback),
+ &guiStuffPtr->vals->tri_map_drawable_id);
+ }
+ gtk_widget_show(combo);
+
+
+
+
+ row++;
+
+ /* create_layermask checkbutton */
+ label = gtk_label_new (_("Create Layermask:"));
+ gtk_widget_show (label);
+ gtk_table_attach (GTK_TABLE (table1), label, 0, 1, row, row+1,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
+
+
+ checkbutton = gtk_check_button_new_with_label (" ");
+ g_object_set_data (G_OBJECT (checkbutton), "guiStuffPtr", guiStuffPtr);
+ guiStuffPtr->create_layermaskCheckbutton = checkbutton;
+ gimp_help_set_help_data (checkbutton, _("ON: render opacity by creating a new layer mask, "
+ "OFF: apply rendered opacity to the alpha channel"), NULL);
+ gtk_widget_show (checkbutton);
+ gtk_table_attach( GTK_TABLE(table1), checkbutton, 1, 2, row, row+1,
+ GTK_FILL, 0, 0, 0 );
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (checkbutton), cuvals->create_layermask);
+ g_signal_connect (checkbutton, "toggled",
+ G_CALLBACK (on_gboolean_button_update),
+ &cuvals->create_layermask);
+
+ row++;
+
+
+ /* lock_color checkbutton */
+ label = gtk_label_new (_("Lock Colors:"));
+ gtk_widget_show (label);
+ gtk_table_attach (GTK_TABLE (table1), label, 0, 1, row, row+1,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
+
+ checkbutton = gtk_check_button_new_with_label (" ");
+ g_object_set_data (G_OBJECT (checkbutton), "guiStuffPtr", guiStuffPtr);
+ guiStuffPtr->lock_colorCheckbutton = checkbutton;
+ gimp_help_set_help_data (checkbutton, _("ON: Keep RGB channels of the input layer, "
+ "OFF: allow Background color removal in processed undefined regions"), NULL);
+ gtk_widget_show (checkbutton);
+ gtk_table_attach( GTK_TABLE(table1), checkbutton, 1, 2, row, row+1,
+ GTK_FILL, 0, 0, 0 );
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (checkbutton), cuvals->lock_color);
+ g_signal_connect (checkbutton, "toggled",
+ G_CALLBACK (on_gboolean_button_update),
+ &cuvals->lock_color);
+
+ row++;
+
+ /* create_result (create_result checkbutton */
+ label = gtk_label_new (_("Create Result Layer:"));
+ //gtk_widget_show (label);
+ gtk_table_attach (GTK_TABLE (table1), label, 0, 1, row, row+1,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
+
+
+ checkbutton = gtk_check_button_new_with_label (" ");
+ g_object_set_data (G_OBJECT (checkbutton), "guiStuffPtr", guiStuffPtr);
+ guiStuffPtr->create_resultCheckbutton = checkbutton;
+ //gtk_widget_show (checkbutton);
+ gimp_help_set_help_data (checkbutton, _("ON: create a new layer as result of the foreground extraction processing. "
+ "OFF: render transparency and background color removal on "
+ "the input drawable"), NULL);
+ gtk_table_attach( GTK_TABLE(table1), checkbutton, 1, 2, row, row+1,
+ GTK_FILL, 0, 0, 0 );
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (checkbutton), cuvals->create_result);
+ g_signal_connect (checkbutton, "toggled",
+ G_CALLBACK (on_gboolean_button_update),
+ &cuvals->create_result);
+
+
+ row++;
+
+
+
+ /* colordiff_threshold spinbutton */
+ label = gtk_label_new (_("Color Diff Threshold"));
+ //gtk_widget_show (label);
+ gtk_table_attach (GTK_TABLE (table1), label, 0, 1, row, row+1,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
+ spinbutton_adj = gtk_adjustment_new (cuvals->colordiff_threshold, 0.0, 100, 0.1, 1, 0);
+ spinbutton = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton_adj), 1, 2);
+ gimp_help_set_help_data (spinbutton, _("sensitivity for color comparison"), NULL);
+ //gtk_widget_show (spinbutton);
+ gtk_table_attach (GTK_TABLE (table1), spinbutton, 1, 2, row, row+1,
+ (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ g_signal_connect (G_OBJECT (spinbutton_adj), "value_changed", G_CALLBACK (gimp_double_adjustment_update),
+ &cuvals->colordiff_threshold);
+ guiStuffPtr->colordiff_threshold_spinbutton_adj = spinbutton_adj;
+ guiStuffPtr->colordiff_threshold_spinbutton = spinbutton;
+
+
+
+
+
+
+ /* -- */
+
+
+ dialog_action_area1 = GTK_DIALOG (dialog1)->action_area;
+ gtk_widget_show (dialog_action_area1);
+ gtk_container_set_border_width (GTK_CONTAINER (dialog_action_area1), 10);
+
+ p_init_widget_values(guiStuffPtr);
+ p_update_widget_sensitivity (guiStuffPtr);
+
+ gtk_widget_show (dialog1);
+
+ gtk_main ();
+ gdk_flush ();
+
+
+} /* end do_dialog */
+
+
+
+void
+gap_fg_matting_init_default_vals(GapFgExtractValues *fgVals)
+{
+ fgVals->create_result = TRUE;
+ fgVals->create_layermask = FALSE;
+ fgVals->lock_color = FALSE;
+ fgVals->colordiff_threshold = 1.0;
+}
+
+
+gboolean
+gap_fg_matting_dialog(GapFgExtractValues *fgVals)
+{
+ FgExtractDialogGuiStuff guiStuff;
+ FgExtractDialogGuiStuff *guiStuffPtr;
+
+ guiStuffPtr = &guiStuff;
+ guiStuffPtr->run = FALSE;
+ guiStuffPtr->countTriMapCanidates = 0;
+ guiStuffPtr->drawable_id = fgVals->input_drawable_id;
+
+ /* Get information from the dialog */
+ do_dialog(guiStuffPtr, fgVals);
+
+ return (guiStuffPtr->run);
+
+} /* end gap_fg_matting_dialog */
diff --git a/gap/gap_fg_matting_dialog.h b/gap/gap_fg_matting_dialog.h
new file mode 100644
index 0000000..1b16107
--- /dev/null
+++ b/gap/gap_fg_matting_dialog.h
@@ -0,0 +1,41 @@
+/* gap_fg_matting_dialog.h
+ * 2011.10.05 hof (Wolfgang Hofer)
+ *
+ * GAP ... Gimp Animation Plugins
+ *
+ * This Module contains:
+ * - stuff for the GUI dialog
+ * of the foreground selection via alpha matting plug-in.
+ *
+ */
+/* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef GAP_FG_MATTING_DIALOG_H
+#define GAP_FG_MATTING_DIALOG_H
+
+#include "libgimp/gimp.h"
+
+/*
+ * DIALOG and callback stuff
+ */
+gboolean gap_fg_matting_dialog(GapFgExtractValues *fgVals);
+void gap_fg_matting_init_default_vals(GapFgExtractValues *fgVals);
+
+
+#endif /* GAP_FG_MATTING_DIALOG_H */
diff --git a/gap/gap_fg_matting_exec.c b/gap/gap_fg_matting_exec.c
new file mode 100644
index 0000000..e3c2890
--- /dev/null
+++ b/gap/gap_fg_matting_exec.c
@@ -0,0 +1,572 @@
+/* gap_fg_matting_exec.c
+ * foreground extraction based on alpha matting algorithm.
+ * Render transparancy for a layer based on a tri-map drawable (provided by the user).
+ * The tri-map defines what pixels are FOREGROUND (white) BACKGROUND (black) or UNDEFINED (gray).
+ * foreground extraction affects the UNDEFINED pixels and calculates transparency for those pixels.
+ *
+ * This module provides the top level processing procedures
+ * and does some pre and postprocessing on the tri-map input.
+ * 2011/10/05
+ */
+/* 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
+ * (2011/10/05) 2.7.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_fg_matting_main.h"
+#include "gap_fg_matting_exec.h"
+#include "gap_fg_tile_manager.h"
+#include "gap_fg_matting_dialog.h"
+#include "gap_fg_matting.h"
+#include "gap_fg_regions.h"
+
+#include "gap-intl.h"
+
+
+static gboolean globalDoProgress;
+
+
+static GimpDrawable *globalDrawable = NULL;
+
+
+
+static gint32 gap_drawable_foreground_extract (GimpDrawable *drawable,
+ GimpDrawable *maskDrawable,
+ GapFgExtractValues *fgValPtr
+ );
+static GappMattingState * gap_drawable_foreground_extract_matting_init (GimpDrawable *drawable,
+ gint mask_x,
+ gint mask_y,
+ gint mask_width,
+ gint mask_height);
+static void gap_drawable_foreground_extract_matting (GimpDrawable *maskDrawable,
+ GimpDrawable *resultDrawable,
+ GappMattingState *state,
+ gfloat start_percentage
+ );
+static void gap_drawable_foreground_extract_matting_done (GappMattingState *state);
+
+static gint32 p_tri_map_preprocessing (GimpDrawable *drawable, GapFgExtractValues *fgValPtr, gint32 *dummyLayerId);
+
+
+
+/* ---------------------------------
+ * p_progressFunc
+ * ---------------------------------
+ * MattingProgressFunc
+ * progress callback function.
+ */
+static void
+p_progressFunc(gpointer progress_data, gdouble fraction)
+{
+ if(globalDoProgress)
+ {
+ gimp_progress_update(fraction);
+ }
+} /* end p_progressFunc */
+
+
+
+/* -----------------------------
+ * gap_fg_matting_exec_apply_run
+ * -----------------------------
+ * handle undo, progress init and
+ * apply the processing functions
+ */
+gint32
+gap_fg_matting_exec_apply_run (gint32 image_id, gint32 drawable_id
+ , gboolean doProgress, gboolean doFlush
+ , GapFgExtractValues *fgValPtr)
+{
+ gint32 retLayerId;
+ gint32 oldLayerMaskId;
+ gint32 triMapOrig;
+ gint32 triMapRelevant;
+ gint32 dummyLayerId;
+ GimpDrawable *maskDrawable;
+ GimpDrawable *activeDrawable;
+
+ /* dont operate on other drawables than layers */
+ g_return_val_if_fail (gimp_drawable_is_layer(drawable_id), -1);
+
+ globalDoProgress = doProgress;
+ triMapOrig = fgValPtr->tri_map_drawable_id;
+ /* try to use layermask as tri-mask
+ * in case negative id was specified by the caller
+ */
+ oldLayerMaskId = gimp_layer_get_mask(drawable_id);
+ if (fgValPtr->tri_map_drawable_id < 0)
+ {
+ fgValPtr->tri_map_drawable_id = oldLayerMaskId;
+ }
+
+ gimp_image_undo_group_start (image_id);
+
+ if (doProgress)
+ {
+ gimp_progress_init (_("Foreground Extract"));
+ }
+
+ activeDrawable = gimp_drawable_get (drawable_id);
+
+ triMapRelevant = p_tri_map_preprocessing (activeDrawable, fgValPtr, &dummyLayerId);
+
+ maskDrawable = gimp_drawable_get(triMapRelevant);
+ if (maskDrawable == NULL)
+ {
+ gimp_image_undo_group_end (image_id);
+ gimp_drawable_detach (activeDrawable);
+
+ printf("ERROR: no valid tri-mask was specified\n");
+
+ return (-1);
+ }
+
+
+ if(gap_debug)
+ {
+ printf("gap_fg_matting_exec_apply_run START: drawableID:%d triMapOrig:%d tri_map_drawable_id:%d triMapRelevant:%d\n"
+ " create_layermask:%d lock_color:%d "
+ " create_result:%d colordiff_threshold:%.5f"
+ "\n"
+ , (int)drawable_id
+ , (int)triMapOrig
+ , (int)fgValPtr->tri_map_drawable_id
+ , (int)triMapRelevant
+ , (int)fgValPtr->create_layermask
+ , (int)fgValPtr->lock_color
+ , (int)fgValPtr->create_result
+ , (float)fgValPtr->colordiff_threshold
+ );
+ }
+
+ retLayerId = gap_drawable_foreground_extract (activeDrawable, maskDrawable, fgValPtr);
+
+ gimp_drawable_detach (maskDrawable);
+
+
+ if(dummyLayerId >= 0)
+ {
+ if(gap_debug)
+ {
+ printf("removing dummy layer:%d\n"
+ ,(int) dummyLayerId
+ );
+ }
+ gimp_image_remove_layer(image_id, dummyLayerId);
+ }
+
+ if (doProgress)
+ {
+ gimp_progress_update(1.0);
+ }
+
+ gimp_image_undo_group_end (image_id);
+
+ if(gap_debug)
+ {
+ printf("gap_fg_matting_exec_apply_run DONE: retLayerId:%d\n"
+ , (int)retLayerId
+ );
+ }
+
+ if (doFlush != FALSE)
+ {
+ gimp_drawable_flush (activeDrawable);
+ }
+
+ gimp_drawable_detach (activeDrawable);
+
+ return (retLayerId);
+} /* end gap_fg_matting_exec_apply_run */
+
+
+
+
+
+
+
+
+
+
+
+/* -----------------------
+ * p_tri_map_preprocessing
+ * -----------------------
+ * prepare the tri mask for processing
+ * - have bpp == 1
+ * - have same size and offset as the input drawable (that is a layer)
+ * - pixel values >= 240 are set to value 240 (MATTING_USER_FOREGROUND)
+ * - in case the input layer already has an alpha channel
+ * all fully transparent (alpha == 0) pixels are also set 0 (MATTING_USER_BACKGROUND)
+ * in the tri map to keep pixels fully transparent. (such pixels typicall do not
+ * have a useful color information in the RGB channels)
+ *
+ *
+ * in case the user provided the tri map as layer or channel that is NOT the layermask of the input layer
+ * we create a new dummy layer with same size and offset as the input layer
+ * and add a layermask to this dummy layer.
+ * The layermask of the dummy layer is then filled with the intersecting grayscale copy
+ * of the user-provided triMap drawable and will be used as tri map in the alpha matting processing.
+ *
+ * returns the dawable Id of the relevant TRI MAP that fulfills the conditons listed above.
+ */
+static gint32
+p_tri_map_preprocessing (GimpDrawable *drawable, GapFgExtractValues *fgValPtr, gint32 *dummyLayerId)
+{
+ gint32 prepocessedTriMapLayerId;
+ gint32 inputLayerMaskId;
+ gint32 imageId;
+
+ *dummyLayerId = -1;
+ imageId = gimp_drawable_get_image(drawable->drawable_id);
+
+
+ inputLayerMaskId = gimp_layer_get_mask(drawable->drawable_id);
+ if (fgValPtr->tri_map_drawable_id == inputLayerMaskId)
+ {
+ prepocessedTriMapLayerId = inputLayerMaskId;
+ }
+ else
+ {
+ gint offset_x;
+ gint offset_y;
+ gint32 dummyLayerMaskId;
+ gint32 l_fsel_layer_id;
+
+ *dummyLayerId = gimp_layer_new(imageId
+ , "DUMMY"
+ , drawable->width
+ , drawable->height
+ , GIMP_RGBA_IMAGE
+ , 100.0 /* full opacity */
+ , GIMP_NORMAL_MODE /* normal mode */
+ );
+
+ /* get offsets of the input drawable (layer) within the image */
+ gimp_drawable_offsets (drawable->drawable_id, &offset_x, &offset_y);
+
+ /* add dummy layer (of same size at same offsets) to the same image */
+ gimp_image_add_layer(imageId, *dummyLayerId, -1 /* stackposition */ );
+ gimp_layer_set_offsets(*dummyLayerId, offset_x, offset_y);
+
+ /* create a new layermask (black is full transparent */
+ dummyLayerMaskId = gimp_layer_create_mask(*dummyLayerId, GIMP_ADD_BLACK_MASK);
+ gimp_layer_add_mask(*dummyLayerId, dummyLayerMaskId);
+
+ gimp_edit_copy(fgValPtr->tri_map_drawable_id);
+ l_fsel_layer_id = gimp_edit_paste(dummyLayerMaskId, FALSE);
+ gimp_floating_sel_anchor(l_fsel_layer_id);
+
+ prepocessedTriMapLayerId = dummyLayerMaskId;
+ }
+
+ gap_fg_rgn_tri_map_normalize(drawable, prepocessedTriMapLayerId);
+
+ return(prepocessedTriMapLayerId);
+
+} /* end p_tri_map_preprocessing */
+
+
+
+/* -------------------------------
+ * gap_drawable_foreground_extract
+ * -------------------------------
+ * perform foreground extraction.
+ * This is done in 3 steps INIT, EXTRACTION, DONE (e.g. cleanup)
+ */
+static gint32
+gap_drawable_foreground_extract (GimpDrawable *drawable,
+ GimpDrawable *maskDrawable,
+ GapFgExtractValues *fgValPtr
+ )
+{
+ GappMattingState *state;
+ gint32 resultLayerId;
+ gint mask_offset_x;
+ gint mask_offset_y;
+
+ resultLayerId = -1;
+
+ /* get mask offsets within the image
+ * - in case mask is a channel offsets are always 0)
+ * - in case mask is a layer retieve its offsets
+ */
+ gimp_drawable_offsets (drawable->drawable_id, &mask_offset_x, &mask_offset_y);
+
+ state = gap_drawable_foreground_extract_matting_init (drawable,
+ mask_offset_x, mask_offset_y,
+ maskDrawable->width,
+ maskDrawable->height
+ );
+
+ if (state)
+ {
+ gint32 imageId;
+
+ imageId = gimp_drawable_get_image(drawable->drawable_id);
+ resultLayerId = gimp_layer_new(imageId
+ , "FG"
+ , drawable->width
+ , drawable->height
+ , GIMP_RGBA_IMAGE
+ , 100.0 /* full opacity */
+ , GIMP_NORMAL_MODE /* normal mode */
+ );
+ if (resultLayerId != -1)
+ {
+ GimpDrawable *resultDrawable;
+
+ resultDrawable = gimp_drawable_get(resultLayerId);
+ if (resultDrawable != NULL)
+ {
+ gint offset_x;
+ gint offset_y;
+ gboolean resultUpdateRequired;
+
+
+ resultUpdateRequired = FALSE;
+
+ /* get offsets of the input drawable (layer) within the image */
+ gimp_drawable_offsets (drawable->drawable_id, &offset_x, &offset_y);
+
+ /* add resulting layer (of same size at same offsets) to the same image */
+ gimp_image_add_layer(imageId, resultLayerId, -1 /* stackposition */ );
+ gimp_layer_set_offsets(resultLayerId, offset_x, offset_y);
+
+ /* perform the foreground extraction */
+ gap_drawable_foreground_extract_matting (maskDrawable, resultDrawable, state,
+ 0.0 // start_percentage 0 (non-interactive shall always start rendering immediate
+ );
+
+ /* clean up after fg extract is done */
+ gap_drawable_foreground_extract_matting_done (state);
+
+ /* postprocessing */
+ if (fgValPtr->lock_color)
+ {
+ if(gap_debug)
+ {
+ printf("postprocessing: restore resultDrawable:%d RGB channels from original drawable:%d\n"
+ ,(int)resultDrawable->drawable_id
+ ,(int)drawable->drawable_id
+ );
+ }
+ resultUpdateRequired = TRUE;
+ gap_fg_rgn_copy_rgb_channels(drawable, resultDrawable);
+ }
+
+ if (fgValPtr->create_layermask)
+ {
+ gint32 resultLayerMaskId;
+
+ /* create a new layermask (from alpha channel) */
+ resultLayerMaskId = gimp_layer_create_mask(resultLayerId, GIMP_ADD_ALPHA_MASK);
+ gimp_layer_add_mask(resultLayerId, resultLayerMaskId);
+ if (gimp_drawable_has_alpha(drawable->drawable_id))
+ {
+ if(gap_debug)
+ {
+ printf("postprocessing: restore resultDrawable:%d ALPHA channel from original drawable:%d\n"
+ ,(int)resultDrawable->drawable_id
+ ,(int)drawable->drawable_id
+ );
+ }
+ /* copy the original alpha channel to the result layer */
+ gap_fg_rgn_copy_alpha_channel(drawable, resultDrawable);
+ resultUpdateRequired = TRUE;
+ }
+ }
+
+ if(resultUpdateRequired)
+ {
+ gimp_drawable_update (resultDrawable->drawable_id
+ , 0, 0
+ , resultDrawable->width, resultDrawable->height
+ );
+ }
+
+
+ gimp_drawable_detach (resultDrawable);
+ }
+ }
+ }
+
+ return (resultLayerId);
+
+} /* end gap_drawable_foreground_extract */
+
+
+
+/* --------------------------------------------
+ * gap_drawable_foreground_extract_matting_init
+ * --------------------------------------------
+ *
+ */
+static GappMattingState *
+gap_drawable_foreground_extract_matting_init (GimpDrawable *drawable,
+ gint mask_x,
+ gint mask_y,
+ gint mask_width,
+ gint mask_height)
+{
+ GappMattingState *state;
+ GappTileManager *tm;
+ const guchar *colormap = NULL;
+ gboolean intersect;
+ gint offset_x;
+ gint offset_y;
+ gint is_x, is_y, is_width, is_height;
+
+ if(gap_debug)
+ {
+ printf("init: START\n");
+ }
+
+ /* get offsets within the image */
+ gimp_drawable_offsets (drawable->drawable_id, &offset_x, &offset_y);
+
+ intersect = gimp_rectangle_intersect (offset_x, offset_y,
+ drawable->width,
+ drawable->height,
+ mask_x, mask_y, mask_width, mask_height,
+ &is_x, &is_y, &is_width, &is_height);
+
+
+ /* FIXME:
+ * Clear the mask outside the rectangle that we are working on?
+ */
+
+ if (! intersect)
+ {
+ return NULL;
+ }
+
+ tm = gapp_tile_manager_new(drawable);
+
+ state = matting_init (tm, colormap,
+ offset_x, offset_y,
+ is_x, is_y, is_width, is_height);
+ if(gap_debug)
+ {
+ printf("init: END state:%d\n"
+ ,(int) state
+ );
+ }
+
+ return (state);
+
+
+} /* end gap_drawable_foreground_extract_matting_init */
+
+
+/* ---------------------------------------
+ * gap_drawable_foreground_extract_matting
+ * ---------------------------------------
+ *
+ */
+static void
+gap_drawable_foreground_extract_matting (GimpDrawable *maskDrawable,
+ GimpDrawable *resultDrawable,
+ GappMattingState *state,
+ gfloat start_percentage
+ )
+{
+ GappTileManager *tmMask;
+ GappTileManager *tmResult;
+ gint x1, y1;
+ gint x2, y2;
+ gpointer progress_data;
+ gdouble progressDataUnused;
+
+ if(gap_debug)
+ {
+ printf("extract_matting: START\n");
+ }
+
+ g_return_if_fail (state != NULL);
+
+ progress_data = &progressDataUnused;
+
+ x1 = 0;
+ y1 = 0;
+ x2 = maskDrawable->width;
+ y2 = maskDrawable->height;
+
+ tmMask = gapp_tile_manager_new(maskDrawable);
+ tmResult = gapp_tile_manager_new(resultDrawable);
+
+ matting_foreground_extract (state,
+ tmMask, x1, y1, x2, y2,
+ start_percentage,
+ (MattingProgressFunc) p_progressFunc,
+ progress_data,
+ tmResult);
+
+
+ gimp_drawable_update (resultDrawable->drawable_id, x1, y1, x2, y2);
+ gimp_drawable_update (maskDrawable->drawable_id, x1, y1, x2, y2);
+
+ if(gap_debug)
+ {
+ printf("extract_matting: END\n");
+ }
+
+} /* end gap_drawable_foreground_extract_matting */
+
+
+/* --------------------------------------------
+ * gap_drawable_foreground_extract_matting_done
+ * --------------------------------------------
+ *
+ */
+static void
+gap_drawable_foreground_extract_matting_done (GappMattingState *state)
+{
+ if(gap_debug)
+ {
+ printf("matting_cleanup: START\n");
+ }
+
+ g_return_if_fail (state != NULL);
+
+
+ matting_done (state);
+
+ if(gap_debug)
+ {
+ printf("matting_cleanup: END\n");
+ }
+
+} /* end gap_drawable_foreground_extract_matting_done */
+
+
+
+
diff --git a/gap/gap_fg_matting_exec.h b/gap/gap_fg_matting_exec.h
new file mode 100644
index 0000000..0e715c9
--- /dev/null
+++ b/gap/gap_fg_matting_exec.h
@@ -0,0 +1,46 @@
+/* gap_fg_matting_exec.h
+ * foreground extraction based on alpha matting algorithm.
+ * Render transparancy for a layer based on a tri-map drawable (provided by the user).
+ * The tri-map defines what pixels are FOREGROUND (white) BACKGROUND (black) or UNDEFINED (gray).
+ * foreground extraction affects the UNDEFINED pixels and calculates transparency for those pixels.
+ *
+ * This module provides the top level processing procedures
+ * 2011/10/05
+ */
+/* 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
+ * (2011/10/05) 2.7.0 hof: created
+ */
+#ifndef GAP_FG_MATTING_EXEC_H
+#define GAP_FG_MATTING_EXEC_H
+
+#include <gtk/gtk.h>
+#include <libgimp/gimp.h>
+#include <libgimp/gimpui.h>
+
+#include "gap_fg_matting_main.h"
+
+
+gint
+gap_fg_matting_exec_apply_run (gint32 image_id, gint32 drawable_id
+ , gboolean doProgress, gboolean doFlush
+ , GapFgExtractValues *fgValPtr);
+
+#endif /* GAP_FG_MATTING_EXEC_H */
diff --git a/gap/gap_fg_matting_main.c b/gap/gap_fg_matting_main.c
new file mode 100644
index 0000000..f9ef6ec
--- /dev/null
+++ b/gap/gap_fg_matting_main.c
@@ -0,0 +1,312 @@
+/* gap_fg_matting_main.c
+ * foreground extraction based on alpha matting algorithm.
+ * Render transparancy for a layer based on a tri-map drawable (provided by the user).
+ * The tri-map defines what pixels are FOREGROUND (white) BACKGROUND (black) or UNDEFINED (gray).
+ * foreground extraction affects the UNDEFINED pixels and calculates transparency for those pixels.
+ *
+ * This module handles PDB registration as GIMP plug-in
+ * 2011/10/05
+ */
+/* 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
+ * (2011/10/05) 2.7.0 hof: created
+ */
+int gap_debug = 1; /* 1 == print debug infos , 0 dont print debug infos */
+#define GAP_DEBUG_DECLARED 1
+
+
+#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_fg_matting_main.h"
+#include "gap_fg_matting_exec.h"
+#include "gap_fg_tile_manager.h"
+#include "gap_fg_matting_dialog.h"
+#include "gap_fg_matting.h"
+#include "gap_fg_regions.h"
+
+#include "gap-intl.h"
+
+static GapFgExtractValues fgVals =
+{
+ -1 /* input_drawable_id */
+ , -1 /* tri_map_drawable_id */
+ , FALSE /* create_layermask */
+ , TRUE /* lock_color */
+// , TRUE /* create_result */
+// , 1.0 /* colordiff_threshold */
+};
+
+
+
+
+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 gint32 gap_drawable_foreground_extract (GimpDrawable *drawable,
+ GimpDrawable *maskDrawable,
+ GapFgExtractValues *fgValPtr
+ );
+static GappMattingState * gap_drawable_foreground_extract_matting_init (GimpDrawable *drawable,
+ gint mask_x,
+ gint mask_y,
+ gint mask_width,
+ gint mask_height);
+static void gap_drawable_foreground_extract_matting (GimpDrawable *maskDrawable,
+ GimpDrawable *resultDrawable,
+ GappMattingState *state,
+ gfloat start_percentage
+ );
+static void gap_drawable_foreground_extract_matting_done (GappMattingState *state);
+
+static gint32 p_tri_map_preprocessing (GimpDrawable *drawable, GapFgExtractValues *fgValPtr, gint32 *dummyLayerId);
+
+
+
+/* Global Variables */
+GimpPlugInInfo PLUG_IN_INFO =
+{
+ NULL, /* init_proc */
+ NULL, /* quit_proc */
+ query, /* query_proc */
+ run /* run_proc */
+};
+
+static const GimpParamDef in_args[] =
+{
+ { GIMP_PDB_INT32, "run-mode", "Interactive, non-interactive" },
+ { GIMP_PDB_IMAGE, "image", "Input image" },
+ { GIMP_PDB_DRAWABLE, "drawable", "Input layer (RGB or RGBA)" },
+ { GIMP_PDB_DRAWABLE, "tri-mask", "tri-mask drawable that defines "
+ "konwn forground (>= 240), known background (0) and unkonwn (128) values"
+ "This drawable must have same size as the Input-Layer "
+ "specify -1 to use the layer-mask of the input drawable as tri-map."},
+ { GIMP_PDB_INT32, "create-result", "0 .. overwrite the input layer with the processing result. "
+ "1 .. return the result as new layer (and add the resulting layer above the input layer)" },
+ { GIMP_PDB_INT32, "create-layermask", "0 .. render transparency as alpha channel. "
+ "1 .. render transparency as layer mask." },
+ { GIMP_PDB_INT32, "lock-color", "0 .. remove background color in semi transparent pixels. "
+ "1 .. keep original colors for all pixels (affect only transparency)." },
+ { GIMP_PDB_FLOAT, "colordiff-threshold", "colordiff threshold in range #.# to #.#." }
+};
+
+
+static const GimpParamDef return_vals[] = {
+ { GIMP_PDB_DRAWABLE, "resulting-layer", "depending on result-mode this may be the input drawable or a newly created layer" }
+};
+
+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)
+{
+
+ gimp_plugin_domain_register (GETTEXT_PACKAGE, LOCALEDIR);
+
+
+ /* the actual installation of the plugin */
+ gimp_install_procedure (PLUG_IN_NAME,
+ "Set layer opacity by foreground extraction based on alpha matting algorithm.",
+ "This plug-in renders the opacity for the specified Input drawable (a layer), "
+ "according to the supplied tri-mask, where the tri mask defines the opacity in the corresponding "
+ "pixel in the resulting layer. "
+ "White pixels (>= 240) in the tri-mask will set corresponding result pixels to fully opaque, "
+ "Black pixels (0) in the tri-mask will set corresponding result pixels to fully tranparent, "
+ "Gray pixels in the tri-mask mark UNDEFINED areas and will trigger cthe calculation of transparency (and optionally color) "
+ "of the corresponding result pixel, depending on its color compared with near foreground and backround pixels. "
+ "the result is written to a newly created layer or optionally overwrites the input layer. "
+ "in case where the input layer has already an alpha channel fully transparent pixels in the input layer"
+ "are not affected "
+ "(e.g. keep their full transparency, even if the tri-map marks this pixels as foreground) "
+ " ",
+ PLUG_IN_AUTHOR,
+ PLUG_IN_COPYRIGHT,
+ GAP_VERSION_WITH_DATE,
+ N_("Foreground Extract..."),
+ 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/");
+ const char *menupath_image_layer_tranparency = N_("<Image>/Layer/Transparency/");
+
+
+ //gimp_plugin_menu_branch_register("<Image>", "Video");
+ //gimp_plugin_menu_branch_register("<Image>/Video", "Layer");
+
+ gimp_plugin_menu_register (PLUG_IN_NAME, menupath_image_video_layer_attr);
+ gimp_plugin_menu_register (PLUG_IN_NAME, menupath_image_layer_tranparency);
+ }
+
+} /* 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;
+ gint32 activeDrawableId = -1;
+ gboolean doProgress;
+
+
+
+ /* 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);
+ }
+
+
+ doProgress = FALSE;
+
+ /* 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;
+
+ gap_fg_matting_init_default_vals(&fgVals);
+
+ /* get image and drawable */
+ image_id = param[1].data.d_int32;
+ activeDrawableId = param[2].data.d_drawable;
+
+ /* Possibly retrieve data from a previous run */
+ gimp_get_data (name, &fgVals);
+ fgVals.input_drawable_id = activeDrawableId;
+
+ /* how are we running today? */
+ switch (run_mode)
+ {
+ case GIMP_RUN_INTERACTIVE:
+ /* Get information from the dialog */
+ if (!gap_fg_matting_dialog(&fgVals))
+ {
+ /* return without processing in case the Dialog was cancelled */
+ return;
+ }
+ doProgress = TRUE;
+ break;
+
+ case GIMP_RUN_NONINTERACTIVE:
+ /* check to see if invoked with the correct number of parameters */
+ if (nparams == global_number_in_args)
+ {
+ fgVals.input_drawable_id = activeDrawableId;
+ fgVals.tri_map_drawable_id = (gint32) param[3].data.d_drawable;
+ fgVals.create_layermask = (param[4].data.d_int32 == 0) ? FALSE : TRUE;
+ fgVals.lock_color = (param[5].data.d_int32 == 0) ? FALSE : TRUE;
+// fgVals.create_result = (param[6].data.d_int32 == 0) ? FALSE : TRUE;
+// fgVals.colordiff_threshold = (gdouble) param[7].data.d_float;
+ }
+ else
+ {
+ status = GIMP_PDB_CALLING_ERROR;
+ }
+
+ break;
+
+ case GIMP_RUN_WITH_LAST_VALS:
+ break;
+
+ default:
+ break;
+ }
+
+ if (status == GIMP_PDB_SUCCESS)
+ {
+ gboolean doFlush;
+
+ doFlush = (run_mode == GIMP_RUN_INTERACTIVE);
+ fgVals.input_drawable_id = (gint32) param[2].data.d_drawable;
+
+ /* Run the main function */
+ values[1].data.d_drawable =
+ gap_fg_matting_exec_apply_run(image_id, param[2].data.d_drawable, doProgress, doFlush, &fgVals);
+ 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_INTERACTIVE)
+ {
+ gimp_displays_flush ();
+ }
+
+ /* Store variable states for next run */
+ if (run_mode == GIMP_RUN_INTERACTIVE)
+ {
+ gimp_set_data (name, &fgVals, sizeof (GapFgExtractValues));
+ }
+
+ }
+ values[0].data.d_status = status;
+
+
+} /* end run */
+
diff --git a/gap/gap_fg_matting_main.h b/gap/gap_fg_matting_main.h
new file mode 100644
index 0000000..1e9f2b9
--- /dev/null
+++ b/gap/gap_fg_matting_main.h
@@ -0,0 +1,61 @@
+/* gap_fg_matting_main.h
+ * foreground extraction based on alpha matting algorithm.
+ * Render transparancy for a layer based on a tri-map drawable (provided by the user).
+ * The tri-map defines what pixels are FOREGROUND (white) BACKGROUND (black) or UNDEFINED (gray).
+ * foreground extraction affects the UNDEFINED pixels and calculates transparency for those pixels.
+ *
+ * This module provides main data structures of the plug-in
+ * 2011/10/05
+ */
+/* 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
+ * (2011/10/05) 2.7.0 hof: created
+ */
+#ifndef GAP_FG_MATTING_MAIN_H
+#define GAP_FG_MATTING_MAIN_H
+
+#include <gtk/gtk.h>
+#include <libgimp/gimp.h>
+#include <libgimp/gimpui.h>
+
+
+/* Defines */
+#define PLUG_IN_NAME "plug-in-foreground-extract-matting"
+#define PLUG_IN_PRINT_NAME "Foreground Extract"
+#define PLUG_IN_IMAGE_TYPES "RGB*"
+#define PLUG_IN_AUTHOR "Wolfgang Hofer (hof gimp org)"
+#define PLUG_IN_COPYRIGHT "Jan Ruegg / Wolfgang Hofer"
+#define PLUG_IN_HELP_ID "plug-in-foreground-extract-matting"
+
+
+
+
+typedef struct GapFgExtractValues {
+ gint32 input_drawable_id;
+ gint32 tri_map_drawable_id;
+ gboolean create_result;
+ gboolean create_layermask;
+ gboolean lock_color;
+ gdouble colordiff_threshold;
+
+} GapFgExtractValues;
+
+
+#endif /* GAP_FG_MATTING_MAIN_H */
diff --git a/gap/gap_fg_regions.c b/gap/gap_fg_regions.c
new file mode 100644
index 0000000..fc59478
--- /dev/null
+++ b/gap/gap_fg_regions.c
@@ -0,0 +1,472 @@
+/* gap_fg_regions.c
+ * This module contains gimp region processing utilities
+ * intended as helper procedures for preprocessing and postprocessing
+ * for the foreground sextract plug-in.
+ * 2011/10/05
+ */
+/* 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
+ * (2011/10/05) 2.7.0 hof: created
+ */
+#include "config.h"
+
+#include <stdio.h>
+
+#include <gtk/gtk.h>
+#include <libgimp/gimp.h>
+
+#include "gap_fg_matting_main.h"
+#include "gap_fg_matting.h"
+#include "gap_fg_regions.h"
+
+#include "gap-intl.h"
+
+/* -------------------------------------
+ * p_rgn_render_copy_alpha_channel
+ * -------------------------------------
+ * copy RGB channels from src to dst region for the current Tile
+ * (src and dst must have same size, but may have bpp 3 or 4)
+ */
+static void
+p_rgn_render_copy_alpha_channel (const GimpPixelRgn *srcPR
+ ,const GimpPixelRgn *dstPR
+ , guint srcAlphaOffs, guint dstAlphaOffs
+ )
+{
+ guint row;
+ guchar* src = srcPR->data;
+ guchar* dst = dstPR->data;
+
+
+ for (row = 0; row < dstPR->h; row++)
+ {
+ guint col;
+ guint idxSrc;
+ guint idxDst;
+
+ idxSrc = 0;
+ idxDst = 0;
+
+ for(col = 0; col < dstPR->w; col++)
+ {
+ dst[idxDst + dstAlphaOffs] = src[idxSrc + srcAlphaOffs]; /* alpha */
+
+ idxSrc += srcPR->bpp;
+ idxDst += dstPR->bpp;
+ }
+
+ src += srcPR->rowstride;
+ dst += dstPR->rowstride;
+ }
+} /* end p_rgn_render_copy_alpha_channel */
+
+
+
+static guint
+getAlphaOffset(guint bpp)
+{
+ if (bpp == 4) { return (3); }
+ if (bpp == 2) { return (1); }
+ return (0);
+}
+
+
+/* ---------------------------------
+ * gap_fg_rgn_copy_alpha_channel
+ * ---------------------------------
+ *
+ * copy alpha channel from src to result region
+ * (src and result drawables must have same size, but may differ in bpp)
+ * the resultDrawable must have an alpha channel (bpp 2 or 4) or
+ * must be a layermask or channel (bpp 1)
+ * e.g bpp 3 for the resultDrawable is NOT accepted.
+ *
+ * Note the caller must also call gimp_drawable_update to write
+ * the changes back to gimp's tiles.
+ */
+void
+gap_fg_rgn_copy_alpha_channel(GimpDrawable *drawable
+ ,GimpDrawable *resultDrawable
+ )
+{
+ GimpPixelRgn inputPR;
+ GimpPixelRgn resultPR;
+ gpointer pr;
+
+ guint srcAlphaOffs;
+ guint dstAlphaOffs;
+
+
+ g_return_if_fail(drawable != NULL && resultDrawable != NULL);
+
+ g_return_if_fail(drawable->width == resultDrawable->width);
+ g_return_if_fail(drawable->height == resultDrawable->height);
+ g_return_if_fail(drawable->bpp != 3 && resultDrawable->bpp != 3);
+
+
+ gimp_pixel_rgn_init (&resultPR, resultDrawable
+ , 0, 0 /* x1, y1 */
+ , resultDrawable->width
+ , resultDrawable->height
+ , TRUE /* dirty */
+ , FALSE /* shadow */
+ );
+
+
+ gimp_pixel_rgn_init (&inputPR, drawable
+ , 0, 0 /* x1, y1 */
+ , drawable->width
+ , drawable->height
+ , FALSE /* dirty */
+ , FALSE /* shadow */
+ );
+ srcAlphaOffs = getAlphaOffset(drawable->bpp);
+ dstAlphaOffs = getAlphaOffset(resultDrawable->bpp);
+
+ for (pr = gimp_pixel_rgns_register (2, &inputPR, &resultPR);
+ pr != NULL;
+ pr = gimp_pixel_rgns_process (pr))
+ {
+ p_rgn_render_copy_alpha_channel (&inputPR, &resultPR
+ , srcAlphaOffs, dstAlphaOffs);
+ }
+
+
+ /* gimp_drawable_update (resultDrawable->drawable_id, 0, 0, resultDrawable->width, resultDrawable->height); */
+
+} /* end gap_fg_rgn_copy_alpha_channel */
+
+
+
+
+/* -------------------------------------
+ * p_rgn_render_copy_rgb_channels
+ * -------------------------------------
+ * copy RGB channels from src to dst region for the current Tile
+ * (src and dst must have same size, but may have bpp 3 or 4)
+ */
+static void
+p_rgn_render_copy_rgb_channels (const GimpPixelRgn *srcPR
+ ,const GimpPixelRgn *dstPR)
+{
+ guint row;
+ guchar* src = srcPR->data;
+ guchar* dst = dstPR->data;
+
+ for (row = 0; row < dstPR->h; row++)
+ {
+ guint col;
+ guint idxSrc;
+ guint idxDst;
+
+ idxSrc = 0;
+ idxDst = 0;
+
+ for(col = 0; col < dstPR->w; col++)
+ {
+ dst[idxDst] = src[idxSrc]; /* red */
+ dst[idxDst +1] = src[idxSrc +1]; /* green */
+ dst[idxDst +2] = src[idxSrc +2]; /* blue */
+
+ idxSrc += srcPR->bpp;
+ idxDst += dstPR->bpp;
+ }
+
+ src += srcPR->rowstride;
+ dst += dstPR->rowstride;
+ }
+} /* end p_rgn_render_copy_rgb_channels */
+
+
+
+
+/* ---------------------------------
+ * gap_fg_rgn_copy_rgb_channels
+ * ---------------------------------
+ *
+ * copy RGB channels from src to dst region
+ * (src and dst must have same size, but may have bpp 3 or 4)
+ *
+ * Note the caller must also call gimp_drawable_update to write
+ * the changes back to gimp's tiles.
+ */
+void
+gap_fg_rgn_copy_rgb_channels(GimpDrawable *drawable
+ ,GimpDrawable *resultDrawable
+ )
+{
+ GimpPixelRgn inputPR;
+ GimpPixelRgn resultPR;
+ gpointer pr;
+
+
+ g_return_if_fail(drawable != NULL && resultDrawable != NULL);
+
+ g_return_if_fail(drawable->width == resultDrawable->width);
+ g_return_if_fail(drawable->height == resultDrawable->height);
+ g_return_if_fail(resultDrawable->bpp >= 3);
+ g_return_if_fail(drawable->bpp >= 3);
+
+
+ gimp_pixel_rgn_init (&resultPR, resultDrawable
+ , 0, 0 /* x1, y1 */
+ , resultDrawable->width
+ , resultDrawable->height
+ , TRUE /* dirty */
+ , FALSE /* shadow */
+ );
+
+
+ gimp_pixel_rgn_init (&inputPR, drawable
+ , 0, 0 /* x1, y1 */
+ , drawable->width
+ , drawable->height
+ , FALSE /* dirty */
+ , FALSE /* shadow */
+ );
+
+ for (pr = gimp_pixel_rgns_register (2, &inputPR, &resultPR);
+ pr != NULL;
+ pr = gimp_pixel_rgns_process (pr))
+ {
+ p_rgn_render_copy_rgb_channels (&inputPR, &resultPR);
+ }
+
+
+ /* gimp_drawable_update (resultDrawable->drawable_id, 0, 0, resultDrawable->width, resultDrawable->height); */
+
+} /* end gap_fg_rgn_copy_rgb_channels */
+
+
+
+
+
+
+
+
+
+/* -------------------------------------
+ * p_rgn_render_normalized_alpha_tri_map
+ * -------------------------------------
+ * processing variant for the case where the
+ * input drawable already has an alpha channel
+ */
+static void
+p_rgn_render_normalized_alpha_tri_map (const GimpPixelRgn *srcPR
+ ,const GimpPixelRgn *maskPR)
+{
+ guint row;
+ guchar* src = srcPR->data;
+ guchar* mask = maskPR->data;
+
+ for (row = 0; row < maskPR->h; row++)
+ {
+ guint col;
+ guint idxMask;
+ guint idxSrc;
+
+ idxMask = 0;
+ idxSrc = 0;
+
+ for(col = 0; col < maskPR->w; col++)
+ {
+ if ((mask[idxMask] <= MATTING_ALGO_BACKGROUND)
+ || (src[idxSrc + (srcPR->bpp -1)] < 1)) // alpha channel
+ {
+ mask[idxMask]= MATTING_USER_BACKGROUND; // 0
+ }
+ else if (mask[idxMask] >= MATTING_USER_FOREGROUND)
+ {
+ mask[idxMask]= MATTING_USER_FOREGROUND; // 240
+ }
+ else
+ {
+ mask[idxMask]= MATTING_ALGO_UNDEFINED; // 128
+ }
+
+
+ idxSrc += srcPR->bpp;
+ idxMask += maskPR->bpp;
+ }
+
+ src += srcPR->rowstride;
+ mask += maskPR->rowstride;
+ }
+} /* end p_rgn_render_normalized_alpha_tri_map */
+
+
+/* ---------------------------------
+ * p_rgn_render_normalized_tri_map
+ * ---------------------------------
+ * processing variant for the case where the
+ * input drawable already has NO alpha channel
+ * (and therefore is not relevant for normalizing the tri map)
+ */
+static void
+p_rgn_render_normalized_tri_map (const GimpPixelRgn *maskPR)
+{
+ guint row;
+ guchar* mask = maskPR->data;
+ gint alphaOffset;
+
+ alphaOffset = maskPR->bpp -1;
+
+
+ for (row = 0; row < maskPR->h; row++)
+ {
+ guint col;
+ guint idxMask;
+
+ idxMask = 0;
+
+ for(col = 0; col < maskPR->w; col++)
+ {
+ if (mask[idxMask + alphaOffset] <= MATTING_ALGO_BACKGROUND)
+ {
+ mask[idxMask + alphaOffset]= MATTING_USER_BACKGROUND; // 0
+ }
+ else if (mask[idxMask + alphaOffset] >= MATTING_USER_FOREGROUND)
+ {
+ mask[idxMask + alphaOffset]= MATTING_USER_FOREGROUND; // 240
+ }
+ else
+ {
+ mask[idxMask + alphaOffset]= MATTING_ALGO_UNDEFINED; // 128
+ }
+
+ idxMask += maskPR->bpp;
+ }
+ mask += maskPR->rowstride;
+ }
+} /* end p_rgn_render_normalized_tri_map */
+
+
+/* ---------------------------------
+ * gap_fg_rgn_tri_map_normalize
+ * ---------------------------------
+ *
+ * set tri map pixels to one of the values:
+ * 0, MATTING_USER_BACKGROUND
+ * 128 undefined
+ * 240 MATTING_USER_FOREGROUND
+ *
+ * depending on the original mask value and the alpha channel
+ * of the input drawable.
+ */
+void
+gap_fg_rgn_tri_map_normalize(GimpDrawable *drawable
+ , gint32 maskId
+ )
+{
+ GimpPixelRgn inputPR;
+ GimpPixelRgn maskPR;
+ GimpDrawable *maskDrawable;
+ gpointer pr;
+
+
+ maskDrawable = gimp_drawable_get (maskId);
+
+ g_return_if_fail(drawable->width == maskDrawable->width);
+ g_return_if_fail(drawable->height == maskDrawable->height);
+ g_return_if_fail(maskDrawable->bpp == 1);
+
+
+ gimp_pixel_rgn_init (&maskPR, maskDrawable
+ , 0, 0 /* x1, y1 */
+ , maskDrawable->width
+ , maskDrawable->height
+ , TRUE /* dirty */
+ , FALSE /* shadow */
+ );
+
+ if (gimp_drawable_has_alpha(drawable->drawable_id))
+ {
+ gimp_pixel_rgn_init (&inputPR, drawable
+ , 0, 0 /* x1, y1 */
+ , drawable->width
+ , drawable->height
+ , FALSE /* dirty */
+ , FALSE /* shadow */
+ );
+
+ for (pr = gimp_pixel_rgns_register (2, &inputPR, &maskPR);
+ pr != NULL;
+ pr = gimp_pixel_rgns_process (pr))
+ {
+ p_rgn_render_normalized_alpha_tri_map (&inputPR, &maskPR);
+ }
+ }
+ else
+ {
+ for (pr = gimp_pixel_rgns_register (1, &maskPR);
+ pr != NULL;
+ pr = gimp_pixel_rgns_process (pr))
+ {
+ p_rgn_render_normalized_tri_map (&maskPR);
+ }
+ }
+
+
+
+ /* update the processed region */
+ gimp_drawable_flush (maskDrawable);
+ gimp_drawable_detach(maskDrawable);
+
+} /* end gap_fg_rgn_tri_map_normalize */
+
+
+
+
+
+/* ----------------------------------
+ * gap_fg_rgn_normalize_alpha_channel
+ * ----------------------------------
+ *
+ * set alpha channel to one of the values:
+ * 0, MATTING_USER_BACKGROUND
+ * 128 undefined
+ * 240 MATTING_USER_FOREGROUND
+ *
+ * depending on the original alpha channel
+ * of the input drawable.
+ */
+void
+gap_fg_rgn_normalize_alpha_channel(GimpDrawable *drawable)
+{
+ GimpPixelRgn inputPR;
+ gpointer pr;
+
+ gimp_pixel_rgn_init (&inputPR, drawable
+ , 0, 0 /* x1, y1 */
+ , drawable->width
+ , drawable->height
+ , TRUE /* dirty */
+ , FALSE /* shadow */
+ );
+
+ for (pr = gimp_pixel_rgns_register (1, &inputPR);
+ pr != NULL;
+ pr = gimp_pixel_rgns_process (pr))
+ {
+ p_rgn_render_normalized_tri_map (&inputPR);
+ }
+ gimp_drawable_flush (drawable);
+
+} /* end gap_fg_rgn_normalize_alpha_channel */
diff --git a/gap/gap_fg_regions.h b/gap/gap_fg_regions.h
new file mode 100644
index 0000000..9de4a94
--- /dev/null
+++ b/gap/gap_fg_regions.h
@@ -0,0 +1,50 @@
+/* gap_fg_regions.h
+ * This module contains gimp pixel region processing utilities
+ * intended as helper procedures for preprocessing and postprocessing
+ * for the foreground sextract plug-in.
+ * 2011/10/05
+ */
+/* 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
+ * (2011/10/05) 2.7.0 hof: created
+ */
+#ifndef GAP_FG_REGIONS_H
+#define GAP_FG_REGIONS_H
+
+#include <gtk/gtk.h>
+#include <libgimp/gimp.h>
+
+
+
+void gap_fg_rgn_copy_alpha_channel(GimpDrawable *srcDrawable
+ ,GimpDrawable *resultDrawable
+ );
+
+void gap_fg_rgn_copy_rgb_channels(GimpDrawable *srcDrawable
+ ,GimpDrawable *resultDrawable
+ );
+
+void gap_fg_rgn_tri_map_normalize(GimpDrawable *drawable
+ , gint32 maskId
+ );
+void gap_fg_rgn_normalize_alpha_channel(GimpDrawable *drawable);
+
+
+#endif /* GAP_FG_REGIONS_H */
diff --git a/gap/gap_fg_tile_manager.h b/gap/gap_fg_tile_manager.h
new file mode 100644
index 0000000..af7befa
--- /dev/null
+++ b/gap/gap_fg_tile_manager.h
@@ -0,0 +1,334 @@
+/* gap_fg_tile_manager.h
+ * 2011.10.05 hof (Wolfgang Hofer)
+ *
+ * GAP ... Gimp Animation Plugins
+ *
+ * This Module contains:
+ * - simplified tile manager emulation for porting the
+ * foreground selection via alpha matting.
+ *
+ * This module provides types and procedures for porting
+ * calls of gimp core tile manager procedures that are used in the alpha matting implementation
+ * (done by Jan Ruegg as gimp-tool in the unofficial repository
+ * https://github.com/rggjan/Gimp-Matting in the "new_layer" branch)
+ *
+ * Note that this module does NOT cover the full features of the tile manager in the GIMP core
+ * it provides just a reduced subset that was required to compile and run the
+ * alpha matting foreground selection code with only few trivial changes
+ * (prefixing the relevant names names with gapp_).
+ *
+ * tiles are emulated via pixel regions (that are accessable in plug-ins)
+ * the real tile management is still done in the GIMP-core implicite when
+ * drawable and pixel region calls to libgimp are performed.
+ *
+ * the simplified tileManager emulation is limited to handle only one tile at once.
+ * e.g. requesting the next tile from the same tileManager implicite
+ * releases the previous requested tile.
+ * (that is sufficient to run the alpha matting)
+ *
+ * All emulated procedures are declared as static inline
+ * and already implemented in this header file for performance reasons.
+ * gap_fg_tile_manager.c is not required for this reason.
+ *
+ *
+ */
+/* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef GAP_FG_TILE_MANAGER_H
+#define GAP_FG_TILE_MANAGER_H
+
+#include "libgimp/gimp.h"
+
+
+#define GAPP_TILE_WIDTH 64
+#define GAPP_TILE_HEIGHT 64
+
+
+typedef struct _GappMattingState GappMattingState;
+
+
+/* simplified Tile emulation via Pixel Region (where one PixelRegion represents a tile of size 64x64) */
+typedef struct GappTile {
+ void /*GappTileManager*/ *tm;
+ GimpPixelRgn pixelRegion;
+
+} GappTile;
+
+
+typedef struct GappTileManager {
+ GappTile tile; /* holds information about the (one) managed tile */
+ gint32 drawableId;
+ GimpDrawable *drawable;
+ GimpPixelRgn *currentPR;
+} GappTileManager;
+
+#ifndef GAP_DEBUG_DECLARED
+extern int gap_debug; /* ==0 ... dont print debug infos */
+#endif
+
+
+static inline gint
+gapp_tile_manager_width(const GappTileManager *tm)
+{
+ return (tm->drawable->width);
+}
+
+static inline gint
+gapp_tile_manager_height(const GappTileManager *tm)
+{
+ return (tm->drawable->height);
+}
+
+static inline gint
+gapp_tile_manager_bpp(const GappTileManager *tm)
+{
+ return (tm->drawable->bpp);
+}
+
+
+/* -----------------------------------
+ * gapp_tile_ewidth
+ * -----------------------------------
+ * get effective width of the tile. (64 or smaller for tiles on the drawable borders)
+ */
+static inline gint
+gapp_tile_ewidth (GappTile *tile)
+{
+ if (tile == NULL)
+ {
+ return (0);
+ }
+ return (tile->pixelRegion.w);
+}
+
+/* -----------------------------------
+ * gapp_tile_eheight
+ * -----------------------------------
+ * get effective height of the tile. (64 or smaller for tiles on the drawable borders)
+ */
+static inline gint
+gapp_tile_eheight (GappTile *tile)
+{
+ if (tile == NULL)
+ {
+ return (0);
+ }
+ return (tile->pixelRegion.h);
+}
+
+/* -----------------------------------
+ * gapp_tile_eheight
+ * -----------------------------------
+ * get bytes per pixel for the tile. (1 upto 4)
+ */
+static inline gint
+gapp_tile_bpp (GappTile *tile)
+{
+ if (tile == NULL)
+ {
+ return (0);
+ }
+ return (tile->pixelRegion.bpp);
+}
+
+/* -----------------------------------
+ * gapp_tile_data_pointer
+ * -----------------------------------
+ * get data pointer to specified pixel in the tile.
+ * coordinates are local to tile in unit pixels.
+ * and must be 0 <= coord <= effective tile witdth or height
+ */
+static inline gpointer
+gapp_tile_data_pointer (GappTile *tile,
+ gint xoff,
+ gint yoff)
+{
+ if (tile != NULL)
+ {
+ if (xoff < tile->pixelRegion.w && xoff >= 0
+ && yoff < tile->pixelRegion.h && yoff >= 0)
+ {
+ gint offs;
+ guchar *pointer;
+
+ offs = (xoff * tile->pixelRegion.bpp) + (yoff * tile->pixelRegion.w * tile->pixelRegion.bpp);
+ pointer = tile->pixelRegion.data + offs;
+
+ return (pointer);
+ }
+
+ }
+ return (NULL);
+
+
+} /* end gapp_tile_data_pointer */
+
+
+
+/* -----------------------------------
+ * gapp_tile_manager_get_at
+ * -----------------------------------
+ * get data pointer to tile at tile raster position tile_col / tile_row.
+ * Note that the returned tile points to the one tile that is part
+ * of the GappTilemanager structure and MUST NOT be free'd by the caller.
+ * the caller shall call gapp_tile_release when processing of the tile is finished.
+ *
+ * RESTRICTION:
+ * This simplified tile manager can only deal with one tile at a time.
+ * (e.g. the next call implicite releases the tile and provides the newly requested one)
+ * Therfore the caller MUST not use 2 or more tiles obtained from tha same
+ * tile manager at the same time.
+ *
+ * TODO: how to emulate the wantread flag,
+ * TODO: maybe operate on shadow tiles (requires merge_in_shadows before drawable detach)
+ *
+ */
+static inline GappTile *
+gapp_tile_manager_get_at (GappTileManager *tm,
+ gint tile_col,
+ gint tile_row,
+ gboolean wantread,
+ gboolean wantwrite)
+{
+ GappTile *tile;
+ gint px;
+ gint py;
+
+ g_return_val_if_fail (tm != NULL, NULL);
+
+ if(tm->drawable == NULL)
+ {
+ tm->drawable = gimp_drawable_get (tm->drawableId);
+ }
+ g_return_val_if_fail (tm->drawable != NULL, NULL);
+
+ if((tile_col < 0) || (tile_row < 0))
+ {
+ return (NULL);
+ }
+ if((tile_col >= tm->drawable->width / GAPP_TILE_WIDTH )
+ || (tile_row >= tm->drawable->height / GAPP_TILE_HEIGHT))
+ {
+ return (NULL);
+ }
+
+
+ while (tm->currentPR != NULL)
+ {
+ tm->currentPR = gimp_pixel_rgns_process (tm->currentPR);
+
+ if (tm->currentPR != NULL)
+ {
+ printf("gapp_tile_manager_get_at ERROR: next region is NOT NULL region is larger than expected one tile size 64x64\n");
+ }
+
+ }
+
+ tile = &tm->tile;
+ tile->tm = tm;
+
+ px = tile_col * GAPP_TILE_WIDTH;
+ py = tile_row * GAPP_TILE_HEIGHT;
+
+// if(gap_debug)
+// {
+// printf("gapp_tile_manager_get_at: col:%d row:%d px:%d py:%d drawable->width:%d height:%d\n"
+// , (int)tile_col
+// , (int)tile_row
+// , (int)px
+// , (int)py
+// , (int)tm->drawable->width
+// , (int)tm->drawable->height
+// );
+// }
+
+ gimp_pixel_rgn_init (&tile->pixelRegion, tm->drawable, px, py
+ , GAPP_TILE_WIDTH, GAPP_TILE_HEIGHT
+ , wantwrite /* dirty */
+ , FALSE /* shadow */
+ );
+ tm->currentPR = gimp_pixel_rgns_register (1, &tile->pixelRegion);
+
+
+ return (tile);
+
+} /* end gapp_tile_manager_get_at */
+
+
+/* -----------------------------------
+ * gapp_tile_release
+ * -----------------------------------
+ * release the tile via calling gimp_pixel_rgns_process.
+ * this procedure also sets the pointer in the tile manager to NULL (tm->currentPR)
+ * to indicate that there is no currently managed tile available.
+ */
+static inline void
+gapp_tile_release (GappTile *tile,
+ gboolean dirty)
+{
+ GappTileManager *tm;
+
+ if (tile == NULL)
+ {
+ return;
+ }
+
+ tm = (GappTileManager*)tile->tm;
+ g_return_if_fail (tm != NULL);
+
+
+ if (dirty)
+ {
+// TODO: how to force settin dirty state (the flag is not public , and not accessable here)
+// tm->currentPR.dirty = 1;
+ }
+
+ while (tm->currentPR != NULL)
+ {
+ tm->currentPR = gimp_pixel_rgns_process (tm->currentPR);
+
+ if (tm->currentPR != NULL)
+ {
+ printf("gapp_tile_release ERROR: next region is NOT NULL region is larger than expected one tile size 64x64\n");
+ }
+
+ }
+
+} /* end gapp_tile_release */
+
+
+/* -----------------------------------
+ * gapp_tile_manager_new
+ * -----------------------------------
+ */
+static inline GappTileManager *
+gapp_tile_manager_new(GimpDrawable *drawable)
+{
+ GappTileManager *tm;
+
+ tm = g_new ( GappTileManager, 1 );
+ tm->drawableId = drawable->drawable_id;
+ tm->drawable = drawable;
+ tm->currentPR = NULL; /* NULL indicates invalid tile */
+ tm->tile.tm = tm;
+
+ return (tm);
+}
+
+#endif
diff --git a/gap/gap_layer_copy.c b/gap/gap_layer_copy.c
index c18de6a..cff3b90 100644
--- a/gap/gap_layer_copy.c
+++ b/gap/gap_layer_copy.c
@@ -202,11 +202,68 @@ p_copy_rgn_render_region (const GimpPixelRgn *srcPR
} /* end p_copy_rgn_render_region */
+
+
+
+/* ---------------------------------
+ * p_copy_rgn_render_region_bpp
+ * ---------------------------------
+ * copy region where source and destination bpp
+ * are different.
+ */
+static void
+p_copy_rgn_render_region_bpp (const GimpPixelRgn *srcPR
+ ,const GimpPixelRgn *dstPR)
+{
+ guint row;
+ guint col;
+ guint minBpp = MIN(srcPR->bpp, dstPR->bpp);
+ guchar* src = srcPR->data;
+ guchar* dest = dstPR->data;
+
+
+ for (row = 0; row < dstPR->h; row++)
+ {
+ gint srcOff;
+ gint dstOff;
+ gint ii;
+
+ srcOff = 0;
+ dstOff = 0;
+
+ for (col = 0; col < dstPR->w; col++)
+ {
+ for(ii=0; ii < minBpp; ii++)
+ {
+ dest[dstOff + ii] = src[srcOff + ii];
+ }
+
+ srcOff += srcPR->bpp;
+ dstOff += dstPR->bpp;
+ }
+
+ src += srcPR->rowstride;
+ dest += dstPR->rowstride;
+ }
+} /* end p_copy_rgn_render_region_bpp */
+
+
/* ============================================================================
* gap_layer_copy_content
- * - source and dest must be the same size and type
+ * - source and dest must be the same size
* - selections are ignored
* (the full drawable content is copied without use of the shadow buffer)
+ * - different bpp values will copy only up to the smaller of both bpp values
+ * and leaves the higher channel number(s) unchanged.
+ * useful combinations are:
+ * srcBpp == 4 (RBGA) and dstBpp == 3 (RBG) where only RGB is copied
+ * srcBpp == 3 (RBG) and dstBpp == 4 (RBGA) where only RGB is copied and alpha is left unchanged
+ * srcBpp == 2 (GRAYA) and dstBpp == 1 (GRAY) where only the gray value is copied
+ * srcBpp == 1 (GRAY) and dstBpp == 2 (GRAYA) where only the gray value is copied and alpha is left unchanged
+ * other combinations may not make sense
+ * where gray value or alpha channel is copied to Red or green channel
+ * and gives strange results.
+ *
* ============================================================================
*/
gboolean
@@ -221,10 +278,9 @@ gap_layer_copy_content (gint32 dst_drawable_id, gint32 src_drawable_id)
dst_drawable = gimp_drawable_get (dst_drawable_id);
if((src_drawable->width != dst_drawable->width)
- || (src_drawable->height != dst_drawable->height)
- || (src_drawable->bpp != dst_drawable->bpp))
+ || (src_drawable->height != dst_drawable->height))
{
- printf("gap_layer_copy_content: calling ERROR src_drawable and dst_drawable do not match in size or bpp\n");
+ printf("gap_layer_copy_content: calling ERROR src_drawable and dst_drawable do not match in size\n");
printf("src: w:%d h:%d bpp:%d\n"
,(int)src_drawable->width
,(int)src_drawable->height
@@ -251,12 +307,24 @@ gap_layer_copy_content (gint32 dst_drawable_id, gint32 src_drawable_id)
, FALSE /* shadow */
);
-
- for (pr = gimp_pixel_rgns_register (2, &srcPR, &dstPR);
- pr != NULL;
- pr = gimp_pixel_rgns_process (pr))
+ if (src_drawable->bpp == dst_drawable->bpp)
{
- p_copy_rgn_render_region (&srcPR, &dstPR);
+ /* can use faster variant for same bpp */
+ for (pr = gimp_pixel_rgns_register (2, &srcPR, &dstPR);
+ pr != NULL;
+ pr = gimp_pixel_rgns_process (pr))
+ {
+ p_copy_rgn_render_region (&srcPR, &dstPR);
+ }
+ }
+ else
+ {
+ for (pr = gimp_pixel_rgns_register (2, &srcPR, &dstPR);
+ pr != NULL;
+ pr = gimp_pixel_rgns_process (pr))
+ {
+ p_copy_rgn_render_region_bpp (&srcPR, &dstPR);
+ }
}
gimp_drawable_flush (dst_drawable);
diff --git a/gap/gap_lib.c b/gap/gap_lib.c
index 1fdfdbe..2b2bc4e 100644
--- a/gap/gap_lib.c
+++ b/gap/gap_lib.c
@@ -157,13 +157,19 @@ extern int gap_debug; /* ==0 ... dont print debug infos */
/* forward working procedures */
/* ------------------------------------------ */
-gboolean p_set_active_layer_by_pos(gint32 image_id
+static gint32 p_set_or_pick_active_layer_by_pos(gint32 image_id
,gint32 ref_layer_stackpos
+ ,gboolean setActiveLayer
+ ,gboolean ignoreOnionLayers
);
-gboolean p_set_active_layer_by_name(gint32 image_id
+static gint32 p_set_or_pick_active_layer_by_name(gint32 image_id
,const gchar *ref_layer_name
,gint32 ref_layer_stackpos
+ ,gboolean setActiveLayer
+ ,gboolean ignoreOnionLayers
);
+
+
static gchar * p_get_active_layer_name(gint32 image_id
,gint32 *active_layer
,gint32 *stack_pos
@@ -190,30 +196,90 @@ static char* p_gzip (char *orig_name, char *new_name, char *zip);
+/* ------------------------------------
+ * gap_lib_layer_tracking
+ * ------------------------------------
+ * try to locate the specified reference layer within the image by name or stack position.
+ * this procedure is typically used to find a corresponding layer while
+ * processing a sequence of frames or when stepping to another frame with
+ * the "Active Layer Tracking" feature enabled.
+ *
+ * setActiveLayer: TRUE set the corresponding layer as active layer (when present)
+ * FALSE do not change the active layer
+ *
+ * ignoreOnionLayers: TRUE ignore onion skin layers when present (useful for AL tracking)
+ * FALSE do not ccare about onion skin layers.
+ *
+ * return the corresponding layer id (that is part of to the target image_id)
+ * or -1 in case no corresponding layer was found.
+ */
+gint32
+gap_lib_layer_tracking(gint32 image_id
+ , gchar *ref_layer_name
+ , gint32 ref_layer_stackpos
+ , gboolean setActiveLayer
+ , gboolean ignoreOnionLayers
+ , gboolean trackByName
+ , gboolean trackByStackPosition
+ )
+{
+ gint32 l_matching_layer_id;
+
+ l_matching_layer_id = -1;
+ if (trackByName)
+ {
+ l_matching_layer_id = p_set_or_pick_active_layer_by_name(image_id
+ ,ref_layer_name
+ ,ref_layer_stackpos
+ ,setActiveLayer
+ ,ignoreOnionLayers
+ );
+ if (l_matching_layer_id >= 0)
+ {
+ return(l_matching_layer_id);
+ }
+ }
+
+ if (trackByStackPosition)
+ {
+ l_matching_layer_id = p_set_or_pick_active_layer_by_pos(image_id
+ ,ref_layer_stackpos
+ ,setActiveLayer
+ ,ignoreOnionLayers
+ );
+ }
+
+ return(l_matching_layer_id);
+
+} /* end gap_lib_layer_tracking */
+
+
/* ---------------------------------
- * p_set_active_layer_by_pos
+ * p_set_or_pick_active_layer_by_pos
* ---------------------------------
* set the layer with same stackposition as ref_layer_stackpos
* as the active layer, where stackpositions of onionskin layers are not counted.
* if the image has less layers than ref_layer_stackpos
* then pick the top-most layer, that is no onionskin layer
*/
-gboolean
-p_set_active_layer_by_pos(gint32 image_id
+static gint32
+p_set_or_pick_active_layer_by_pos(gint32 image_id
,gint32 ref_layer_stackpos
+ ,gboolean setActiveLayer
+ ,gboolean ignoreOnionLayers
)
{
gint32 *l_layers_list;
gint l_nlayers;
gint l_idx;
- gboolean l_is_onion;
+ gboolean l_is_layer_ignored;
gint32 l_layer_id;
gint32 l_matching_layer_id;
gint l_pos;
if(gap_debug)
{
- printf("p_set_active_layer_by_pos START\n");
+ printf("p_set_or_pick_active_layer_by_pos START\n");
}
l_pos = 0;
l_matching_layer_id = -1;
@@ -223,9 +289,16 @@ p_set_active_layer_by_pos(gint32 image_id
for(l_idx=0;l_idx < l_nlayers;l_idx++)
{
l_layer_id = l_layers_list[l_idx];
- l_is_onion = gap_onion_base_check_is_onion_layer(l_layer_id);
+ if (ignoreOnionLayers == TRUE)
+ {
+ l_is_layer_ignored = gap_onion_base_check_is_onion_layer(l_layer_id);
+ }
+ else
+ {
+ l_is_layer_ignored = FALSE;
+ }
- if(!l_is_onion)
+ if(!l_is_layer_ignored)
{
l_matching_layer_id = l_layer_id;
if(l_pos == ref_layer_stackpos)
@@ -241,49 +314,64 @@ p_set_active_layer_by_pos(gint32 image_id
if(l_matching_layer_id >= 0)
{
- gimp_image_set_active_layer(image_id, l_matching_layer_id);
+ if(setActiveLayer == TRUE)
+ {
+ gimp_image_set_active_layer(image_id, l_matching_layer_id);
+ }
if(gap_debug)
{
char *l_name;
l_name = gimp_drawable_get_name(l_matching_layer_id);
- printf("p_set_active_layer_by_pos SET layer_id %d '%s' as ACTIVE\n"
+ if(setActiveLayer == TRUE)
+ {
+ printf("p_set_or_pick_active_layer_by_pos SET layer_id %d '%s' as ACTIVE\n"
, (int)l_matching_layer_id
, l_name
);
+ }
+ else
+ {
+ printf("p_set_or_pick_active_layer_by_pos layer_id %d '%s' was PICKED\n"
+ , (int)l_matching_layer_id
+ , l_name
+ );
+ }
if(l_name)
{
g_free(l_name);
}
}
- return (TRUE);
+ return (l_matching_layer_id);
}
- return (FALSE);
+ return (-1);
-} /* end p_set_active_layer_by_pos */
+} /* end p_set_or_pick_active_layer_by_pos */
-/* ---------------------------------
- * p_set_active_layer_by_name
- * ---------------------------------
+/* ----------------------------------
+ * p_set_or_pick_active_layer_by_name
+ * ----------------------------------
* set active layer by picking the layer
- * whos name matches best with ref_layer_name.
+ * who's name matches best with ref_layer_name.
* ref_layer_stackpos is the 2nd criterium
* restriction: works only for utf8 compliant layernames.
*/
-gboolean
-p_set_active_layer_by_name(gint32 image_id
+static gint32
+p_set_or_pick_active_layer_by_name(gint32 image_id
,const gchar *ref_layer_name
,gint32 ref_layer_stackpos
+ ,gboolean setActiveLayer
+ ,gboolean ignoreOnionLayers
)
{
gint32 *l_layers_list;
gint l_nlayers;
gint l_idx;
- gboolean l_is_onion;
+ gboolean l_is_layer_ignored;
gint32 l_layer_id;
gint32 l_matching_layer_id;
gint l_pos;
@@ -296,7 +384,7 @@ p_set_active_layer_by_name(gint32 image_id
if(gap_debug)
{
- printf("p_set_active_layer_by_name START\n");
+ printf("p_set_or_pick_active_layer_by_name START\n");
}
l_pos = 0;
l_max_score = 0;
@@ -304,12 +392,12 @@ p_set_active_layer_by_name(gint32 image_id
if(ref_layer_name == NULL)
{
- return(p_set_active_layer_by_pos(image_id, ref_layer_stackpos));
+ 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_active_layer_by_pos(image_id, ref_layer_stackpos));
+ 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);
@@ -387,8 +475,17 @@ p_set_active_layer_by_name(gint32 image_id
* (score +1) in case there are more names matching
* in the same number of characters
*/
- l_is_onion = gap_onion_base_check_is_onion_layer(l_layer_id);
- if(!l_is_onion)
+ if (ignoreOnionLayers == TRUE)
+ {
+ l_is_layer_ignored = gap_onion_base_check_is_onion_layer(l_layer_id);
+ }
+ else
+ {
+ l_is_layer_ignored = FALSE;
+ }
+
+
+ if(!l_is_layer_ignored)
{
if(l_pos == ref_layer_stackpos)
{
@@ -409,29 +506,40 @@ p_set_active_layer_by_name(gint32 image_id
if(l_matching_layer_id >= 0)
{
- gimp_image_set_active_layer(image_id, l_matching_layer_id);
+ if (setActiveLayer == TRUE)
+ {
+ gimp_image_set_active_layer(image_id, l_matching_layer_id);
+ }
if(gap_debug)
{
char *l_name;
l_name = gimp_drawable_get_name(l_matching_layer_id);
- printf("p_set_active_layer_by_name SET layer_id %d '%s' as ACTIVE\n"
+ if (setActiveLayer == TRUE)
+ {
+ printf("p_set_or_pick_active_layer_by_name SET layer_id %d '%s' as ACTIVE\n"
+ , (int)l_matching_layer_id
+ , l_name
+ );
+ }
+ else
+ {
+ printf("p_set_or_pick_active_layer_by_name layer_id %d '%s' was PICKED\n"
, (int)l_matching_layer_id
, l_name
);
+ }
if(l_name)
{
g_free(l_name);
}
}
- return (TRUE);
+ return (l_matching_layer_id);
}
- return (FALSE);
-} /* end p_set_active_layer_by_name */
-
-
+ return (-1);
+} /* end p_set_or_pick_active_layer_by_name */
/* ---------------------------------
@@ -512,17 +620,25 @@ p_do_active_layer_tracking(gint32 image_id
switch(vin_ptr->active_layer_tracking)
{
case GAP_ACTIVE_LAYER_TRACKING_BY_NAME:
- p_set_active_layer_by_name(image_id, ref_layer_name, ref_layer_stackpos);
+ gap_lib_layer_tracking(image_id, ref_layer_name, ref_layer_stackpos
+ , TRUE /* setActiveLayer */
+ , TRUE /* ignoreOnionLayers */
+ , TRUE /* trackByName */
+ , TRUE /* trackByStackPosition */
+ );
break;
case GAP_ACTIVE_LAYER_TRACKING_BY_STACKPOS:
- p_set_active_layer_by_pos(image_id, ref_layer_stackpos);
+ gap_lib_layer_tracking(image_id, ref_layer_name, ref_layer_stackpos
+ , TRUE /* setActiveLayer */
+ , TRUE /* ignoreOnionLayers */
+ , FALSE /* trackByName */
+ , TRUE /* trackByStackPosition */
+ );
break;
default: /* GAP_ACTIVE_LAYER_TRACKING_OFF */
break;
}
} /* end p_do_active_layer_tracking */
-
-
/* ============================================================================
diff --git a/gap/gap_lib.h b/gap/gap_lib.h
index 8277542..5f60aa5 100644
--- a/gap/gap_lib.h
+++ b/gap/gap_lib.h
@@ -55,6 +55,18 @@
/* procedures used in other gap*.c files */
+
+gint32 gap_lib_layer_tracking(gint32 image_id
+ , gchar *ref_layer_name
+ , gint32 ref_layer_stackpos
+ , gboolean setActiveLayer
+ , gboolean ignoreOnionLayers
+ , gboolean trackByName
+ , gboolean trackByStackPosition
+ );
+
+
+
int gap_lib_file_exists(const char *fname);
char* gap_lib_searchpath_for_exefile(const char *exefile, const char *path);
int gap_lib_file_copy(char *fname, char *fname_copy);
@@ -82,7 +94,6 @@ long gap_lib_get_frame_nr(gint32 image_id);
long gap_lib_get_frame_nr_from_name(char *fname);
int gap_lib_image_file_copy(char *fname, char *fname_copy);
-
gchar *gap_lib_get_video_paste_name(void);
gint32 gap_vid_edit_clear(void);
gint32 gap_vid_edit_framecount(void);
diff --git a/po/POTFILES.in b/po/POTFILES.in
index ed11178..a4d178f 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -17,6 +17,11 @@ gap/gap_decode_xanim.c
gap/gap_filter_foreach.c
gap/gap_filter_main.c
gap/gap_fire_pattern.c
+gap/gap_fg_matting_main.c
+gap/gap_fg_matting_exec.c
+gap/gap_fg_matting.c
+gap/gap_fg_matting_dialog.c
+gap/gap_fg_regions.c
gap/gap_fmac_base.c
gap/gap_fmac_main.c
gap/gap_frontends_main.c
diff --git a/vid_common/gap_cme_callbacks.c b/vid_common/gap_cme_callbacks.c
index 61b93c5..14f0e84 100644
--- a/vid_common/gap_cme_callbacks.c
+++ b/vid_common/gap_cme_callbacks.c
@@ -356,8 +356,8 @@ on_cme__combo_scale (GtkWidget *widget,
{
gint value;
gint l_idx;
- static gint tab_width[GAP_CME_STANDARD_SIZE_MAX_ELEMENTS] = { 0, 320, 320, 640, 720, 720 };
- static gint tab_height[GAP_CME_STANDARD_SIZE_MAX_ELEMENTS] = { 0, 240, 288, 480, 480, 576 };
+ static gint tab_width[GAP_CME_STANDARD_SIZE_MAX_ELEMENTS] = { 0, 320, 320, 640, 720, 720, 1280, 1920, 1920 };
+ static gint tab_height[GAP_CME_STANDARD_SIZE_MAX_ELEMENTS] = { 0, 240, 288, 480, 480, 576, 720, 1080, 1088 };
if(gap_debug) printf("CB: on_cme__combo_scale\n");
@@ -365,8 +365,17 @@ on_cme__combo_scale (GtkWidget *widget,
gimp_int_combo_box_get_active (GIMP_INT_COMBO_BOX (widget), &value);
l_idx = value;
+ if(gap_debug)
+ {
+ printf("CB: on_cme__combo_scale index: %d\n", (int)l_idx);
+ }
+
+ if(l_idx == GAP_CME_STANDARD_SIZE_KEEP)
+ {
+ /* the "unchanged" entry selection does nothing */
+ return;
+ }
- if(gap_debug) printf("CB: on_cme__combo_scale index: %d\n", (int)l_idx);
if((l_idx >= GAP_CME_STANDARD_SIZE_MAX_ELEMENTS) || (l_idx < 1))
{
l_idx = 0;
@@ -410,6 +419,11 @@ on_cme__combo_framerate (GtkWidget *widget,
gimp_int_combo_box_get_active (GIMP_INT_COMBO_BOX (widget), &value);
l_idx = value;
+
+ if(l_idx == GAP_CME_STANDARD_FRAMERATE_KEEP)
+ {
+ return;
+ }
if(gap_debug) printf("CB: on_cme__combo_framerate index: %d\n", (int)l_idx);
if((l_idx >= GAP_CME_STANDARD_FRAMERATE_MAX_ELEMENTS) || (l_idx < 1))
@@ -795,6 +809,11 @@ on_cme__spinbutton_width_changed (GtkEditable *editable,
if((gint)adj->value != gpp->val.vid_width)
{
gpp->val.vid_width = (gint)adj->value;
+ if(gpp->cme__combo_scale != NULL)
+ {
+ gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (gpp->cme__combo_scale), GAP_CME_STANDARD_SIZE_KEEP);
+ }
+
}
}
@@ -819,6 +838,10 @@ on_cme__spinbutton_height_changed (GtkEditable *editable,
if((gint)adj->value != gpp->val.vid_height)
{
gpp->val.vid_height = (gint)adj->value;
+ if(gpp->cme__combo_scale != NULL)
+ {
+ gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (gpp->cme__combo_scale), GAP_CME_STANDARD_SIZE_KEEP);
+ }
}
}
@@ -892,7 +915,12 @@ on_cme__spinbutton_framerate_changed (GtkEditable *editable,
if((gint)adj->value != gpp->val.framerate)
{
gpp->val.framerate = adj->value;
+ if(gpp->cme__combo_framerate != NULL)
+ {
+ gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (gpp->cme__combo_framerate), GAP_CME_STANDARD_FRAMERATE_KEEP);
+ }
gap_cme_gui_update_vid_labels (gpp);
+
}
}
diff --git a/vid_common/gap_cme_gui.c b/vid_common/gap_cme_gui.c
index 14b794a..23636c5 100644
--- a/vid_common/gap_cme_gui.c
+++ b/vid_common/gap_cme_gui.c
@@ -3659,12 +3659,16 @@ p_create_video_options_frame (GapCmeGlobalParams *gpp)
/* the Frame width/height scale combo (for picking common used video sizes) */
- combo = gimp_int_combo_box_new (_("Framesize (1:1)"), GAP_CME_STANDARD_SIZE_IMAGE,
+ combo = gimp_int_combo_box_new (_("keep"), GAP_CME_STANDARD_SIZE_KEEP,
+ _("Framesize (1:1)"), GAP_CME_STANDARD_SIZE_IMAGE,
_("320x240 NTSC"), GAP_CME_STANDARD_SIZE_320x240,
_("320x288 PAL"), GAP_CME_STANDARD_SIZE_320x288,
_("640x480"), GAP_CME_STANDARD_SIZE_640x480,
_("720x480 NTSC"), GAP_CME_STANDARD_SIZE_720x480,
_("720x576 PAL"), GAP_CME_STANDARD_SIZE_720x576,
+ _("1280x720 HD"), GAP_CME_STANDARD_SIZE_1280x720,
+ _("1920x1080 FullHD"), GAP_CME_STANDARD_SIZE_1920x1080,
+ _("1920x1088 EosHD"), GAP_CME_STANDARD_SIZE_1920x1088,
NULL);
gpp->cme__combo_scale = combo;
@@ -3734,7 +3738,8 @@ p_create_video_options_frame (GapCmeGlobalParams *gpp)
/* the framerate combo (to select common used video framerates) */
- combo = gimp_int_combo_box_new (_("unchanged"), GAP_CME_STANDARD_FRAMERATE_00_UNCHANGED,
+ combo = gimp_int_combo_box_new (_("keep"), GAP_CME_STANDARD_FRAMERATE_KEEP,
+ _("original"), GAP_CME_STANDARD_FRAMERATE_00_UNCHANGED,
"23.98", GAP_CME_STANDARD_FRAMERATE_01_23_98,
"24", GAP_CME_STANDARD_FRAMERATE_02_24,
"25", GAP_CME_STANDARD_FRAMERATE_03_25,
diff --git a/vid_common/gap_cme_main.h b/vid_common/gap_cme_main.h
index ad43903..fe23eb8 100644
--- a/vid_common/gap_cme_main.h
+++ b/vid_common/gap_cme_main.h
@@ -41,14 +41,19 @@
#define GAP_CME_PLUGIN_HELP_ID_VID_ENCODE_MASTER "plug-in-gap-vid-encode-master"
+#define GAP_CME_STANDARD_SIZE_KEEP -1
#define GAP_CME_STANDARD_SIZE_IMAGE 0
#define GAP_CME_STANDARD_SIZE_320x240 1
#define GAP_CME_STANDARD_SIZE_320x288 2
#define GAP_CME_STANDARD_SIZE_640x480 3
#define GAP_CME_STANDARD_SIZE_720x480 4
#define GAP_CME_STANDARD_SIZE_720x576 5
-#define GAP_CME_STANDARD_SIZE_MAX_ELEMENTS 6
+#define GAP_CME_STANDARD_SIZE_1280x720 6
+#define GAP_CME_STANDARD_SIZE_1920x1080 7
+#define GAP_CME_STANDARD_SIZE_1920x1088 8
+#define GAP_CME_STANDARD_SIZE_MAX_ELEMENTS 9
+#define GAP_CME_STANDARD_FRAMERATE_KEEP -1
#define GAP_CME_STANDARD_FRAMERATE_00_UNCHANGED 0
#define GAP_CME_STANDARD_FRAMERATE_01_23_98 1
#define GAP_CME_STANDARD_FRAMERATE_02_24 2
diff --git a/vid_enc_ffmpeg/Makefile.am b/vid_enc_ffmpeg/Makefile.am
index c24cc9f..3af3c05 100644
--- a/vid_enc_ffmpeg/Makefile.am
+++ b/vid_enc_ffmpeg/Makefile.am
@@ -2,7 +2,20 @@
libexecdir = $(GIMP_PLUGIN_DIR)/plug-ins
-scriptdatadir = $(GIMP_DATA_DIR)/scripts
+presetdatadir = $(GIMP_DATA_DIR)/video_encoder_presets
+presetdata_DATA = \
+ ff_divx_hq.preset \
+ ff_divx_low.preset \
+ ff_divx_standard.preset \
+ ff_divx_win.preset \
+ ff_mpeg1_hq.preset \
+ ff_mpeg1_vcd.preset \
+ ff_mpeg2_dvd.preset \
+ ff_mpeg2_svcd.preset \
+ ff_real_standard.preset \
+ ff_x264_hq.preset
+
+
# we depend on libavformat / ibavcodec to build that encoder
# (without those libs the ffmpeg encoder can not be built at all)
@@ -25,7 +38,6 @@ INC_LIBGAPVIDUTIL = -I$(top_srcdir)/libgapvidutil
libexec_PROGRAMS = gap_vid_enc_ffmpeg
-
gap_vid_enc_ffmpeg_SOURCES = \
gap_enc_ffmpeg_main.c \
gap_enc_ffmpeg_main.h \
@@ -60,4 +72,7 @@ LDADD = $(GIMP_LIBS)
gap_vid_enc_ffmpeg_LDADD = $(LIBGAPVIDUTIL) $(LIBGAPSTORY) $(GAPVIDEOAPI) $(LIBGAPBASE) $(GIMP_LIBS)
+
+EXTRA_DIST = $(presetdata_DATA)
+
endif
diff --git a/vid_enc_ffmpeg/ff_divx_hq.preset b/vid_enc_ffmpeg/ff_divx_hq.preset
new file mode 100644
index 0000000..08c1971
--- /dev/null
+++ b/vid_enc_ffmpeg/ff_divx_hq.preset
@@ -0,0 +1,191 @@
+# GIMP / GAP FFMPEG videoencoder parameter file
+(preset_name "DivX high quality preset")
+(format_name "avi")
+(vcodec_name "mpeg4")
+(acodec_name "mp2")
+(title "")
+(author "")
+(copyright "")
+(comment "")
+(passlogfile "ffmpeg2pass")
+(pass 1) # 1: one pass encoding, 2: for two-pass encoding
+(audio_bitrate 192) # audio bitrate in kBit/sec
+(video_bitrate 1500) # video bitrate in kBit/sec
+(gop_size 12) # group of picture size
+(qscale 1) # use fixed video quantiser scale (VBR). 0=const bitrate
+(qmin 2) # min video quantiser scale (VBR)
+(qmax 8) # max video quantiser scale (VBR)
+(qdiff 2) # max difference between the quantiser scale (VBR)
+(qblur 0.5) # video quantiser scale blur (VBR)
+(qcomp 0.5) # video quantiser scale compression (VBR)
+(rc_init_cplx 0) # initial complexity for 1-pass encoding
+(b_qfactor 1.25) # qp factor between p and b frames
+(i_qfactor -0.80000001192092896) # qp factor between p and i frames
+(b_qoffset 1.25) # qp offset between p and b frames
+(i_qoffset 0) # qp offset between p and i frames
+(bitrate_tol 6000) # set video bitrate tolerance (in kbit/s)
+(maxrate_tol 0) # set max video bitrate tolerance (in kbit/s)
+(minrate_tol 0) # set min video bitrate tolerance (in kbit/s)
+(bufsize 0) # set ratecontrol buffere size (in kbit)
+(motion_estimation 5) # algorithm for motion estimation (1-6)
+(dct_algo 0) # algorithm for DCT (0-6)
+(idct_algo 0) # algorithm for IDCT (0-11)
+(strict 0) # how strictly to follow the standards
+(mb_qmin 2) # OBSOLETE min macroblock quantiser scale (VBR)
+(mb_qmax 18) # OBSOLETE max macroblock quantiser scale (VBR)
+(mb_decision 0) # algorithm for macroblock decision (0-2)
+(b_frames 2) # max number of B-frames in sequence
+(packet_size 0)
+(intra no) # use only intra frames
+(set_aspect_ratio yes) # store aspectratio information (width/height) in the output video
+(factor_aspect_ratio 0) # the aspect ratio (width/height). 0.0 = auto ratio assuming sqaure pixels
+(dont_recode_flag no) # bypass the video encoder where frames can be copied 1:1
+(thread_count 1)
+(mb_cmp 0) # macroblock compare function (0-13,255)
+(ildct_cmp 8) # ildct compare function (0-13,255)
+(sub_cmp 0) # subpel compare function (0-13,255)
+(cmp 0) # fullpel compare function (0-13,255)
+(pre_cmp 0) # pre motion estimation compare function (0-13,255)
+(pre_me 0) # pre motion estimation
+(lumi_mask 0) # luminance masking
+(dark_mask 0) # darkness masking
+(scplx_mask 0) # spatial complexity masking
+(tcplx_mask 0) # temporary complexity masking
+(p_mask 0) # p block masking
+(qns 0) # quantization noise shaping
+(video_lmin 236) # min video lagrange factor (VBR) 0-3658
+(video_lmax 3658) # max video lagrange factor (VBR) 0-3658
+(video_lelim 0) # luma elimination threshold
+(video_celim 0) # chroma elimination threshold
+(video_intra_quant_bias 999999) # intra quant bias
+(video_inter_quant_bias 999999) # inter quant bias
+(me_threshold 0) # motion estimaton threshold
+(mb_threshold 0) # macroblock threshold
+(intra_dc_precision 8) # precision of the intra dc coefficient - 8
+(error_rate 0) # simulates errors in the bitstream to test error concealment
+(noise_reduction 0) # noise reduction strength
+(sc_threshold 0) # scene change detection threshold
+(me_range 0) # limit motion vectors range (1023 for DivX player, 0 = no limit)
+(coder 0) # coder type 0=VLC 1=AC
+(context 0) # context model
+(predictor 0) # prediction method (0 LEFT, 1 PLANE, 2 MEDIAN
+(nsse_weight 8) # noise vs. sse weight for the nsse comparsion function.
+(subpel_quality 8) # subpel ME quality
+(strict_gop 0) # strictly enforce GOP size
+(no_output 0) # skip bitstream encoding
+(video_mb_lmin 236) # min macroblock quantiser scale (VBR) 0-3658
+(video_mb_lmax 3658) # max macroblock quantiser scale (VBR) 0-3658
+(video_profile -99)
+(video_level -99)
+(frame_skip_threshold 0) # frame skip threshold
+(frame_skip_factor 0) # frame skip factor
+(frame_skip_exp 0) # frame skip exponent
+(frame_skip_cmp 13) # frame skip comparission function
+(mux_rate 0)
+(mux_packet_size 0)
+(mux_preload 0.5) # set the initial demux-decode delay (secs)
+(mux_max_delay 0.69999998807907104) # set the maximum demux-decode delay (secs)
+(b_frame_strategy 0) # strategy to choose between I/P/B-frames
+(workaround_bugs 1) # 1:FF_BUG_AUTODETECT, 2:FF_BUG_OLD_MSMPEG4 4:FF_BUG_XVID_ILACE 8:FF_BUG_UMP4 1
+(error_recognition 1) # 1:FF_ER_CAREFUL 2:FF_ER_COMPLIANT 3:FF_ER_AGGRESSIVE 4:FF_ER_VERY_AGGRESSIVE
+(mpeg_quant 0) # 0-> h263 quant 1-> mpeg quant
+(rc_qsquish 0) # how to keep quantizer between qmin and qmax (0 = clip, 1 = use differentiable
+(rc_qmod_amp 0) # experimental quantizer modulation
+(rc_qmod_freq 0) # experimental quantizer modulation
+(rc_eq[60] "") # rate control equation (tex^qComp)
+(rc_buffer_aggressivity 1) # currently useless
+(dia_size 0) # ME diamond size & shape
+(last_predictor_count 0) # amount of previous MV predictors (2a+1 x 2a+1 square)
+(pre_dia_size 0) # ME prepass diamond size & shape
+(inter_threshold 0)
+(border_masking 0) # increases the quantizer for macroblocks close to borders
+(me_penalty_compensation 256) # motion estimation bitrate penalty compensation (1.0 = 256)
+(bidir_refine 0) # refine the two motion vectors used in bidirectional macroblocks
+(brd_scale 0) # downscales frames for dynamic B-frame decision
+(crf 0) # constant rate factor - quality-based VBR - values ~correspond to qps
+(cqp -1) # constant quantization parameter rate control method
+(keyint_min 25) # minimum GOP size
+(refs 1) # number of reference frames
+(chromaoffset 0) # chroma qp offset from luma
+(bframebias 0) # Influences how often B-frames are used
+(trellis 0) # trellis RD quantization
+(complexityblur 20) # Reduce fluctuations in qp (before curve compression)
+(deblockalpha 0) # in-loop deblocking filter alphac0 parameter. alpha is in the range -6...6
+(deblockbeta 0) # in-loop deblocking filter beta parameter. beta is in the range -6...6
+(partitions 0) # macroblock subpartition sizes to consider - p8x8, p4x4, b8x8, i8x8, i4x4
+(directpred 2) # direct MV prediction mode - 0 (none), 1 (spatial), 2 (temporal), 3 (auto)
+(cutoff 0) # Audio cutoff bandwidth (0 means automatic)
+(scenechange_factor 6) # Multiplied by qscale for each frame and added to scene_change_score.
+(mv0_threshold 256) # Value depends upon the compare function used for fullpel ME
+(b_sensitivity 40) # Adjusts sensitivity of b_frame_strategy 1
+(compression_level -1)
+(use_lpc -1) # Sets whether to use LPC mode - used by FLAC encoder
+(lpc_coeff_precision 0) # LPC coefficient precision - used by FLAC encoder
+(min_prediction_order -1)
+(max_prediction_order -1)
+(prediction_order_method -1) # search method for selecting prediction order
+(min_partition_order -1)
+(timecode_frame_start 0) # GOP timecode frame start number, in non drop frame format
+(bits_per_raw_sample 0) # This field is applicable only when sample_fmt is SAMPLE_FMT_S32
+(channel_layout 0) # Audio channel layout
+(rc_max_available_vbv_use 0.33333333333333331) # Ratecontrol attempt to use, at maximum, <value> of what can be used without a
+(rc_min_vbv_overflow_use 3) # Ratecontrol attempt to use, at least, <value> times the amount needed to prev
+(color_primaries 0) # Chromaticity coordinates of the source primaries.
+(color_trc 0) # Color Transfer Characteristic.
+(colorspace 0) # YUV colorspace type.
+(color_range 0) # MPEG vs JPEG YUV range.
+(chroma_sample_location 0) # This defines the location of chroma samples.
+(weighted_p_pred 0) # explicit P-frame weighted prediction analysis method 0:off, 1: fast blind wei
+(aq_mode 0) # AQ mode
+(aq_strength 0) # AQ strength, Reduces blocking and blurring in flat and textured areas.
+(psy_rd 0) # PSY RD Strength of psychovisual optimization
+(psy_trellis 0) # PSY trellis Strength of psychovisual optimization
+(rc_lookahead 0) # Number of frames for frametype and ratecontrol lookahead
+(bitexact no) # CODEC_FLAG_BITEXACT (for testing, unused in productive version)
+(use_ss no) # CODEC_FLAG_H263P_SLICE_STRUCT enable Slice Structured mode (h263+)
+(use_aiv no) # CODEC_FLAG_H263P_AIV enable Alternative inter vlc (h263+)
+(use_obmc no) # CODEC_FLAG_OBMC use overlapped block motion compensation (h263+)
+(use_loop no) # CODEC_FLAG_LOOP_FILTER use loop filter (h263+)
+(use_alt_scan no) # CODEC_FLAG_ALT_SCAN enable alternate scantable (MPEG2/MPEG4)
+(use_mv0 no) # CODEC_FLAG_MV0 try to encode each MB with MV=<0,0> and choose the better one
+(do_normalize_aqp no) # CODEC_FLAG_NORMALIZE_AQP normalize adaptive quantization
+(use_scan_offset no) # CODEC_FLAG_SVCD_SCAN_OFFSET enable SVCD Scan Offset placeholder
+(closed_gop no) # CODEC_FLAG_CLOSED_GOP closed gop
+(use_qpel no) # CODEC_FLAG_QPEL enable 1/4-pel
+(use_qprd no) # CODEC_FLAG_QP_RD use rate distortion optimization for qp selection
+(use_cbprd no) # CODEC_FLAG_CBP_RD use rate distortion optimization for cbp
+(do_interlace_dct no) # CODEC_FLAG_INTERLACED_DCT use interlaced dct
+(do_interlace_me no) # CODEC_FLAG_INTERLACED_ME interlaced motion estimation
+(aic no) # CODEC_FLAG_AC_PRED activate intra frame coding (only h263+ CODEC)
+(umv no) # CODEC_FLAG_H263P_UMV enable unlimited motion vector (only h263+ CODEC)
+(mv4 no) # CODEC_FLAG_4MV use four motion vector by macroblock (only MPEG-4 CODEC)
+(partitioning no) # CODEC_FLAG_PART use data partitioning (only MPEG-4 CODEC)
+(use_gmc no) # CODEC_FLAG_GMC Use GMC
+(input_preserved no) # CODEC_FLAG_INPUT_PRESERVED
+(use_gray no) # CODEC_FLAG_GRAY Only encode grayscale
+(use_emu_edge no) # CODEC_FLAG_EMU_EDGE Dont draw edges
+(use_truncated no) # CODEC_FLAG_TRUNCATED Input bitstream might be truncated at a rando
+(use_fast no) # CODEC_FLAG2_FAST Allow non spec compliant speedup tricks
+(use_local_header no) # CODEC_FLAG2_LOCAL_HEADER Place global headers at every keyframe instea
+(use_bpyramid no) # CODEC_FLAG2_BPYRAMID H.264 allow B-frames to be used as references
+(use_wpred no) # CODEC_FLAG2_WPRED H.264 weighted biprediction for B-frames
+(use_mixed_refs no) # CODEC_FLAG2_MIXED_REFS H.264 one reference per partition, as opposed
+(use_dct8x8 no) # CODEC_FLAG2_8X8DCT H.264 high profile 8x8 transform
+(use_fastpskip no) # CODEC_FLAG2_FASTPSKIP H.264 fast pskip
+(use_aud no) # CODEC_FLAG2_AUD H.264 access unit delimiters
+(use_brdo no) # CODEC_FLAG2_BRDO B-frame rate-distortion optimization
+(use_ivlc no) # CODEC_FLAG2_INTRA_VLC Use MPEG-2 intra VLC table.
+(use_memc_only no) # CODEC_FLAG2_MEMC_ONLY Only do ME/MC (I frames -> ref, P frame -> ME
+(use_drop_frame_timecode no) # CODEC_FLAG2_DROP_FRAME_TIMECODE timecode is in drop frame format
+(use_skip_rd no) # CODEC_FLAG2_SKIP_RD RD optimal MB level residual skipping
+(use_chunks no) # CODEC_FLAG2_CHUNKS Input bitstream might be truncated at a packe
+(use_non_linear_quant no) # CODEC_FLAG2_NON_LINEAR_QUANT Use MPEG-2 nonlinear quantizer
+(use_bit_reservoir no) # CODEC_FLAG2_BIT_RESERVOIR Use a bit reservoir when encoding if possible
+(use_bit_mbtree no) # CODEC_FLAG2_MBTREE Use macroblock tree ratecontrol (x264 only)
+(use_bit_psy no) # CODEC_FLAG2_PSY Use psycho visual optimizations.
+(use_bit_ssim no) # CODEC_FLAG2_SSIM Compute SSIM during encoding, error[] values
+(parti4x4 no) # X264_PART_I4X4 Analyze i4x4
+(parti8x8 no) # X264_PART_I8X8 Analyze i8x8 (requires 8x8 transform)
+(partp4x4 no) # X264_PART_P8X8 Analyze p16x8, p8x16 and p8x8
+(partp8x8 no) # X264_PART_P4X4 Analyze p8x4, p4x8, p4x4
+(partb8x8 no) # X264_PART_B8X8 Analyze b16x8, b8x16 and b8x8
diff --git a/vid_enc_ffmpeg/ff_divx_low.preset b/vid_enc_ffmpeg/ff_divx_low.preset
new file mode 100644
index 0000000..a6f60e8
--- /dev/null
+++ b/vid_enc_ffmpeg/ff_divx_low.preset
@@ -0,0 +1,191 @@
+# GIMP / GAP FFMPEG videoencoder parameter file
+(preset_name "DivX low quality preset")
+(format_name "avi")
+(vcodec_name "mpeg4")
+(acodec_name "mp2")
+(title "")
+(author "")
+(copyright "")
+(comment "")
+(passlogfile "ffmpeg2pass")
+(pass 1) # 1: one pass encoding, 2: for two-pass encoding
+(audio_bitrate 96) # audio bitrate in kBit/sec
+(video_bitrate 150) # video bitrate in kBit/sec
+(gop_size 96) # group of picture size
+(qscale 6) # use fixed video quantiser scale (VBR). 0=const bitrate
+(qmin 8) # min video quantiser scale (VBR)
+(qmax 31) # max video quantiser scale (VBR)
+(qdiff 9) # max difference between the quantiser scale (VBR)
+(qblur 0.5) # video quantiser scale blur (VBR)
+(qcomp 0.5) # video quantiser scale compression (VBR)
+(rc_init_cplx 0) # initial complexity for 1-pass encoding
+(b_qfactor 1.25) # qp factor between p and b frames
+(i_qfactor -0.80000001192092896) # qp factor between p and i frames
+(b_qoffset 1.25) # qp offset between p and b frames
+(i_qoffset 0) # qp offset between p and i frames
+(bitrate_tol 2000) # set video bitrate tolerance (in kbit/s)
+(maxrate_tol 0) # set max video bitrate tolerance (in kbit/s)
+(minrate_tol 0) # set min video bitrate tolerance (in kbit/s)
+(bufsize 0) # set ratecontrol buffere size (in kbit)
+(motion_estimation 5) # algorithm for motion estimation (1-6)
+(dct_algo 0) # algorithm for DCT (0-6)
+(idct_algo 0) # algorithm for IDCT (0-11)
+(strict 0) # how strictly to follow the standards
+(mb_qmin 8) # OBSOLETE min macroblock quantiser scale (VBR)
+(mb_qmax 31) # OBSOLETE max macroblock quantiser scale (VBR)
+(mb_decision 0) # algorithm for macroblock decision (0-2)
+(b_frames 4) # max number of B-frames in sequence
+(packet_size 0)
+(intra no) # use only intra frames
+(set_aspect_ratio yes) # store aspectratio information (width/height) in the output video
+(factor_aspect_ratio 0) # the aspect ratio (width/height). 0.0 = auto ratio assuming sqaure pixels
+(dont_recode_flag no) # bypass the video encoder where frames can be copied 1:1
+(thread_count 1)
+(mb_cmp 0) # macroblock compare function (0-13,255)
+(ildct_cmp 8) # ildct compare function (0-13,255)
+(sub_cmp 0) # subpel compare function (0-13,255)
+(cmp 0) # fullpel compare function (0-13,255)
+(pre_cmp 0) # pre motion estimation compare function (0-13,255)
+(pre_me 0) # pre motion estimation
+(lumi_mask 0) # luminance masking
+(dark_mask 0) # darkness masking
+(scplx_mask 0) # spatial complexity masking
+(tcplx_mask 0) # temporary complexity masking
+(p_mask 0) # p block masking
+(qns 0) # quantization noise shaping
+(video_lmin 236) # min video lagrange factor (VBR) 0-3658
+(video_lmax 3658) # max video lagrange factor (VBR) 0-3658
+(video_lelim 0) # luma elimination threshold
+(video_celim 0) # chroma elimination threshold
+(video_intra_quant_bias 999999) # intra quant bias
+(video_inter_quant_bias 999999) # inter quant bias
+(me_threshold 0) # motion estimaton threshold
+(mb_threshold 0) # macroblock threshold
+(intra_dc_precision 8) # precision of the intra dc coefficient - 8
+(error_rate 0) # simulates errors in the bitstream to test error concealment
+(noise_reduction 0) # noise reduction strength
+(sc_threshold 0) # scene change detection threshold
+(me_range 0) # limit motion vectors range (1023 for DivX player, 0 = no limit)
+(coder 0) # coder type 0=VLC 1=AC
+(context 0) # context model
+(predictor 0) # prediction method (0 LEFT, 1 PLANE, 2 MEDIAN
+(nsse_weight 8) # noise vs. sse weight for the nsse comparsion function.
+(subpel_quality 8) # subpel ME quality
+(strict_gop 0) # strictly enforce GOP size
+(no_output 0) # skip bitstream encoding
+(video_mb_lmin 236) # min macroblock quantiser scale (VBR) 0-3658
+(video_mb_lmax 3658) # max macroblock quantiser scale (VBR) 0-3658
+(video_profile -99)
+(video_level -99)
+(frame_skip_threshold 0) # frame skip threshold
+(frame_skip_factor 0) # frame skip factor
+(frame_skip_exp 0) # frame skip exponent
+(frame_skip_cmp 13) # frame skip comparission function
+(mux_rate 0)
+(mux_packet_size 0)
+(mux_preload 0.5) # set the initial demux-decode delay (secs)
+(mux_max_delay 0.69999998807907104) # set the maximum demux-decode delay (secs)
+(b_frame_strategy 0) # strategy to choose between I/P/B-frames
+(workaround_bugs 1) # 1:FF_BUG_AUTODETECT, 2:FF_BUG_OLD_MSMPEG4 4:FF_BUG_XVID_ILACE 8:FF_BUG_UMP4 1
+(error_recognition 1) # 1:FF_ER_CAREFUL 2:FF_ER_COMPLIANT 3:FF_ER_AGGRESSIVE 4:FF_ER_VERY_AGGRESSIVE
+(mpeg_quant 0) # 0-> h263 quant 1-> mpeg quant
+(rc_qsquish 0) # how to keep quantizer between qmin and qmax (0 = clip, 1 = use differentiable
+(rc_qmod_amp 0) # experimental quantizer modulation
+(rc_qmod_freq 0) # experimental quantizer modulation
+(rc_eq[60] "") # rate control equation (tex^qComp)
+(rc_buffer_aggressivity 1) # currently useless
+(dia_size 0) # ME diamond size & shape
+(last_predictor_count 0) # amount of previous MV predictors (2a+1 x 2a+1 square)
+(pre_dia_size 0) # ME prepass diamond size & shape
+(inter_threshold 0)
+(border_masking 0) # increases the quantizer for macroblocks close to borders
+(me_penalty_compensation 256) # motion estimation bitrate penalty compensation (1.0 = 256)
+(bidir_refine 0) # refine the two motion vectors used in bidirectional macroblocks
+(brd_scale 0) # downscales frames for dynamic B-frame decision
+(crf 0) # constant rate factor - quality-based VBR - values ~correspond to qps
+(cqp -1) # constant quantization parameter rate control method
+(keyint_min 25) # minimum GOP size
+(refs 1) # number of reference frames
+(chromaoffset 0) # chroma qp offset from luma
+(bframebias 0) # Influences how often B-frames are used
+(trellis 0) # trellis RD quantization
+(complexityblur 20) # Reduce fluctuations in qp (before curve compression)
+(deblockalpha 0) # in-loop deblocking filter alphac0 parameter. alpha is in the range -6...6
+(deblockbeta 0) # in-loop deblocking filter beta parameter. beta is in the range -6...6
+(partitions 0) # macroblock subpartition sizes to consider - p8x8, p4x4, b8x8, i8x8, i4x4
+(directpred 2) # direct MV prediction mode - 0 (none), 1 (spatial), 2 (temporal), 3 (auto)
+(cutoff 0) # Audio cutoff bandwidth (0 means automatic)
+(scenechange_factor 6) # Multiplied by qscale for each frame and added to scene_change_score.
+(mv0_threshold 256) # Value depends upon the compare function used for fullpel ME
+(b_sensitivity 40) # Adjusts sensitivity of b_frame_strategy 1
+(compression_level -1)
+(use_lpc -1) # Sets whether to use LPC mode - used by FLAC encoder
+(lpc_coeff_precision 0) # LPC coefficient precision - used by FLAC encoder
+(min_prediction_order -1)
+(max_prediction_order -1)
+(prediction_order_method -1) # search method for selecting prediction order
+(min_partition_order -1)
+(timecode_frame_start 0) # GOP timecode frame start number, in non drop frame format
+(bits_per_raw_sample 0) # This field is applicable only when sample_fmt is SAMPLE_FMT_S32
+(channel_layout 0) # Audio channel layout
+(rc_max_available_vbv_use 0.33333333333333331) # Ratecontrol attempt to use, at maximum, <value> of what can be used without a
+(rc_min_vbv_overflow_use 3) # Ratecontrol attempt to use, at least, <value> times the amount needed to prev
+(color_primaries 0) # Chromaticity coordinates of the source primaries.
+(color_trc 0) # Color Transfer Characteristic.
+(colorspace 0) # YUV colorspace type.
+(color_range 0) # MPEG vs JPEG YUV range.
+(chroma_sample_location 0) # This defines the location of chroma samples.
+(weighted_p_pred 0) # explicit P-frame weighted prediction analysis method 0:off, 1: fast blind wei
+(aq_mode 0) # AQ mode
+(aq_strength 0) # AQ strength, Reduces blocking and blurring in flat and textured areas.
+(psy_rd 0) # PSY RD Strength of psychovisual optimization
+(psy_trellis 0) # PSY trellis Strength of psychovisual optimization
+(rc_lookahead 0) # Number of frames for frametype and ratecontrol lookahead
+(bitexact no) # CODEC_FLAG_BITEXACT (for testing, unused in productive version)
+(use_ss no) # CODEC_FLAG_H263P_SLICE_STRUCT enable Slice Structured mode (h263+)
+(use_aiv no) # CODEC_FLAG_H263P_AIV enable Alternative inter vlc (h263+)
+(use_obmc no) # CODEC_FLAG_OBMC use overlapped block motion compensation (h263+)
+(use_loop no) # CODEC_FLAG_LOOP_FILTER use loop filter (h263+)
+(use_alt_scan no) # CODEC_FLAG_ALT_SCAN enable alternate scantable (MPEG2/MPEG4)
+(use_mv0 no) # CODEC_FLAG_MV0 try to encode each MB with MV=<0,0> and choose the better one
+(do_normalize_aqp no) # CODEC_FLAG_NORMALIZE_AQP normalize adaptive quantization
+(use_scan_offset no) # CODEC_FLAG_SVCD_SCAN_OFFSET enable SVCD Scan Offset placeholder
+(closed_gop no) # CODEC_FLAG_CLOSED_GOP closed gop
+(use_qpel no) # CODEC_FLAG_QPEL enable 1/4-pel
+(use_qprd no) # CODEC_FLAG_QP_RD use rate distortion optimization for qp selection
+(use_cbprd no) # CODEC_FLAG_CBP_RD use rate distortion optimization for cbp
+(do_interlace_dct no) # CODEC_FLAG_INTERLACED_DCT use interlaced dct
+(do_interlace_me no) # CODEC_FLAG_INTERLACED_ME interlaced motion estimation
+(aic no) # CODEC_FLAG_AC_PRED activate intra frame coding (only h263+ CODEC)
+(umv no) # CODEC_FLAG_H263P_UMV enable unlimited motion vector (only h263+ CODEC)
+(mv4 no) # CODEC_FLAG_4MV use four motion vector by macroblock (only MPEG-4 CODEC)
+(partitioning no) # CODEC_FLAG_PART use data partitioning (only MPEG-4 CODEC)
+(use_gmc no) # CODEC_FLAG_GMC Use GMC
+(input_preserved no) # CODEC_FLAG_INPUT_PRESERVED
+(use_gray no) # CODEC_FLAG_GRAY Only encode grayscale
+(use_emu_edge no) # CODEC_FLAG_EMU_EDGE Dont draw edges
+(use_truncated no) # CODEC_FLAG_TRUNCATED Input bitstream might be truncated at a rando
+(use_fast no) # CODEC_FLAG2_FAST Allow non spec compliant speedup tricks
+(use_local_header no) # CODEC_FLAG2_LOCAL_HEADER Place global headers at every keyframe instea
+(use_bpyramid no) # CODEC_FLAG2_BPYRAMID H.264 allow B-frames to be used as references
+(use_wpred no) # CODEC_FLAG2_WPRED H.264 weighted biprediction for B-frames
+(use_mixed_refs no) # CODEC_FLAG2_MIXED_REFS H.264 one reference per partition, as opposed
+(use_dct8x8 no) # CODEC_FLAG2_8X8DCT H.264 high profile 8x8 transform
+(use_fastpskip no) # CODEC_FLAG2_FASTPSKIP H.264 fast pskip
+(use_aud no) # CODEC_FLAG2_AUD H.264 access unit delimiters
+(use_brdo no) # CODEC_FLAG2_BRDO B-frame rate-distortion optimization
+(use_ivlc no) # CODEC_FLAG2_INTRA_VLC Use MPEG-2 intra VLC table.
+(use_memc_only no) # CODEC_FLAG2_MEMC_ONLY Only do ME/MC (I frames -> ref, P frame -> ME
+(use_drop_frame_timecode no) # CODEC_FLAG2_DROP_FRAME_TIMECODE timecode is in drop frame format
+(use_skip_rd no) # CODEC_FLAG2_SKIP_RD RD optimal MB level residual skipping
+(use_chunks no) # CODEC_FLAG2_CHUNKS Input bitstream might be truncated at a packe
+(use_non_linear_quant no) # CODEC_FLAG2_NON_LINEAR_QUANT Use MPEG-2 nonlinear quantizer
+(use_bit_reservoir no) # CODEC_FLAG2_BIT_RESERVOIR Use a bit reservoir when encoding if possible
+(use_bit_mbtree no) # CODEC_FLAG2_MBTREE Use macroblock tree ratecontrol (x264 only)
+(use_bit_psy no) # CODEC_FLAG2_PSY Use psycho visual optimizations.
+(use_bit_ssim no) # CODEC_FLAG2_SSIM Compute SSIM during encoding, error[] values
+(parti4x4 no) # X264_PART_I4X4 Analyze i4x4
+(parti8x8 no) # X264_PART_I8X8 Analyze i8x8 (requires 8x8 transform)
+(partp4x4 no) # X264_PART_P8X8 Analyze p16x8, p8x16 and p8x8
+(partp8x8 no) # X264_PART_P4X4 Analyze p8x4, p4x8, p4x4
+(partb8x8 no) # X264_PART_B8X8 Analyze b16x8, b8x16 and b8x8
diff --git a/vid_enc_ffmpeg/ff_divx_standard.preset b/vid_enc_ffmpeg/ff_divx_standard.preset
new file mode 100644
index 0000000..afd78ac
--- /dev/null
+++ b/vid_enc_ffmpeg/ff_divx_standard.preset
@@ -0,0 +1,191 @@
+# GIMP / GAP FFMPEG videoencoder parameter file
+(preset_name "DivX default preset")
+(format_name "avi")
+(vcodec_name "mpeg4")
+(acodec_name "mp2")
+(title "")
+(author "")
+(copyright "")
+(comment "")
+(passlogfile "ffmpeg2pass")
+(pass 1) # 1: one pass encoding, 2: for two-pass encoding
+(audio_bitrate 160) # audio bitrate in kBit/sec
+(video_bitrate 200) # video bitrate in kBit/sec
+(gop_size 12) # group of picture size
+(qscale 2) # use fixed video quantiser scale (VBR). 0=const bitrate
+(qmin 2) # min video quantiser scale (VBR)
+(qmax 31) # max video quantiser scale (VBR)
+(qdiff 3) # max difference between the quantiser scale (VBR)
+(qblur 0.5) # video quantiser scale blur (VBR)
+(qcomp 0.5) # video quantiser scale compression (VBR)
+(rc_init_cplx 0) # initial complexity for 1-pass encoding
+(b_qfactor 1.25) # qp factor between p and b frames
+(i_qfactor -0.80000001192092896) # qp factor between p and i frames
+(b_qoffset 1.25) # qp offset between p and b frames
+(i_qoffset 0) # qp offset between p and i frames
+(bitrate_tol 4000) # set video bitrate tolerance (in kbit/s)
+(maxrate_tol 0) # set max video bitrate tolerance (in kbit/s)
+(minrate_tol 0) # set min video bitrate tolerance (in kbit/s)
+(bufsize 0) # set ratecontrol buffere size (in kbit)
+(motion_estimation 5) # algorithm for motion estimation (1-6)
+(dct_algo 0) # algorithm for DCT (0-6)
+(idct_algo 0) # algorithm for IDCT (0-11)
+(strict 0) # how strictly to follow the standards
+(mb_qmin 2) # OBSOLETE min macroblock quantiser scale (VBR)
+(mb_qmax 31) # OBSOLETE max macroblock quantiser scale (VBR)
+(mb_decision 0) # algorithm for macroblock decision (0-2)
+(b_frames 2) # max number of B-frames in sequence
+(packet_size 0)
+(intra no) # use only intra frames
+(set_aspect_ratio yes) # store aspectratio information (width/height) in the output video
+(factor_aspect_ratio 0) # the aspect ratio (width/height). 0.0 = auto ratio assuming sqaure pixels
+(dont_recode_flag no) # bypass the video encoder where frames can be copied 1:1
+(thread_count 1)
+(mb_cmp 0) # macroblock compare function (0-13,255)
+(ildct_cmp 8) # ildct compare function (0-13,255)
+(sub_cmp 0) # subpel compare function (0-13,255)
+(cmp 0) # fullpel compare function (0-13,255)
+(pre_cmp 0) # pre motion estimation compare function (0-13,255)
+(pre_me 0) # pre motion estimation
+(lumi_mask 0) # luminance masking
+(dark_mask 0) # darkness masking
+(scplx_mask 0) # spatial complexity masking
+(tcplx_mask 0) # temporary complexity masking
+(p_mask 0) # p block masking
+(qns 0) # quantization noise shaping
+(video_lmin 236) # min video lagrange factor (VBR) 0-3658
+(video_lmax 3658) # max video lagrange factor (VBR) 0-3658
+(video_lelim 0) # luma elimination threshold
+(video_celim 0) # chroma elimination threshold
+(video_intra_quant_bias 999999) # intra quant bias
+(video_inter_quant_bias 999999) # inter quant bias
+(me_threshold 0) # motion estimaton threshold
+(mb_threshold 0) # macroblock threshold
+(intra_dc_precision 8) # precision of the intra dc coefficient - 8
+(error_rate 0) # simulates errors in the bitstream to test error concealment
+(noise_reduction 0) # noise reduction strength
+(sc_threshold 0) # scene change detection threshold
+(me_range 0) # limit motion vectors range (1023 for DivX player, 0 = no limit)
+(coder 0) # coder type 0=VLC 1=AC
+(context 0) # context model
+(predictor 0) # prediction method (0 LEFT, 1 PLANE, 2 MEDIAN
+(nsse_weight 8) # noise vs. sse weight for the nsse comparsion function.
+(subpel_quality 8) # subpel ME quality
+(strict_gop 0) # strictly enforce GOP size
+(no_output 0) # skip bitstream encoding
+(video_mb_lmin 236) # min macroblock quantiser scale (VBR) 0-3658
+(video_mb_lmax 3658) # max macroblock quantiser scale (VBR) 0-3658
+(video_profile -99)
+(video_level -99)
+(frame_skip_threshold 0) # frame skip threshold
+(frame_skip_factor 0) # frame skip factor
+(frame_skip_exp 0) # frame skip exponent
+(frame_skip_cmp 13) # frame skip comparission function
+(mux_rate 0)
+(mux_packet_size 0)
+(mux_preload 0.5) # set the initial demux-decode delay (secs)
+(mux_max_delay 0.69999998807907104) # set the maximum demux-decode delay (secs)
+(b_frame_strategy 0) # strategy to choose between I/P/B-frames
+(workaround_bugs 1) # 1:FF_BUG_AUTODETECT, 2:FF_BUG_OLD_MSMPEG4 4:FF_BUG_XVID_ILACE 8:FF_BUG_UMP4 1
+(error_recognition 1) # 1:FF_ER_CAREFUL 2:FF_ER_COMPLIANT 3:FF_ER_AGGRESSIVE 4:FF_ER_VERY_AGGRESSIVE
+(mpeg_quant 0) # 0-> h263 quant 1-> mpeg quant
+(rc_qsquish 0) # how to keep quantizer between qmin and qmax (0 = clip, 1 = use differentiable
+(rc_qmod_amp 0) # experimental quantizer modulation
+(rc_qmod_freq 0) # experimental quantizer modulation
+(rc_eq[60] "") # rate control equation (tex^qComp)
+(rc_buffer_aggressivity 1) # currently useless
+(dia_size 0) # ME diamond size & shape
+(last_predictor_count 0) # amount of previous MV predictors (2a+1 x 2a+1 square)
+(pre_dia_size 0) # ME prepass diamond size & shape
+(inter_threshold 0)
+(border_masking 0) # increases the quantizer for macroblocks close to borders
+(me_penalty_compensation 256) # motion estimation bitrate penalty compensation (1.0 = 256)
+(bidir_refine 0) # refine the two motion vectors used in bidirectional macroblocks
+(brd_scale 0) # downscales frames for dynamic B-frame decision
+(crf 0) # constant rate factor - quality-based VBR - values ~correspond to qps
+(cqp -1) # constant quantization parameter rate control method
+(keyint_min 25) # minimum GOP size
+(refs 1) # number of reference frames
+(chromaoffset 0) # chroma qp offset from luma
+(bframebias 0) # Influences how often B-frames are used
+(trellis 0) # trellis RD quantization
+(complexityblur 20) # Reduce fluctuations in qp (before curve compression)
+(deblockalpha 0) # in-loop deblocking filter alphac0 parameter. alpha is in the range -6...6
+(deblockbeta 0) # in-loop deblocking filter beta parameter. beta is in the range -6...6
+(partitions 0) # macroblock subpartition sizes to consider - p8x8, p4x4, b8x8, i8x8, i4x4
+(directpred 2) # direct MV prediction mode - 0 (none), 1 (spatial), 2 (temporal), 3 (auto)
+(cutoff 0) # Audio cutoff bandwidth (0 means automatic)
+(scenechange_factor 6) # Multiplied by qscale for each frame and added to scene_change_score.
+(mv0_threshold 256) # Value depends upon the compare function used for fullpel ME
+(b_sensitivity 40) # Adjusts sensitivity of b_frame_strategy 1
+(compression_level -1)
+(use_lpc -1) # Sets whether to use LPC mode - used by FLAC encoder
+(lpc_coeff_precision 0) # LPC coefficient precision - used by FLAC encoder
+(min_prediction_order -1)
+(max_prediction_order -1)
+(prediction_order_method -1) # search method for selecting prediction order
+(min_partition_order -1)
+(timecode_frame_start 0) # GOP timecode frame start number, in non drop frame format
+(bits_per_raw_sample 0) # This field is applicable only when sample_fmt is SAMPLE_FMT_S32
+(channel_layout 0) # Audio channel layout
+(rc_max_available_vbv_use 0.33333333333333331) # Ratecontrol attempt to use, at maximum, <value> of what can be used without a
+(rc_min_vbv_overflow_use 3) # Ratecontrol attempt to use, at least, <value> times the amount needed to prev
+(color_primaries 0) # Chromaticity coordinates of the source primaries.
+(color_trc 0) # Color Transfer Characteristic.
+(colorspace 0) # YUV colorspace type.
+(color_range 0) # MPEG vs JPEG YUV range.
+(chroma_sample_location 0) # This defines the location of chroma samples.
+(weighted_p_pred 0) # explicit P-frame weighted prediction analysis method 0:off, 1: fast blind wei
+(aq_mode 0) # AQ mode
+(aq_strength 0) # AQ strength, Reduces blocking and blurring in flat and textured areas.
+(psy_rd 0) # PSY RD Strength of psychovisual optimization
+(psy_trellis 0) # PSY trellis Strength of psychovisual optimization
+(rc_lookahead 0) # Number of frames for frametype and ratecontrol lookahead
+(bitexact no) # CODEC_FLAG_BITEXACT (for testing, unused in productive version)
+(use_ss no) # CODEC_FLAG_H263P_SLICE_STRUCT enable Slice Structured mode (h263+)
+(use_aiv no) # CODEC_FLAG_H263P_AIV enable Alternative inter vlc (h263+)
+(use_obmc no) # CODEC_FLAG_OBMC use overlapped block motion compensation (h263+)
+(use_loop no) # CODEC_FLAG_LOOP_FILTER use loop filter (h263+)
+(use_alt_scan no) # CODEC_FLAG_ALT_SCAN enable alternate scantable (MPEG2/MPEG4)
+(use_mv0 no) # CODEC_FLAG_MV0 try to encode each MB with MV=<0,0> and choose the better one
+(do_normalize_aqp no) # CODEC_FLAG_NORMALIZE_AQP normalize adaptive quantization
+(use_scan_offset no) # CODEC_FLAG_SVCD_SCAN_OFFSET enable SVCD Scan Offset placeholder
+(closed_gop no) # CODEC_FLAG_CLOSED_GOP closed gop
+(use_qpel no) # CODEC_FLAG_QPEL enable 1/4-pel
+(use_qprd no) # CODEC_FLAG_QP_RD use rate distortion optimization for qp selection
+(use_cbprd no) # CODEC_FLAG_CBP_RD use rate distortion optimization for cbp
+(do_interlace_dct no) # CODEC_FLAG_INTERLACED_DCT use interlaced dct
+(do_interlace_me no) # CODEC_FLAG_INTERLACED_ME interlaced motion estimation
+(aic no) # CODEC_FLAG_AC_PRED activate intra frame coding (only h263+ CODEC)
+(umv no) # CODEC_FLAG_H263P_UMV enable unlimited motion vector (only h263+ CODEC)
+(mv4 no) # CODEC_FLAG_4MV use four motion vector by macroblock (only MPEG-4 CODEC)
+(partitioning no) # CODEC_FLAG_PART use data partitioning (only MPEG-4 CODEC)
+(use_gmc no) # CODEC_FLAG_GMC Use GMC
+(input_preserved no) # CODEC_FLAG_INPUT_PRESERVED
+(use_gray no) # CODEC_FLAG_GRAY Only encode grayscale
+(use_emu_edge no) # CODEC_FLAG_EMU_EDGE Dont draw edges
+(use_truncated no) # CODEC_FLAG_TRUNCATED Input bitstream might be truncated at a rando
+(use_fast no) # CODEC_FLAG2_FAST Allow non spec compliant speedup tricks
+(use_local_header no) # CODEC_FLAG2_LOCAL_HEADER Place global headers at every keyframe instea
+(use_bpyramid no) # CODEC_FLAG2_BPYRAMID H.264 allow B-frames to be used as references
+(use_wpred no) # CODEC_FLAG2_WPRED H.264 weighted biprediction for B-frames
+(use_mixed_refs no) # CODEC_FLAG2_MIXED_REFS H.264 one reference per partition, as opposed
+(use_dct8x8 no) # CODEC_FLAG2_8X8DCT H.264 high profile 8x8 transform
+(use_fastpskip no) # CODEC_FLAG2_FASTPSKIP H.264 fast pskip
+(use_aud no) # CODEC_FLAG2_AUD H.264 access unit delimiters
+(use_brdo no) # CODEC_FLAG2_BRDO B-frame rate-distortion optimization
+(use_ivlc no) # CODEC_FLAG2_INTRA_VLC Use MPEG-2 intra VLC table.
+(use_memc_only no) # CODEC_FLAG2_MEMC_ONLY Only do ME/MC (I frames -> ref, P frame -> ME
+(use_drop_frame_timecode no) # CODEC_FLAG2_DROP_FRAME_TIMECODE timecode is in drop frame format
+(use_skip_rd no) # CODEC_FLAG2_SKIP_RD RD optimal MB level residual skipping
+(use_chunks no) # CODEC_FLAG2_CHUNKS Input bitstream might be truncated at a packe
+(use_non_linear_quant no) # CODEC_FLAG2_NON_LINEAR_QUANT Use MPEG-2 nonlinear quantizer
+(use_bit_reservoir no) # CODEC_FLAG2_BIT_RESERVOIR Use a bit reservoir when encoding if possible
+(use_bit_mbtree no) # CODEC_FLAG2_MBTREE Use macroblock tree ratecontrol (x264 only)
+(use_bit_psy no) # CODEC_FLAG2_PSY Use psycho visual optimizations.
+(use_bit_ssim no) # CODEC_FLAG2_SSIM Compute SSIM during encoding, error[] values
+(parti4x4 no) # X264_PART_I4X4 Analyze i4x4
+(parti8x8 no) # X264_PART_I8X8 Analyze i8x8 (requires 8x8 transform)
+(partp4x4 no) # X264_PART_P8X8 Analyze p16x8, p8x16 and p8x8
+(partp8x8 no) # X264_PART_P4X4 Analyze p8x4, p4x8, p4x4
+(partb8x8 no) # X264_PART_B8X8 Analyze b16x8, b8x16 and b8x8
diff --git a/vid_enc_ffmpeg/ff_divx_win.preset b/vid_enc_ffmpeg/ff_divx_win.preset
new file mode 100644
index 0000000..9528a6c
--- /dev/null
+++ b/vid_enc_ffmpeg/ff_divx_win.preset
@@ -0,0 +1,191 @@
+# GIMP / GAP FFMPEG videoencoder parameter file
+(preset_name "DivX WINDOWS preset")
+(format_name "avi")
+(vcodec_name "msmpeg4")
+(acodec_name "mp2")
+(title "")
+(author "")
+(copyright "")
+(comment "")
+(passlogfile "ffmpeg2pass")
+(pass 1) # 1: one pass encoding, 2: for two-pass encoding
+(audio_bitrate 160) # audio bitrate in kBit/sec
+(video_bitrate 200) # video bitrate in kBit/sec
+(gop_size 12) # group of picture size
+(qscale 2) # use fixed video quantiser scale (VBR). 0=const bitrate
+(qmin 2) # min video quantiser scale (VBR)
+(qmax 31) # max video quantiser scale (VBR)
+(qdiff 3) # max difference between the quantiser scale (VBR)
+(qblur 0.5) # video quantiser scale blur (VBR)
+(qcomp 0.5) # video quantiser scale compression (VBR)
+(rc_init_cplx 0) # initial complexity for 1-pass encoding
+(b_qfactor 1.25) # qp factor between p and b frames
+(i_qfactor -0.80000001192092896) # qp factor between p and i frames
+(b_qoffset 1.25) # qp offset between p and b frames
+(i_qoffset 0) # qp offset between p and i frames
+(bitrate_tol 4000) # set video bitrate tolerance (in kbit/s)
+(maxrate_tol 0) # set max video bitrate tolerance (in kbit/s)
+(minrate_tol 0) # set min video bitrate tolerance (in kbit/s)
+(bufsize 0) # set ratecontrol buffere size (in kbit)
+(motion_estimation 5) # algorithm for motion estimation (1-6)
+(dct_algo 0) # algorithm for DCT (0-6)
+(idct_algo 0) # algorithm for IDCT (0-11)
+(strict 0) # how strictly to follow the standards
+(mb_qmin 2) # OBSOLETE min macroblock quantiser scale (VBR)
+(mb_qmax 31) # OBSOLETE max macroblock quantiser scale (VBR)
+(mb_decision 0) # algorithm for macroblock decision (0-2)
+(b_frames 0) # max number of B-frames in sequence
+(packet_size 0)
+(intra no) # use only intra frames
+(set_aspect_ratio yes) # store aspectratio information (width/height) in the output video
+(factor_aspect_ratio 0) # the aspect ratio (width/height). 0.0 = auto ratio assuming sqaure pixels
+(dont_recode_flag no) # bypass the video encoder where frames can be copied 1:1
+(thread_count 1)
+(mb_cmp 0) # macroblock compare function (0-13,255)
+(ildct_cmp 8) # ildct compare function (0-13,255)
+(sub_cmp 0) # subpel compare function (0-13,255)
+(cmp 0) # fullpel compare function (0-13,255)
+(pre_cmp 0) # pre motion estimation compare function (0-13,255)
+(pre_me 0) # pre motion estimation
+(lumi_mask 0) # luminance masking
+(dark_mask 0) # darkness masking
+(scplx_mask 0) # spatial complexity masking
+(tcplx_mask 0) # temporary complexity masking
+(p_mask 0) # p block masking
+(qns 0) # quantization noise shaping
+(video_lmin 236) # min video lagrange factor (VBR) 0-3658
+(video_lmax 3658) # max video lagrange factor (VBR) 0-3658
+(video_lelim 0) # luma elimination threshold
+(video_celim 0) # chroma elimination threshold
+(video_intra_quant_bias 999999) # intra quant bias
+(video_inter_quant_bias 999999) # inter quant bias
+(me_threshold 0) # motion estimaton threshold
+(mb_threshold 0) # macroblock threshold
+(intra_dc_precision 8) # precision of the intra dc coefficient - 8
+(error_rate 0) # simulates errors in the bitstream to test error concealment
+(noise_reduction 0) # noise reduction strength
+(sc_threshold 0) # scene change detection threshold
+(me_range 0) # limit motion vectors range (1023 for DivX player, 0 = no limit)
+(coder 0) # coder type 0=VLC 1=AC
+(context 0) # context model
+(predictor 0) # prediction method (0 LEFT, 1 PLANE, 2 MEDIAN
+(nsse_weight 8) # noise vs. sse weight for the nsse comparsion function.
+(subpel_quality 8) # subpel ME quality
+(strict_gop 0) # strictly enforce GOP size
+(no_output 0) # skip bitstream encoding
+(video_mb_lmin 236) # min macroblock quantiser scale (VBR) 0-3658
+(video_mb_lmax 3658) # max macroblock quantiser scale (VBR) 0-3658
+(video_profile -99)
+(video_level -99)
+(frame_skip_threshold 0) # frame skip threshold
+(frame_skip_factor 0) # frame skip factor
+(frame_skip_exp 0) # frame skip exponent
+(frame_skip_cmp 13) # frame skip comparission function
+(mux_rate 0)
+(mux_packet_size 0)
+(mux_preload 0.5) # set the initial demux-decode delay (secs)
+(mux_max_delay 0.69999998807907104) # set the maximum demux-decode delay (secs)
+(b_frame_strategy 0) # strategy to choose between I/P/B-frames
+(workaround_bugs 1) # 1:FF_BUG_AUTODETECT, 2:FF_BUG_OLD_MSMPEG4 4:FF_BUG_XVID_ILACE 8:FF_BUG_UMP4 1
+(error_recognition 1) # 1:FF_ER_CAREFUL 2:FF_ER_COMPLIANT 3:FF_ER_AGGRESSIVE 4:FF_ER_VERY_AGGRESSIVE
+(mpeg_quant 0) # 0-> h263 quant 1-> mpeg quant
+(rc_qsquish 0) # how to keep quantizer between qmin and qmax (0 = clip, 1 = use differentiable
+(rc_qmod_amp 0) # experimental quantizer modulation
+(rc_qmod_freq 0) # experimental quantizer modulation
+(rc_eq[60] "") # rate control equation (tex^qComp)
+(rc_buffer_aggressivity 1) # currently useless
+(dia_size 0) # ME diamond size & shape
+(last_predictor_count 0) # amount of previous MV predictors (2a+1 x 2a+1 square)
+(pre_dia_size 0) # ME prepass diamond size & shape
+(inter_threshold 0)
+(border_masking 0) # increases the quantizer for macroblocks close to borders
+(me_penalty_compensation 256) # motion estimation bitrate penalty compensation (1.0 = 256)
+(bidir_refine 0) # refine the two motion vectors used in bidirectional macroblocks
+(brd_scale 0) # downscales frames for dynamic B-frame decision
+(crf 0) # constant rate factor - quality-based VBR - values ~correspond to qps
+(cqp -1) # constant quantization parameter rate control method
+(keyint_min 25) # minimum GOP size
+(refs 1) # number of reference frames
+(chromaoffset 0) # chroma qp offset from luma
+(bframebias 0) # Influences how often B-frames are used
+(trellis 0) # trellis RD quantization
+(complexityblur 20) # Reduce fluctuations in qp (before curve compression)
+(deblockalpha 0) # in-loop deblocking filter alphac0 parameter. alpha is in the range -6...6
+(deblockbeta 0) # in-loop deblocking filter beta parameter. beta is in the range -6...6
+(partitions 0) # macroblock subpartition sizes to consider - p8x8, p4x4, b8x8, i8x8, i4x4
+(directpred 2) # direct MV prediction mode - 0 (none), 1 (spatial), 2 (temporal), 3 (auto)
+(cutoff 0) # Audio cutoff bandwidth (0 means automatic)
+(scenechange_factor 6) # Multiplied by qscale for each frame and added to scene_change_score.
+(mv0_threshold 256) # Value depends upon the compare function used for fullpel ME
+(b_sensitivity 40) # Adjusts sensitivity of b_frame_strategy 1
+(compression_level -1)
+(use_lpc -1) # Sets whether to use LPC mode - used by FLAC encoder
+(lpc_coeff_precision 0) # LPC coefficient precision - used by FLAC encoder
+(min_prediction_order -1)
+(max_prediction_order -1)
+(prediction_order_method -1) # search method for selecting prediction order
+(min_partition_order -1)
+(timecode_frame_start 0) # GOP timecode frame start number, in non drop frame format
+(bits_per_raw_sample 0) # This field is applicable only when sample_fmt is SAMPLE_FMT_S32
+(channel_layout 0) # Audio channel layout
+(rc_max_available_vbv_use 0.33333333333333331) # Ratecontrol attempt to use, at maximum, <value> of what can be used without a
+(rc_min_vbv_overflow_use 3) # Ratecontrol attempt to use, at least, <value> times the amount needed to prev
+(color_primaries 0) # Chromaticity coordinates of the source primaries.
+(color_trc 0) # Color Transfer Characteristic.
+(colorspace 0) # YUV colorspace type.
+(color_range 0) # MPEG vs JPEG YUV range.
+(chroma_sample_location 0) # This defines the location of chroma samples.
+(weighted_p_pred 0) # explicit P-frame weighted prediction analysis method 0:off, 1: fast blind wei
+(aq_mode 0) # AQ mode
+(aq_strength 0) # AQ strength, Reduces blocking and blurring in flat and textured areas.
+(psy_rd 0) # PSY RD Strength of psychovisual optimization
+(psy_trellis 0) # PSY trellis Strength of psychovisual optimization
+(rc_lookahead 0) # Number of frames for frametype and ratecontrol lookahead
+(bitexact no) # CODEC_FLAG_BITEXACT (for testing, unused in productive version)
+(use_ss no) # CODEC_FLAG_H263P_SLICE_STRUCT enable Slice Structured mode (h263+)
+(use_aiv no) # CODEC_FLAG_H263P_AIV enable Alternative inter vlc (h263+)
+(use_obmc no) # CODEC_FLAG_OBMC use overlapped block motion compensation (h263+)
+(use_loop no) # CODEC_FLAG_LOOP_FILTER use loop filter (h263+)
+(use_alt_scan no) # CODEC_FLAG_ALT_SCAN enable alternate scantable (MPEG2/MPEG4)
+(use_mv0 no) # CODEC_FLAG_MV0 try to encode each MB with MV=<0,0> and choose the better one
+(do_normalize_aqp no) # CODEC_FLAG_NORMALIZE_AQP normalize adaptive quantization
+(use_scan_offset no) # CODEC_FLAG_SVCD_SCAN_OFFSET enable SVCD Scan Offset placeholder
+(closed_gop no) # CODEC_FLAG_CLOSED_GOP closed gop
+(use_qpel no) # CODEC_FLAG_QPEL enable 1/4-pel
+(use_qprd no) # CODEC_FLAG_QP_RD use rate distortion optimization for qp selection
+(use_cbprd no) # CODEC_FLAG_CBP_RD use rate distortion optimization for cbp
+(do_interlace_dct no) # CODEC_FLAG_INTERLACED_DCT use interlaced dct
+(do_interlace_me no) # CODEC_FLAG_INTERLACED_ME interlaced motion estimation
+(aic no) # CODEC_FLAG_AC_PRED activate intra frame coding (only h263+ CODEC)
+(umv no) # CODEC_FLAG_H263P_UMV enable unlimited motion vector (only h263+ CODEC)
+(mv4 no) # CODEC_FLAG_4MV use four motion vector by macroblock (only MPEG-4 CODEC)
+(partitioning no) # CODEC_FLAG_PART use data partitioning (only MPEG-4 CODEC)
+(use_gmc no) # CODEC_FLAG_GMC Use GMC
+(input_preserved no) # CODEC_FLAG_INPUT_PRESERVED
+(use_gray no) # CODEC_FLAG_GRAY Only encode grayscale
+(use_emu_edge no) # CODEC_FLAG_EMU_EDGE Dont draw edges
+(use_truncated no) # CODEC_FLAG_TRUNCATED Input bitstream might be truncated at a rando
+(use_fast no) # CODEC_FLAG2_FAST Allow non spec compliant speedup tricks
+(use_local_header no) # CODEC_FLAG2_LOCAL_HEADER Place global headers at every keyframe instea
+(use_bpyramid no) # CODEC_FLAG2_BPYRAMID H.264 allow B-frames to be used as references
+(use_wpred no) # CODEC_FLAG2_WPRED H.264 weighted biprediction for B-frames
+(use_mixed_refs no) # CODEC_FLAG2_MIXED_REFS H.264 one reference per partition, as opposed
+(use_dct8x8 no) # CODEC_FLAG2_8X8DCT H.264 high profile 8x8 transform
+(use_fastpskip no) # CODEC_FLAG2_FASTPSKIP H.264 fast pskip
+(use_aud no) # CODEC_FLAG2_AUD H.264 access unit delimiters
+(use_brdo no) # CODEC_FLAG2_BRDO B-frame rate-distortion optimization
+(use_ivlc no) # CODEC_FLAG2_INTRA_VLC Use MPEG-2 intra VLC table.
+(use_memc_only no) # CODEC_FLAG2_MEMC_ONLY Only do ME/MC (I frames -> ref, P frame -> ME
+(use_drop_frame_timecode no) # CODEC_FLAG2_DROP_FRAME_TIMECODE timecode is in drop frame format
+(use_skip_rd no) # CODEC_FLAG2_SKIP_RD RD optimal MB level residual skipping
+(use_chunks no) # CODEC_FLAG2_CHUNKS Input bitstream might be truncated at a packe
+(use_non_linear_quant no) # CODEC_FLAG2_NON_LINEAR_QUANT Use MPEG-2 nonlinear quantizer
+(use_bit_reservoir no) # CODEC_FLAG2_BIT_RESERVOIR Use a bit reservoir when encoding if possible
+(use_bit_mbtree no) # CODEC_FLAG2_MBTREE Use macroblock tree ratecontrol (x264 only)
+(use_bit_psy no) # CODEC_FLAG2_PSY Use psycho visual optimizations.
+(use_bit_ssim no) # CODEC_FLAG2_SSIM Compute SSIM during encoding, error[] values
+(parti4x4 no) # X264_PART_I4X4 Analyze i4x4
+(parti8x8 no) # X264_PART_I8X8 Analyze i8x8 (requires 8x8 transform)
+(partp4x4 no) # X264_PART_P8X8 Analyze p16x8, p8x16 and p8x8
+(partp8x8 no) # X264_PART_P4X4 Analyze p8x4, p4x8, p4x4
+(partb8x8 no) # X264_PART_B8X8 Analyze b16x8, b8x16 and b8x8
diff --git a/vid_enc_ffmpeg/ff_mpeg1_hq.preset b/vid_enc_ffmpeg/ff_mpeg1_hq.preset
new file mode 100644
index 0000000..ff050fd
--- /dev/null
+++ b/vid_enc_ffmpeg/ff_mpeg1_hq.preset
@@ -0,0 +1,191 @@
+# GIMP / GAP FFMPEG videoencoder parameter file
+(preset_name "MPEG1 high quality preset")
+(format_name "mpeg")
+(vcodec_name "mpeg1video")
+(acodec_name "mp2")
+(title "")
+(author "")
+(copyright "")
+(comment "")
+(passlogfile "ffmpeg2pass")
+(pass 1) # 1: one pass encoding, 2: for two-pass encoding
+(audio_bitrate 192) # audio bitrate in kBit/sec
+(video_bitrate 6000) # video bitrate in kBit/sec
+(gop_size 12) # group of picture size
+(qscale 1) # use fixed video quantiser scale (VBR). 0=const bitrate
+(qmin 2) # min video quantiser scale (VBR)
+(qmax 8) # max video quantiser scale (VBR)
+(qdiff 2) # max difference between the quantiser scale (VBR)
+(qblur 0.5) # video quantiser scale blur (VBR)
+(qcomp 0.5) # video quantiser scale compression (VBR)
+(rc_init_cplx 0) # initial complexity for 1-pass encoding
+(b_qfactor 1.25) # qp factor between p and b frames
+(i_qfactor -0.80000001192092896) # qp factor between p and i frames
+(b_qoffset 1.25) # qp offset between p and b frames
+(i_qoffset 0) # qp offset between p and i frames
+(bitrate_tol 4000) # set video bitrate tolerance (in kbit/s)
+(maxrate_tol 0) # set max video bitrate tolerance (in kbit/s)
+(minrate_tol 0) # set min video bitrate tolerance (in kbit/s)
+(bufsize 0) # set ratecontrol buffere size (in kbit)
+(motion_estimation 5) # algorithm for motion estimation (1-6)
+(dct_algo 0) # algorithm for DCT (0-6)
+(idct_algo 0) # algorithm for IDCT (0-11)
+(strict 0) # how strictly to follow the standards
+(mb_qmin 2) # OBSOLETE min macroblock quantiser scale (VBR)
+(mb_qmax 18) # OBSOLETE max macroblock quantiser scale (VBR)
+(mb_decision 0) # algorithm for macroblock decision (0-2)
+(b_frames 0) # max number of B-frames in sequence
+(packet_size 0)
+(intra no) # use only intra frames
+(set_aspect_ratio yes) # store aspectratio information (width/height) in the output video
+(factor_aspect_ratio 0) # the aspect ratio (width/height). 0.0 = auto ratio assuming sqaure pixels
+(dont_recode_flag no) # bypass the video encoder where frames can be copied 1:1
+(thread_count 1)
+(mb_cmp 0) # macroblock compare function (0-13,255)
+(ildct_cmp 8) # ildct compare function (0-13,255)
+(sub_cmp 0) # subpel compare function (0-13,255)
+(cmp 0) # fullpel compare function (0-13,255)
+(pre_cmp 0) # pre motion estimation compare function (0-13,255)
+(pre_me 0) # pre motion estimation
+(lumi_mask 0) # luminance masking
+(dark_mask 0) # darkness masking
+(scplx_mask 0) # spatial complexity masking
+(tcplx_mask 0) # temporary complexity masking
+(p_mask 0) # p block masking
+(qns 0) # quantization noise shaping
+(video_lmin 236) # min video lagrange factor (VBR) 0-3658
+(video_lmax 3658) # max video lagrange factor (VBR) 0-3658
+(video_lelim 0) # luma elimination threshold
+(video_celim 0) # chroma elimination threshold
+(video_intra_quant_bias 999999) # intra quant bias
+(video_inter_quant_bias 999999) # inter quant bias
+(me_threshold 0) # motion estimaton threshold
+(mb_threshold 0) # macroblock threshold
+(intra_dc_precision 8) # precision of the intra dc coefficient - 8
+(error_rate 0) # simulates errors in the bitstream to test error concealment
+(noise_reduction 0) # noise reduction strength
+(sc_threshold 0) # scene change detection threshold
+(me_range 0) # limit motion vectors range (1023 for DivX player, 0 = no limit)
+(coder 0) # coder type 0=VLC 1=AC
+(context 0) # context model
+(predictor 0) # prediction method (0 LEFT, 1 PLANE, 2 MEDIAN
+(nsse_weight 8) # noise vs. sse weight for the nsse comparsion function.
+(subpel_quality 8) # subpel ME quality
+(strict_gop 0) # strictly enforce GOP size
+(no_output 0) # skip bitstream encoding
+(video_mb_lmin 236) # min macroblock quantiser scale (VBR) 0-3658
+(video_mb_lmax 3658) # max macroblock quantiser scale (VBR) 0-3658
+(video_profile -99)
+(video_level -99)
+(frame_skip_threshold 0) # frame skip threshold
+(frame_skip_factor 0) # frame skip factor
+(frame_skip_exp 0) # frame skip exponent
+(frame_skip_cmp 13) # frame skip comparission function
+(mux_rate 0)
+(mux_packet_size 2324)
+(mux_preload 0.5) # set the initial demux-decode delay (secs)
+(mux_max_delay 0.69999998807907104) # set the maximum demux-decode delay (secs)
+(b_frame_strategy 0) # strategy to choose between I/P/B-frames
+(workaround_bugs 1) # 1:FF_BUG_AUTODETECT, 2:FF_BUG_OLD_MSMPEG4 4:FF_BUG_XVID_ILACE 8:FF_BUG_UMP4 1
+(error_recognition 1) # 1:FF_ER_CAREFUL 2:FF_ER_COMPLIANT 3:FF_ER_AGGRESSIVE 4:FF_ER_VERY_AGGRESSIVE
+(mpeg_quant 0) # 0-> h263 quant 1-> mpeg quant
+(rc_qsquish 0) # how to keep quantizer between qmin and qmax (0 = clip, 1 = use differentiable
+(rc_qmod_amp 0) # experimental quantizer modulation
+(rc_qmod_freq 0) # experimental quantizer modulation
+(rc_eq[60] "") # rate control equation (tex^qComp)
+(rc_buffer_aggressivity 1) # currently useless
+(dia_size 0) # ME diamond size & shape
+(last_predictor_count 0) # amount of previous MV predictors (2a+1 x 2a+1 square)
+(pre_dia_size 0) # ME prepass diamond size & shape
+(inter_threshold 0)
+(border_masking 0) # increases the quantizer for macroblocks close to borders
+(me_penalty_compensation 256) # motion estimation bitrate penalty compensation (1.0 = 256)
+(bidir_refine 0) # refine the two motion vectors used in bidirectional macroblocks
+(brd_scale 0) # downscales frames for dynamic B-frame decision
+(crf 0) # constant rate factor - quality-based VBR - values ~correspond to qps
+(cqp -1) # constant quantization parameter rate control method
+(keyint_min 25) # minimum GOP size
+(refs 1) # number of reference frames
+(chromaoffset 0) # chroma qp offset from luma
+(bframebias 0) # Influences how often B-frames are used
+(trellis 0) # trellis RD quantization
+(complexityblur 20) # Reduce fluctuations in qp (before curve compression)
+(deblockalpha 0) # in-loop deblocking filter alphac0 parameter. alpha is in the range -6...6
+(deblockbeta 0) # in-loop deblocking filter beta parameter. beta is in the range -6...6
+(partitions 0) # macroblock subpartition sizes to consider - p8x8, p4x4, b8x8, i8x8, i4x4
+(directpred 2) # direct MV prediction mode - 0 (none), 1 (spatial), 2 (temporal), 3 (auto)
+(cutoff 0) # Audio cutoff bandwidth (0 means automatic)
+(scenechange_factor 6) # Multiplied by qscale for each frame and added to scene_change_score.
+(mv0_threshold 256) # Value depends upon the compare function used for fullpel ME
+(b_sensitivity 40) # Adjusts sensitivity of b_frame_strategy 1
+(compression_level -1)
+(use_lpc -1) # Sets whether to use LPC mode - used by FLAC encoder
+(lpc_coeff_precision 0) # LPC coefficient precision - used by FLAC encoder
+(min_prediction_order -1)
+(max_prediction_order -1)
+(prediction_order_method -1) # search method for selecting prediction order
+(min_partition_order -1)
+(timecode_frame_start 0) # GOP timecode frame start number, in non drop frame format
+(bits_per_raw_sample 0) # This field is applicable only when sample_fmt is SAMPLE_FMT_S32
+(channel_layout 0) # Audio channel layout
+(rc_max_available_vbv_use 0.33333333333333331) # Ratecontrol attempt to use, at maximum, <value> of what can be used without a
+(rc_min_vbv_overflow_use 3) # Ratecontrol attempt to use, at least, <value> times the amount needed to prev
+(color_primaries 0) # Chromaticity coordinates of the source primaries.
+(color_trc 0) # Color Transfer Characteristic.
+(colorspace 0) # YUV colorspace type.
+(color_range 0) # MPEG vs JPEG YUV range.
+(chroma_sample_location 0) # This defines the location of chroma samples.
+(weighted_p_pred 0) # explicit P-frame weighted prediction analysis method 0:off, 1: fast blind wei
+(aq_mode 0) # AQ mode
+(aq_strength 0) # AQ strength, Reduces blocking and blurring in flat and textured areas.
+(psy_rd 0) # PSY RD Strength of psychovisual optimization
+(psy_trellis 0) # PSY trellis Strength of psychovisual optimization
+(rc_lookahead 0) # Number of frames for frametype and ratecontrol lookahead
+(bitexact no) # CODEC_FLAG_BITEXACT (for testing, unused in productive version)
+(use_ss no) # CODEC_FLAG_H263P_SLICE_STRUCT enable Slice Structured mode (h263+)
+(use_aiv no) # CODEC_FLAG_H263P_AIV enable Alternative inter vlc (h263+)
+(use_obmc no) # CODEC_FLAG_OBMC use overlapped block motion compensation (h263+)
+(use_loop no) # CODEC_FLAG_LOOP_FILTER use loop filter (h263+)
+(use_alt_scan no) # CODEC_FLAG_ALT_SCAN enable alternate scantable (MPEG2/MPEG4)
+(use_mv0 no) # CODEC_FLAG_MV0 try to encode each MB with MV=<0,0> and choose the better one
+(do_normalize_aqp no) # CODEC_FLAG_NORMALIZE_AQP normalize adaptive quantization
+(use_scan_offset no) # CODEC_FLAG_SVCD_SCAN_OFFSET enable SVCD Scan Offset placeholder
+(closed_gop no) # CODEC_FLAG_CLOSED_GOP closed gop
+(use_qpel no) # CODEC_FLAG_QPEL enable 1/4-pel
+(use_qprd no) # CODEC_FLAG_QP_RD use rate distortion optimization for qp selection
+(use_cbprd no) # CODEC_FLAG_CBP_RD use rate distortion optimization for cbp
+(do_interlace_dct no) # CODEC_FLAG_INTERLACED_DCT use interlaced dct
+(do_interlace_me no) # CODEC_FLAG_INTERLACED_ME interlaced motion estimation
+(aic no) # CODEC_FLAG_AC_PRED activate intra frame coding (only h263+ CODEC)
+(umv no) # CODEC_FLAG_H263P_UMV enable unlimited motion vector (only h263+ CODEC)
+(mv4 no) # CODEC_FLAG_4MV use four motion vector by macroblock (only MPEG-4 CODEC)
+(partitioning no) # CODEC_FLAG_PART use data partitioning (only MPEG-4 CODEC)
+(use_gmc no) # CODEC_FLAG_GMC Use GMC
+(input_preserved no) # CODEC_FLAG_INPUT_PRESERVED
+(use_gray no) # CODEC_FLAG_GRAY Only encode grayscale
+(use_emu_edge no) # CODEC_FLAG_EMU_EDGE Dont draw edges
+(use_truncated no) # CODEC_FLAG_TRUNCATED Input bitstream might be truncated at a rando
+(use_fast no) # CODEC_FLAG2_FAST Allow non spec compliant speedup tricks
+(use_local_header no) # CODEC_FLAG2_LOCAL_HEADER Place global headers at every keyframe instea
+(use_bpyramid no) # CODEC_FLAG2_BPYRAMID H.264 allow B-frames to be used as references
+(use_wpred no) # CODEC_FLAG2_WPRED H.264 weighted biprediction for B-frames
+(use_mixed_refs no) # CODEC_FLAG2_MIXED_REFS H.264 one reference per partition, as opposed
+(use_dct8x8 no) # CODEC_FLAG2_8X8DCT H.264 high profile 8x8 transform
+(use_fastpskip no) # CODEC_FLAG2_FASTPSKIP H.264 fast pskip
+(use_aud no) # CODEC_FLAG2_AUD H.264 access unit delimiters
+(use_brdo no) # CODEC_FLAG2_BRDO B-frame rate-distortion optimization
+(use_ivlc no) # CODEC_FLAG2_INTRA_VLC Use MPEG-2 intra VLC table.
+(use_memc_only no) # CODEC_FLAG2_MEMC_ONLY Only do ME/MC (I frames -> ref, P frame -> ME
+(use_drop_frame_timecode no) # CODEC_FLAG2_DROP_FRAME_TIMECODE timecode is in drop frame format
+(use_skip_rd no) # CODEC_FLAG2_SKIP_RD RD optimal MB level residual skipping
+(use_chunks no) # CODEC_FLAG2_CHUNKS Input bitstream might be truncated at a packe
+(use_non_linear_quant no) # CODEC_FLAG2_NON_LINEAR_QUANT Use MPEG-2 nonlinear quantizer
+(use_bit_reservoir no) # CODEC_FLAG2_BIT_RESERVOIR Use a bit reservoir when encoding if possible
+(use_bit_mbtree no) # CODEC_FLAG2_MBTREE Use macroblock tree ratecontrol (x264 only)
+(use_bit_psy no) # CODEC_FLAG2_PSY Use psycho visual optimizations.
+(use_bit_ssim no) # CODEC_FLAG2_SSIM Compute SSIM during encoding, error[] values
+(parti4x4 no) # X264_PART_I4X4 Analyze i4x4
+(parti8x8 no) # X264_PART_I8X8 Analyze i8x8 (requires 8x8 transform)
+(partp4x4 no) # X264_PART_P8X8 Analyze p16x8, p8x16 and p8x8
+(partp8x8 no) # X264_PART_P4X4 Analyze p8x4, p4x8, p4x4
+(partb8x8 no) # X264_PART_B8X8 Analyze b16x8, b8x16 and b8x8
diff --git a/vid_enc_ffmpeg/ff_mpeg1_vcd.preset b/vid_enc_ffmpeg/ff_mpeg1_vcd.preset
new file mode 100644
index 0000000..e393e1f
--- /dev/null
+++ b/vid_enc_ffmpeg/ff_mpeg1_vcd.preset
@@ -0,0 +1,195 @@
+# GIMP / GAP FFMPEG videoencoder parameter file
+(preset_name "MPEG1 (VCD) preset")
+(format_name "vcd")
+(vcodec_name "mpeg1video")
+(acodec_name "mp2")
+(title "")
+(author "")
+(copyright "")
+(comment "")
+(passlogfile "ffmpeg2pass")
+(pass 1) # 1: one pass encoding, 2: for two-pass encoding
+(ntsc_width 352) # recommanded width NTSC, 0: not available
+(ntsc_height 240) # recommanded height NTSC, 0: not available
+(pal_width 352) # recommanded width PAL, 0: not available
+(pal_height 288) # recommanded height PAL, 0: not available
+(audio_bitrate 224) # audio bitrate in kBit/sec
+(video_bitrate 1150) # video bitrate in kBit/sec
+(gop_size 18) # group of picture size
+(qscale 1) # use fixed video quantiser scale (VBR). 0=const bitrate
+(qmin 2) # min video quantiser scale (VBR)
+(qmax 31) # max video quantiser scale (VBR)
+(qdiff 3) # max difference between the quantiser scale (VBR)
+(qblur 0.5) # video quantiser scale blur (VBR)
+(qcomp 0.5) # video quantiser scale compression (VBR)
+(rc_init_cplx 0) # initial complexity for 1-pass encoding
+(b_qfactor 1.25) # qp factor between p and b frames
+(i_qfactor -0.80000001192092896) # qp factor between p and i frames
+(b_qoffset 1.25) # qp offset between p and b frames
+(i_qoffset 0) # qp offset between p and i frames
+(bitrate_tol 1150) # set video bitrate tolerance (in kbit/s)
+(maxrate_tol 1150) # set max video bitrate tolerance (in kbit/s)
+(minrate_tol 1150) # set min video bitrate tolerance (in kbit/s)
+(bufsize 40) # set ratecontrol buffere size (in kbit)
+(motion_estimation 5) # algorithm for motion estimation (1-6)
+(dct_algo 0) # algorithm for DCT (0-6)
+(idct_algo 0) # algorithm for IDCT (0-11)
+(strict 0) # how strictly to follow the standards
+(mb_qmin 2) # OBSOLETE min macroblock quantiser scale (VBR)
+(mb_qmax 31) # OBSOLETE max macroblock quantiser scale (VBR)
+(mb_decision 0) # algorithm for macroblock decision (0-2)
+(b_frames 0) # max number of B-frames in sequence
+(packet_size 0)
+(intra no) # use only intra frames
+(set_aspect_ratio yes) # store aspectratio information (width/height) in the output video
+(factor_aspect_ratio 0) # the aspect ratio (width/height). 0.0 = auto ratio assuming sqaure pixels
+(dont_recode_flag no) # bypass the video encoder where frames can be copied 1:1
+(thread_count 1)
+(mb_cmp 0) # macroblock compare function (0-13,255)
+(ildct_cmp 8) # ildct compare function (0-13,255)
+(sub_cmp 0) # subpel compare function (0-13,255)
+(cmp 0) # fullpel compare function (0-13,255)
+(pre_cmp 0) # pre motion estimation compare function (0-13,255)
+(pre_me 0) # pre motion estimation
+(lumi_mask 0) # luminance masking
+(dark_mask 0) # darkness masking
+(scplx_mask 0) # spatial complexity masking
+(tcplx_mask 0) # temporary complexity masking
+(p_mask 0) # p block masking
+(qns 0) # quantization noise shaping
+(video_lmin 236) # min video lagrange factor (VBR) 0-3658
+(video_lmax 3658) # max video lagrange factor (VBR) 0-3658
+(video_lelim 0) # luma elimination threshold
+(video_celim 0) # chroma elimination threshold
+(video_intra_quant_bias 999999) # intra quant bias
+(video_inter_quant_bias 999999) # inter quant bias
+(me_threshold 0) # motion estimaton threshold
+(mb_threshold 0) # macroblock threshold
+(intra_dc_precision 8) # precision of the intra dc coefficient - 8
+(error_rate 0) # simulates errors in the bitstream to test error concealment
+(noise_reduction 0) # noise reduction strength
+(sc_threshold 0) # scene change detection threshold
+(me_range 0) # limit motion vectors range (1023 for DivX player, 0 = no limit)
+(coder 0) # coder type 0=VLC 1=AC
+(context 0) # context model
+(predictor 0) # prediction method (0 LEFT, 1 PLANE, 2 MEDIAN
+(nsse_weight 8) # noise vs. sse weight for the nsse comparsion function.
+(subpel_quality 8) # subpel ME quality
+(strict_gop 0) # strictly enforce GOP size
+(no_output 0) # skip bitstream encoding
+(video_mb_lmin 236) # min macroblock quantiser scale (VBR) 0-3658
+(video_mb_lmax 3658) # max macroblock quantiser scale (VBR) 0-3658
+(video_profile -99)
+(video_level -99)
+(frame_skip_threshold 0) # frame skip threshold
+(frame_skip_factor 0) # frame skip factor
+(frame_skip_exp 0) # frame skip exponent
+(frame_skip_cmp 13) # frame skip comparission function
+(mux_rate 1000000)
+(mux_packet_size 2324)
+(mux_preload 0.43999999761581421) # set the initial demux-decode delay (secs)
+(mux_max_delay 0.69999998807907104) # set the maximum demux-decode delay (secs)
+(b_frame_strategy 0) # strategy to choose between I/P/B-frames
+(workaround_bugs 1) # 1:FF_BUG_AUTODETECT, 2:FF_BUG_OLD_MSMPEG4 4:FF_BUG_XVID_ILACE 8:FF_BUG_UMP4 1
+(error_recognition 1) # 1:FF_ER_CAREFUL 2:FF_ER_COMPLIANT 3:FF_ER_AGGRESSIVE 4:FF_ER_VERY_AGGRESSIVE
+(mpeg_quant 0) # 0-> h263 quant 1-> mpeg quant
+(rc_qsquish 0) # how to keep quantizer between qmin and qmax (0 = clip, 1 = use differentiable
+(rc_qmod_amp 0) # experimental quantizer modulation
+(rc_qmod_freq 0) # experimental quantizer modulation
+(rc_eq[60] "") # rate control equation (tex^qComp)
+(rc_buffer_aggressivity 1) # currently useless
+(dia_size 0) # ME diamond size & shape
+(last_predictor_count 0) # amount of previous MV predictors (2a+1 x 2a+1 square)
+(pre_dia_size 0) # ME prepass diamond size & shape
+(inter_threshold 0)
+(border_masking 0) # increases the quantizer for macroblocks close to borders
+(me_penalty_compensation 256) # motion estimation bitrate penalty compensation (1.0 = 256)
+(bidir_refine 0) # refine the two motion vectors used in bidirectional macroblocks
+(brd_scale 0) # downscales frames for dynamic B-frame decision
+(crf 0) # constant rate factor - quality-based VBR - values ~correspond to qps
+(cqp -1) # constant quantization parameter rate control method
+(keyint_min 25) # minimum GOP size
+(refs 1) # number of reference frames
+(chromaoffset 0) # chroma qp offset from luma
+(bframebias 0) # Influences how often B-frames are used
+(trellis 0) # trellis RD quantization
+(complexityblur 20) # Reduce fluctuations in qp (before curve compression)
+(deblockalpha 0) # in-loop deblocking filter alphac0 parameter. alpha is in the range -6...6
+(deblockbeta 0) # in-loop deblocking filter beta parameter. beta is in the range -6...6
+(partitions 0) # macroblock subpartition sizes to consider - p8x8, p4x4, b8x8, i8x8, i4x4
+(directpred 2) # direct MV prediction mode - 0 (none), 1 (spatial), 2 (temporal), 3 (auto)
+(cutoff 0) # Audio cutoff bandwidth (0 means automatic)
+(scenechange_factor 6) # Multiplied by qscale for each frame and added to scene_change_score.
+(mv0_threshold 256) # Value depends upon the compare function used for fullpel ME
+(b_sensitivity 40) # Adjusts sensitivity of b_frame_strategy 1
+(compression_level -1)
+(use_lpc -1) # Sets whether to use LPC mode - used by FLAC encoder
+(lpc_coeff_precision 0) # LPC coefficient precision - used by FLAC encoder
+(min_prediction_order -1)
+(max_prediction_order -1)
+(prediction_order_method -1) # search method for selecting prediction order
+(min_partition_order -1)
+(timecode_frame_start 0) # GOP timecode frame start number, in non drop frame format
+(bits_per_raw_sample 0) # This field is applicable only when sample_fmt is SAMPLE_FMT_S32
+(channel_layout 0) # Audio channel layout
+(rc_max_available_vbv_use 0.33333333333333331) # Ratecontrol attempt to use, at maximum, <value> of what can be used without a
+(rc_min_vbv_overflow_use 3) # Ratecontrol attempt to use, at least, <value> times the amount needed to prev
+(color_primaries 0) # Chromaticity coordinates of the source primaries.
+(color_trc 0) # Color Transfer Characteristic.
+(colorspace 0) # YUV colorspace type.
+(color_range 0) # MPEG vs JPEG YUV range.
+(chroma_sample_location 0) # This defines the location of chroma samples.
+(weighted_p_pred 0) # explicit P-frame weighted prediction analysis method 0:off, 1: fast blind wei
+(aq_mode 0) # AQ mode
+(aq_strength 0) # AQ strength, Reduces blocking and blurring in flat and textured areas.
+(psy_rd 0) # PSY RD Strength of psychovisual optimization
+(psy_trellis 0) # PSY trellis Strength of psychovisual optimization
+(rc_lookahead 0) # Number of frames for frametype and ratecontrol lookahead
+(bitexact no) # CODEC_FLAG_BITEXACT (for testing, unused in productive version)
+(use_ss no) # CODEC_FLAG_H263P_SLICE_STRUCT enable Slice Structured mode (h263+)
+(use_aiv no) # CODEC_FLAG_H263P_AIV enable Alternative inter vlc (h263+)
+(use_obmc no) # CODEC_FLAG_OBMC use overlapped block motion compensation (h263+)
+(use_loop no) # CODEC_FLAG_LOOP_FILTER use loop filter (h263+)
+(use_alt_scan no) # CODEC_FLAG_ALT_SCAN enable alternate scantable (MPEG2/MPEG4)
+(use_mv0 no) # CODEC_FLAG_MV0 try to encode each MB with MV=<0,0> and choose the better one
+(do_normalize_aqp no) # CODEC_FLAG_NORMALIZE_AQP normalize adaptive quantization
+(use_scan_offset no) # CODEC_FLAG_SVCD_SCAN_OFFSET enable SVCD Scan Offset placeholder
+(closed_gop no) # CODEC_FLAG_CLOSED_GOP closed gop
+(use_qpel no) # CODEC_FLAG_QPEL enable 1/4-pel
+(use_qprd no) # CODEC_FLAG_QP_RD use rate distortion optimization for qp selection
+(use_cbprd no) # CODEC_FLAG_CBP_RD use rate distortion optimization for cbp
+(do_interlace_dct no) # CODEC_FLAG_INTERLACED_DCT use interlaced dct
+(do_interlace_me no) # CODEC_FLAG_INTERLACED_ME interlaced motion estimation
+(aic no) # CODEC_FLAG_AC_PRED activate intra frame coding (only h263+ CODEC)
+(umv no) # CODEC_FLAG_H263P_UMV enable unlimited motion vector (only h263+ CODEC)
+(mv4 no) # CODEC_FLAG_4MV use four motion vector by macroblock (only MPEG-4 CODEC)
+(partitioning no) # CODEC_FLAG_PART use data partitioning (only MPEG-4 CODEC)
+(use_gmc no) # CODEC_FLAG_GMC Use GMC
+(input_preserved no) # CODEC_FLAG_INPUT_PRESERVED
+(use_gray no) # CODEC_FLAG_GRAY Only encode grayscale
+(use_emu_edge no) # CODEC_FLAG_EMU_EDGE Dont draw edges
+(use_truncated no) # CODEC_FLAG_TRUNCATED Input bitstream might be truncated at a rando
+(use_fast no) # CODEC_FLAG2_FAST Allow non spec compliant speedup tricks
+(use_local_header no) # CODEC_FLAG2_LOCAL_HEADER Place global headers at every keyframe instea
+(use_bpyramid no) # CODEC_FLAG2_BPYRAMID H.264 allow B-frames to be used as references
+(use_wpred no) # CODEC_FLAG2_WPRED H.264 weighted biprediction for B-frames
+(use_mixed_refs no) # CODEC_FLAG2_MIXED_REFS H.264 one reference per partition, as opposed
+(use_dct8x8 no) # CODEC_FLAG2_8X8DCT H.264 high profile 8x8 transform
+(use_fastpskip no) # CODEC_FLAG2_FASTPSKIP H.264 fast pskip
+(use_aud no) # CODEC_FLAG2_AUD H.264 access unit delimiters
+(use_brdo no) # CODEC_FLAG2_BRDO B-frame rate-distortion optimization
+(use_ivlc no) # CODEC_FLAG2_INTRA_VLC Use MPEG-2 intra VLC table.
+(use_memc_only no) # CODEC_FLAG2_MEMC_ONLY Only do ME/MC (I frames -> ref, P frame -> ME
+(use_drop_frame_timecode no) # CODEC_FLAG2_DROP_FRAME_TIMECODE timecode is in drop frame format
+(use_skip_rd no) # CODEC_FLAG2_SKIP_RD RD optimal MB level residual skipping
+(use_chunks no) # CODEC_FLAG2_CHUNKS Input bitstream might be truncated at a packe
+(use_non_linear_quant no) # CODEC_FLAG2_NON_LINEAR_QUANT Use MPEG-2 nonlinear quantizer
+(use_bit_reservoir no) # CODEC_FLAG2_BIT_RESERVOIR Use a bit reservoir when encoding if possible
+(use_bit_mbtree no) # CODEC_FLAG2_MBTREE Use macroblock tree ratecontrol (x264 only)
+(use_bit_psy no) # CODEC_FLAG2_PSY Use psycho visual optimizations.
+(use_bit_ssim no) # CODEC_FLAG2_SSIM Compute SSIM during encoding, error[] values
+(parti4x4 no) # X264_PART_I4X4 Analyze i4x4
+(parti8x8 no) # X264_PART_I8X8 Analyze i8x8 (requires 8x8 transform)
+(partp4x4 no) # X264_PART_P8X8 Analyze p16x8, p8x16 and p8x8
+(partp8x8 no) # X264_PART_P4X4 Analyze p8x4, p4x8, p4x4
+(partb8x8 no) # X264_PART_B8X8 Analyze b16x8, b8x16 and b8x8
diff --git a/vid_enc_ffmpeg/ff_mpeg2_dvd.preset b/vid_enc_ffmpeg/ff_mpeg2_dvd.preset
new file mode 100644
index 0000000..a3d8b23
--- /dev/null
+++ b/vid_enc_ffmpeg/ff_mpeg2_dvd.preset
@@ -0,0 +1,195 @@
+# GIMP / GAP FFMPEG videoencoder parameter file
+(preset_name "MPEG2 (DVD) preset")
+(format_name "vob")
+(vcodec_name "mpeg2video")
+(acodec_name "ac3")
+(title "")
+(author "")
+(copyright "")
+(comment "")
+(passlogfile "ffmpeg2pass")
+(pass 1) # 1: one pass encoding, 2: for two-pass encoding
+(ntsc_width 720) # recommanded width NTSC, 0: not available
+(ntsc_height 480) # recommanded height NTSC, 0: not available
+(pal_width 720) # recommanded width PAL, 0: not available
+(pal_height 576) # recommanded height PAL, 0: not available
+(audio_bitrate 192) # audio bitrate in kBit/sec
+(video_bitrate 6000) # video bitrate in kBit/sec
+(gop_size 18) # group of picture size
+(qscale 1) # use fixed video quantiser scale (VBR). 0=const bitrate
+(qmin 2) # min video quantiser scale (VBR)
+(qmax 8) # max video quantiser scale (VBR)
+(qdiff 2) # max difference between the quantiser scale (VBR)
+(qblur 0.5) # video quantiser scale blur (VBR)
+(qcomp 0.5) # video quantiser scale compression (VBR)
+(rc_init_cplx 0) # initial complexity for 1-pass encoding
+(b_qfactor 1.25) # qp factor between p and b frames
+(i_qfactor -0.80000001192092896) # qp factor between p and i frames
+(b_qoffset 1.25) # qp offset between p and b frames
+(i_qoffset 0) # qp offset between p and i frames
+(bitrate_tol 2000) # set video bitrate tolerance (in kbit/s)
+(maxrate_tol 9000) # set max video bitrate tolerance (in kbit/s)
+(minrate_tol 0) # set min video bitrate tolerance (in kbit/s)
+(bufsize 224) # set ratecontrol buffere size (in kbit)
+(motion_estimation 5) # algorithm for motion estimation (1-6)
+(dct_algo 0) # algorithm for DCT (0-6)
+(idct_algo 0) # algorithm for IDCT (0-11)
+(strict 0) # how strictly to follow the standards
+(mb_qmin 2) # OBSOLETE min macroblock quantiser scale (VBR)
+(mb_qmax 31) # OBSOLETE max macroblock quantiser scale (VBR)
+(mb_decision 0) # algorithm for macroblock decision (0-2)
+(b_frames 2) # max number of B-frames in sequence
+(packet_size 0)
+(intra no) # use only intra frames
+(set_aspect_ratio yes) # store aspectratio information (width/height) in the output video
+(factor_aspect_ratio 0) # the aspect ratio (width/height). 0.0 = auto ratio assuming sqaure pixels
+(dont_recode_flag no) # bypass the video encoder where frames can be copied 1:1
+(thread_count 1)
+(mb_cmp 0) # macroblock compare function (0-13,255)
+(ildct_cmp 8) # ildct compare function (0-13,255)
+(sub_cmp 0) # subpel compare function (0-13,255)
+(cmp 0) # fullpel compare function (0-13,255)
+(pre_cmp 0) # pre motion estimation compare function (0-13,255)
+(pre_me 0) # pre motion estimation
+(lumi_mask 0) # luminance masking
+(dark_mask 0) # darkness masking
+(scplx_mask 0) # spatial complexity masking
+(tcplx_mask 0) # temporary complexity masking
+(p_mask 0) # p block masking
+(qns 0) # quantization noise shaping
+(video_lmin 236) # min video lagrange factor (VBR) 0-3658
+(video_lmax 3658) # max video lagrange factor (VBR) 0-3658
+(video_lelim 0) # luma elimination threshold
+(video_celim 0) # chroma elimination threshold
+(video_intra_quant_bias 999999) # intra quant bias
+(video_inter_quant_bias 999999) # inter quant bias
+(me_threshold 0) # motion estimaton threshold
+(mb_threshold 0) # macroblock threshold
+(intra_dc_precision 8) # precision of the intra dc coefficient - 8
+(error_rate 0) # simulates errors in the bitstream to test error concealment
+(noise_reduction 0) # noise reduction strength
+(sc_threshold 0) # scene change detection threshold
+(me_range 0) # limit motion vectors range (1023 for DivX player, 0 = no limit)
+(coder 0) # coder type 0=VLC 1=AC
+(context 0) # context model
+(predictor 0) # prediction method (0 LEFT, 1 PLANE, 2 MEDIAN
+(nsse_weight 8) # noise vs. sse weight for the nsse comparsion function.
+(subpel_quality 8) # subpel ME quality
+(strict_gop 0) # strictly enforce GOP size
+(no_output 0) # skip bitstream encoding
+(video_mb_lmin 236) # min macroblock quantiser scale (VBR) 0-3658
+(video_mb_lmax 3658) # max macroblock quantiser scale (VBR) 0-3658
+(video_profile -99)
+(video_level -99)
+(frame_skip_threshold 0) # frame skip threshold
+(frame_skip_factor 0) # frame skip factor
+(frame_skip_exp 0) # frame skip exponent
+(frame_skip_cmp 13) # frame skip comparission function
+(mux_rate 1000000)
+(mux_packet_size 2048)
+(mux_preload 0.5) # set the initial demux-decode delay (secs)
+(mux_max_delay 0.69999998807907104) # set the maximum demux-decode delay (secs)
+(b_frame_strategy 0) # strategy to choose between I/P/B-frames
+(workaround_bugs 1) # 1:FF_BUG_AUTODETECT, 2:FF_BUG_OLD_MSMPEG4 4:FF_BUG_XVID_ILACE 8:FF_BUG_UMP4 1
+(error_recognition 1) # 1:FF_ER_CAREFUL 2:FF_ER_COMPLIANT 3:FF_ER_AGGRESSIVE 4:FF_ER_VERY_AGGRESSIVE
+(mpeg_quant 0) # 0-> h263 quant 1-> mpeg quant
+(rc_qsquish 0) # how to keep quantizer between qmin and qmax (0 = clip, 1 = use differentiable
+(rc_qmod_amp 0) # experimental quantizer modulation
+(rc_qmod_freq 0) # experimental quantizer modulation
+(rc_eq[60] "") # rate control equation (tex^qComp)
+(rc_buffer_aggressivity 1) # currently useless
+(dia_size 0) # ME diamond size & shape
+(last_predictor_count 0) # amount of previous MV predictors (2a+1 x 2a+1 square)
+(pre_dia_size 0) # ME prepass diamond size & shape
+(inter_threshold 0)
+(border_masking 0) # increases the quantizer for macroblocks close to borders
+(me_penalty_compensation 256) # motion estimation bitrate penalty compensation (1.0 = 256)
+(bidir_refine 0) # refine the two motion vectors used in bidirectional macroblocks
+(brd_scale 0) # downscales frames for dynamic B-frame decision
+(crf 0) # constant rate factor - quality-based VBR - values ~correspond to qps
+(cqp -1) # constant quantization parameter rate control method
+(keyint_min 25) # minimum GOP size
+(refs 1) # number of reference frames
+(chromaoffset 0) # chroma qp offset from luma
+(bframebias 0) # Influences how often B-frames are used
+(trellis 0) # trellis RD quantization
+(complexityblur 20) # Reduce fluctuations in qp (before curve compression)
+(deblockalpha 0) # in-loop deblocking filter alphac0 parameter. alpha is in the range -6...6
+(deblockbeta 0) # in-loop deblocking filter beta parameter. beta is in the range -6...6
+(partitions 0) # macroblock subpartition sizes to consider - p8x8, p4x4, b8x8, i8x8, i4x4
+(directpred 2) # direct MV prediction mode - 0 (none), 1 (spatial), 2 (temporal), 3 (auto)
+(cutoff 0) # Audio cutoff bandwidth (0 means automatic)
+(scenechange_factor 6) # Multiplied by qscale for each frame and added to scene_change_score.
+(mv0_threshold 256) # Value depends upon the compare function used for fullpel ME
+(b_sensitivity 40) # Adjusts sensitivity of b_frame_strategy 1
+(compression_level -1)
+(use_lpc -1) # Sets whether to use LPC mode - used by FLAC encoder
+(lpc_coeff_precision 0) # LPC coefficient precision - used by FLAC encoder
+(min_prediction_order -1)
+(max_prediction_order -1)
+(prediction_order_method -1) # search method for selecting prediction order
+(min_partition_order -1)
+(timecode_frame_start 0) # GOP timecode frame start number, in non drop frame format
+(bits_per_raw_sample 0) # This field is applicable only when sample_fmt is SAMPLE_FMT_S32
+(channel_layout 0) # Audio channel layout
+(rc_max_available_vbv_use 0.33333333333333331) # Ratecontrol attempt to use, at maximum, <value> of what can be used without a
+(rc_min_vbv_overflow_use 3) # Ratecontrol attempt to use, at least, <value> times the amount needed to prev
+(color_primaries 0) # Chromaticity coordinates of the source primaries.
+(color_trc 0) # Color Transfer Characteristic.
+(colorspace 0) # YUV colorspace type.
+(color_range 0) # MPEG vs JPEG YUV range.
+(chroma_sample_location 0) # This defines the location of chroma samples.
+(weighted_p_pred 0) # explicit P-frame weighted prediction analysis method 0:off, 1: fast blind wei
+(aq_mode 0) # AQ mode
+(aq_strength 0) # AQ strength, Reduces blocking and blurring in flat and textured areas.
+(psy_rd 0) # PSY RD Strength of psychovisual optimization
+(psy_trellis 0) # PSY trellis Strength of psychovisual optimization
+(rc_lookahead 0) # Number of frames for frametype and ratecontrol lookahead
+(bitexact no) # CODEC_FLAG_BITEXACT (for testing, unused in productive version)
+(use_ss no) # CODEC_FLAG_H263P_SLICE_STRUCT enable Slice Structured mode (h263+)
+(use_aiv no) # CODEC_FLAG_H263P_AIV enable Alternative inter vlc (h263+)
+(use_obmc no) # CODEC_FLAG_OBMC use overlapped block motion compensation (h263+)
+(use_loop no) # CODEC_FLAG_LOOP_FILTER use loop filter (h263+)
+(use_alt_scan no) # CODEC_FLAG_ALT_SCAN enable alternate scantable (MPEG2/MPEG4)
+(use_mv0 no) # CODEC_FLAG_MV0 try to encode each MB with MV=<0,0> and choose the better one
+(do_normalize_aqp no) # CODEC_FLAG_NORMALIZE_AQP normalize adaptive quantization
+(use_scan_offset no) # CODEC_FLAG_SVCD_SCAN_OFFSET enable SVCD Scan Offset placeholder
+(closed_gop no) # CODEC_FLAG_CLOSED_GOP closed gop
+(use_qpel no) # CODEC_FLAG_QPEL enable 1/4-pel
+(use_qprd no) # CODEC_FLAG_QP_RD use rate distortion optimization for qp selection
+(use_cbprd no) # CODEC_FLAG_CBP_RD use rate distortion optimization for cbp
+(do_interlace_dct no) # CODEC_FLAG_INTERLACED_DCT use interlaced dct
+(do_interlace_me no) # CODEC_FLAG_INTERLACED_ME interlaced motion estimation
+(aic no) # CODEC_FLAG_AC_PRED activate intra frame coding (only h263+ CODEC)
+(umv no) # CODEC_FLAG_H263P_UMV enable unlimited motion vector (only h263+ CODEC)
+(mv4 no) # CODEC_FLAG_4MV use four motion vector by macroblock (only MPEG-4 CODEC)
+(partitioning no) # CODEC_FLAG_PART use data partitioning (only MPEG-4 CODEC)
+(use_gmc no) # CODEC_FLAG_GMC Use GMC
+(input_preserved no) # CODEC_FLAG_INPUT_PRESERVED
+(use_gray no) # CODEC_FLAG_GRAY Only encode grayscale
+(use_emu_edge no) # CODEC_FLAG_EMU_EDGE Dont draw edges
+(use_truncated no) # CODEC_FLAG_TRUNCATED Input bitstream might be truncated at a rando
+(use_fast no) # CODEC_FLAG2_FAST Allow non spec compliant speedup tricks
+(use_local_header no) # CODEC_FLAG2_LOCAL_HEADER Place global headers at every keyframe instea
+(use_bpyramid no) # CODEC_FLAG2_BPYRAMID H.264 allow B-frames to be used as references
+(use_wpred no) # CODEC_FLAG2_WPRED H.264 weighted biprediction for B-frames
+(use_mixed_refs no) # CODEC_FLAG2_MIXED_REFS H.264 one reference per partition, as opposed
+(use_dct8x8 no) # CODEC_FLAG2_8X8DCT H.264 high profile 8x8 transform
+(use_fastpskip no) # CODEC_FLAG2_FASTPSKIP H.264 fast pskip
+(use_aud no) # CODEC_FLAG2_AUD H.264 access unit delimiters
+(use_brdo no) # CODEC_FLAG2_BRDO B-frame rate-distortion optimization
+(use_ivlc no) # CODEC_FLAG2_INTRA_VLC Use MPEG-2 intra VLC table.
+(use_memc_only no) # CODEC_FLAG2_MEMC_ONLY Only do ME/MC (I frames -> ref, P frame -> ME
+(use_drop_frame_timecode no) # CODEC_FLAG2_DROP_FRAME_TIMECODE timecode is in drop frame format
+(use_skip_rd no) # CODEC_FLAG2_SKIP_RD RD optimal MB level residual skipping
+(use_chunks no) # CODEC_FLAG2_CHUNKS Input bitstream might be truncated at a packe
+(use_non_linear_quant no) # CODEC_FLAG2_NON_LINEAR_QUANT Use MPEG-2 nonlinear quantizer
+(use_bit_reservoir no) # CODEC_FLAG2_BIT_RESERVOIR Use a bit reservoir when encoding if possible
+(use_bit_mbtree no) # CODEC_FLAG2_MBTREE Use macroblock tree ratecontrol (x264 only)
+(use_bit_psy no) # CODEC_FLAG2_PSY Use psycho visual optimizations.
+(use_bit_ssim no) # CODEC_FLAG2_SSIM Compute SSIM during encoding, error[] values
+(parti4x4 no) # X264_PART_I4X4 Analyze i4x4
+(parti8x8 no) # X264_PART_I8X8 Analyze i8x8 (requires 8x8 transform)
+(partp4x4 no) # X264_PART_P8X8 Analyze p16x8, p8x16 and p8x8
+(partp8x8 no) # X264_PART_P4X4 Analyze p8x4, p4x8, p4x4
+(partb8x8 no) # X264_PART_B8X8 Analyze b16x8, b8x16 and b8x8
diff --git a/vid_enc_ffmpeg/ff_mpeg2_svcd.preset b/vid_enc_ffmpeg/ff_mpeg2_svcd.preset
new file mode 100644
index 0000000..961cdc3
--- /dev/null
+++ b/vid_enc_ffmpeg/ff_mpeg2_svcd.preset
@@ -0,0 +1,195 @@
+# GIMP / GAP FFMPEG videoencoder parameter file
+(preset_name "MPEG2 (SVCD) preset")
+(format_name "svcd")
+(vcodec_name "mpeg2video")
+(acodec_name "mp2")
+(title "")
+(author "")
+(copyright "")
+(comment "")
+(passlogfile "ffmpeg2pass")
+(pass 1) # 1: one pass encoding, 2: for two-pass encoding
+(ntsc_width 480) # recommanded width NTSC, 0: not available
+(ntsc_height 480) # recommanded height NTSC, 0: not available
+(pal_width 480) # recommanded width PAL, 0: not available
+(pal_height 576) # recommanded height PAL, 0: not available
+(audio_bitrate 224) # audio bitrate in kBit/sec
+(video_bitrate 2040) # video bitrate in kBit/sec
+(gop_size 18) # group of picture size
+(qscale 1) # use fixed video quantiser scale (VBR). 0=const bitrate
+(qmin 2) # min video quantiser scale (VBR)
+(qmax 16) # max video quantiser scale (VBR)
+(qdiff 2) # max difference between the quantiser scale (VBR)
+(qblur 0.5) # video quantiser scale blur (VBR)
+(qcomp 0.5) # video quantiser scale compression (VBR)
+(rc_init_cplx 0) # initial complexity for 1-pass encoding
+(b_qfactor 1.25) # qp factor between p and b frames
+(i_qfactor -0.80000001192092896) # qp factor between p and i frames
+(b_qoffset 1.25) # qp offset between p and b frames
+(i_qoffset 0) # qp offset between p and i frames
+(bitrate_tol 2000) # set video bitrate tolerance (in kbit/s)
+(maxrate_tol 2516) # set max video bitrate tolerance (in kbit/s)
+(minrate_tol 0) # set min video bitrate tolerance (in kbit/s)
+(bufsize 224) # set ratecontrol buffere size (in kbit)
+(motion_estimation 5) # algorithm for motion estimation (1-6)
+(dct_algo 0) # algorithm for DCT (0-6)
+(idct_algo 0) # algorithm for IDCT (0-11)
+(strict 0) # how strictly to follow the standards
+(mb_qmin 2) # OBSOLETE min macroblock quantiser scale (VBR)
+(mb_qmax 31) # OBSOLETE max macroblock quantiser scale (VBR)
+(mb_decision 0) # algorithm for macroblock decision (0-2)
+(b_frames 2) # max number of B-frames in sequence
+(packet_size 0)
+(intra no) # use only intra frames
+(set_aspect_ratio yes) # store aspectratio information (width/height) in the output video
+(factor_aspect_ratio 0) # the aspect ratio (width/height). 0.0 = auto ratio assuming sqaure pixels
+(dont_recode_flag no) # bypass the video encoder where frames can be copied 1:1
+(thread_count 1)
+(mb_cmp 0) # macroblock compare function (0-13,255)
+(ildct_cmp 8) # ildct compare function (0-13,255)
+(sub_cmp 0) # subpel compare function (0-13,255)
+(cmp 0) # fullpel compare function (0-13,255)
+(pre_cmp 0) # pre motion estimation compare function (0-13,255)
+(pre_me 0) # pre motion estimation
+(lumi_mask 0) # luminance masking
+(dark_mask 0) # darkness masking
+(scplx_mask 0) # spatial complexity masking
+(tcplx_mask 0) # temporary complexity masking
+(p_mask 0) # p block masking
+(qns 0) # quantization noise shaping
+(video_lmin 236) # min video lagrange factor (VBR) 0-3658
+(video_lmax 3658) # max video lagrange factor (VBR) 0-3658
+(video_lelim 0) # luma elimination threshold
+(video_celim 0) # chroma elimination threshold
+(video_intra_quant_bias 999999) # intra quant bias
+(video_inter_quant_bias 999999) # inter quant bias
+(me_threshold 0) # motion estimaton threshold
+(mb_threshold 0) # macroblock threshold
+(intra_dc_precision 8) # precision of the intra dc coefficient - 8
+(error_rate 0) # simulates errors in the bitstream to test error concealment
+(noise_reduction 0) # noise reduction strength
+(sc_threshold 0) # scene change detection threshold
+(me_range 0) # limit motion vectors range (1023 for DivX player, 0 = no limit)
+(coder 0) # coder type 0=VLC 1=AC
+(context 0) # context model
+(predictor 0) # prediction method (0 LEFT, 1 PLANE, 2 MEDIAN
+(nsse_weight 8) # noise vs. sse weight for the nsse comparsion function.
+(subpel_quality 8) # subpel ME quality
+(strict_gop 0) # strictly enforce GOP size
+(no_output 0) # skip bitstream encoding
+(video_mb_lmin 236) # min macroblock quantiser scale (VBR) 0-3658
+(video_mb_lmax 3658) # max macroblock quantiser scale (VBR) 0-3658
+(video_profile -99)
+(video_level -99)
+(frame_skip_threshold 0) # frame skip threshold
+(frame_skip_factor 0) # frame skip factor
+(frame_skip_exp 0) # frame skip exponent
+(frame_skip_cmp 13) # frame skip comparission function
+(mux_rate 0)
+(mux_packet_size 2324)
+(mux_preload 0.5) # set the initial demux-decode delay (secs)
+(mux_max_delay 0.69999998807907104) # set the maximum demux-decode delay (secs)
+(b_frame_strategy 0) # strategy to choose between I/P/B-frames
+(workaround_bugs 1) # 1:FF_BUG_AUTODETECT, 2:FF_BUG_OLD_MSMPEG4 4:FF_BUG_XVID_ILACE 8:FF_BUG_UMP4 1
+(error_recognition 1) # 1:FF_ER_CAREFUL 2:FF_ER_COMPLIANT 3:FF_ER_AGGRESSIVE 4:FF_ER_VERY_AGGRESSIVE
+(mpeg_quant 0) # 0-> h263 quant 1-> mpeg quant
+(rc_qsquish 0) # how to keep quantizer between qmin and qmax (0 = clip, 1 = use differentiable
+(rc_qmod_amp 0) # experimental quantizer modulation
+(rc_qmod_freq 0) # experimental quantizer modulation
+(rc_eq[60] "") # rate control equation (tex^qComp)
+(rc_buffer_aggressivity 1) # currently useless
+(dia_size 0) # ME diamond size & shape
+(last_predictor_count 0) # amount of previous MV predictors (2a+1 x 2a+1 square)
+(pre_dia_size 0) # ME prepass diamond size & shape
+(inter_threshold 0)
+(border_masking 0) # increases the quantizer for macroblocks close to borders
+(me_penalty_compensation 256) # motion estimation bitrate penalty compensation (1.0 = 256)
+(bidir_refine 0) # refine the two motion vectors used in bidirectional macroblocks
+(brd_scale 0) # downscales frames for dynamic B-frame decision
+(crf 0) # constant rate factor - quality-based VBR - values ~correspond to qps
+(cqp -1) # constant quantization parameter rate control method
+(keyint_min 25) # minimum GOP size
+(refs 1) # number of reference frames
+(chromaoffset 0) # chroma qp offset from luma
+(bframebias 0) # Influences how often B-frames are used
+(trellis 0) # trellis RD quantization
+(complexityblur 20) # Reduce fluctuations in qp (before curve compression)
+(deblockalpha 0) # in-loop deblocking filter alphac0 parameter. alpha is in the range -6...6
+(deblockbeta 0) # in-loop deblocking filter beta parameter. beta is in the range -6...6
+(partitions 0) # macroblock subpartition sizes to consider - p8x8, p4x4, b8x8, i8x8, i4x4
+(directpred 2) # direct MV prediction mode - 0 (none), 1 (spatial), 2 (temporal), 3 (auto)
+(cutoff 0) # Audio cutoff bandwidth (0 means automatic)
+(scenechange_factor 6) # Multiplied by qscale for each frame and added to scene_change_score.
+(mv0_threshold 256) # Value depends upon the compare function used for fullpel ME
+(b_sensitivity 40) # Adjusts sensitivity of b_frame_strategy 1
+(compression_level -1)
+(use_lpc -1) # Sets whether to use LPC mode - used by FLAC encoder
+(lpc_coeff_precision 0) # LPC coefficient precision - used by FLAC encoder
+(min_prediction_order -1)
+(max_prediction_order -1)
+(prediction_order_method -1) # search method for selecting prediction order
+(min_partition_order -1)
+(timecode_frame_start 0) # GOP timecode frame start number, in non drop frame format
+(bits_per_raw_sample 0) # This field is applicable only when sample_fmt is SAMPLE_FMT_S32
+(channel_layout 0) # Audio channel layout
+(rc_max_available_vbv_use 0.33333333333333331) # Ratecontrol attempt to use, at maximum, <value> of what can be used without a
+(rc_min_vbv_overflow_use 3) # Ratecontrol attempt to use, at least, <value> times the amount needed to prev
+(color_primaries 0) # Chromaticity coordinates of the source primaries.
+(color_trc 0) # Color Transfer Characteristic.
+(colorspace 0) # YUV colorspace type.
+(color_range 0) # MPEG vs JPEG YUV range.
+(chroma_sample_location 0) # This defines the location of chroma samples.
+(weighted_p_pred 0) # explicit P-frame weighted prediction analysis method 0:off, 1: fast blind wei
+(aq_mode 0) # AQ mode
+(aq_strength 0) # AQ strength, Reduces blocking and blurring in flat and textured areas.
+(psy_rd 0) # PSY RD Strength of psychovisual optimization
+(psy_trellis 0) # PSY trellis Strength of psychovisual optimization
+(rc_lookahead 0) # Number of frames for frametype and ratecontrol lookahead
+(bitexact no) # CODEC_FLAG_BITEXACT (for testing, unused in productive version)
+(use_ss no) # CODEC_FLAG_H263P_SLICE_STRUCT enable Slice Structured mode (h263+)
+(use_aiv no) # CODEC_FLAG_H263P_AIV enable Alternative inter vlc (h263+)
+(use_obmc no) # CODEC_FLAG_OBMC use overlapped block motion compensation (h263+)
+(use_loop no) # CODEC_FLAG_LOOP_FILTER use loop filter (h263+)
+(use_alt_scan no) # CODEC_FLAG_ALT_SCAN enable alternate scantable (MPEG2/MPEG4)
+(use_mv0 no) # CODEC_FLAG_MV0 try to encode each MB with MV=<0,0> and choose the better one
+(do_normalize_aqp no) # CODEC_FLAG_NORMALIZE_AQP normalize adaptive quantization
+(use_scan_offset yes) # CODEC_FLAG_SVCD_SCAN_OFFSET enable SVCD Scan Offset placeholder
+(closed_gop no) # CODEC_FLAG_CLOSED_GOP closed gop
+(use_qpel no) # CODEC_FLAG_QPEL enable 1/4-pel
+(use_qprd no) # CODEC_FLAG_QP_RD use rate distortion optimization for qp selection
+(use_cbprd no) # CODEC_FLAG_CBP_RD use rate distortion optimization for cbp
+(do_interlace_dct no) # CODEC_FLAG_INTERLACED_DCT use interlaced dct
+(do_interlace_me no) # CODEC_FLAG_INTERLACED_ME interlaced motion estimation
+(aic no) # CODEC_FLAG_AC_PRED activate intra frame coding (only h263+ CODEC)
+(umv no) # CODEC_FLAG_H263P_UMV enable unlimited motion vector (only h263+ CODEC)
+(mv4 no) # CODEC_FLAG_4MV use four motion vector by macroblock (only MPEG-4 CODEC)
+(partitioning no) # CODEC_FLAG_PART use data partitioning (only MPEG-4 CODEC)
+(use_gmc no) # CODEC_FLAG_GMC Use GMC
+(input_preserved no) # CODEC_FLAG_INPUT_PRESERVED
+(use_gray no) # CODEC_FLAG_GRAY Only encode grayscale
+(use_emu_edge no) # CODEC_FLAG_EMU_EDGE Dont draw edges
+(use_truncated no) # CODEC_FLAG_TRUNCATED Input bitstream might be truncated at a rando
+(use_fast no) # CODEC_FLAG2_FAST Allow non spec compliant speedup tricks
+(use_local_header no) # CODEC_FLAG2_LOCAL_HEADER Place global headers at every keyframe instea
+(use_bpyramid no) # CODEC_FLAG2_BPYRAMID H.264 allow B-frames to be used as references
+(use_wpred no) # CODEC_FLAG2_WPRED H.264 weighted biprediction for B-frames
+(use_mixed_refs no) # CODEC_FLAG2_MIXED_REFS H.264 one reference per partition, as opposed
+(use_dct8x8 no) # CODEC_FLAG2_8X8DCT H.264 high profile 8x8 transform
+(use_fastpskip no) # CODEC_FLAG2_FASTPSKIP H.264 fast pskip
+(use_aud no) # CODEC_FLAG2_AUD H.264 access unit delimiters
+(use_brdo no) # CODEC_FLAG2_BRDO B-frame rate-distortion optimization
+(use_ivlc no) # CODEC_FLAG2_INTRA_VLC Use MPEG-2 intra VLC table.
+(use_memc_only no) # CODEC_FLAG2_MEMC_ONLY Only do ME/MC (I frames -> ref, P frame -> ME
+(use_drop_frame_timecode no) # CODEC_FLAG2_DROP_FRAME_TIMECODE timecode is in drop frame format
+(use_skip_rd no) # CODEC_FLAG2_SKIP_RD RD optimal MB level residual skipping
+(use_chunks no) # CODEC_FLAG2_CHUNKS Input bitstream might be truncated at a packe
+(use_non_linear_quant no) # CODEC_FLAG2_NON_LINEAR_QUANT Use MPEG-2 nonlinear quantizer
+(use_bit_reservoir no) # CODEC_FLAG2_BIT_RESERVOIR Use a bit reservoir when encoding if possible
+(use_bit_mbtree no) # CODEC_FLAG2_MBTREE Use macroblock tree ratecontrol (x264 only)
+(use_bit_psy no) # CODEC_FLAG2_PSY Use psycho visual optimizations.
+(use_bit_ssim no) # CODEC_FLAG2_SSIM Compute SSIM during encoding, error[] values
+(parti4x4 no) # X264_PART_I4X4 Analyze i4x4
+(parti8x8 no) # X264_PART_I8X8 Analyze i8x8 (requires 8x8 transform)
+(partp4x4 no) # X264_PART_P8X8 Analyze p16x8, p8x16 and p8x8
+(partp8x8 no) # X264_PART_P4X4 Analyze p8x4, p4x8, p4x4
+(partb8x8 no) # X264_PART_B8X8 Analyze b16x8, b8x16 and b8x8
diff --git a/vid_enc_ffmpeg/ff_real_standard.preset b/vid_enc_ffmpeg/ff_real_standard.preset
new file mode 100644
index 0000000..3184d64
--- /dev/null
+++ b/vid_enc_ffmpeg/ff_real_standard.preset
@@ -0,0 +1,191 @@
+# GIMP / GAP FFMPEG videoencoder parameter file
+(preset_name "REAL video preset")
+(format_name "rm")
+(vcodec_name "rv10")
+(acodec_name "ac3")
+(title "")
+(author "")
+(copyright "")
+(comment "")
+(passlogfile "ffmpeg2pass")
+(pass 1) # 1: one pass encoding, 2: for two-pass encoding
+(audio_bitrate 160) # audio bitrate in kBit/sec
+(video_bitrate 1200) # video bitrate in kBit/sec
+(gop_size 18) # group of picture size
+(qscale 2) # use fixed video quantiser scale (VBR). 0=const bitrate
+(qmin 2) # min video quantiser scale (VBR)
+(qmax 31) # max video quantiser scale (VBR)
+(qdiff 3) # max difference between the quantiser scale (VBR)
+(qblur 0.5) # video quantiser scale blur (VBR)
+(qcomp 0.5) # video quantiser scale compression (VBR)
+(rc_init_cplx 0) # initial complexity for 1-pass encoding
+(b_qfactor 1.25) # qp factor between p and b frames
+(i_qfactor -0.80000001192092896) # qp factor between p and i frames
+(b_qoffset 1.25) # qp offset between p and b frames
+(i_qoffset 0) # qp offset between p and i frames
+(bitrate_tol 5000) # set video bitrate tolerance (in kbit/s)
+(maxrate_tol 0) # set max video bitrate tolerance (in kbit/s)
+(minrate_tol 0) # set min video bitrate tolerance (in kbit/s)
+(bufsize 0) # set ratecontrol buffere size (in kbit)
+(motion_estimation 5) # algorithm for motion estimation (1-6)
+(dct_algo 0) # algorithm for DCT (0-6)
+(idct_algo 0) # algorithm for IDCT (0-11)
+(strict 0) # how strictly to follow the standards
+(mb_qmin 2) # OBSOLETE min macroblock quantiser scale (VBR)
+(mb_qmax 31) # OBSOLETE max macroblock quantiser scale (VBR)
+(mb_decision 0) # algorithm for macroblock decision (0-2)
+(b_frames 0) # max number of B-frames in sequence
+(packet_size 0)
+(intra no) # use only intra frames
+(set_aspect_ratio yes) # store aspectratio information (width/height) in the output video
+(factor_aspect_ratio 0) # the aspect ratio (width/height). 0.0 = auto ratio assuming sqaure pixels
+(dont_recode_flag no) # bypass the video encoder where frames can be copied 1:1
+(thread_count 1)
+(mb_cmp 0) # macroblock compare function (0-13,255)
+(ildct_cmp 8) # ildct compare function (0-13,255)
+(sub_cmp 0) # subpel compare function (0-13,255)
+(cmp 0) # fullpel compare function (0-13,255)
+(pre_cmp 0) # pre motion estimation compare function (0-13,255)
+(pre_me 0) # pre motion estimation
+(lumi_mask 0) # luminance masking
+(dark_mask 0) # darkness masking
+(scplx_mask 0) # spatial complexity masking
+(tcplx_mask 0) # temporary complexity masking
+(p_mask 0) # p block masking
+(qns 0) # quantization noise shaping
+(video_lmin 236) # min video lagrange factor (VBR) 0-3658
+(video_lmax 3658) # max video lagrange factor (VBR) 0-3658
+(video_lelim 0) # luma elimination threshold
+(video_celim 0) # chroma elimination threshold
+(video_intra_quant_bias 999999) # intra quant bias
+(video_inter_quant_bias 999999) # inter quant bias
+(me_threshold 0) # motion estimaton threshold
+(mb_threshold 0) # macroblock threshold
+(intra_dc_precision 8) # precision of the intra dc coefficient - 8
+(error_rate 0) # simulates errors in the bitstream to test error concealment
+(noise_reduction 0) # noise reduction strength
+(sc_threshold 0) # scene change detection threshold
+(me_range 0) # limit motion vectors range (1023 for DivX player, 0 = no limit)
+(coder 0) # coder type 0=VLC 1=AC
+(context 0) # context model
+(predictor 0) # prediction method (0 LEFT, 1 PLANE, 2 MEDIAN
+(nsse_weight 8) # noise vs. sse weight for the nsse comparsion function.
+(subpel_quality 8) # subpel ME quality
+(strict_gop 0) # strictly enforce GOP size
+(no_output 0) # skip bitstream encoding
+(video_mb_lmin 236) # min macroblock quantiser scale (VBR) 0-3658
+(video_mb_lmax 3658) # max macroblock quantiser scale (VBR) 0-3658
+(video_profile -99)
+(video_level -99)
+(frame_skip_threshold 0) # frame skip threshold
+(frame_skip_factor 0) # frame skip factor
+(frame_skip_exp 0) # frame skip exponent
+(frame_skip_cmp 13) # frame skip comparission function
+(mux_rate 0)
+(mux_packet_size 0)
+(mux_preload 0.5) # set the initial demux-decode delay (secs)
+(mux_max_delay 0.69999998807907104) # set the maximum demux-decode delay (secs)
+(b_frame_strategy 0) # strategy to choose between I/P/B-frames
+(workaround_bugs 1) # 1:FF_BUG_AUTODETECT, 2:FF_BUG_OLD_MSMPEG4 4:FF_BUG_XVID_ILACE 8:FF_BUG_UMP4 1
+(error_recognition 1) # 1:FF_ER_CAREFUL 2:FF_ER_COMPLIANT 3:FF_ER_AGGRESSIVE 4:FF_ER_VERY_AGGRESSIVE
+(mpeg_quant 0) # 0-> h263 quant 1-> mpeg quant
+(rc_qsquish 0) # how to keep quantizer between qmin and qmax (0 = clip, 1 = use differentiable
+(rc_qmod_amp 0) # experimental quantizer modulation
+(rc_qmod_freq 0) # experimental quantizer modulation
+(rc_eq[60] "") # rate control equation (tex^qComp)
+(rc_buffer_aggressivity 1) # currently useless
+(dia_size 0) # ME diamond size & shape
+(last_predictor_count 0) # amount of previous MV predictors (2a+1 x 2a+1 square)
+(pre_dia_size 0) # ME prepass diamond size & shape
+(inter_threshold 0)
+(border_masking 0) # increases the quantizer for macroblocks close to borders
+(me_penalty_compensation 256) # motion estimation bitrate penalty compensation (1.0 = 256)
+(bidir_refine 0) # refine the two motion vectors used in bidirectional macroblocks
+(brd_scale 0) # downscales frames for dynamic B-frame decision
+(crf 0) # constant rate factor - quality-based VBR - values ~correspond to qps
+(cqp -1) # constant quantization parameter rate control method
+(keyint_min 25) # minimum GOP size
+(refs 1) # number of reference frames
+(chromaoffset 0) # chroma qp offset from luma
+(bframebias 0) # Influences how often B-frames are used
+(trellis 0) # trellis RD quantization
+(complexityblur 20) # Reduce fluctuations in qp (before curve compression)
+(deblockalpha 0) # in-loop deblocking filter alphac0 parameter. alpha is in the range -6...6
+(deblockbeta 0) # in-loop deblocking filter beta parameter. beta is in the range -6...6
+(partitions 0) # macroblock subpartition sizes to consider - p8x8, p4x4, b8x8, i8x8, i4x4
+(directpred 2) # direct MV prediction mode - 0 (none), 1 (spatial), 2 (temporal), 3 (auto)
+(cutoff 0) # Audio cutoff bandwidth (0 means automatic)
+(scenechange_factor 6) # Multiplied by qscale for each frame and added to scene_change_score.
+(mv0_threshold 256) # Value depends upon the compare function used for fullpel ME
+(b_sensitivity 40) # Adjusts sensitivity of b_frame_strategy 1
+(compression_level -1)
+(use_lpc -1) # Sets whether to use LPC mode - used by FLAC encoder
+(lpc_coeff_precision 0) # LPC coefficient precision - used by FLAC encoder
+(min_prediction_order -1)
+(max_prediction_order -1)
+(prediction_order_method -1) # search method for selecting prediction order
+(min_partition_order -1)
+(timecode_frame_start 0) # GOP timecode frame start number, in non drop frame format
+(bits_per_raw_sample 0) # This field is applicable only when sample_fmt is SAMPLE_FMT_S32
+(channel_layout 0) # Audio channel layout
+(rc_max_available_vbv_use 0.33333333333333331) # Ratecontrol attempt to use, at maximum, <value> of what can be used without a
+(rc_min_vbv_overflow_use 3) # Ratecontrol attempt to use, at least, <value> times the amount needed to prev
+(color_primaries 0) # Chromaticity coordinates of the source primaries.
+(color_trc 0) # Color Transfer Characteristic.
+(colorspace 0) # YUV colorspace type.
+(color_range 0) # MPEG vs JPEG YUV range.
+(chroma_sample_location 0) # This defines the location of chroma samples.
+(weighted_p_pred 0) # explicit P-frame weighted prediction analysis method 0:off, 1: fast blind wei
+(aq_mode 0) # AQ mode
+(aq_strength 0) # AQ strength, Reduces blocking and blurring in flat and textured areas.
+(psy_rd 0) # PSY RD Strength of psychovisual optimization
+(psy_trellis 0) # PSY trellis Strength of psychovisual optimization
+(rc_lookahead 0) # Number of frames for frametype and ratecontrol lookahead
+(bitexact no) # CODEC_FLAG_BITEXACT (for testing, unused in productive version)
+(use_ss no) # CODEC_FLAG_H263P_SLICE_STRUCT enable Slice Structured mode (h263+)
+(use_aiv no) # CODEC_FLAG_H263P_AIV enable Alternative inter vlc (h263+)
+(use_obmc no) # CODEC_FLAG_OBMC use overlapped block motion compensation (h263+)
+(use_loop no) # CODEC_FLAG_LOOP_FILTER use loop filter (h263+)
+(use_alt_scan no) # CODEC_FLAG_ALT_SCAN enable alternate scantable (MPEG2/MPEG4)
+(use_mv0 no) # CODEC_FLAG_MV0 try to encode each MB with MV=<0,0> and choose the better one
+(do_normalize_aqp no) # CODEC_FLAG_NORMALIZE_AQP normalize adaptive quantization
+(use_scan_offset no) # CODEC_FLAG_SVCD_SCAN_OFFSET enable SVCD Scan Offset placeholder
+(closed_gop no) # CODEC_FLAG_CLOSED_GOP closed gop
+(use_qpel no) # CODEC_FLAG_QPEL enable 1/4-pel
+(use_qprd no) # CODEC_FLAG_QP_RD use rate distortion optimization for qp selection
+(use_cbprd no) # CODEC_FLAG_CBP_RD use rate distortion optimization for cbp
+(do_interlace_dct no) # CODEC_FLAG_INTERLACED_DCT use interlaced dct
+(do_interlace_me no) # CODEC_FLAG_INTERLACED_ME interlaced motion estimation
+(aic no) # CODEC_FLAG_AC_PRED activate intra frame coding (only h263+ CODEC)
+(umv no) # CODEC_FLAG_H263P_UMV enable unlimited motion vector (only h263+ CODEC)
+(mv4 no) # CODEC_FLAG_4MV use four motion vector by macroblock (only MPEG-4 CODEC)
+(partitioning no) # CODEC_FLAG_PART use data partitioning (only MPEG-4 CODEC)
+(use_gmc no) # CODEC_FLAG_GMC Use GMC
+(input_preserved no) # CODEC_FLAG_INPUT_PRESERVED
+(use_gray no) # CODEC_FLAG_GRAY Only encode grayscale
+(use_emu_edge no) # CODEC_FLAG_EMU_EDGE Dont draw edges
+(use_truncated no) # CODEC_FLAG_TRUNCATED Input bitstream might be truncated at a rando
+(use_fast no) # CODEC_FLAG2_FAST Allow non spec compliant speedup tricks
+(use_local_header no) # CODEC_FLAG2_LOCAL_HEADER Place global headers at every keyframe instea
+(use_bpyramid no) # CODEC_FLAG2_BPYRAMID H.264 allow B-frames to be used as references
+(use_wpred no) # CODEC_FLAG2_WPRED H.264 weighted biprediction for B-frames
+(use_mixed_refs no) # CODEC_FLAG2_MIXED_REFS H.264 one reference per partition, as opposed
+(use_dct8x8 no) # CODEC_FLAG2_8X8DCT H.264 high profile 8x8 transform
+(use_fastpskip no) # CODEC_FLAG2_FASTPSKIP H.264 fast pskip
+(use_aud no) # CODEC_FLAG2_AUD H.264 access unit delimiters
+(use_brdo no) # CODEC_FLAG2_BRDO B-frame rate-distortion optimization
+(use_ivlc no) # CODEC_FLAG2_INTRA_VLC Use MPEG-2 intra VLC table.
+(use_memc_only no) # CODEC_FLAG2_MEMC_ONLY Only do ME/MC (I frames -> ref, P frame -> ME
+(use_drop_frame_timecode no) # CODEC_FLAG2_DROP_FRAME_TIMECODE timecode is in drop frame format
+(use_skip_rd no) # CODEC_FLAG2_SKIP_RD RD optimal MB level residual skipping
+(use_chunks no) # CODEC_FLAG2_CHUNKS Input bitstream might be truncated at a packe
+(use_non_linear_quant no) # CODEC_FLAG2_NON_LINEAR_QUANT Use MPEG-2 nonlinear quantizer
+(use_bit_reservoir no) # CODEC_FLAG2_BIT_RESERVOIR Use a bit reservoir when encoding if possible
+(use_bit_mbtree no) # CODEC_FLAG2_MBTREE Use macroblock tree ratecontrol (x264 only)
+(use_bit_psy no) # CODEC_FLAG2_PSY Use psycho visual optimizations.
+(use_bit_ssim no) # CODEC_FLAG2_SSIM Compute SSIM during encoding, error[] values
+(parti4x4 no) # X264_PART_I4X4 Analyze i4x4
+(parti8x8 no) # X264_PART_I8X8 Analyze i8x8 (requires 8x8 transform)
+(partp4x4 no) # X264_PART_P8X8 Analyze p16x8, p8x16 and p8x8
+(partp8x8 no) # X264_PART_P4X4 Analyze p8x4, p4x8, p4x4
+(partb8x8 no) # X264_PART_B8X8 Analyze b16x8, b8x16 and b8x8
diff --git a/vid_enc_ffmpeg/ff_x264_hq.preset b/vid_enc_ffmpeg/ff_x264_hq.preset
new file mode 100644
index 0000000..b6e69aa
--- /dev/null
+++ b/vid_enc_ffmpeg/ff_x264_hq.preset
@@ -0,0 +1,191 @@
+# GIMP / GAP FFMPEG videoencoder parameter file
+(preset_name "x264 HD HighQuality")
+(format_name "mp4")
+(vcodec_name "libx264")
+(acodec_name "ac3")
+(title "")
+(author "")
+(copyright "")
+(comment "")
+(passlogfile "ffmpeg2pass")
+(pass 1) # 1: one pass encoding, 2: for two-pass encoding
+(ntsc_width 1920) # recommanded width NTSC, 0: not available
+(ntsc_height 1080) # recommanded height NTSC, 0: not available
+(pal_width 1920) # recommanded width PAL, 0: not available
+(pal_height 1080) # recommanded height PAL, 0: not available
+(audio_bitrate 128) # audio bitrate in kBit/sec
+(video_bitrate 200) # video bitrate in kBit/sec
+(gop_size 250) # group of picture size
+(qscale 0) # use fixed video quantiser scale (VBR). 0=const bitrate
+(qmin 10) # min video quantiser scale (VBR)
+(qmax 51) # max video quantiser scale (VBR)
+(qdiff 4) # max difference between the quantiser scale (VBR)
+(qblur 0.5) # video quantiser scale blur (VBR)
+(qcomp 0.6) # video quantiser scale compression (VBR)
+(rc_init_cplx 0) # initial complexity for 1-pass encoding
+(b_qfactor 1.25) # qp factor between p and b frames
+(i_qfactor 0.71) # qp factor between p and i frames
+(b_qoffset 1.25) # qp offset between p and b frames
+(i_qoffset 0) # qp offset between p and i frames
+(bitrate_tol 4000) # set video bitrate tolerance (in kbit/s)
+(maxrate_tol 0) # set max video bitrate tolerance (in kbit/s)
+(minrate_tol 0) # set min video bitrate tolerance (in kbit/s)
+(bufsize 0) # set ratecontrol buffere size (in kbit)
+(motion_estimation 8) # algorithm for motion estimation (1-6)
+(dct_algo 0) # algorithm for DCT (0-6)
+(idct_algo 0) # algorithm for IDCT (0-11)
+(strict 0) # how strictly to follow the standards
+(mb_qmin 0) # min macroblock quantiser scale (VBR)
+(mb_qmax 0) # max macroblock quantiser scale (VBR)
+(mb_decision 0) # algorithm for macroblock decision (0-2)
+(b_frames 3) # max number of B-frames in sequence
+(packet_size 0)
+(intra no) # use only intra frames
+(set_aspect_ratio yes) # store aspectratio information (width/height) in the output video
+(factor_aspect_ratio 1.7777777779999999) # the aspect ratio (width/height). 0.0 = auto ratio assuming sqaure pixels
+(dont_recode_flag no) # bypass the video encoder where frames can be copied 1:1
+(thread_count 0)
+(mb_cmp 0) # macroblock compare function (0-13,255)
+(ildct_cmp 8) # ildct compare function (0-13,255)
+(sub_cmp 0) # subpel compare function (0-13,255)
+(cmp 256) # fullpel compare function (0-13,255)
+(pre_cmp 0) # pre motion estimation compare function (0-13,255)
+(pre_me 0) # pre motion estimation
+(lumi_mask 0) # luminance masking
+(dark_mask 0) # darkness masking
+(scplx_mask 0) # spatial complexity masking
+(tcplx_mask 0) # temporary complexity masking
+(p_mask 0) # p block masking
+(qns 0) # quantization noise shaping
+(video_lmin 236) # min video lagrange factor (VBR) 0-3658
+(video_lmax 3658) # max video lagrange factor (VBR) 0-3658
+(video_lelim 0) # luma elimination threshold
+(video_celim 0) # chroma elimination threshold
+(video_intra_quant_bias 999999) # intra quant bias
+(video_inter_quant_bias 999999) # inter quant bias
+(me_threshold 0) # motion estimaton threshold
+(mb_threshold 0) # macroblock threshold
+(intra_dc_precision 8) # precision of the intra dc coefficient - 8
+(error_rate 0) # simulates errors in the bitstream to test error concealment
+(noise_reduction 0) # noise reduction strength
+(sc_threshold 40) # scene change detection threshold
+(me_range 16) # limit motion vectors range (1023 for DivX player, 0 = no limit)
+(coder 1) # coder type 0=VLC 1=AC
+(context 0) # context model
+(predictor 0) # prediction method (0 LEFT, 1 PLANE, 2 MEDIAN
+(nsse_weight 8) # noise vs. sse weight for the nsse comparsion function.
+(subpel_quality 8) # subpel ME quality
+(strict_gop 0) # strictly enforce GOP size
+(no_output 0) # skip bitstream encoding
+(video_mb_lmin 236) # min macroblock quantiser scale (VBR) 0-3658
+(video_mb_lmax 3658) # max macroblock quantiser scale (VBR) 0-3658
+(video_profile -99)
+(video_level -99)
+(frame_skip_threshold 0) # frame skip threshold
+(frame_skip_factor 0) # frame skip factor
+(frame_skip_exp 0) # frame skip exponent
+(frame_skip_cmp 13) # frame skip comparission function
+(mux_rate 0)
+(mux_packet_size 0)
+(mux_preload 0.5) # set the initial demux-decode delay (secs)
+(mux_max_delay 0.69999998807907104) # set the maximum demux-decode delay (secs)
+(b_frame_strategy 2) # strategy to choose between I/P/B-frames
+(workaround_bugs 1) # 1:FF_BUG_AUTODETECT, 2:FF_BUG_OLD_MSMPEG4 4:FF_BUG_XVID_ILACE 8:FF_BUG_UMP4 1
+(error_recognition 1) # 1:FF_ER_CAREFUL 2:FF_ER_COMPLIANT 3:FF_ER_AGGRESSIVE 4:FF_ER_VERY_AGGRESSIVE
+(mpeg_quant 0) # 0-> h263 quant 1-> mpeg quant
+(rc_qsquish 0) # how to keep quantizer between qmin and qmax (0 = clip, 1 = use differentiable
+(rc_qmod_amp 0) # experimental quantizer modulation
+(rc_qmod_freq 0) # experimental quantizer modulation
+(rc_eq[60] "") # rate control equation (tex^qComp)
+(rc_buffer_aggressivity 1) # currently useless
+(dia_size 0) # ME diamond size & shape
+(last_predictor_count 0) # amount of previous MV predictors (2a+1 x 2a+1 square)
+(pre_dia_size 0) # ME prepass diamond size & shape
+(inter_threshold 0)
+(border_masking 0) # increases the quantizer for macroblocks close to borders
+(me_penalty_compensation 256) # motion estimation bitrate penalty compensation (1.0 = 256)
+(bidir_refine 1) # refine the two motion vectors used in bidirectional macroblocks
+(brd_scale 0) # downscales frames for dynamic B-frame decision
+(crf 22) # constant rate factor - quality-based VBR - values ~correspond to qps
+(cqp -1) # constant quantization parameter rate control method
+(keyint_min 25) # minimum GOP size
+(refs 5) # number of reference frames
+(chromaoffset 0) # chroma qp offset from luma
+(bframebias 0) # Influences how often B-frames are used
+(trellis 1) # trellis RD quantization
+(complexityblur 20) # Reduce fluctuations in qp (before curve compression)
+(deblockalpha 0) # in-loop deblocking filter alphac0 parameter. alpha is in the range -6...6
+(deblockbeta 0) # in-loop deblocking filter beta parameter. beta is in the range -6...6
+(partitions 275) # macroblock subpartition sizes to consider - p8x8, p4x4, b8x8, i8x8, i4x4
+(directpred 3) # direct MV prediction mode - 0 (none), 1 (spatial), 2 (temporal), 3 (auto)
+(cutoff 0) # Audio cutoff bandwidth (0 means automatic)
+(scenechange_factor 6) # Multiplied by qscale for each frame and added to scene_change_score.
+(mv0_threshold 256) # Value depends upon the compare function used for fullpel ME
+(b_sensitivity 40) # Adjusts sensitivity of b_frame_strategy 1
+(compression_level -1)
+(use_lpc -1) # Sets whether to use LPC mode - used by FLAC encoder
+(lpc_coeff_precision 0) # LPC coefficient precision - used by FLAC encoder
+(min_prediction_order -1)
+(max_prediction_order -1)
+(prediction_order_method -1) # search method for selecting prediction order
+(min_partition_order -1)
+(timecode_frame_start 0) # GOP timecode frame start number, in non drop frame format
+(bits_per_raw_sample 0) # This field is applicable only when sample_fmt is SAMPLE_FMT_S32
+(channel_layout 0) # Audio channel layout
+(rc_max_available_vbv_use 0.33333333333333331) # Ratecontrol attempt to use, at maximum, <value> of what can be used without a
+(rc_min_vbv_overflow_use 3) # Ratecontrol attempt to use, at least, <value> times the amount needed to prev
+(color_primaries 2) # Chromaticity coordinates of the source primaries.
+(color_trc 2) # Color Transfer Characteristic.
+(colorspace 2) # YUV colorspace type.
+(color_range 0) # MPEG vs JPEG YUV range.
+(chroma_sample_location 1) # This defines the location of chroma samples.
+(weighted_p_pred 2) # explicit P-frame weighted prediction analysis method 0:off, 1: fast blind wei
+(aq_mode 1) # AQ mode
+(aq_strength 1.0) # AQ strength, Reduces blocking and blurring in flat and textured areas.
+(psy_rd 1.0) # PSY RD Strength of psychovisual optimization
+(psy_trellis 0.0) # PSY trellis Strength of psychovisual optimization
+(rc_lookahead 50) # Number of frames for frametype and ratecontrol lookahead
+(bitexact no) # CODEC_FLAG_BITEXACT (for testing, unused in productive version)
+(use_ss no) # CODEC_FLAG_H263P_SLICE_STRUCT enable Slice Structured mode (h263+)
+(use_aiv no) # CODEC_FLAG_H263P_AIV enable Alternative inter vlc (h263+)
+(use_obmc no) # CODEC_FLAG_OBMC use overlapped block motion compensation (h263+)
+(use_loop yes) # CODEC_FLAG_LOOP_FILTER use loop filter (h263+)
+(use_alt_scan no) # CODEC_FLAG_ALT_SCAN enable alternate scantable (MPEG2/MPEG4)
+(use_mv0 no) # CODEC_FLAG_MV0 try to encode each MB with MV=<0,0> and choose the better one
+(do_normalize_aqp no) # CODEC_FLAG_NORMALIZE_AQP normalize adaptive quantization
+(use_scan_offset no) # CODEC_FLAG_SVCD_SCAN_OFFSET enable SVCD Scan Offset placeholder
+(closed_gop no) # CODEC_FLAG_CLOSED_GOP closed gop
+(use_qpel no) # CODEC_FLAG_QPEL enable 1/4-pel
+(use_qprd no) # CODEC_FLAG_QP_RD use rate distortion optimization for qp selection
+(use_cbprd no) # CODEC_FLAG_CBP_RD use rate distortion optimization for cbp
+(do_interlace_dct no) # CODEC_FLAG_INTERLACED_DCT use interlaced dct
+(do_interlace_me no) # CODEC_FLAG_INTERLACED_ME interlaced motion estimation
+(aic no) # CODEC_FLAG_AC_PRED activate intra frame coding (only h263+ CODEC)
+(umv no) # CODEC_FLAG_H263P_UMV enable unlimited motion vector (only h263+ CODEC)
+(mv4 no) # CODEC_FLAG_4MV use four motion vector by macroblock (only MPEG-4 CODEC)
+(partitioning no) # CODEC_FLAG_PART use data partitioning (only MPEG-4 CODEC)
+(use_gmc no) # CODEC_FLAG_GMC Use GMC
+(input_preserved no) # CODEC_FLAG_INPUT_PRESERVED
+(use_gray no) # CODEC_FLAG_GRAY Only encode grayscale
+(use_emu_edge no) # CODEC_FLAG_EMU_EDGE Dont draw edges
+(use_truncated no) # CODEC_FLAG_TRUNCATED Input bitstream might be truncated at a rando
+(use_fast no) # CODEC_FLAG2_FAST Allow non spec compliant speedup tricks
+(use_local_header no) # CODEC_FLAG2_LOCAL_HEADER Place global headers at every keyframe instea
+(use_bpyramid yes) # CODEC_FLAG2_BPYRAMID H.264 allow B-frames to be used as references
+(use_wpred yes) # CODEC_FLAG2_WPRED H.264 weighted biprediction for B-frames
+(use_mixed_refs yes) # CODEC_FLAG2_MIXED_REFS H.264 one reference per partition, as opposed
+(use_dct8x8 yes) # CODEC_FLAG2_8X8DCT H.264 high profile 8x8 transform
+(use_fastpskip yes) # CODEC_FLAG2_FASTPSKIP H.264 fast pskip
+(use_aud no) # CODEC_FLAG2_AUD H.264 access unit delimiters
+(use_brdo no) # CODEC_FLAG2_BRDO B-frame rate-distortion optimization
+(use_ivlc no) # CODEC_FLAG2_INTRA_VLC Use MPEG-2 intra VLC table.
+(use_memc_only no) # CODEC_FLAG2_MEMC_ONLY Only do ME/MC (I frames -> ref, P frame -> ME
+(use_drop_frame_timecode no) # CODEC_FLAG2_DROP_FRAME_TIMECODE timecode is in drop frame format
+(use_skip_rd no) # CODEC_FLAG2_SKIP_RD RD optimal MB level residual skipping
+(use_chunks no) # CODEC_FLAG2_CHUNKS Input bitstream might be truncated at a packe
+(use_non_linear_quant no) # CODEC_FLAG2_NON_LINEAR_QUANT Use MPEG-2 nonlinear quantizer
+(use_bit_reservoir no) # CODEC_FLAG2_BIT_RESERVOIR Use a bit reservoir when encoding if possible
+(use_bit_reservoir no) # CODEC_FLAG2_BIT_RESERVOIR Use a bit reservoir when encoding if possible
+(use_bit_mbtree no) # CODEC_FLAG2_MBTREE Use macroblock tree ratecontrol (x264 only)
+(use_bit_psy no) # CODEC_FLAG2_PSY Use psycho visual optimizations.
+(use_bit_ssim no) # CODEC_FLAG2_SSIM Compute SSIM during encoding, error[] values
diff --git a/vid_enc_ffmpeg/gap_enc_ffmpeg_callbacks.c b/vid_enc_ffmpeg/gap_enc_ffmpeg_callbacks.c
index f03cb3f..67c8e6c 100644
--- a/vid_enc_ffmpeg/gap_enc_ffmpeg_callbacks.c
+++ b/vid_enc_ffmpeg/gap_enc_ffmpeg_callbacks.c
@@ -206,6 +206,69 @@ on_ff_gdouble_spinbutton_changed (GtkWidget *widget,
} /* end on_ff_gdouble_spinbutton_changed */
+/* ---------------------------------
+ * gap_ffcb_set_widget_sensitivity
+ * ---------------------------------
+ * some of the ffmpeg checkbuttons need extra actions (set other widgets sensitiv)
+ * or use other values for TRUE/FALSE representations
+ */
+void
+gap_ffcb_set_widget_sensitivity (GapGveFFMpegGlobalParams *gpp)
+{
+ gboolean l_sensitive;
+
+
+ if(gpp == NULL)
+ {
+ return;
+ }
+
+ if(gpp->evl.intra)
+ {
+ l_sensitive = FALSE;
+ }
+ else
+ {
+ l_sensitive = TRUE;
+ }
+ if(gpp->ff_gop_size_spinbutton)
+ {
+ gtk_widget_set_sensitive(gpp->ff_gop_size_spinbutton, l_sensitive);
+ gtk_widget_set_sensitive(gpp->ff_b_frames_spinbutton, l_sensitive);
+ }
+
+
+ if(gpp->evl.set_aspect_ratio)
+ {
+ l_sensitive = TRUE;
+ }
+ else
+ {
+ l_sensitive = FALSE;
+ }
+ if(gpp->ff_aspect_combo)
+ {
+ gtk_widget_set_sensitive(gpp->ff_aspect_combo, l_sensitive);
+ }
+
+
+
+ if(gpp->show_expert_settings)
+ {
+ l_sensitive = TRUE;
+ }
+ else
+ {
+ l_sensitive = FALSE;
+ }
+
+ if(gpp->main_notebook != NULL)
+ {
+ gtk_notebook_set_show_tabs(gpp->main_notebook, l_sensitive);
+ }
+
+
+} /* end gap_ffcb_set_widget_sensitivity */
/* ---------------------------------
* on_ff_gint32_checkbutton_toggled
@@ -228,54 +291,47 @@ on_ff_gint32_checkbutton_toggled (GtkToggleButton *checkbutton,
return;
}
+ if (checkbutton->active)
+ {
+ *dest_value_ptr = TRUE;
+ }
+ else
+ {
+ *dest_value_ptr = FALSE;
+ }
+
gpp = g_object_get_data (G_OBJECT (checkbutton), GAP_ENC_FFGUI_GPP);
if(gpp)
{
- if((GtkWidget *)checkbutton == gpp->ff_intra_checkbutton)
+ if(((GtkWidget *)checkbutton == gpp->ff_intra_checkbutton)
+ || ((GtkWidget *)checkbutton == gpp->ff_aspect_checkbutton)
+ || ((GtkWidget *)checkbutton == gpp->show_expert_settings_checkbutton))
{
- if(gap_debug) printf("WGT is: gpp->ff_intra_checkbutton\n");
- if (checkbutton->active)
- {
- l_sensitive = FALSE;
- }
- else
- {
- l_sensitive = TRUE;
- }
- if(gpp->ff_gop_size_spinbutton)
- {
- gtk_widget_set_sensitive(gpp->ff_gop_size_spinbutton, l_sensitive);
- gtk_widget_set_sensitive(gpp->ff_b_frames_spinbutton, l_sensitive);
- }
+ gap_ffcb_set_widget_sensitivity(gpp);
}
- if((GtkWidget *)checkbutton == gpp->ff_aspect_checkbutton)
+
+ if((GtkWidget *)checkbutton == gpp->show_expert_settings_checkbutton)
{
- if(gap_debug) printf("WGT is: gpp->ff_aspect_checkbutton\n");
- if (checkbutton->active)
+ gap_ffcb_set_widget_sensitivity(gpp);
+
+ /* persist user decision (for next gimp session) */
+ if(gpp->show_expert_settings)
{
- l_sensitive = TRUE;
+ gimp_gimprc_set(GAP_GVE_FFMPEG_SHOW_EXPERT_SETTINGS, "yes");
}
else
{
- l_sensitive = FALSE;
- }
- if(gpp->ff_aspect_combo)
- {
- gtk_widget_set_sensitive(gpp->ff_aspect_combo, l_sensitive);
+ gimp_gimprc_set(GAP_GVE_FFMPEG_SHOW_EXPERT_SETTINGS, "no");
+ gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (gpp->ff_presets_combo)
+ , GAP_GVE_FFMPEG_PRESET_00_NONE
+ );
}
}
- }
- if (checkbutton->active)
- {
- *dest_value_ptr = TRUE;
- }
- else
- {
- *dest_value_ptr = FALSE;
}
+
} /* end on_ff_gint32_checkbutton_toggled */
/* --- combos with string results
@@ -503,12 +559,19 @@ on_ff_presets_combo (GtkWidget *widget,
}
gap_enc_ffmpeg_main_init_preset_params(&gpp->evl, l_idx);
gap_enc_ffgui_init_main_dialog_widgets(gpp); /* update all wdgets */
-
-
+
/* switch back to index 0 (OOPS, do not change presets)
* after presets were loaded.
+ * NOTE this switchback workaround is not needed in case
+ * the expert flags are all hidden where the user can not change
+ * single values in the current preset.
+ * therefore it does not matter when selecting the same preset again
+ * does not trigger reset all values to the the values of the preset.
*/
- gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (widget), GAP_GVE_FFMPEG_PRESET_00_NONE);
+ if (gpp->show_expert_settings)
+ {
+ gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (widget), GAP_GVE_FFMPEG_PRESET_00_NONE);
+ }
}
} /* end on_ff_presets_combo */
diff --git a/vid_enc_ffmpeg/gap_enc_ffmpeg_callbacks.h b/vid_enc_ffmpeg/gap_enc_ffmpeg_callbacks.h
index bd5feb6..3864502 100644
--- a/vid_enc_ffmpeg/gap_enc_ffmpeg_callbacks.h
+++ b/vid_enc_ffmpeg/gap_enc_ffmpeg_callbacks.h
@@ -44,6 +44,8 @@
#include <gtk/gtk.h>
+void
+gap_ffcb_set_widget_sensitivity (GapGveFFMpegGlobalParams *gpp);
void
on_ff_response (GtkWidget *widget,
diff --git a/vid_enc_ffmpeg/gap_enc_ffmpeg_gui.c b/vid_enc_ffmpeg/gap_enc_ffmpeg_gui.c
index 29eacd1..3ec04b3 100644
--- a/vid_enc_ffmpeg/gap_enc_ffmpeg_gui.c
+++ b/vid_enc_ffmpeg/gap_enc_ffmpeg_gui.c
@@ -50,12 +50,14 @@
#include "gap_libgapvidutil.h"
#include "gap-intl.h"
+#include "gap_base.h"
#include "gap_libgapvidutil.h"
#include "gap_libgimpgap.h"
#include "gap_enc_ffmpeg_main.h"
#include "gap_enc_ffmpeg_gui.h"
#include "gap_enc_ffmpeg_callbacks.h"
+#include "gap_enc_ffmpeg_par.h"
/* Includes for encoder specific extra LIBS */
#include "avformat.h"
@@ -412,7 +414,7 @@ p_replace_combo_aud_codec(GapGveFFMpegGlobalParams *gpp)
* ----------------------------
* - findout the default CODECS and Extensions for the current selected fileformat
* and show this informations in the info label widget.
- * - opül (if set_codec_menus == TRUE)
+ * - optional (if set_codec_menus == TRUE)
* set both VIDEO_CODEC and AUDIO_CODEC combo to these default CODECS
*/
void
@@ -428,7 +430,11 @@ gap_enc_ffgui_set_default_codecs(GapGveFFMpegGlobalParams *gpp, gboolean set_cod
if(gpp == NULL) return;
if(gpp->shell_window == NULL) return;
+#ifndef GAP_USES_OLD_FFMPEG_0_5
+ ofmt = av_guess_format(gpp->evl.format_name, NULL, NULL);
+#else
ofmt = guess_format(gpp->evl.format_name, NULL, NULL);
+#endif
if(ofmt)
{
@@ -478,25 +484,49 @@ gap_enc_ffgui_set_default_codecs(GapGveFFMpegGlobalParams *gpp, gboolean set_cod
{
char *recomand_size;
+ char *detailInfo;
+ char *selectedPreset;
+ selectedPreset = g_strdup_printf(_("Selected Preset : %s")
+ ,gpp->evl.presetName
+ );
recomand_size = NULL;
if((gpp->evl.ntsc_width > 0)
- && (gpp->evl.ntsc_height > 0)
- && (gpp->evl.pal_width > 0)
- && (gpp->evl.pal_height > 0))
+ || (gpp->evl.ntsc_height > 0)
+ || (gpp->evl.pal_width > 0)
+ || (gpp->evl.pal_height > 0))
{
- recomand_size = g_strdup_printf(" Recommanded Framesize : %d x %d (PAL) %d x %d (NTSC)"
+ if (gpp->evl.ntsc_height != gpp->evl.pal_height)
+ {
+ recomand_size = g_strdup_printf(" %s : %d x %d (PAL) %d x %d (NTSC)"
+ ,_("Recommanded Framesize")
,(int)gpp->evl.pal_width
,(int)gpp->evl.pal_height
,(int)gpp->evl.ntsc_width
,(int)gpp->evl.ntsc_height
);
+ }
+ else
+ {
+ gint recWidth;
+ gint recHeight;
+
+ recWidth = MAX(gpp->evl.ntsc_width, gpp->evl.pal_width);
+ recHeight = MAX(gpp->evl.ntsc_height, gpp->evl.pal_height);
+
+ recomand_size = g_strdup_printf(" %s : %d x %d"
+ ,_("Recommanded Framesize")
+ ,(int)recWidth
+ ,(int)recHeight
+ );
+
+ }
}
else
{
recomand_size = g_strdup_printf(" ");
}
- info_msg = g_strdup_printf(_("Selected Fileformat : [%s] %s\n"
+ detailInfo = g_strdup_printf(_("Selected Fileformat : [%s] %s\n"
"Recommanded Video CODEC : %s\n"
"Recommanded Audio CODEC : %s\n"
"Extension(s): %s %s"
@@ -508,7 +538,14 @@ gap_enc_ffgui_set_default_codecs(GapGveFFMpegGlobalParams *gpp, gboolean set_cod
, ofmt->extensions
, recomand_size
);
+
+ info_msg = g_strdup_printf("%s\n%s"
+ , selectedPreset
+ , detailInfo
+ );
g_free(recomand_size);
+ g_free(selectedPreset);
+ g_free(detailInfo);
}
/* store the current video extension
@@ -793,8 +830,6 @@ p_set_combo_box_callbacks(GapGveFFMpegGlobalParams *gpp)
* are set up by queries to the FFMPEG avcodec library
*/
- av_register_all(); /* register all fileformats and codecs before we can use the lib */
-
p_replace_combo_file_format(gpp);
p_replace_combo_vid_codec(gpp);
p_replace_combo_aud_codec(gpp);
@@ -916,6 +951,10 @@ p_init_vid_checkbuttons(GapGveFFMpegGlobalParams *gpp)
return;
}
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (gpp->show_expert_settings_checkbutton)
+ , gpp->show_expert_settings);
+
+
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (gpp->ff_intra_checkbutton)
, gpp->evl.intra);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (gpp->ff_bitexact_checkbutton)
@@ -1557,58 +1596,6 @@ p_create_basic_options_frame (GapGveFFMpegGlobalParams *gpp)
G_CALLBACK (on_ff_gint32_spinbutton_changed),
&gpp->evl.b_frames);
- row++;
-
- /* the qdiff label */
- label = gtk_label_new (_("Aspect:"));
- gtk_widget_show (label);
- gtk_table_attach (GTK_TABLE (table), label, 0, 1, row, row+1,
- (GtkAttachOptions) (GTK_FILL),
- (GtkAttachOptions) (0), 0, 0);
- gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
-
-
- /* the Set Aspectratio checkbutton */
- checkbutton = gtk_check_button_new_with_label (_("Set Aspectratio"));
- gpp->ff_aspect_checkbutton = checkbutton;
- gtk_widget_show (checkbutton);
- gtk_table_attach (GTK_TABLE (table), checkbutton, 1, 2, row, row+1,
- (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
- (GtkAttachOptions) (0), 0, 0);
- gimp_help_set_help_data (checkbutton, _("store aspectratio information (width/height) in the output video"), NULL);
- g_object_set_data (G_OBJECT (checkbutton), GAP_ENC_FFGUI_GPP, (gpointer)gpp);
- g_signal_connect (G_OBJECT (checkbutton), "toggled",
- G_CALLBACK (on_ff_gint32_checkbutton_toggled),
- &gpp->evl.set_aspect_ratio);
-
-
- /* the ASPECT combo */
- combo = gimp_int_combo_box_new (_("auto"), GAP_GVE_FFMPEG_ASPECT_00_AUTO,
- _("3:2"), GAP_GVE_FFMPEG_ASPECT_01_3_2,
- _("4:3"), GAP_GVE_FFMPEG_ASPECT_02_4_3,
- _("16:9"), GAP_GVE_FFMPEG_ASPECT_03_16_9,
- NULL);
-
- gpp->ff_aspect_combo = combo;
- gtk_widget_show (combo);
-
- gtk_table_attach (GTK_TABLE (table), combo, 2, 3, row, row+1,
- (GtkAttachOptions) (GTK_FILL),
- (GtkAttachOptions) (0), 0, 0);
- gimp_help_set_help_data (combo, _("Select aspect ratio"), NULL);
-
- inital_value = p_init_gdouble_combo_actual_idx(gpp
- , combo
- , >ab_aspect[0]
- , gpp->evl.factor_aspect_ratio
- , GAP_GVE_FFMPEG_ASPECT_MAX_ELEMENTS
- );
-
- gimp_int_combo_box_connect (GIMP_INT_COMBO_BOX (combo),
- inital_value,
- G_CALLBACK (on_ff_aspect_combo),
- gpp);
-
return(frame);
} /* end p_create_basic_options_frame */
@@ -3647,28 +3634,31 @@ GtkWidget*
p_create_file_comment_frame (GapGveFFMpegGlobalParams *gpp)
{
GtkWidget *frame;
- GtkWidget *table6;
+ GtkWidget *table;
GtkWidget *label;
GtkWidget *entry;
+ GtkWidget *combo;
+ GtkWidget *checkbutton;
gint row;
+ gint inital_value;
frame = gimp_frame_new (_("FFMpeg File Comment settings"));
- table6 = gtk_table_new (5, 2, FALSE);
- gtk_widget_show (table6);
- gtk_container_add (GTK_CONTAINER (frame), table6);
- gtk_container_set_border_width (GTK_CONTAINER (table6), 4);
- gtk_table_set_row_spacings (GTK_TABLE (table6), 4);
- gtk_table_set_col_spacings (GTK_TABLE (table6), 4);
+ table = gtk_table_new (5, 2, FALSE);
+ gtk_widget_show (table);
+ gtk_container_add (GTK_CONTAINER (frame), table);
+ gtk_container_set_border_width (GTK_CONTAINER (table), 4);
+ gtk_table_set_row_spacings (GTK_TABLE (table), 4);
+ gtk_table_set_col_spacings (GTK_TABLE (table), 4);
row = 0;
/* the title lable */
label = gtk_label_new (_("Title:"));
gtk_widget_show (label);
- gtk_table_attach (GTK_TABLE (table6), label, 0, 1, row, row+1,
+ gtk_table_attach (GTK_TABLE (table), label, 0, 1, row, row+1,
(GtkAttachOptions) (GTK_FILL),
(GtkAttachOptions) (0), 0, 0);
gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
@@ -3678,7 +3668,7 @@ p_create_file_comment_frame (GapGveFFMpegGlobalParams *gpp)
gtk_entry_set_max_length (GTK_ENTRY (entry), 40);
gpp->ff_title_entry = entry;
gtk_widget_show (entry);
- gtk_table_attach (GTK_TABLE (table6), entry, 1, 2, row, row+1,
+ gtk_table_attach (GTK_TABLE (table), entry, 1, 2, row, row+1,
(GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
(GtkAttachOptions) (0), 0, 0);
g_signal_connect (G_OBJECT (entry), "changed",
@@ -3691,7 +3681,7 @@ p_create_file_comment_frame (GapGveFFMpegGlobalParams *gpp)
/* the Author lable */
label = gtk_label_new (_("Author:"));
gtk_widget_show (label);
- gtk_table_attach (GTK_TABLE (table6), label, 0, 1, row, row+1,
+ gtk_table_attach (GTK_TABLE (table), label, 0, 1, row, row+1,
(GtkAttachOptions) (GTK_FILL),
(GtkAttachOptions) (0), 0, 0);
gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
@@ -3701,7 +3691,7 @@ p_create_file_comment_frame (GapGveFFMpegGlobalParams *gpp)
gtk_entry_set_max_length (GTK_ENTRY (entry), 40);
gpp->ff_author_entry = entry;
gtk_widget_show (entry);
- gtk_table_attach (GTK_TABLE (table6), entry, 1, 2, row, row+1,
+ gtk_table_attach (GTK_TABLE (table), entry, 1, 2, row, row+1,
(GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
(GtkAttachOptions) (0), 0, 0);
g_signal_connect (G_OBJECT (entry), "changed",
@@ -3713,7 +3703,7 @@ p_create_file_comment_frame (GapGveFFMpegGlobalParams *gpp)
/* the Copyright lable */
label = gtk_label_new (_("Copyright:"));
gtk_widget_show (label);
- gtk_table_attach (GTK_TABLE (table6), label, 0, 1, row, row+1,
+ gtk_table_attach (GTK_TABLE (table), label, 0, 1, row, row+1,
(GtkAttachOptions) (GTK_FILL),
(GtkAttachOptions) (0), 0, 0);
gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
@@ -3723,7 +3713,7 @@ p_create_file_comment_frame (GapGveFFMpegGlobalParams *gpp)
gtk_entry_set_max_length (GTK_ENTRY (entry), 40);
gpp->ff_copyright_entry = entry;
gtk_widget_show (entry);
- gtk_table_attach (GTK_TABLE (table6), entry, 1, 2, row, row+1,
+ gtk_table_attach (GTK_TABLE (table), entry, 1, 2, row, row+1,
(GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
(GtkAttachOptions) (0), 0, 0);
g_signal_connect (G_OBJECT (entry), "changed",
@@ -3736,7 +3726,7 @@ p_create_file_comment_frame (GapGveFFMpegGlobalParams *gpp)
/* the Comment lable */
label = gtk_label_new (_("Comment:"));
gtk_widget_show (label);
- gtk_table_attach (GTK_TABLE (table6), label, 0, 1, row, row+1,
+ gtk_table_attach (GTK_TABLE (table), label, 0, 1, row, row+1,
(GtkAttachOptions) (GTK_FILL),
(GtkAttachOptions) (0), 0, 0);
gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
@@ -3746,7 +3736,7 @@ p_create_file_comment_frame (GapGveFFMpegGlobalParams *gpp)
gtk_entry_set_max_length (GTK_ENTRY (entry), 80);
gpp->ff_comment_entry = entry;
gtk_widget_show (entry);
- gtk_table_attach (GTK_TABLE (table6), entry, 1, 2, row, row+1,
+ gtk_table_attach (GTK_TABLE (table), entry, 1, 2, row, row+1,
(GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
(GtkAttachOptions) (0), 0, 0);
g_signal_connect (G_OBJECT (entry), "changed",
@@ -3759,12 +3749,92 @@ p_create_file_comment_frame (GapGveFFMpegGlobalParams *gpp)
label = gtk_label_new (_("\nText tags will be inserted in the\n"
"resulting video for all non blank entry fields."));
gtk_widget_show (label);
- gtk_table_attach (GTK_TABLE (table6), label, 1, 2, row, row+1,
+ gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
+
+ row++;
+
+
+ /* the aspect label */
+ label = gtk_label_new (_("Aspect:"));
+ gtk_widget_show (label);
+ gtk_table_attach (GTK_TABLE (table), label, 0, 1, row, row+1,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
+
+
+ /* the Set Aspectratio checkbutton */
+ checkbutton = gtk_check_button_new_with_label (_("Set Aspectratio"));
+ gpp->ff_aspect_checkbutton = checkbutton;
+ gtk_widget_show (checkbutton);
+ gtk_table_attach (GTK_TABLE (table), checkbutton, 1, 2, row, row+1,
+ (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gimp_help_set_help_data (checkbutton, _("store aspectratio information (width/height) in the output video"), NULL);
+ g_object_set_data (G_OBJECT (checkbutton), GAP_ENC_FFGUI_GPP, (gpointer)gpp);
+ g_signal_connect (G_OBJECT (checkbutton), "toggled",
+ G_CALLBACK (on_ff_gint32_checkbutton_toggled),
+ &gpp->evl.set_aspect_ratio);
+
+
+ /* the ASPECT combo */
+ combo = gimp_int_combo_box_new (_("auto"), GAP_GVE_FFMPEG_ASPECT_00_AUTO,
+ _("3:2"), GAP_GVE_FFMPEG_ASPECT_01_3_2,
+ _("4:3"), GAP_GVE_FFMPEG_ASPECT_02_4_3,
+ _("16:9"), GAP_GVE_FFMPEG_ASPECT_03_16_9,
+ NULL);
+
+ gpp->ff_aspect_combo = combo;
+ gtk_widget_show (combo);
+
+ gtk_table_attach (GTK_TABLE (table), combo, 2, 3, row, row+1,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gimp_help_set_help_data (combo, _("Select aspect ratio"), NULL);
+
+ inital_value = p_init_gdouble_combo_actual_idx(gpp
+ , combo
+ , >ab_aspect[0]
+ , gpp->evl.factor_aspect_ratio
+ , GAP_GVE_FFMPEG_ASPECT_MAX_ELEMENTS
+ );
+
+ gimp_int_combo_box_connect (GIMP_INT_COMBO_BOX (combo),
+ inital_value,
+ G_CALLBACK (on_ff_aspect_combo),
+ gpp);
+
+
+
+ row++;
+
+
+ /* the show expert settings label */
+ label = gtk_label_new (_("Expert settings:"));
+ gtk_widget_show (label);
+ gtk_table_attach (GTK_TABLE (table), label, 0, 1, row, row+1,
(GtkAttachOptions) (GTK_FILL),
(GtkAttachOptions) (0), 0, 0);
gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
+ /* the Set Aspectratio checkbutton */
+ checkbutton = gtk_check_button_new_with_label (_("Show expert settings"));
+ gpp->show_expert_settings_checkbutton = checkbutton;
+ gtk_widget_show (checkbutton);
+ gtk_table_attach (GTK_TABLE (table), checkbutton, 1, 2, row, row+1,
+ (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gimp_help_set_help_data (checkbutton, _("show video encoder expert settings"), NULL);
+ g_object_set_data (G_OBJECT (checkbutton), GAP_ENC_FFGUI_GPP, (gpointer)gpp);
+ g_signal_connect (G_OBJECT (checkbutton), "toggled",
+ G_CALLBACK (on_ff_gint32_checkbutton_toggled),
+ &gpp->show_expert_settings);
+
+
return(frame);
} /* end p_create_file_comment_frame */
@@ -3795,11 +3865,17 @@ p_create_ffmpeg_dialog_shell (GapGveFFMpegGlobalParams *gpp)
GtkWidget *ff_basic_info_label;
GtkWidget *spc_hbox;
+ gpp->show_expert_settings =
+ gap_base_get_gimprc_gboolean_value (GAP_GVE_FFMPEG_SHOW_EXPERT_SETTINGS
+ , FALSE /* default_value */
+ );
/* set the widgets to defined NULL before we create them
* (some callbacks may refer to those widgets before
* all of them are created. those callbacks check for NULL
* but would crash if the widgets are undefined yet)
*/
+ gpp->main_notebook = NULL;
+ gpp->show_expert_settings_checkbutton = NULL;
gpp->ff_aspect_combo = NULL;
gpp->ff_aud_bitrate_combo = NULL;
gpp->ff_aud_bitrate_spinbutton = NULL;
@@ -3946,16 +4022,16 @@ p_create_ffmpeg_dialog_shell (GapGveFFMpegGlobalParams *gpp)
/* the presets combo */
combo = gimp_int_combo_box_new (
- _("** OOPS do not change any parameter **"), GAP_GVE_FFMPEG_PRESET_00_NONE,
- _("DivX default preset"), GAP_GVE_FFMPEG_PRESET_01_DIVX_DEFAULT,
- _("DivX high quality preset"), GAP_GVE_FFMPEG_PRESET_02_DIVX_BEST,
- _("DivX low quality preset"), GAP_GVE_FFMPEG_PRESET_03_DIVX_LOW,
- _("DivX WINDOWS preset"), GAP_GVE_FFMPEG_PRESET_04_DIVX_MS,
- _("MPEG1 (VCD) preset"), GAP_GVE_FFMPEG_PRESET_05_MPEG1_VCD,
- _("MPEG1 high quality preset"), GAP_GVE_FFMPEG_PRESET_06_MPEG1_BEST,
- _("MPEG2 (SVCD) preset"), GAP_GVE_FFMPEG_PRESET_07_MPEG2_SVCD,
- _("MPEG2 (DVD) preset"), GAP_GVE_FFMPEG_PRESET_08_MPEG2_DVD,
- _("REAL video preset"), GAP_GVE_FFMPEG_PRESET_09_REAL,
+ _("** keep current parameters **"), GAP_GVE_FFMPEG_PRESET_00_NONE,
+// _("DivX default preset"), GAP_GVE_FFMPEG_PRESET_01_DIVX_DEFAULT,
+// _("DivX high quality preset"), GAP_GVE_FFMPEG_PRESET_02_DIVX_BEST,
+// _("DivX low quality preset"), GAP_GVE_FFMPEG_PRESET_03_DIVX_LOW,
+// _("DivX WINDOWS preset"), GAP_GVE_FFMPEG_PRESET_04_DIVX_MS,
+// _("MPEG1 (VCD) preset"), GAP_GVE_FFMPEG_PRESET_05_MPEG1_VCD,
+// _("MPEG1 high quality preset"), GAP_GVE_FFMPEG_PRESET_06_MPEG1_BEST,
+// _("MPEG2 (SVCD) preset"), GAP_GVE_FFMPEG_PRESET_07_MPEG2_SVCD,
+// _("MPEG2 (DVD) preset"), GAP_GVE_FFMPEG_PRESET_08_MPEG2_DVD,
+// _("REAL video preset"), GAP_GVE_FFMPEG_PRESET_09_REAL,
NULL);
{
GapGveFFMpegValues *epp;
@@ -3982,8 +4058,9 @@ p_create_ffmpeg_dialog_shell (GapGveFFMpegGlobalParams *gpp)
* the last time)
* but the combo box widgets seems to support only the "changed" signal
*
- * therefore the on_ff_presets_combo callback does always swicth back
- * to index 0 (OOPS, dont change preset params)
+ * therefore the on_ff_presets_combo callback does swicth back
+ * to index 0 (** keep current parameters **) in the expert mode
+ * (where the widgets for changing preset relevant vaules are visible)
*/
gtk_widget_show (combo);
@@ -4021,12 +4098,28 @@ p_create_ffmpeg_dialog_shell (GapGveFFMpegGlobalParams *gpp)
/* the notebook for detailed parameter settings */
/* -------------------------------------------- */
notebook1 = gtk_notebook_new ();
+ gpp->main_notebook = notebook1;
gtk_widget_show (notebook1);
gtk_container_add (GTK_CONTAINER (frame), notebook1);
gtk_container_set_border_width (GTK_CONTAINER (notebook1), 4);
nb_page_nr = 0;
+ /* the frame with file comment and aspect settings */
+ frame = p_create_file_comment_frame(gpp);
+ gtk_widget_show (frame);
+
+ gtk_container_add (GTK_CONTAINER (notebook1), frame);
+ gtk_container_set_border_width (GTK_CONTAINER (frame), 4);
+
+
+ /* the notebook page label for file comment settings */
+ nb1_label = gtk_label_new (_("File Comment"));
+ gtk_widget_show (nb1_label);
+ gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook1), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook1), nb_page_nr), nb1_label);
+
+ nb_page_nr++;
+
/* the frame with basic options */
frame = p_create_basic_options_frame(gpp);
gtk_widget_show (frame);
@@ -4114,22 +4207,9 @@ p_create_ffmpeg_dialog_shell (GapGveFFMpegGlobalParams *gpp)
gtk_widget_show (nb1_label);
gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook1), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook1), nb_page_nr), nb1_label);
-
- nb_page_nr++;
-
- /* the frame with the 2-pass settings */
- frame = p_create_file_comment_frame(gpp);
- gtk_widget_show (frame);
-
- gtk_container_add (GTK_CONTAINER (notebook1), frame);
- gtk_container_set_border_width (GTK_CONTAINER (frame), 4);
+ gap_ffcb_set_widget_sensitivity (gpp);
- /* the notebook page label for file comment settings */
- nb1_label = gtk_label_new (_("File Comment"));
- gtk_widget_show (nb1_label);
- gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook1), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook1), nb_page_nr), nb1_label);
-
return shell_window;
} /* end p_create_ffmpeg_dialog_shell */
@@ -4147,6 +4227,8 @@ gap_enc_ffgui_ffmpeg_encode_dialog(GapGveFFMpegGlobalParams *gpp)
gimp_ui_init ("gap_enc_ffmpeg_params", FALSE);
gap_stock_init();
+ av_register_all(); /* register all fileformats and codecs before we can use the lib */
+
/* ---------- sub dialog windows ----------*/
gpp->startup = TRUE;
gpp->ffpar_filename[0] = '\0';
diff --git a/vid_enc_ffmpeg/gap_enc_ffmpeg_main.c b/vid_enc_ffmpeg/gap_enc_ffmpeg_main.c
index 8f89160..857cdd8 100644
--- a/vid_enc_ffmpeg/gap_enc_ffmpeg_main.c
+++ b/vid_enc_ffmpeg/gap_enc_ffmpeg_main.c
@@ -1126,6 +1126,23 @@ static void
p_initPresetFromPresetIndex(GapGveFFMpegValues *epp, gint presetId)
{
GapGveFFMpegValues *eppAtId;
+ GapGveFFMpegValues eppBackup;
+ GapGveFFMpegValues *eppBck;
+
+ eppBck = &eppBackup;
+ memcpy(eppBck, epp, sizeof(GapGveFFMpegValues));
+
+
+ if(gap_debug)
+ {
+ printf("p_initPresetFromPresetIndex: name:%s title:%s bckTitle:%s size:%d\n"
+ ,epp->presetName
+ ,epp->title
+ ,eppBck->title
+ ,sizeof(epp->title)
+ );
+ }
+
for(eppAtId = gap_ffpar_getPresetList(); eppAtId != NULL; eppAtId = eppAtId->next)
{
@@ -1138,6 +1155,26 @@ p_initPresetFromPresetIndex(GapGveFFMpegValues *epp, gint presetId)
if(eppAtId != NULL)
{
memcpy(epp, eppAtId, sizeof(GapGveFFMpegValues));
+
+ /* restore original title, author, copyright and comment
+ * where present.
+ */
+ if(eppBck->title[0] != '\0')
+ {
+ memcpy(epp->title, eppBck->title, sizeof(epp->title));
+ }
+ if(eppBck->author[0] != '\0')
+ {
+ memcpy(epp->author, eppBck->author, sizeof(epp->author));
+ }
+ if(eppBck->copyright[0] != '\0')
+ {
+ memcpy(epp->copyright, eppBck->copyright, sizeof(epp->copyright));
+ }
+ if(eppBck->comment[0] != '\0')
+ {
+ memcpy(epp->comment, eppBck->comment, sizeof(epp->comment));
+ }
}
} /* end p_initPresetFromPresetIndex */
@@ -1159,72 +1196,81 @@ p_initPresetFromPresetIndex(GapGveFFMpegValues *epp, gint presetId)
* 8 .. Real Video default
*
* Higher IDs may be available when preset files are installed.
+ *
+ * NOTE: the hardcoded presets are not used since standard presets are
+ * now part of the installation.
+ * BUT: preset with index 0 is still relevant to init default settings
+ * for parameters that are NOT available in the preset files.
+ * (this is important when updates to newer ffmpeg releases introduce new params
+ * that are not present in private preset files created by users)
*/
void
gap_enc_ffmpeg_main_init_preset_params(GapGveFFMpegValues *epp, gint preset_idx)
{
+#define GAP_FFPRESET_TABSIZE 10 /* GAP_GVE_FFMPEG_PRESET_MAX_ELEMENTS */
+
gint l_idx;
- /* DivX def best low MS-def VCD MPGbest SVCD DVD Real */
- static gint32 tab_ntsc_width[GAP_GVE_FFMPEG_PRESET_MAX_ELEMENTS] = { 0, 0, 0, 0, 352, 0, 480, 720, 0 };
- static gint32 tab_ntsc_height[GAP_GVE_FFMPEG_PRESET_MAX_ELEMENTS] = { 0, 0, 0, 0, 240, 0, 480, 480, 0 };
-
- static gint32 tab_pal_width[GAP_GVE_FFMPEG_PRESET_MAX_ELEMENTS] = { 0, 0, 0, 0, 352, 0, 480, 720, 0 };
- static gint32 tab_pal_height[GAP_GVE_FFMPEG_PRESET_MAX_ELEMENTS] = { 0, 0, 0, 0, 288, 0, 576, 576, 0 };
-
- static gint32 tab_audio_bitrate[GAP_GVE_FFMPEG_PRESET_MAX_ELEMENTS] = { 160, 192, 96, 160, 224, 192, 224, 192, 160 };
- static gint32 tab_video_bitrate[GAP_GVE_FFMPEG_PRESET_MAX_ELEMENTS] = { 200, 1500, 150, 200, 1150, 6000, 2040, 6000, 1200 };
- static gint32 tab_gop_size[GAP_GVE_FFMPEG_PRESET_MAX_ELEMENTS] = { 12, 12, 96, 12, 18, 12, 18, 18, 18 };
- static gint32 tab_intra[GAP_GVE_FFMPEG_PRESET_MAX_ELEMENTS] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-
- static float tab_qscale[GAP_GVE_FFMPEG_PRESET_MAX_ELEMENTS] = { 2, 1, 6, 2, 1, 1, 1, 1, 2 };
-
- static gint32 tab_qmin[GAP_GVE_FFMPEG_PRESET_MAX_ELEMENTS] = { 2, 2, 8, 2, 2, 2, 2, 2, 2 };
- static gint32 tab_qmax[GAP_GVE_FFMPEG_PRESET_MAX_ELEMENTS] = { 31, 8, 31, 31, 31, 8, 16, 8, 31 };
- static gint32 tab_qdiff[GAP_GVE_FFMPEG_PRESET_MAX_ELEMENTS] = { 3, 2, 9, 3, 3, 2, 2, 2, 3 };
-
- static float tab_qblur[GAP_GVE_FFMPEG_PRESET_MAX_ELEMENTS] = { 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 };
- static float tab_qcomp[GAP_GVE_FFMPEG_PRESET_MAX_ELEMENTS] = { 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 };
- static float tab_rc_init_cplx[GAP_GVE_FFMPEG_PRESET_MAX_ELEMENTS] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
- static float tab_b_qfactor[GAP_GVE_FFMPEG_PRESET_MAX_ELEMENTS] = { 1.25, 1.25, 1.25, 1.25, 1.25, 1.25, 1.25, 1.25, 1.25 };
- static float tab_i_qfactor[GAP_GVE_FFMPEG_PRESET_MAX_ELEMENTS] = { -0.8, -0.8, -0.8, -0.8, -0.8, -0.8, -0.8, -0.8, -0.8 };
- static float tab_b_qoffset[GAP_GVE_FFMPEG_PRESET_MAX_ELEMENTS] = { 1.25, 1.25, 1.25, 1.25, 1.25, 1.25, 1.25, 1.25, 1.25 };
- static float tab_i_qoffset[GAP_GVE_FFMPEG_PRESET_MAX_ELEMENTS] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
-
- static gint32 tab_bitrate_tol[GAP_GVE_FFMPEG_PRESET_MAX_ELEMENTS] = { 4000, 6000, 2000, 4000, 1150, 4000, 2000, 2000, 5000 };
- static gint32 tab_maxrate_tol[GAP_GVE_FFMPEG_PRESET_MAX_ELEMENTS] = { 0, 0, 0, 0, 1150, 0, 2516, 9000, 0 };
- static gint32 tab_minrate_tol[GAP_GVE_FFMPEG_PRESET_MAX_ELEMENTS] = { 0, 0, 0, 0, 1150, 0, 0, 0, 0 };
- static gint32 tab_bufsize[GAP_GVE_FFMPEG_PRESET_MAX_ELEMENTS] = { 0, 0, 0, 0, 40, 0, 224, 224, 0 };
-
- static gint32 tab_motion_estimation[GAP_GVE_FFMPEG_PRESET_MAX_ELEMENTS] = { 5, 5, 5, 5, 5, 5, 5, 5, 5 };
-
- static gint32 tab_dct_algo[GAP_GVE_FFMPEG_PRESET_MAX_ELEMENTS] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
- static gint32 tab_idct_algo[GAP_GVE_FFMPEG_PRESET_MAX_ELEMENTS] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
- static gint32 tab_strict[GAP_GVE_FFMPEG_PRESET_MAX_ELEMENTS] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
- static gint32 tab_mb_qmin[GAP_GVE_FFMPEG_PRESET_MAX_ELEMENTS] = { 2, 2, 8, 2, 2, 2, 2, 2, 2 };
- static gint32 tab_mb_qmax[GAP_GVE_FFMPEG_PRESET_MAX_ELEMENTS] = { 31, 18, 31, 31, 31, 18, 31, 31, 31 };
- static gint32 tab_mb_decision[GAP_GVE_FFMPEG_PRESET_MAX_ELEMENTS] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
- static gint32 tab_aic[GAP_GVE_FFMPEG_PRESET_MAX_ELEMENTS] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
- static gint32 tab_umv[GAP_GVE_FFMPEG_PRESET_MAX_ELEMENTS] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-
- static gint32 tab_b_frames[GAP_GVE_FFMPEG_PRESET_MAX_ELEMENTS] = { 2, 2, 4, 0, 0, 0, 2, 2, 0 };
- static gint32 tab_mv4[GAP_GVE_FFMPEG_PRESET_MAX_ELEMENTS] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
- static gint32 tab_partitioning[GAP_GVE_FFMPEG_PRESET_MAX_ELEMENTS] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
- static gint32 tab_packet_size[GAP_GVE_FFMPEG_PRESET_MAX_ELEMENTS] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
- static gint32 tab_bitexact[GAP_GVE_FFMPEG_PRESET_MAX_ELEMENTS] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
- static gint32 tab_aspect[GAP_GVE_FFMPEG_PRESET_MAX_ELEMENTS] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 };
- static gint32 tab_aspect_fact[GAP_GVE_FFMPEG_PRESET_MAX_ELEMENTS] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
-
- static char* tab_format_name[GAP_GVE_FFMPEG_PRESET_MAX_ELEMENTS] = { "avi", "avi", "avi", "avi", "vcd", "mpeg", "svcd", "vob", "rm" };
- static char* tab_vcodec_name[GAP_GVE_FFMPEG_PRESET_MAX_ELEMENTS] = { "mpeg4", "mpeg4", "mpeg4", "msmpeg4", "mpeg1video", "mpeg1video", "mpeg2video", "mpeg2video", "rv10" };
- static char* tab_acodec_name[GAP_GVE_FFMPEG_PRESET_MAX_ELEMENTS] = { "mp2", "mp2", "mp2", "mp2", "mp2", "mp2", "mp2", "ac3", "ac3" };
-
- static gint32 tab_mux_rate[GAP_GVE_FFMPEG_PRESET_MAX_ELEMENTS] = { 0, 0, 0, 0, 1411200, 0, 0, 10080000, 0 };
- static gint32 tab_mux_packet_size[GAP_GVE_FFMPEG_PRESET_MAX_ELEMENTS] = { 0, 0, 0, 0, 2324, 2324, 2324, 2048, 0 };
- static float tab_mux_preload[GAP_GVE_FFMPEG_PRESET_MAX_ELEMENTS] = { 0.5, 0.5, 0.5, 0.5, 0.44, 0.5, 0.5, 0.5, 0.5 };
- static float tab_mux_max_delay[GAP_GVE_FFMPEG_PRESET_MAX_ELEMENTS] = { 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7 };
- static gint32 tab_use_scann_offset[GAP_GVE_FFMPEG_PRESET_MAX_ELEMENTS] = { 0, 0, 0, 0, 0, 0, 1, 0, 0 };
-
- static char* tab_presetName[GAP_GVE_FFMPEG_PRESET_MAX_ELEMENTS] = {
+ /* DivX def best low MS-def VCD MPGbest SVCD DVD Real */
+ static gint32 tab_ntsc_width[GAP_FFPRESET_TABSIZE] = { 0, 0, 0, 0, 352, 0, 480, 720, 0 };
+ static gint32 tab_ntsc_height[GAP_FFPRESET_TABSIZE] = { 0, 0, 0, 0, 240, 0, 480, 480, 0 };
+
+ static gint32 tab_pal_width[GAP_FFPRESET_TABSIZE] = { 0, 0, 0, 0, 352, 0, 480, 720, 0 };
+ static gint32 tab_pal_height[GAP_FFPRESET_TABSIZE] = { 0, 0, 0, 0, 288, 0, 576, 576, 0 };
+
+ static gint32 tab_audio_bitrate[GAP_FFPRESET_TABSIZE] = { 160, 192, 96, 160, 224, 192, 224, 192, 160 };
+ static gint32 tab_video_bitrate[GAP_FFPRESET_TABSIZE] = { 200, 1500, 150, 200, 1150, 6000, 2040, 6000, 1200 };
+ static gint32 tab_gop_size[GAP_FFPRESET_TABSIZE] = { 12, 12, 96, 12, 18, 12, 18, 18, 18 };
+ static gint32 tab_intra[GAP_FFPRESET_TABSIZE] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+
+ static float tab_qscale[GAP_FFPRESET_TABSIZE] = { 2, 1, 6, 2, 1, 1, 1, 1, 2 };
+
+ static gint32 tab_qmin[GAP_FFPRESET_TABSIZE] = { 2, 2, 8, 2, 2, 2, 2, 2, 2 };
+ static gint32 tab_qmax[GAP_FFPRESET_TABSIZE] = { 31, 8, 31, 31, 31, 8, 16, 8, 31 };
+ static gint32 tab_qdiff[GAP_FFPRESET_TABSIZE] = { 3, 2, 9, 3, 3, 2, 2, 2, 3 };
+
+ static float tab_qblur[GAP_FFPRESET_TABSIZE] = { 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 };
+ static float tab_qcomp[GAP_FFPRESET_TABSIZE] = { 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 };
+ static float tab_rc_init_cplx[GAP_FFPRESET_TABSIZE] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
+ static float tab_b_qfactor[GAP_FFPRESET_TABSIZE] = { 1.25, 1.25, 1.25, 1.25, 1.25, 1.25, 1.25, 1.25, 1.25 };
+ static float tab_i_qfactor[GAP_FFPRESET_TABSIZE] = { -0.8, -0.8, -0.8, -0.8, -0.8, -0.8, -0.8, -0.8, -0.8 };
+ static float tab_b_qoffset[GAP_FFPRESET_TABSIZE] = { 1.25, 1.25, 1.25, 1.25, 1.25, 1.25, 1.25, 1.25, 1.25 };
+ static float tab_i_qoffset[GAP_FFPRESET_TABSIZE] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
+
+ static gint32 tab_bitrate_tol[GAP_FFPRESET_TABSIZE] = { 4000, 6000, 2000, 4000, 1150, 4000, 2000, 2000, 5000 };
+ static gint32 tab_maxrate_tol[GAP_FFPRESET_TABSIZE] = { 0, 0, 0, 0, 1150, 0, 2516, 9000, 0 };
+ static gint32 tab_minrate_tol[GAP_FFPRESET_TABSIZE] = { 0, 0, 0, 0, 1150, 0, 0, 0, 0 };
+ static gint32 tab_bufsize[GAP_FFPRESET_TABSIZE] = { 0, 0, 0, 0, 40, 0, 224, 224, 0 };
+
+ static gint32 tab_motion_estimation[GAP_FFPRESET_TABSIZE] = { 5, 5, 5, 5, 5, 5, 5, 5, 5 };
+
+ static gint32 tab_dct_algo[GAP_FFPRESET_TABSIZE] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+ static gint32 tab_idct_algo[GAP_FFPRESET_TABSIZE] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+ static gint32 tab_strict[GAP_FFPRESET_TABSIZE] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+ static gint32 tab_mb_qmin[GAP_FFPRESET_TABSIZE] = { 2, 2, 8, 2, 2, 2, 2, 2, 2 };
+ static gint32 tab_mb_qmax[GAP_FFPRESET_TABSIZE] = { 31, 18, 31, 31, 31, 18, 31, 31, 31 };
+ static gint32 tab_mb_decision[GAP_FFPRESET_TABSIZE] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+ static gint32 tab_aic[GAP_FFPRESET_TABSIZE] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+ static gint32 tab_umv[GAP_FFPRESET_TABSIZE] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+
+ static gint32 tab_b_frames[GAP_FFPRESET_TABSIZE] = { 2, 2, 4, 0, 0, 0, 2, 2, 0 };
+ static gint32 tab_mv4[GAP_FFPRESET_TABSIZE] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+ static gint32 tab_partitioning[GAP_FFPRESET_TABSIZE] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+ static gint32 tab_packet_size[GAP_FFPRESET_TABSIZE] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+ static gint32 tab_bitexact[GAP_FFPRESET_TABSIZE] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+ static gint32 tab_aspect[GAP_FFPRESET_TABSIZE] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 };
+ static gint32 tab_aspect_fact[GAP_FFPRESET_TABSIZE] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
+
+ static char* tab_format_name[GAP_FFPRESET_TABSIZE] = { "avi", "avi", "avi", "avi", "vcd", "mpeg", "svcd", "vob", "rm" };
+ static char* tab_vcodec_name[GAP_FFPRESET_TABSIZE] = { "mpeg4", "mpeg4", "mpeg4", "msmpeg4", "mpeg1video", "mpeg1video", "mpeg2video", "mpeg2video", "rv10" };
+ static char* tab_acodec_name[GAP_FFPRESET_TABSIZE] = { "mp2", "mp2", "mp2", "mp2", "mp2", "mp2", "mp2", "ac3", "ac3" };
+
+ static gint32 tab_mux_rate[GAP_FFPRESET_TABSIZE] = { 0, 0, 0, 0, 1411200, 0, 0, 10080000, 0 };
+ static gint32 tab_mux_packet_size[GAP_FFPRESET_TABSIZE] = { 0, 0, 0, 0, 2324, 2324, 2324, 2048, 0 };
+ static float tab_mux_preload[GAP_FFPRESET_TABSIZE] = { 0.5, 0.5, 0.5, 0.5, 0.44, 0.5, 0.5, 0.5, 0.5 };
+ static float tab_mux_max_delay[GAP_FFPRESET_TABSIZE] = { 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7 };
+ static gint32 tab_use_scann_offset[GAP_FFPRESET_TABSIZE] = { 0, 0, 0, 0, 0, 0, 1, 0, 0 };
+
+ static char* tab_presetName[GAP_FFPRESET_TABSIZE] = {
"DivX default preset"
,"DivX high quality preset"
,"DivX low quality preset"
@@ -1237,7 +1283,10 @@ gap_enc_ffmpeg_main_init_preset_params(GapGveFFMpegValues *epp, gint preset_idx)
};
l_idx = preset_idx -1;
- if ((preset_idx < 1) || (preset_idx >= GAP_GVE_FFMPEG_PRESET_MAX_ELEMENTS))
+ if ((preset_idx < 1)
+ || (preset_idx >= GAP_FFPRESET_TABSIZE)
+ || (preset_idx >= GAP_GVE_FFMPEG_PRESET_MAX_ELEMENTS)
+ )
{
/* use hardcoded preset 0 as base initialisation for non-hardcoded Id presets
*/
diff --git a/vid_enc_ffmpeg/gap_enc_ffmpeg_main.h b/vid_enc_ffmpeg/gap_enc_ffmpeg_main.h
index f9f2cb9..8f8d1f1 100644
--- a/vid_enc_ffmpeg/gap_enc_ffmpeg_main.h
+++ b/vid_enc_ffmpeg/gap_enc_ffmpeg_main.h
@@ -68,16 +68,23 @@
#define GAP_FFMPEG_CURRENT_VID_EXTENSION "plug-in-gap-enc-ffmpeg-CURRENT-VIDEO-EXTENSION"
#define GAP_GVE_FFMPEG_PRESET_00_NONE 0
-#define GAP_GVE_FFMPEG_PRESET_01_DIVX_DEFAULT 1
-#define GAP_GVE_FFMPEG_PRESET_02_DIVX_BEST 2
-#define GAP_GVE_FFMPEG_PRESET_03_DIVX_LOW 3
-#define GAP_GVE_FFMPEG_PRESET_04_DIVX_MS 4
-#define GAP_GVE_FFMPEG_PRESET_05_MPEG1_VCD 5
-#define GAP_GVE_FFMPEG_PRESET_06_MPEG1_BEST 6
-#define GAP_GVE_FFMPEG_PRESET_07_MPEG2_SVCD 7
-#define GAP_GVE_FFMPEG_PRESET_08_MPEG2_DVD 8
-#define GAP_GVE_FFMPEG_PRESET_09_REAL 9
-#define GAP_GVE_FFMPEG_PRESET_MAX_ELEMENTS 10
+// #define GAP_GVE_FFMPEG_PRESET_01_DIVX_DEFAULT 1
+// #define GAP_GVE_FFMPEG_PRESET_02_DIVX_BEST 2
+// #define GAP_GVE_FFMPEG_PRESET_03_DIVX_LOW 3
+// #define GAP_GVE_FFMPEG_PRESET_04_DIVX_MS 4
+// #define GAP_GVE_FFMPEG_PRESET_05_MPEG1_VCD 5
+// #define GAP_GVE_FFMPEG_PRESET_06_MPEG1_BEST 6
+// #define GAP_GVE_FFMPEG_PRESET_07_MPEG2_SVCD 7
+// #define GAP_GVE_FFMPEG_PRESET_08_MPEG2_DVD 8
+// #define GAP_GVE_FFMPEG_PRESET_09_REAL 9
+// #define GAP_GVE_FFMPEG_PRESET_MAX_ELEMENTS 10
+
+/* NOTE:
+ * since 2011.10.29 gimp-gap is shiped with preset files that are installed
+ * automatically and checked for valid codecs at runtime.
+ * therefore all the hardcoded presets are disabled.
+ */
+#define GAP_GVE_FFMPEG_PRESET_MAX_ELEMENTS 1
#define GAP_GVE_FFMPEG_AUDIO_KBIT_RATE_00_32 0
#define GAP_GVE_FFMPEG_AUDIO_KBIT_RATE_01_40 1
@@ -195,6 +202,9 @@
#define GAP_ENCODER_PRESET_NAME_MAX_LENGTH 60
#define GAP_ENCODER_PRESET_FILENAME_MAX_LENGTH 1024
+#define GAP_GVE_FFMPEG_SHOW_EXPERT_SETTINGS "video-enoder-ffmpeg-show-expert-settings"
+
+
/* GapGveFFMpegValues ffmpeg specific encoder params */
typedef struct {
@@ -445,10 +455,14 @@ typedef struct GapGveFFMpegGlobalParams { /* nick: gpp */
GtkWidget *shell_window;
gboolean startup;
gboolean ffpar_save_flag;
+ gboolean show_expert_settings;
char ffpar_filename[1024];
GtkWidget *ffpar_fileselection; /* ffmpeg video encoder parameter file */
GtkWidget *fsb__fileselection; /* passlog file */
+ GtkWidget *main_notebook;
+ GtkWidget *show_expert_settings_checkbutton;
+
GtkWidget *ff_aspect_combo;
GtkWidget *ff_aud_bitrate_combo;
GtkWidget *ff_aud_bitrate_spinbutton;
diff --git a/vid_enc_ffmpeg/gap_enc_ffmpeg_par.c b/vid_enc_ffmpeg/gap_enc_ffmpeg_par.c
index f0909af..955fd4d 100644
--- a/vid_enc_ffmpeg/gap_enc_ffmpeg_par.c
+++ b/vid_enc_ffmpeg/gap_enc_ffmpeg_par.c
@@ -30,6 +30,8 @@
#include <locale.h>
#include <errno.h>
+#include <glib/gstdio.h>
+
/* GIMP includes */
#include "libgimp/gimp.h"
@@ -70,6 +72,7 @@ p_set_keyword_bool32(GapValKeyList *keylist, const char *key, void *addr, const
static void
p_set_master_keywords(GapValKeyList *keylist, GapGveFFMpegValues *epp)
{
+ gap_val_set_keyword(keylist, "(preset_name ", &epp->presetName[0], GAP_VAL_STRING, sizeof(epp->presetName), "\0");
gap_val_set_keyword(keylist, "(format_name ", &epp->format_name[0], GAP_VAL_STRING, sizeof(epp->format_name), "\0");
gap_val_set_keyword(keylist, "(vcodec_name ", &epp->vcodec_name[0], GAP_VAL_STRING, sizeof(epp->vcodec_name), "\0");
@@ -81,6 +84,11 @@ p_set_master_keywords(GapValKeyList *keylist, GapGveFFMpegValues *epp)
gap_val_set_keyword(keylist, "(passlogfile ", &epp->passlogfile[0], GAP_VAL_STRING, sizeof(epp->passlogfile), "\0");
gap_val_set_keyword(keylist, "(pass ", &epp->pass_nr, GAP_VAL_GINT32, 0, "# 1: one pass encoding, 2: for two-pass encoding");
+ gap_val_set_keyword(keylist, "(ntsc_width ", &epp->ntsc_width, GAP_VAL_GINT32, 0, "# recommanded width NTSC, 0: not available");
+ gap_val_set_keyword(keylist, "(ntsc_height ", &epp->ntsc_height, GAP_VAL_GINT32, 0, "# recommanded height NTSC, 0: not available");
+ gap_val_set_keyword(keylist, "(pal_width ", &epp->pal_width, GAP_VAL_GINT32, 0, "# recommanded width PAL, 0: not available");
+ gap_val_set_keyword(keylist, "(pal_height ", &epp->pal_height, GAP_VAL_GINT32, 0, "# recommanded height PAL, 0: not available");
+
gap_val_set_keyword(keylist, "(audio_bitrate ", &epp->audio_bitrate, GAP_VAL_GINT32, 0, "# audio bitrate in kBit/sec");
gap_val_set_keyword(keylist, "(video_bitrate ", &epp->video_bitrate, GAP_VAL_GINT32, 0, "# video bitrate in kBit/sec\0");
gap_val_set_keyword(keylist, "(gop_size ", &epp->gop_size, GAP_VAL_GINT32, 0, "# group of picture size");
@@ -378,6 +386,7 @@ gap_ffpar_get(const char *filename, GapGveFFMpegValues *epp)
* (use preset index 0 for the default settings)
*/
gap_enc_ffmpeg_main_init_preset_params(epp, 0);
+ epp->presetName[0] = '\0';
keylist = gap_val_new_keylist();
p_set_master_keywords(keylist, epp);
@@ -475,6 +484,78 @@ gap_ffpar_set(const char *filename, GapGveFFMpegValues *epp)
} /* end gap_ffpar_set */
+/* ----------------------------------
+ * p_check_valid_codecs
+ * ----------------------------------
+ *
+ */
+gboolean
+p_check_valid_codecs(const char *fullPresetFilename)
+{
+ GapGveFFMpegValues *epp;
+ gboolean videoValid;
+ gboolean audioValid;
+ AVCodec *avcodec;
+
+ videoValid = FALSE;
+ audioValid = FALSE;
+ epp = g_new(GapGveFFMpegValues ,1);
+ gap_ffpar_get(fullPresetFilename, epp);
+ epp->next = NULL;
+
+ if(epp->vcodec_name[0] == '\0')
+ {
+ videoValid = TRUE;
+ }
+ if(epp->acodec_name[0] == '\0')
+ {
+ audioValid = TRUE;
+ }
+
+ for(avcodec = av_codec_next(NULL); avcodec != NULL; avcodec = av_codec_next(avcodec))
+ {
+ char *codecName;
+ codecName = (char *)avcodec->name;
+
+ /* debug logging */
+ /* printf("codecName:%s: Type:%d\n", codecName , (int)avcodec->type);
+ */
+
+ if ((avcodec->encode) && (avcodec->type == AVMEDIA_TYPE_VIDEO))
+ {
+ if(strcmp(codecName, epp->vcodec_name) == 0)
+ {
+ videoValid = TRUE;
+ }
+ }
+ if ((avcodec->encode) && (avcodec->type == AVMEDIA_TYPE_AUDIO))
+ {
+ if(strcmp(codecName, epp->acodec_name) == 0)
+ {
+ audioValid = TRUE;
+ }
+ }
+ }
+
+ if(!videoValid)
+ {
+ printf("preset: %s INVALID videoCodec:%s:\n"
+ ,fullPresetFilename
+ ,epp->vcodec_name
+ );
+ }
+ if(!audioValid)
+ {
+ printf("preset: %s INVALID audioCodec:%s:\n"
+ ,fullPresetFilename
+ ,epp->acodec_name
+ );
+ }
+ g_free(epp);
+
+ return(audioValid & videoValid);
+
+} /* end p_check_valid_codecs */
/* ----------------------------------
@@ -495,14 +576,30 @@ gap_ffpar_isValidPresetFile(const char *fullPresetFilename)
l_fp = g_fopen(fullPresetFilename, "rb"); /* open read */
if(l_fp != NULL)
{
- fread(&buffer[0], 1, (size_t)sizeof(buffer -1), l_fp);
+ gint relevantLength;
+
+ relevantLength = MIN(sizeof(buffer) -1, strlen(GAP_FFENC_FILEHEADER_LINE));
+ fread(&buffer[0], 1, relevantLength, l_fp);
+ buffer[relevantLength+1] = '\0';
+
fclose(l_fp);
- if(memcmp(&buffer[0], GAP_FFENC_FILEHEADER_LINE, strlen(GAP_FFENC_FILEHEADER_LINE -1)) == 0)
+
+ if(gap_debug)
{
- return(TRUE);
+ printf("HDR:%s\n EXP:%s\n", &buffer[0], GAP_FFENC_FILEHEADER_LINE);
+ }
+ if(memcmp(&buffer[0], GAP_FFENC_FILEHEADER_LINE, relevantLength) == 0)
+ {
+
+
+ return(p_check_valid_codecs(fullPresetFilename));
}
}
}
+ if(gap_debug)
+ {
+ printf("** INValidPresetFile: %s", fullPresetFilename);
+ }
return(FALSE);
} /* end gap_ffpar_isValidPresetFile */
@@ -519,7 +616,7 @@ p_find_preset_by_filename(const char *fullPresetFilename)
for(epp = eppRoot; epp != NULL; epp = epp->next)
{
- if(strncmp(&epp->presetFileName[0], fullPresetFilename, GAP_ENCODER_PRESET_NAME_MAX_LENGTH -1) == 0)
+ if(strcmp(&epp->presetFileName[0], fullPresetFilename) == 0)
{
return(epp);
}
@@ -528,32 +625,141 @@ p_find_preset_by_filename(const char *fullPresetFilename)
} /* end p_find_preset_by_filename */
+
/* ----------------------------------
- * gap_ffpar_getPresetList
+ * p_add_entry_sorted_by_name
* ----------------------------------
- * returns a list of all available encoder presets.
- * the list includes harcoded internal presets
- * and optional presets files found in $GIMPDIR/video_encoder_presets
- *
- * presetId is generated as unique value > offset for hardcoded presets
- * presetName derived from filename.
+ * insert the new element eppNew in the list sorted by presetName
+ * but do not insert before the element referenced by eppStart.
+ * use eppStart value NULL in case insert at any position is desired
+ * or set eppStart to the last element in case appending to the list is
+ * necessary.
*/
-GapGveFFMpegValues *
-gap_ffpar_getPresetList()
+static void
+p_add_entry_sorted_by_name(GapGveFFMpegValues *eppStart, GapGveFFMpegValues *eppNew)
{
GapGveFFMpegValues *epp;
GapGveFFMpegValues *eppPrev;
- char *presetDir;
- GDir *dirPtr;
- const gchar *entry;
+ GapGveFFMpegValues *eppNext;
+ gboolean enableInsert;
- eppPrev = eppRoot;
- for(epp = eppRoot; epp != NULL; epp = epp->next)
+ eppNext = NULL;
+ eppPrev = NULL;
+ epp = eppRoot;
+
+ enableInsert = FALSE;
+ if (eppStart == NULL)
{
- eppPrev = epp;
+ enableInsert = TRUE;
}
- presetDir = g_build_filename(gimp_directory(), GAP_VIDEO_ENCODER_PRESET_DIR, NULL);
+ if(gap_debug)
+ {
+ printf("SORT: START\n");
+ }
+
+ while(epp != NULL)
+ {
+ if(gap_debug)
+ {
+ printf("SORT: new:%s list:%s\n"
+ ,eppNew->presetName
+ ,epp->presetName
+ );
+ }
+ if(enableInsert)
+ {
+ if (strcmp(eppNew->presetName, epp->presetName) < 0)
+ {
+ /* found position to insert eppNew entry */
+ eppNext = epp;
+ break;
+ }
+ }
+ eppPrev = epp;
+ if(epp == eppStart)
+ {
+ enableInsert = TRUE;
+ }
+ epp = epp->next;
+ }
+
+
+ eppNew->next = eppNext;
+ if(eppPrev == NULL)
+ {
+ /* have no previos element, create the first entry as root */
+ eppRoot = eppNew;
+ }
+ else
+ {
+ eppPrev->next = eppNew;
+ }
+
+
+
+
+ if(gap_debug)
+ {
+ gint ii;
+ printf("SORT: RESULT\n");
+
+
+ ii=0;
+
+ for(epp = eppRoot; epp != NULL; epp = epp->next)
+ {
+ printf("[%d]:%s: addr:%d next:%d"
+ , (int)ii
+ , epp->presetName
+ ,(int)epp
+ ,(int)epp->next
+ );
+ if(epp == eppRoot)
+ {
+ printf(" eppRoot ");
+ }
+ if(epp == eppStart)
+ {
+ printf(" eppStart ");
+ }
+ if(epp == eppPrev)
+ {
+ printf(" eppPrev ");
+ }
+ printf("\n");
+ ii++;
+
+ if(ii>30)
+ {
+ printf("ERROR exit\n");
+ exit (-1);
+ }
+ }
+ printf("SORT: END\n");
+ }
+
+} /* end p_add_entry_sorted_by_name */
+
+
+/* ----------------------------------
+ * p_add_presets_from_directory
+ * ----------------------------------
+ * adds available encoder presets found in the specified presetDir
+ * to the static list of optional encoder presets.
+ *
+ * the presetId is generated as unique counter value
+ * (starting with offset to avoid conflicts with the
+ * presetId's for the reserved hardcoded presets)
+ * presetName is read from the preset, or derived from filename.
+ */
+static void
+p_add_presets_from_directory(GapGveFFMpegValues *eppStart, const char *presetDir)
+{
+ GapGveFFMpegValues *epp;
+ GDir *dirPtr;
+ const gchar *entry;
+
dirPtr = g_dir_open( presetDir, 0, NULL );
if(dirPtr != NULL)
{
@@ -588,14 +794,23 @@ gap_ffpar_getPresetList()
/* read the parameters form preset file */
gap_ffpar_get(fullPresetFilename, epp);
- /* generate name and id (from filename and position in the list) */
+ /* generate uniqe id (from static counter) */
epp->presetId = nextPresetId;
- g_snprintf(&epp->presetName[0]
+
+ /* in case the presetName is not provided in the preset file content
+ * generate name and id (from filename and position in the list)
+ */
+ epp->presetName[GAP_ENCODER_PRESET_NAME_MAX_LENGTH -1] = '\0';
+ if(epp->presetName[0] == '\0')
+ {
+ g_snprintf(&epp->presetName[0]
, (GAP_ENCODER_PRESET_NAME_MAX_LENGTH -1)
, "%d %s"
, epp->presetId
, entry
);
+ }
+ epp->presetFileName[GAP_ENCODER_PRESET_FILENAME_MAX_LENGTH -1] = '\0';
g_snprintf(&epp->presetFileName[0]
, (GAP_ENCODER_PRESET_FILENAME_MAX_LENGTH -1)
, "%s"
@@ -608,16 +823,15 @@ gap_ffpar_getPresetList()
printf("PRESET:%s\n", &epp->presetName[0]);
}
- /* append epp to the list */
- if(eppPrev == NULL)
- {
- eppRoot = epp;
- }
- else
- {
- eppPrev->next = epp;
- }
- eppPrev = epp;
+ /* insert new entry sorted by name
+ * note that sort is limited to the newly added list elements
+ * that are added after eppStart element.
+ * this is done to keep the order for elements that were already
+ * read in previous directory scans and sort
+ * only new elements on refresh of the presets combo box
+ * within the same process.
+ */
+ p_add_entry_sorted_by_name(eppStart, epp);
nextPresetId++;
}
}
@@ -625,6 +839,46 @@ gap_ffpar_getPresetList()
}
g_dir_close( dirPtr );
}
+
+
+} /* end p_add_presets_from_directory */
+
+
+
+/* ----------------------------------
+ * gap_ffpar_getPresetList
+ * ----------------------------------
+ * returns a list of all available encoder presets.
+ * the list includes presets files found in user specific $GIMPDIR/video_encoder_presets
+ * or in systemwide $GIMPDATADIR/video_encoder_presets.
+ *
+ * Note that Hardcoded presetes are not included in the list
+ * but the presetId is generated as unique value > offset for hardcoded presets.
+ */
+GapGveFFMpegValues *
+gap_ffpar_getPresetList()
+{
+ GapGveFFMpegValues *epp;
+ GapGveFFMpegValues *eppPrev;
+ char *presetDir;
+
+ eppPrev = eppRoot;
+ for(epp = eppRoot; epp != NULL; epp = epp->next)
+ {
+ eppPrev = epp;
+ }
+
+ /* system wide data directory example: /usr/local/share/gimp/2.0 */
+ presetDir = g_build_filename(gimp_data_directory(), GAP_VIDEO_ENCODER_PRESET_DIR, NULL);
+ p_add_presets_from_directory(eppPrev, presetDir);
+ g_free(presetDir);
+
+ /* user specific directory example: /home/hof/.gimp-2.6
+ * (preset names that are already present in previous processed directory
+ * will be overwritten. e.g. user specific variant is preferred)
+ */
+ presetDir = g_build_filename(gimp_directory(), GAP_VIDEO_ENCODER_PRESET_DIR, NULL);
+ p_add_presets_from_directory(eppPrev, presetDir);
g_free(presetDir);
return(eppRoot);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]