diff --git a/app/pdb/internal-procs.c b/app/pdb/internal-procs.c index 830e322786..64d0540af1 100644 --- a/app/pdb/internal-procs.c +++ b/app/pdb/internal-procs.c @@ -28,7 +28,7 @@ #include "internal-procs.h" -/* 750 procedures registered total */ +/* 753 procedures registered total */ void internal_procs_init (GimpPDB *pdb) diff --git a/app/pdb/plug-in-compat-cmds.c b/app/pdb/plug-in-compat-cmds.c index 4d43dc082c..f6347ee6ed 100644 --- a/app/pdb/plug-in-compat-cmds.c +++ b/app/pdb/plug-in-compat-cmds.c @@ -3013,6 +3013,204 @@ plug_in_vinvert_invoker (GimpProcedure *procedure, error ? *error : NULL); } +static GimpValueArray * +plug_in_vpropagate_invoker (GimpProcedure *procedure, + Gimp *gimp, + GimpContext *context, + GimpProgress *progress, + const GimpValueArray *args, + GError **error) +{ + gboolean success = TRUE; + GimpDrawable *drawable; + gint32 propagate_mode; + gint32 propagating_channel; + gdouble propagating_rate; + gint32 direction_mask; + gint32 lower_limit; + gint32 upper_limit; + + drawable = gimp_value_get_drawable (gimp_value_array_index (args, 2), gimp); + propagate_mode = g_value_get_int (gimp_value_array_index (args, 3)); + propagating_channel = g_value_get_int (gimp_value_array_index (args, 4)); + propagating_rate = g_value_get_double (gimp_value_array_index (args, 5)); + direction_mask = g_value_get_int (gimp_value_array_index (args, 6)); + lower_limit = g_value_get_int (gimp_value_array_index (args, 7)); + upper_limit = g_value_get_int (gimp_value_array_index (args, 8)); + + if (success) + { + if (gimp_pdb_item_is_attached (GIMP_ITEM (drawable), NULL, + GIMP_PDB_ITEM_CONTENT, error) && + gimp_pdb_item_is_not_group (GIMP_ITEM (drawable), error)) + { + GeglNode *node; + GimpRGB color; + GeglColor *gegl_color = NULL; + gint gegl_mode = 0; + gboolean to_left = (direction_mask & (0x1 << 0)) != 0; + gboolean to_top = (direction_mask & (0x1 << 1)) != 0; + gboolean to_right = (direction_mask & (0x1 << 2)) != 0; + gboolean to_bottom = (direction_mask & (0x1 << 3)) != 0; + gboolean value = (propagating_channel & (0x1 << 0)) != 0; + gboolean alpha = (propagating_channel & (0x1 << 1)) != 0; + + switch (propagate_mode) + { + case 0: + case 1: + case 2: + gegl_mode = propagate_mode; + break; + + case 3: + gegl_mode = propagate_mode; + /* fall thru */ + + case 4: + case 5: + gegl_mode = 4; + + if (propagate_mode != 3) + gimp_context_get_foreground (context, &color); + else + gimp_context_get_background (context, &color); + + gegl_color = gimp_gegl_color_new (&color); + break; + + case 6: + case 7: + gegl_mode = propagate_mode - 1; + break; + } + + node = + gegl_node_new_child (NULL, + "operation", "gegl:value-propagate", + "mode", gegl_mode, + "lower-threshold", (gdouble) lower_limit / 255.0, + "upper-threshold", (gdouble) upper_limit / 255.0, + "rate", propagating_rate, + "color", gegl_color, + "top", to_top, + "left", to_left, + "right", to_right, + "bottom", to_bottom, + "value", value, + "alpha", alpha, + NULL); + + if (gegl_color) + g_object_unref (gegl_color); + + gimp_drawable_apply_operation (drawable, progress, + C_("undo-type", "Value Propagate"), + node); + g_object_unref (node); + } + else + success = FALSE; + } + + return gimp_procedure_get_return_values (procedure, success, + error ? *error : NULL); +} + +static GimpValueArray * +plug_in_dilate_invoker (GimpProcedure *procedure, + Gimp *gimp, + GimpContext *context, + GimpProgress *progress, + const GimpValueArray *args, + GError **error) +{ + gboolean success = TRUE; + GimpDrawable *drawable; + + drawable = gimp_value_get_drawable (gimp_value_array_index (args, 2), gimp); + + if (success) + { + if (gimp_pdb_item_is_attached (GIMP_ITEM (drawable), NULL, + GIMP_PDB_ITEM_CONTENT, error) && + gimp_pdb_item_is_not_group (GIMP_ITEM (drawable), error)) + { + GeglNode *node = + gegl_node_new_child (NULL, + "operation", "gegl:value-propagate", + "mode", 0, /* GEGL_VALUE_PROPAGATE_MODE_WHITE */ + "lower-threshold", 0.0, + "upper-threshold", 1.0, + "rate", 1.0, + "top", TRUE, + "left", TRUE, + "right", TRUE, + "bottom", TRUE, + "value", TRUE, + "alpha", FALSE, + NULL); + + gimp_drawable_apply_operation (drawable, progress, + C_("undo-type", "Dilate"), + node); + g_object_unref (node); + } + else + success = FALSE; + } + + return gimp_procedure_get_return_values (procedure, success, + error ? *error : NULL); +} + +static GimpValueArray * +plug_in_erode_invoker (GimpProcedure *procedure, + Gimp *gimp, + GimpContext *context, + GimpProgress *progress, + const GimpValueArray *args, + GError **error) +{ + gboolean success = TRUE; + GimpDrawable *drawable; + + drawable = gimp_value_get_drawable (gimp_value_array_index (args, 2), gimp); + + if (success) + { + if (gimp_pdb_item_is_attached (GIMP_ITEM (drawable), NULL, + GIMP_PDB_ITEM_CONTENT, error) && + gimp_pdb_item_is_not_group (GIMP_ITEM (drawable), error)) + { + GeglNode *node = + gegl_node_new_child (NULL, + "operation", "gegl:value-propagate", + "mode", 1, /* GEGL_VALUE_PROPAGATE_MODE_BLACK */ + "lower-threshold", 0.0, + "upper-threshold", 1.0, + "rate", 1.0, + "top", TRUE, + "left", TRUE, + "right", TRUE, + "bottom", TRUE, + "value", TRUE, + "alpha", FALSE, + NULL); + + gimp_drawable_apply_operation (drawable, progress, + C_("undo-type", "Erode"), + node); + g_object_unref (node); + } + else + success = FALSE; + } + + return gimp_procedure_get_return_values (procedure, success, + error ? *error : NULL); +} + static GimpValueArray * plug_in_waves_invoker (GimpProcedure *procedure, Gimp *gimp, @@ -6113,6 +6311,222 @@ register_plug_in_compat_procs (GimpPDB *pdb) gimp_pdb_register_procedure (pdb, procedure); g_object_unref (procedure); + /* + * gimp-plug-in-vpropagate + */ + procedure = gimp_procedure_new (plug_in_vpropagate_invoker); + gimp_object_set_static_name (GIMP_OBJECT (procedure), + "plug-in-vpropagate"); + gimp_procedure_set_static_strings (procedure, + "plug-in-vpropagate", + "Propagate certain colors to neighboring pixels", + "Propagate values of the layer.", + "Compatibility procedure. Please see 'gegl:value-propagate' for credits.", + "Compatibility procedure. Please see 'gegl:value-propagate' for credits.", + "2015", + NULL); + gimp_procedure_add_argument (procedure, + g_param_spec_enum ("run-mode", + "run mode", + "The run mode", + GIMP_TYPE_RUN_MODE, + GIMP_RUN_INTERACTIVE, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + gimp_param_spec_image_id ("image", + "image", + "Input image (unused)", + pdb->gimp, FALSE, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + gimp_param_spec_drawable_id ("drawable", + "drawable", + "Input drawable", + pdb->gimp, FALSE, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + gimp_param_spec_int32 ("propagate-mode", + "propagate mode", + "Propagate mode { 0:white, 1:black, 2:middle value 3:foreground to peak, 4:foreground, 5:background, 6:opaque, 7:transparent }", + 0, 7, 0, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + gimp_param_spec_int32 ("propagating-channel", + "propagating channel", + "Channels which values are propagated", + G_MININT32, G_MAXINT32, 0, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + g_param_spec_double ("propagating-rate", + "propagating rate", + "Propagating rate", + 0.0, 1.0, 0.0, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + gimp_param_spec_int32 ("direction-mask", + "direction mask", + "Direction mask", + 0, 15, 0, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + gimp_param_spec_int32 ("lower-limit", + "lower limit", + "Lower limit", + 0, 255, 0, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + gimp_param_spec_int32 ("upper-limit", + "upper limit", + "Upper limit", + 0, 255, 0, + GIMP_PARAM_READWRITE)); + gimp_pdb_register_procedure (pdb, procedure); + g_object_unref (procedure); + + /* + * gimp-plug-in-dilate + */ + procedure = gimp_procedure_new (plug_in_dilate_invoker); + gimp_object_set_static_name (GIMP_OBJECT (procedure), + "plug-in-dilate"); + gimp_procedure_set_static_strings (procedure, + "plug-in-dilate", + "Grow lighter areas of the image", + "Dilate image.", + "Compatibility procedure. Please see 'gegl:value-propagate' for credits.", + "Compatibility procedure. Please see 'gegl:value-propagate' for credits.", + "2015", + NULL); + gimp_procedure_add_argument (procedure, + g_param_spec_enum ("run-mode", + "run mode", + "The run mode", + GIMP_TYPE_RUN_MODE, + GIMP_RUN_INTERACTIVE, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + gimp_param_spec_image_id ("image", + "image", + "Input image (unused)", + pdb->gimp, FALSE, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + gimp_param_spec_drawable_id ("drawable", + "drawable", + "Input drawable", + pdb->gimp, FALSE, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + gimp_param_spec_int32 ("propagate-mode", + "propagate mode", + "Propagate mode { 0:white, 1:black, 2:middle value 3:foreground to peak, 4:foreground, 5:background, 6:opaque, 7:transparent }", + 0, 7, 0, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + gimp_param_spec_int32 ("propagating-channel", + "propagating channel", + "Channels which values are propagated", + G_MININT32, G_MAXINT32, 0, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + g_param_spec_double ("propagating-rate", + "propagating rate", + "Propagating rate", + 0.0, 1.0, 0.0, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + gimp_param_spec_int32 ("direction-mask", + "direction mask", + "Direction mask", + 0, 15, 0, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + gimp_param_spec_int32 ("lower-limit", + "lower limit", + "Lower limit", + 0, 255, 0, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + gimp_param_spec_int32 ("upper-limit", + "upper limit", + "Upper limit", + 0, 255, 0, + GIMP_PARAM_READWRITE)); + gimp_pdb_register_procedure (pdb, procedure); + g_object_unref (procedure); + + /* + * gimp-plug-in-erode + */ + procedure = gimp_procedure_new (plug_in_erode_invoker); + gimp_object_set_static_name (GIMP_OBJECT (procedure), + "plug-in-erode"); + gimp_procedure_set_static_strings (procedure, + "plug-in-erode", + "Shrink lighter areas of the image", + "Erode image.", + "Compatibility procedure. Please see 'gegl:value-propagate' for credits.", + "Compatibility procedure. Please see 'gegl:value-propagate' for credits.", + "2015", + NULL); + gimp_procedure_add_argument (procedure, + g_param_spec_enum ("run-mode", + "run mode", + "The run mode", + GIMP_TYPE_RUN_MODE, + GIMP_RUN_INTERACTIVE, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + gimp_param_spec_image_id ("image", + "image", + "Input image (unused)", + pdb->gimp, FALSE, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + gimp_param_spec_drawable_id ("drawable", + "drawable", + "Input drawable", + pdb->gimp, FALSE, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + gimp_param_spec_int32 ("propagate-mode", + "propagate mode", + "Propagate mode { 0:white, 1:black, 2:middle value 3:foreground to peak, 4:foreground, 5:background, 6:opaque, 7:transparent }", + 0, 7, 0, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + gimp_param_spec_int32 ("propagating-channel", + "propagating channel", + "Channels which values are propagated", + G_MININT32, G_MAXINT32, 0, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + g_param_spec_double ("propagating-rate", + "propagating rate", + "Propagating rate", + 0.0, 1.0, 0.0, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + gimp_param_spec_int32 ("direction-mask", + "direction mask", + "Direction mask", + 0, 15, 0, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + gimp_param_spec_int32 ("lower-limit", + "lower limit", + "Lower limit", + 0, 255, 0, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + gimp_param_spec_int32 ("upper-limit", + "upper limit", + "Upper limit", + 0, 255, 0, + GIMP_PARAM_READWRITE)); + gimp_pdb_register_procedure (pdb, procedure); + g_object_unref (procedure); + /* * gimp-plug-in-waves */ diff --git a/plug-ins/common/.gitignore b/plug-ins/common/.gitignore index 9c4ad11276..7e21b996b0 100644 --- a/plug-ins/common/.gitignore +++ b/plug-ins/common/.gitignore @@ -198,8 +198,6 @@ /unit-editor.exe /unsharp-mask /unsharp-mask.exe -/value-propagate -/value-propagate.exe /van-gogh-lic /van-gogh-lic.exe /warp diff --git a/plug-ins/common/Makefile.am b/plug-ins/common/Makefile.am index a2d6e97984..2be1122381 100644 --- a/plug-ins/common/Makefile.am +++ b/plug-ins/common/Makefile.am @@ -142,7 +142,6 @@ libexec_PROGRAMS = \ tile-small \ unit-editor \ unsharp-mask \ - value-propagate \ van-gogh-lic \ warp \ web-browser \ @@ -1907,23 +1906,6 @@ unsharp_mask_LDADD = \ $(INTLLIBS) \ $(unsharp_mask_RC) -value_propagate_SOURCES = \ - value-propagate.c - -value_propagate_LDADD = \ - $(libgimpui) \ - $(libgimpwidgets) \ - $(libgimpmodule) \ - $(libgimp) \ - $(libgimpmath) \ - $(libgimpconfig) \ - $(libgimpcolor) \ - $(libgimpbase) \ - $(GTK_LIBS) \ - $(RT_LIBS) \ - $(INTLLIBS) \ - $(value_propagate_RC) - van_gogh_lic_SOURCES = \ van-gogh-lic.c diff --git a/plug-ins/common/gimprc.common b/plug-ins/common/gimprc.common index d0d8278975..1078c0a1ef 100644 --- a/plug-ins/common/gimprc.common +++ b/plug-ins/common/gimprc.common @@ -96,7 +96,6 @@ tile_paper_RC = tile-paper.rc.o tile_small_RC = tile-small.rc.o unit_editor_RC = unit-editor.rc.o unsharp_mask_RC = unsharp-mask.rc.o -value_propagate_RC = value-propagate.rc.o van_gogh_lic_RC = van-gogh-lic.rc.o warp_RC = warp.rc.o web_browser_RC = web-browser.rc.o diff --git a/plug-ins/common/plugin-defs.pl b/plug-ins/common/plugin-defs.pl index 6a480f6ef6..df42d6ebd5 100644 --- a/plug-ins/common/plugin-defs.pl +++ b/plug-ins/common/plugin-defs.pl @@ -97,7 +97,6 @@ 'tile-small' => { ui => 1 }, 'unit-editor' => { ui => 1 }, 'unsharp-mask' => { ui => 1 }, - 'value-propagate' => { ui => 1 }, 'van-gogh-lic' => { ui => 1 }, 'warp' => { ui => 1 }, 'web-browser' => { ui => 1 }, diff --git a/plug-ins/common/value-propagate.c b/plug-ins/common/value-propagate.c deleted file mode 100644 index cdd5a98e9a..0000000000 --- a/plug-ins/common/value-propagate.c +++ /dev/null @@ -1,1294 +0,0 @@ -/* vpropagate.c -- This is a plug-in for GIMP (1.0's API) - * Author: Shuji Narazaki - * Time-stamp: <2000-01-09 15:50:46 yasuhiro> - * Version: 0.89a - * - * Copyright (C) 1996-1997 Shuji Narazaki - * - * 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 . - */ - -/* memo - the initial value of each pixel is the value of the pixel itself. - To determine whether it is an isolated local peak point, use: - (self == min && (! modified_flag)) ; modified_flag holds history of update - In other word, pixel itself is not a neighbor of it. -*/ -/* - in response to bug #156545, after lengthy discussion, the meanings - of "dilate" and "erode" are being swapped -- 19 May 2006. -*/ - -#include "config.h" - -#include -#include - -#include -#include - -#include "libgimp/stdplugins-intl.h" - - -#define VPROPAGATE_PROC "plug-in-vpropagate" -#define ERODE_PROC "plug-in-erode" -#define DILATE_PROC "plug-in-dilate" -#define PLUG_IN_BINARY "value-propagate" -#define PLUG_IN_ROLE "gimp-value-propagate" -#define PLUG_IN_IMAGE_TYPES "RGB*, GRAY*" - -#define VP_RGB (1 << 0) -#define VP_GRAY (1 << 1) -#define VP_WITH_ALPHA (1 << 2) -#define VP_WO_ALPHA (1 << 3) -#define num_direction 4 -#define Right2Left 0 -#define Bottom2Top 1 -#define Left2Right 2 -#define Top2Bottom 3 - -static void query (void); -static void run (const gchar *name, - gint nparams, - const GimpParam *param, - gint *nreturn_vals, - GimpParam **return_vals); - -static GimpPDBStatusType value_propagate (GimpDrawable *drawable); -static void value_propagate_body (GimpDrawable *drawable, - GimpPreview *preview); -static gboolean vpropagate_dialog (GimpDrawable *drawable); -static void prepare_row (GimpPixelRgn *pixel_rgn, - guchar *data, - gint x, - gint y, - gint w); - -static void vpropagate_toggle_button_update (GtkWidget *widget, - gpointer data); -static GtkWidget * gtk_table_add_toggle (GtkWidget *table, - const gchar *name, - gint x1, - gint x2, - gint y, - GCallback update, - gint *value); - -static int value_difference_check (guchar *, guchar *, int); -static void set_value (GimpImageType, - int, guchar *, guchar *, guchar *, - void *); -static void initialize_white (GimpImageType, - int, guchar *, guchar *, - void **); -static void propagate_white (GimpImageType, - int, guchar *, guchar *, guchar *, - void *); -static void initialize_black (GimpImageType, - int, guchar *, guchar *, - void **); -static void propagate_black (GimpImageType, - int, guchar *, guchar *, guchar *, - void *); -static void initialize_middle (GimpImageType, - int, guchar *, guchar *, - void **); -static void propagate_middle (GimpImageType, - int, guchar *, guchar *, guchar *, - void *); -static void set_middle_to_peak (GimpImageType, - int, guchar *, guchar *, guchar *, - void *); -static void set_foreground_to_peak (GimpImageType, - int, guchar *, guchar *, guchar *, - void *); -static void initialize_foreground (GimpImageType, - int, guchar *, guchar *, - void **); -static void initialize_background (GimpImageType, - int, guchar *, guchar *, - void **); -static void propagate_a_color (GimpImageType, - int, guchar *, guchar *, guchar *, - void *); -static void propagate_opaque (GimpImageType, - int, guchar *, guchar *, guchar *, - void *); -static void propagate_transparent (GimpImageType, - int, guchar *, guchar *, guchar *, - void *); - -const GimpPlugInInfo PLUG_IN_INFO = -{ - NULL, /* init_proc */ - NULL, /* quit_proc */ - query, /* query_proc */ - run, /* run_proc */ -}; - -#define SCALE_WIDTH 100 -#define PROPAGATING_VALUE (1 << 0) -#define PROPAGATING_ALPHA (1 << 1) - -/* parameters */ -typedef struct -{ - gint propagate_mode; - gint propagating_channel; - gdouble propagating_rate; - gint direction_mask; - gint lower_limit; - gint upper_limit; -} VPValueType; - -static VPValueType vpvals = -{ - 0, /* propagate_mode */ - 3, /* PROPAGATING_VALUE + PROPAGATING_ALPHA */ - 1.0, /* [0.0:1.0] */ - 15, /* propagate to all 4 directions */ - 0, /* lower_limit */ - 255 /* upper_limit */ -}; - -/* dialog variables */ -static gint propagate_alpha; -static gint propagate_value; -static gint direction_mask_vec[4]; -static gint channel_mask[] = { 1, 1, 1 }; -static gint peak_max = 1; -static gint peak_min = 1; -static gint peak_includes_equals = 1; -static guchar fore[3]; -static GtkWidget *preview; - -typedef struct -{ - gint applicable_image_type; - gchar *name; - void (*initializer) (GimpImageType, gint, guchar *, guchar *, gpointer *); - void (*updater) (GimpImageType, gint, guchar *, guchar *, guchar *, gpointer); - void (*finalizer) (GimpImageType, gint, guchar *, guchar *, guchar *, gpointer); -} ModeParam; - -#define num_mode 8 -static ModeParam modes[num_mode] = -{ - { VP_RGB | VP_GRAY | VP_WITH_ALPHA | VP_WO_ALPHA, - N_("More _white (larger value)"), - initialize_white, propagate_white, set_value }, - { VP_RGB | VP_GRAY | VP_WITH_ALPHA | VP_WO_ALPHA, - N_("More blac_k (smaller value)"), - initialize_black, propagate_black, set_value }, - { VP_RGB | VP_GRAY | VP_WITH_ALPHA | VP_WO_ALPHA, - N_("_Middle value to peaks"), - initialize_middle, propagate_middle, set_middle_to_peak }, - { VP_RGB | VP_GRAY | VP_WITH_ALPHA | VP_WO_ALPHA, - N_("_Foreground to peaks"), - initialize_middle, propagate_middle, set_foreground_to_peak }, - { VP_RGB | VP_WITH_ALPHA | VP_WO_ALPHA, - N_("O_nly foreground"), - initialize_foreground, propagate_a_color, set_value }, - { VP_RGB | VP_WITH_ALPHA | VP_WO_ALPHA, - N_("Only b_ackground"), - initialize_background, propagate_a_color, set_value }, - { VP_RGB | VP_GRAY | VP_WITH_ALPHA, - N_("Mor_e opaque"), - NULL, propagate_opaque, set_value }, - { VP_RGB | VP_GRAY | VP_WITH_ALPHA, - N_("More t_ransparent"), - NULL, propagate_transparent, set_value }, -}; - -MAIN () - -static void -query (void) -{ - static const GimpParamDef args[] = - { - { GIMP_PDB_INT32, "run-mode", "The run mode { RUN-INTERACTIVE (0), RUN-NONINTERACTIVE (1) }" }, - { GIMP_PDB_IMAGE, "image", "Input image (not used)" }, - { GIMP_PDB_DRAWABLE, "drawable", "Input drawable" }, - { GIMP_PDB_INT32, "propagate-mode", "propagate 0:white, 1:black, 2:middle value 3:foreground to peak, 4:foreground, 5:background, 6:opaque, 7:transparent" }, - { GIMP_PDB_INT32, "propagating-channel", "channels which values are propagated" }, - { GIMP_PDB_FLOAT, "propagating-rate", "0.0 <= propagatating_rate <= 1.0" }, - { GIMP_PDB_INT32, "direction-mask", "0 <= direction-mask <= 15" }, - { GIMP_PDB_INT32, "lower-limit", "0 <= lower-limit <= 255" }, - { GIMP_PDB_INT32, "upper-limit", "0 <= upper-limit <= 255" } - }; - - gimp_install_procedure (VPROPAGATE_PROC, - N_("Propagate certain colors to neighboring pixels"), - "Propagate values of the layer", - "Shuji Narazaki (narazaki@InetQ.or.jp)", - "Shuji Narazaki", - "1996-1997", - N_("_Value Propagate..."), - PLUG_IN_IMAGE_TYPES, - GIMP_PLUGIN, - G_N_ELEMENTS (args), 0, - args, NULL); - - gimp_install_procedure (ERODE_PROC, - N_("Shrink lighter areas of the image"), - "Erode image", - "Shuji Narazaki (narazaki@InetQ.or.jp)", - "Shuji Narazaki", - "1996-1997", - N_("E_rode"), - PLUG_IN_IMAGE_TYPES, - GIMP_PLUGIN, - G_N_ELEMENTS (args), 0, - args, NULL); - - gimp_install_procedure (DILATE_PROC, - N_("Grow lighter areas of the image"), - "Dilate image", - "Shuji Narazaki (narazaki@InetQ.or.jp)", - "Shuji Narazaki", - "1996-1997", - N_("_Dilate"), - PLUG_IN_IMAGE_TYPES, - GIMP_PLUGIN, - G_N_ELEMENTS (args), 0, - args, NULL); - - gimp_plugin_menu_register (VPROPAGATE_PROC, "/Filters/Distorts"); -} - -static void -run (const gchar *name, - gint nparams, - const GimpParam *param, - gint *nreturn_vals, - GimpParam **return_vals) -{ - static GimpParam values[1]; - GimpPDBStatusType status = GIMP_PDB_SUCCESS; - GimpRunMode run_mode; - GimpDrawable *drawable; - - run_mode = param[0].data.d_int32; - drawable = gimp_drawable_get (param[2].data.d_int32); - - INIT_I18N (); - - *nreturn_vals = 1; - *return_vals = values; - - values[0].type = GIMP_PDB_STATUS; - values[0].data.d_status = status; - - switch (run_mode) - { - case GIMP_RUN_INTERACTIVE: - if (strcmp (name, VPROPAGATE_PROC) == 0) - { - gimp_get_data (VPROPAGATE_PROC, &vpvals); - /* building the values of dialog variables from vpvals. */ - propagate_alpha = - (vpvals.propagating_channel & PROPAGATING_ALPHA) ? TRUE : FALSE; - propagate_value = - (vpvals.propagating_channel & PROPAGATING_VALUE) ? TRUE : FALSE; - - { - gint i; - for (i = 0; i < 4; i++) - direction_mask_vec[i] = - (vpvals.direction_mask & (1 << i)) ? TRUE : FALSE; - } - - if (! vpropagate_dialog (drawable)) - return; - } - else if (strcmp (name, ERODE_PROC) == 0 || - strcmp (name, DILATE_PROC) == 0) - { - vpvals.propagating_channel = PROPAGATING_VALUE; - vpvals.propagating_rate = 1.0; - vpvals.direction_mask = 15; - vpvals.lower_limit = 0; - vpvals.upper_limit = 255; - - if (strcmp (name, ERODE_PROC) == 0) - vpvals.propagate_mode = 1; - else if (strcmp (name, DILATE_PROC) == 0) - vpvals.propagate_mode = 0; - } - break; - - case GIMP_RUN_NONINTERACTIVE: - if (strcmp (name, VPROPAGATE_PROC) == 0) - { - vpvals.propagate_mode = param[3].data.d_int32; - vpvals.propagating_channel = param[4].data.d_int32; - vpvals.propagating_rate = param[5].data.d_float; - vpvals.direction_mask = param[6].data.d_int32; - vpvals.lower_limit = param[7].data.d_int32; - vpvals.upper_limit = param[8].data.d_int32; - } - else if (strcmp (name, ERODE_PROC) == 0 || - strcmp (name, DILATE_PROC) == 0) - { - vpvals.propagating_channel = PROPAGATING_VALUE; - vpvals.propagating_rate = 1.0; - vpvals.direction_mask = 15; - vpvals.lower_limit = 0; - vpvals.upper_limit = 255; - - if (strcmp (name, ERODE_PROC) == 0) - vpvals.propagate_mode = 1; - else if (strcmp (name, DILATE_PROC) == 0) - vpvals.propagate_mode = 0; - } - break; - - case GIMP_RUN_WITH_LAST_VALS: - gimp_get_data (name, &vpvals); - break; - } - - status = value_propagate (drawable); - - if (status == GIMP_PDB_SUCCESS) - { - if (run_mode != GIMP_RUN_NONINTERACTIVE) - gimp_displays_flush (); - - if (run_mode == GIMP_RUN_INTERACTIVE) - gimp_set_data (name, &vpvals, sizeof (VPValueType)); - } - - values[0].type = GIMP_PDB_STATUS; - values[0].data.d_status = status; -} - -/* registered function entry */ -static GimpPDBStatusType -value_propagate (GimpDrawable *drawable) -{ - /* check the validness of parameters */ - if (!(vpvals.propagating_channel & (PROPAGATING_VALUE | PROPAGATING_ALPHA))) - { - /* gimp_message ("No channel selected."); */ - return GIMP_PDB_EXECUTION_ERROR; - } - if (vpvals.direction_mask == 0) - { - /* gimp_message ("No direction selected."); */ - return GIMP_PDB_EXECUTION_ERROR; - } - if ((vpvals.lower_limit < 0) || (vpvals.lower_limit > 255) || - (vpvals.upper_limit < 0) || (vpvals.upper_limit > 255) || - (vpvals.upper_limit < vpvals.lower_limit)) - { - /* gimp_message ("Limit values are not valid."); */ - return GIMP_PDB_EXECUTION_ERROR; - } - value_propagate_body (drawable, NULL); - return GIMP_PDB_SUCCESS; -} - -static void -value_propagate_body (GimpDrawable *drawable, - GimpPreview *preview) -{ - GimpImageType dtype; - ModeParam operation; - GimpPixelRgn srcRgn, destRgn; - guchar *here, *best, *dest; - guchar *dest_row, *prev_row, *cur_row, *next_row; - guchar *pr, *cr, *nr, *swap; - gint width, height, bytes, index; - gint begx, begy, endx, endy, x, y, dx; - gint left_index, right_index, up_index, down_index; - gpointer tmp; - GimpRGB foreground; - - /* calculate neighbors' indexes */ - left_index = (vpvals.direction_mask & (1 << Left2Right)) ? -1 : 0; - right_index = (vpvals.direction_mask & (1 << Right2Left)) ? 1 : 0; - up_index = (vpvals.direction_mask & (1 << Top2Bottom)) ? -1 : 0; - down_index = (vpvals.direction_mask & (1 << Bottom2Top)) ? 1 : 0; - operation = modes[vpvals.propagate_mode]; - tmp = NULL; - - dtype = gimp_drawable_type (drawable->drawable_id); - bytes = drawable->bpp; - - /* Here I use the algorithm of blur.c */ - if (preview) - { - gimp_preview_get_position (preview, &begx, &begy); - gimp_preview_get_size (preview, &width, &height); - - endx = begx + width; - endy = begy + height; - } - else - { - if (! gimp_drawable_mask_intersect (drawable->drawable_id, - &begx, &begy, &width, &height)) - return; - - endx = begx + width; - endy = begy + height; - } - - gimp_tile_cache_ntiles (2 * ((width) / gimp_tile_width () + 1)); - - prev_row = g_new (guchar, (width + 2) * bytes); - cur_row = g_new (guchar, (width + 2) * bytes); - next_row = g_new (guchar, (width + 2) * bytes); - dest_row = g_new (guchar, width * bytes); - - gimp_pixel_rgn_init (&srcRgn, drawable, - begx, begy, width, height, - FALSE, FALSE); - gimp_pixel_rgn_init (&destRgn, drawable, - begx, begy, width, height, - (preview == NULL), TRUE); - - pr = prev_row + bytes; - cr = cur_row + bytes; - nr = next_row + bytes; - - prepare_row (&srcRgn, pr, begx, (0 < begy) ? begy : begy - 1, endx-begx); - prepare_row (&srcRgn, cr, begx, begy, endx-begx); - - best = g_new (guchar, bytes); - - if (!preview) - gimp_progress_init (_("Value Propagate")); - - gimp_context_get_foreground (&foreground); - gimp_rgb_get_uchar (&foreground, fore+0, fore+1, fore+2); - - /* start real job */ - for (y = begy ; y < endy ; y++) - { - prepare_row (&srcRgn, nr, begx, ((y+1) < endy) ? y+1 : endy, endx-begx); - - for (index = 0; index < (endx - begx) * bytes; index++) - dest_row[index] = cr[index]; - - for (x = 0 ; x < endx - begx; x++) - { - dest = dest_row + (x * bytes); - here = cr + (x * bytes); - - /* *** copy source value to best value holder *** */ - memcpy (best, here, bytes); - - if (operation.initializer) - (* operation.initializer)(dtype, bytes, best, here, &tmp); - - /* *** gather neighbors' values: loop-unfolded version *** */ - if (up_index == -1) - for (dx = left_index ; dx <= right_index ; dx++) - (* operation.updater)(dtype, bytes, here, pr+((x+dx)*bytes), best, tmp); - for (dx = left_index ; dx <= right_index ; dx++) - if (dx != 0) - (* operation.updater)(dtype, bytes, here, cr+((x+dx)*bytes), best, tmp); - if (down_index == 1) - for (dx = left_index ; dx <= right_index ; dx++) - (* operation.updater)(dtype, bytes, here, nr+((x+dx)*bytes), best, tmp); - /* *** store it to dest_row*** */ - (* operation.finalizer)(dtype, bytes, best, here, dest, tmp); - } - - /* now store destline to destRgn */ - gimp_pixel_rgn_set_row (&destRgn, dest_row, begx, y, endx - begx); - - /* shift the row pointers */ - swap = pr; - pr = cr; - cr = nr; - nr = swap; - - - if (((y % 16) == 0) && !preview) - gimp_progress_update ((gdouble) y / (gdouble) (endy - begy)); - } - - if (preview) - { - gimp_drawable_preview_draw_region (GIMP_DRAWABLE_PREVIEW (preview), - &destRgn); - } - else - { - /* update the region */ - gimp_progress_update (1.0); - gimp_drawable_flush (drawable); - gimp_drawable_merge_shadow (drawable->drawable_id, TRUE); - gimp_drawable_update (drawable->drawable_id, begx, begy, endx-begx, endy-begy); - } -} - -static void -prepare_row (GimpPixelRgn *pixel_rgn, - guchar *data, - gint x, - gint y, - gint w) -{ - gint b; - - if (y <= 0) - gimp_pixel_rgn_get_row (pixel_rgn, data, x, (y + 1), w); - else if (y >= pixel_rgn->h) - gimp_pixel_rgn_get_row (pixel_rgn, data, x, (y - 1), w); - else - gimp_pixel_rgn_get_row (pixel_rgn, data, x, y, w); - - /* Fill in edge pixels */ - for (b = 0; b < pixel_rgn->bpp; b++) - { - data[-(gint)pixel_rgn->bpp + b] = data[b]; - data[w * pixel_rgn->bpp + b] = data[(w - 1) * pixel_rgn->bpp + b]; - } -} - -static void -set_value (GimpImageType dtype, - gint bytes, - guchar *best, - guchar *here, - guchar *dest, - void *tmp) -{ - gint value_chs = 0; - gint alpha = 0; - gint ch; - - switch (dtype) - { - case GIMP_RGB_IMAGE: - value_chs = 3; - break; - case GIMP_RGBA_IMAGE: - value_chs = 3; - alpha = 3; - break; - case GIMP_GRAY_IMAGE: - value_chs = 1; - break; - case GIMP_GRAYA_IMAGE: - value_chs = 1; - alpha = 1; - break; - default: - break; - } - for (ch = 0; ch < value_chs; ch++) - { - if (vpvals.propagating_channel & PROPAGATING_VALUE) /* value channel */ - *dest++ = (guchar)(vpvals.propagating_rate * best[ch] - + (1.0 - vpvals.propagating_rate) * here[ch]); - else - *dest++ = here[ch]; - } - if (alpha) - { - if (vpvals.propagating_channel & PROPAGATING_ALPHA) /* alpha channel */ - *dest++ = (guchar)(vpvals.propagating_rate * best[alpha] - + (1.0 - vpvals.propagating_rate) * here[alpha]); - else - *dest++ = here[alpha]; - } -} - -static inline int -value_difference_check (guchar *pos1, - guchar *pos2, - gint ch) -{ - gint index; - int diff; - - for (index = 0 ; index < ch; index++) - if (channel_mask[index] != 0) - { - diff = abs(pos1[index] - pos2[index]); - if (! ((vpvals.lower_limit <= diff) && (diff <= vpvals.upper_limit))) - return 0; - } - return 1; -} - -/* mothods for each mode */ -static void -initialize_white (GimpImageType dtype, - gint bytes, - guchar *best, - guchar *here, - void **tmp) -{ - - switch (dtype) - { - case GIMP_RGB_IMAGE: - case GIMP_RGBA_IMAGE: - if (*tmp == NULL) - *tmp = (void *) g_new (gfloat, 1); - **(float **)tmp = channel_mask[0] * here[0] * here[0] - + channel_mask[1] * here[1] * here[1] - + channel_mask[2] * here[2] * here[2]; - break; - case GIMP_GRAYA_IMAGE: - case GIMP_GRAY_IMAGE: - break; - default: - break; - } -} - -static void -propagate_white (GimpImageType dtype, - gint bytes, - guchar *orig, - guchar *here, - guchar *best, - void *tmp) -{ - float v_here; - - switch (dtype) - { - case GIMP_RGB_IMAGE: - case GIMP_RGBA_IMAGE: - v_here = channel_mask[0] * here[0] * here[0] - + channel_mask[1] * here[1] * here[1] - + channel_mask[2] * here[2] * here[2]; - if (*(float *)tmp < v_here && value_difference_check(orig, here, 3)) - { - *(float *)tmp = v_here; - memcpy(best, here, 3 * sizeof(guchar)); /* alpha channel holds old value */ - } - break; - case GIMP_GRAYA_IMAGE: - case GIMP_GRAY_IMAGE: - if (*best < *here && value_difference_check(orig, here, 1)) - *best = *here; - break; - default: - break; - } -} - -static void -initialize_black (GimpImageType dtype, - gint channels, - guchar *best, - guchar *here, - void **tmp) -{ - switch (dtype) - { - case GIMP_RGB_IMAGE: - case GIMP_RGBA_IMAGE: - if (*tmp == NULL) - *tmp = (void *) g_new (gfloat, 1); - **(float **)tmp = (channel_mask[0] * here[0] * here[0] - + channel_mask[1] * here[1] * here[1] - + channel_mask[2] * here[2] * here[2]); - break; - case GIMP_GRAYA_IMAGE: - case GIMP_GRAY_IMAGE: - break; - default: - break; - } -} - -static void -propagate_black (GimpImageType image_type, - gint channels, - guchar *orig, - guchar *here, - guchar *best, - void *tmp) -{ - float v_here; - - switch (image_type) - { - case GIMP_RGB_IMAGE: - case GIMP_RGBA_IMAGE: - v_here = (channel_mask[0] * here[0] * here[0] - + channel_mask[1] * here[1] * here[1] - + channel_mask[2] * here[2] * here[2]); - if (v_here < *(float *)tmp && value_difference_check(orig, here, 3)) - { - *(float *)tmp = v_here; - memcpy (best, here, 3 * sizeof(guchar)); /* alpha channel holds old value */ - } - break; - case GIMP_GRAYA_IMAGE: - case GIMP_GRAY_IMAGE: - if (*here < *best && value_difference_check(orig, here, 1)) - *best = *here; - break; - default: - break; - } -} - -typedef struct -{ - gshort min_modified; - gshort max_modified; - glong original_value; - glong minv; - guchar min[3]; - glong maxv; - guchar max[3]; -} MiddlePacket; - -static void -initialize_middle (GimpImageType image_type, - gint channels, - guchar *best, - guchar *here, - void **tmp) -{ - int index; - MiddlePacket *data; - - if (*tmp == NULL) - *tmp = (void *) g_new (MiddlePacket, 1); - data = (MiddlePacket *)*tmp; - for (index = 0; index < channels; index++) - data->min[index] = data->max[index] = here[index]; - switch (image_type) - { - case GIMP_RGB_IMAGE: - case GIMP_RGBA_IMAGE: - data->original_value = (channel_mask[0] * here[0] * here[0] - + channel_mask[1] * here[1] * here[1] - + channel_mask[2] * here[2] * here[2]); - break; - case GIMP_GRAYA_IMAGE: - case GIMP_GRAY_IMAGE: - data->original_value = *here; - break; - default: - break; - } - data->minv = data->maxv = data->original_value; - data->min_modified = data->max_modified = 0; -} - -static void -propagate_middle (GimpImageType image_type, - gint channels, - guchar *orig, - guchar *here, - guchar *best, - void *tmp) -{ - float v_here; - MiddlePacket *data; - - data = (MiddlePacket *)tmp; - - switch (image_type) - { - case GIMP_RGB_IMAGE: - case GIMP_RGBA_IMAGE: - v_here = (channel_mask[0] * here[0] * here[0] - + channel_mask[1] * here[1] * here[1] - + channel_mask[2] * here[2] * here[2]); - if ((v_here <= data->minv) && value_difference_check(orig, here, 3)) - { - data->minv = v_here; - memcpy (data->min, here, 3*sizeof(guchar)); - data->min_modified = 1; - } - if (data->maxv <= v_here && value_difference_check(orig, here, 3)) - { - data->maxv = v_here; - memcpy (data->max, here, 3*sizeof(guchar)); - data->max_modified = 1; - } - break; - case GIMP_GRAYA_IMAGE: - case GIMP_GRAY_IMAGE: - if ((*here <= data->min[0]) && value_difference_check(orig, here, 1)) - { - data->min[0] = *here; - data->min_modified = 1; - } - if ((data->max[0] <= *here) && value_difference_check(orig, here, 1)) - { - data->max[0] = *here; - data->max_modified = 1; - } - break; - default: - break; - } -} - -static void -set_middle_to_peak (GimpImageType image_type, - gint channels, - guchar *here, - guchar *best, - guchar *dest, - void *tmp) -{ - gint value_chs = 0; - gint alpha = 0; - gint ch; - MiddlePacket *data; - - data = (MiddlePacket *)tmp; - if (! ((peak_min & (data->minv == data->original_value)) - || (peak_max & (data->maxv == data->original_value)))) - return; - if ((! peak_includes_equals) - && ((peak_min & (! data->min_modified)) - || (peak_max & (! data->max_modified)))) - return; - - switch (image_type) - { - case GIMP_RGB_IMAGE: - value_chs = 3; - break; - case GIMP_RGBA_IMAGE: - value_chs = 3; - alpha = 3; - break; - case GIMP_GRAY_IMAGE: - value_chs = 1; - break; - case GIMP_GRAYA_IMAGE: - value_chs = 1; - alpha = 1; - break; - default: - break; - } - for (ch = 0; ch < value_chs; ch++) - { - if (vpvals.propagating_channel & PROPAGATING_VALUE) /* value channel */ - *dest++ = (guchar)(vpvals.propagating_rate * 0.5 * (data->min[ch] + data->max[ch]) - + (1.0 - vpvals.propagating_rate) * here[ch]); - else - *dest++ = here[ch]; - } - if (alpha) - { - if (vpvals.propagating_channel & PROPAGATING_ALPHA) /* alpha channel */ - *dest++ = (guchar)(vpvals.propagating_rate * best[alpha] - + (1.0 - vpvals.propagating_rate) * here[alpha]); - else - *dest++ = here[alpha]; - } -} - -static void -set_foreground_to_peak (GimpImageType image_type, - gint channels, - guchar *here, - guchar *best, - guchar *dest, - void *tmp) -{ - gint value_chs = 0; - gint ch; - MiddlePacket *data; - - data = (MiddlePacket *)tmp; - if (! ((peak_min & (data->minv == data->original_value)) - || (peak_max & (data->maxv == data->original_value)))) - return; - if (peak_includes_equals - && ((peak_min & (! data->min_modified)) - || (peak_max & (! data->max_modified)))) - return; - - switch (image_type) - { - case GIMP_RGB_IMAGE: - value_chs = 3; - break; - case GIMP_RGBA_IMAGE: - value_chs = 3; - break; - case GIMP_GRAY_IMAGE: - value_chs = 1; - break; - case GIMP_GRAYA_IMAGE: - value_chs = 1; - break; - default: - break; - } - for (ch = 0; ch < value_chs; ch++) - { - if (vpvals.propagating_channel & PROPAGATING_VALUE) /* value channel */ - *dest++ = (guchar)(vpvals.propagating_rate*fore[ch] - + (1.0 - vpvals.propagating_rate)*here[ch]); - else - *dest++ = here[ch]; - } -} - -static void -initialize_foreground (GimpImageType image_type, - gint channels, - guchar *here, - guchar *best, - void **tmp) -{ - GimpRGB foreground; - guchar *ch; - - if (*tmp == NULL) - { - *tmp = (void *) g_new (guchar, 3); - ch = (guchar *)*tmp; - gimp_context_get_foreground (&foreground); - gimp_rgb_get_uchar (&foreground, &ch[0], &ch[1], &ch[2]); - } -} - -static void -initialize_background (GimpImageType image_type, - gint channels, - guchar *here, - guchar *best, - void **tmp) -{ - GimpRGB background; - guchar *ch; - - if (*tmp == NULL) - { - *tmp = (void *) g_new (guchar, 3); - ch = (guchar *)*tmp; - gimp_context_get_background (&background); - gimp_rgb_get_uchar (&background, &ch[0], &ch[1], &ch[2]); - } -} - -static void -propagate_a_color (GimpImageType image_type, - gint channels, - guchar *orig, - guchar *here, - guchar *best, - void *tmp) -{ - guchar *fg = (guchar *)tmp; - - switch (image_type) - { - case GIMP_RGB_IMAGE: - case GIMP_RGBA_IMAGE: - if (here[0] == fg[0] && here[1] == fg[1] && here[2] == fg[2] && - value_difference_check(orig, here, 3)) - { - memcpy (best, here, 3 * sizeof(guchar)); /* alpha channel holds old value */ - } - break; - case GIMP_GRAYA_IMAGE: - case GIMP_GRAY_IMAGE: - break; - default: - break; - } -} - -static void -propagate_opaque (GimpImageType image_type, - gint channels, - guchar *orig, - guchar *here, - guchar *best, - void *tmp) -{ - switch (image_type) - { - case GIMP_RGBA_IMAGE: - if (best[3] < here[3] && value_difference_check(orig, here, 3)) - memcpy(best, here, channels * sizeof(guchar)); - break; - case GIMP_GRAYA_IMAGE: - if (best[1] < here[1] && value_difference_check(orig, here, 1)) - memcpy(best, here, channels * sizeof(guchar)); - break; - default: - break; - } -} - -static void -propagate_transparent (GimpImageType image_type, - gint channels, - guchar *orig, - guchar *here, - guchar *best, - void *tmp) -{ - switch (image_type) - { - case GIMP_RGBA_IMAGE: - if (here[3] < best[3] && value_difference_check(orig, here, 3)) - memcpy(best, here, channels * sizeof(guchar)); - break; - case GIMP_GRAYA_IMAGE: - if (here[1] < best[1] && value_difference_check(orig, here, 1)) - memcpy(best, here, channels * sizeof(guchar)); - break; - default: - break; - } -} - -/* dialog stuff */ - -static gboolean -vpropagate_dialog (GimpDrawable *drawable) -{ - GtkWidget *dialog; - GtkWidget *main_vbox; - GtkWidget *hbox; - GtkWidget *frame; - GtkWidget *table; - GtkWidget *toggle_vbox; - GtkWidget *button; - GtkObject *adj; - GSList *group = NULL; - gint index = 0; - gboolean run; - - gimp_ui_init (PLUG_IN_BINARY, FALSE); - - dialog = gimp_dialog_new (_("Value Propagate"), PLUG_IN_ROLE, - NULL, 0, - gimp_standard_help_func, VPROPAGATE_PROC, - - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_OK, GTK_RESPONSE_OK, - - NULL); - - gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog), - GTK_RESPONSE_OK, - GTK_RESPONSE_CANCEL, - -1); - - gimp_window_set_transient (GTK_WINDOW (dialog)); - - main_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12); - gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12); - gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), - main_vbox, TRUE, TRUE, 0); - gtk_widget_show (main_vbox); - - preview = gimp_drawable_preview_new (drawable, NULL); - gtk_box_pack_start (GTK_BOX (main_vbox), preview, TRUE, TRUE, 0); - gtk_widget_show (preview); - - g_signal_connect_swapped (preview, "invalidated", - G_CALLBACK (value_propagate_body), - drawable); - - hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12); - gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, FALSE, 0); - gtk_widget_show (hbox); - - /* Propagate Mode */ - frame = gimp_frame_new (_("Mode")); - gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, FALSE, 0); - gtk_widget_show (frame); - - toggle_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2); - gtk_container_add (GTK_CONTAINER (frame), toggle_vbox); - gtk_widget_show (toggle_vbox); - - for (index = 0; index < num_mode; index++) - { - button = - gtk_radio_button_new_with_mnemonic (group, - gettext (modes[index].name)); - group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (button)); - gtk_box_pack_start (GTK_BOX (toggle_vbox), button, FALSE, FALSE, 0); - gtk_widget_show (button); - - g_object_set_data (G_OBJECT (button), "gimp-item-data", - GINT_TO_POINTER (index)); - - g_signal_connect (button, "toggled", - G_CALLBACK (gimp_radio_button_update), - &vpvals.propagate_mode); - g_signal_connect_swapped (button, "toggled", - G_CALLBACK (gimp_preview_invalidate), - preview); - - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), - index == vpvals.propagate_mode); - } - - /* Parameter settings */ - frame = gimp_frame_new (_("Propagate")); - gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, FALSE, 0); - gtk_widget_show (frame); - - table = gtk_table_new (8, 3, FALSE); /* 4 raw, 2 columns(name and value) */ - gtk_table_set_col_spacings (GTK_TABLE (table), 6); - gtk_table_set_row_spacings (GTK_TABLE (table), 6); - gtk_table_set_row_spacing (GTK_TABLE (table), 2, 12); - gtk_table_set_row_spacing (GTK_TABLE (table), 5, 12); - gtk_container_add (GTK_CONTAINER (frame), table); - gtk_widget_show (table); - - adj = gimp_scale_entry_new (GTK_TABLE (table), 0, 0, - _("Lower t_hreshold:"), SCALE_WIDTH, 4, - vpvals.lower_limit, 0, 255, 1, 8, 0, - TRUE, 0, 0, - NULL, NULL); - g_signal_connect (adj, "value-changed", - G_CALLBACK (gimp_int_adjustment_update), - &vpvals.lower_limit); - g_signal_connect_swapped (adj, "value-changed", - G_CALLBACK (gimp_preview_invalidate), - preview); - - adj = gimp_scale_entry_new (GTK_TABLE (table), 0, 1, - _("_Upper threshold:"), SCALE_WIDTH, 4, - vpvals.upper_limit, 0, 255, 1, 8, 0, - TRUE, 0, 0, - NULL, NULL); - g_signal_connect (adj, "value-changed", - G_CALLBACK (gimp_int_adjustment_update), - &vpvals.upper_limit); - g_signal_connect_swapped (adj, "value-changed", - G_CALLBACK (gimp_preview_invalidate), - preview); - - adj = gimp_scale_entry_new (GTK_TABLE (table), 0, 2, - _("_Propagating rate:"), SCALE_WIDTH, 4, - vpvals.propagating_rate, 0, 1, 0.01, 0.1, 2, - TRUE, 0, 0, - NULL, NULL); - g_signal_connect (adj, "value-changed", - G_CALLBACK (gimp_double_adjustment_update), - &vpvals.propagating_rate); - g_signal_connect_swapped (adj, "value-changed", - G_CALLBACK (gimp_preview_invalidate), - preview); - - gtk_table_add_toggle (table, _("To l_eft"), 0, 1, 4, - G_CALLBACK (vpropagate_toggle_button_update), - &direction_mask_vec[Right2Left]); - gtk_table_add_toggle (table, _("To _right"), 2, 3, 4, - G_CALLBACK (vpropagate_toggle_button_update), - &direction_mask_vec[Left2Right]); - gtk_table_add_toggle (table, _("To _top"), 1, 2, 3, - G_CALLBACK (vpropagate_toggle_button_update), - &direction_mask_vec[Bottom2Top]); - gtk_table_add_toggle (table, _("To _bottom"), 1, 2, 5, - G_CALLBACK (vpropagate_toggle_button_update), - &direction_mask_vec[Top2Bottom]); - - if (gimp_drawable_has_alpha (drawable->drawable_id)) - { - GtkWidget *toggle; - - toggle = - gtk_table_add_toggle (table, _("Propagating _alpha channel"), - 0, 3, 6, - G_CALLBACK (vpropagate_toggle_button_update), - &propagate_alpha); - - if (gimp_layer_get_lock_alpha (drawable->drawable_id)) - { - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), 0); - gtk_widget_set_sensitive (toggle, FALSE); - } - - gtk_table_add_toggle (table, _("Propagating value channel"), 0, 3, 7, - G_CALLBACK (vpropagate_toggle_button_update), - &propagate_value); - } - - gtk_widget_show (dialog); - - run = (gimp_dialog_run (GIMP_DIALOG (dialog)) == GTK_RESPONSE_OK); - - if (run) - { - gint i, result; - - for (i = result = 0; i < 4; i++) - result |= (direction_mask_vec[i] ? 1 : 0) << i; - vpvals.direction_mask = result; - - vpvals.propagating_channel = ((propagate_alpha ? PROPAGATING_ALPHA : 0) | - (propagate_value ? PROPAGATING_VALUE : 0)); - } - - gtk_widget_destroy (dialog); - - return run; -} - -static void -vpropagate_toggle_button_update (GtkWidget *widget, - gpointer data) -{ - gint i, result; - - gimp_toggle_button_update (widget, data); - - for (i = result = 0; i < 4; i++) - result |= (direction_mask_vec[i] ? 1 : 0) << i; - vpvals.direction_mask = result; - - vpvals.propagating_channel = ((propagate_alpha ? PROPAGATING_ALPHA : 0) | - (propagate_value ? PROPAGATING_VALUE : 0)); - gimp_preview_invalidate (GIMP_PREVIEW (preview)); -} - -static GtkWidget * -gtk_table_add_toggle (GtkWidget *table, - const gchar *name, - gint x1, - gint x2, - gint y, - GCallback update, - gint *value) -{ - GtkWidget *toggle; - - toggle = gtk_check_button_new_with_mnemonic(name); - gtk_table_attach (GTK_TABLE (table), toggle, x1, x2, y, y+1, - GTK_FILL|GTK_EXPAND, 0, 0, 0); - gtk_widget_show (toggle); - - g_signal_connect (toggle, "toggled", - G_CALLBACK (update), - value); - - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), *value); - - return toggle; -} diff --git a/po-plug-ins/POTFILES.in b/po-plug-ins/POTFILES.in index 013d64bb08..90fc65e9dd 100644 --- a/po-plug-ins/POTFILES.in +++ b/po-plug-ins/POTFILES.in @@ -101,7 +101,6 @@ plug-ins/common/tile-paper.c plug-ins/common/tile-small.c plug-ins/common/unit-editor.c plug-ins/common/unsharp-mask.c -plug-ins/common/value-propagate.c plug-ins/common/van-gogh-lic.c plug-ins/common/warp.c plug-ins/common/web-browser.c diff --git a/tools/pdbgen/pdb/plug_in_compat.pdb b/tools/pdbgen/pdb/plug_in_compat.pdb index d8531c9b9a..be942e2f02 100644 --- a/tools/pdbgen/pdb/plug_in_compat.pdb +++ b/tools/pdbgen/pdb/plug_in_compat.pdb @@ -3215,6 +3215,246 @@ CODE ); } +sub plug_in_vpropagate { + $blurb = 'Propagate certain colors to neighboring pixels', + + $help = <<'HELP'; +Propagate values of the layer. +HELP + + &std_pdb_compat('gegl:value-propagate'); + $date = '2015'; + + @inargs = ( + { name => 'run_mode', type => 'enum GimpRunMode', dead => 1, + desc => 'The run mode' }, + { name => 'image', type => 'image', dead => 1, + desc => 'Input image (unused)' }, + { name => 'drawable', type => 'drawable', + desc => 'Input drawable' }, + { name => 'propagate_mode', type => '0 <= int32 <= 7', + desc => 'Propagate mode { 0:white, 1:black, 2:middle value 3:foreground to peak, 4:foreground, 5:background, 6:opaque, 7:transparent }' }, + { name => 'propagating_channel', type => 'int32', + desc => 'Channels which values are propagated' }, + { name => 'propagating_rate', type => '0.0 <= float <= 1.0', + desc => 'Propagating rate' }, + { name => 'direction_mask', type => '0 <= int32 <= 15', + desc => 'Direction mask' }, + { name => 'lower_limit', type => '0 <= int32 <= 255', + desc => 'Lower limit' }, + { name => 'upper_limit', type => '0 <= int32 <= 255', + desc => 'Upper limit' } + ); + + %invoke = ( + code => <<'CODE' +{ + if (gimp_pdb_item_is_attached (GIMP_ITEM (drawable), NULL, + GIMP_PDB_ITEM_CONTENT, error) && + gimp_pdb_item_is_not_group (GIMP_ITEM (drawable), error)) + { + GeglNode *node; + GimpRGB color; + GeglColor *gegl_color = NULL; + gint gegl_mode = 0; + gboolean to_left = (direction_mask & (0x1 << 0)) != 0; + gboolean to_top = (direction_mask & (0x1 << 1)) != 0; + gboolean to_right = (direction_mask & (0x1 << 2)) != 0; + gboolean to_bottom = (direction_mask & (0x1 << 3)) != 0; + gboolean value = (propagating_channel & (0x1 << 0)) != 0; + gboolean alpha = (propagating_channel & (0x1 << 1)) != 0; + + switch (propagate_mode) + { + case 0: + case 1: + case 2: + gegl_mode = propagate_mode; + break; + + case 3: + gegl_mode = propagate_mode; + /* fall thru */ + + case 4: + case 5: + gegl_mode = 4; + + if (propagate_mode != 3) + gimp_context_get_foreground (context, &color); + else + gimp_context_get_background (context, &color); + + gegl_color = gimp_gegl_color_new (&color); + break; + + case 6: + case 7: + gegl_mode = propagate_mode - 1; + break; + } + + node = + gegl_node_new_child (NULL, + "operation", "gegl:value-propagate", + "mode", gegl_mode, + "lower-threshold", (gdouble) lower_limit / 255.0, + "upper-threshold", (gdouble) upper_limit / 255.0, + "rate", propagating_rate, + "color", gegl_color, + "top", to_top, + "left", to_left, + "right", to_right, + "bottom", to_bottom, + "value", value, + "alpha", alpha, + NULL); + + if (gegl_color) + g_object_unref (gegl_color); + + gimp_drawable_apply_operation (drawable, progress, + C_("undo-type", "Value Propagate"), + node); + g_object_unref (node); + } + else + success = FALSE; +} +CODE + ); +} + +sub plug_in_dilate { + $blurb = 'Grow lighter areas of the image', + + $help = <<'HELP'; +Dilate image. +HELP + + &std_pdb_compat('gegl:value-propagate'); + $date = '2015'; + + @inargs = ( + { name => 'run_mode', type => 'enum GimpRunMode', dead => 1, + desc => 'The run mode' }, + { name => 'image', type => 'image', dead => 1, + desc => 'Input image (unused)' }, + { name => 'drawable', type => 'drawable', + desc => 'Input drawable' }, + { name => 'propagate_mode', type => '0 <= int32 <= 7', dead => 1, + desc => 'Propagate mode { 0:white, 1:black, 2:middle value 3:foreground to peak, 4:foreground, 5:background, 6:opaque, 7:transparent }' }, + { name => 'propagating_channel', type => 'int32', dead => 1, + desc => 'Channels which values are propagated' }, + { name => 'propagating_rate', type => '0.0 <= float <= 1.0', dead => 1, + desc => 'Propagating rate' }, + { name => 'direction_mask', type => '0 <= int32 <= 15', dead => 1, + desc => 'Direction mask' }, + { name => 'lower_limit', type => '0 <= int32 <= 255', dead => 1, + desc => 'Lower limit' }, + { name => 'upper_limit', type => '0 <= int32 <= 255', dead => 1, + desc => 'Upper limit' } + ); + + %invoke = ( + code => <<'CODE' +{ + if (gimp_pdb_item_is_attached (GIMP_ITEM (drawable), NULL, + GIMP_PDB_ITEM_CONTENT, error) && + gimp_pdb_item_is_not_group (GIMP_ITEM (drawable), error)) + { + GeglNode *node = + gegl_node_new_child (NULL, + "operation", "gegl:value-propagate", + "mode", 0, /* GEGL_VALUE_PROPAGATE_MODE_WHITE */ + "lower-threshold", 0.0, + "upper-threshold", 1.0, + "rate", 1.0, + "top", TRUE, + "left", TRUE, + "right", TRUE, + "bottom", TRUE, + "value", TRUE, + "alpha", FALSE, + NULL); + + gimp_drawable_apply_operation (drawable, progress, + C_("undo-type", "Dilate"), + node); + g_object_unref (node); + } + else + success = FALSE; +} +CODE + ); +} + +sub plug_in_erode { + $blurb = 'Shrink lighter areas of the image', + + $help = <<'HELP'; +Erode image. +HELP + + &std_pdb_compat('gegl:value-propagate'); + $date = '2015'; + + @inargs = ( + { name => 'run_mode', type => 'enum GimpRunMode', dead => 1, + desc => 'The run mode' }, + { name => 'image', type => 'image', dead => 1, + desc => 'Input image (unused)' }, + { name => 'drawable', type => 'drawable', + desc => 'Input drawable' }, + { name => 'propagate_mode', type => '0 <= int32 <= 7', dead => 1, + desc => 'Propagate mode { 0:white, 1:black, 2:middle value 3:foreground to peak, 4:foreground, 5:background, 6:opaque, 7:transparent }' }, + { name => 'propagating_channel', type => 'int32', dead => 1, + desc => 'Channels which values are propagated' }, + { name => 'propagating_rate', type => '0.0 <= float <= 1.0', dead => 1, + desc => 'Propagating rate' }, + { name => 'direction_mask', type => '0 <= int32 <= 15', dead => 1, + desc => 'Direction mask' }, + { name => 'lower_limit', type => '0 <= int32 <= 255', dead => 1, + desc => 'Lower limit' }, + { name => 'upper_limit', type => '0 <= int32 <= 255', dead => 1, + desc => 'Upper limit' } + ); + + %invoke = ( + code => <<'CODE' +{ + if (gimp_pdb_item_is_attached (GIMP_ITEM (drawable), NULL, + GIMP_PDB_ITEM_CONTENT, error) && + gimp_pdb_item_is_not_group (GIMP_ITEM (drawable), error)) + { + GeglNode *node = + gegl_node_new_child (NULL, + "operation", "gegl:value-propagate", + "mode", 1, /* GEGL_VALUE_PROPAGATE_MODE_BLACK */ + "lower-threshold", 0.0, + "upper-threshold", 1.0, + "rate", 1.0, + "top", TRUE, + "left", TRUE, + "right", TRUE, + "bottom", TRUE, + "value", TRUE, + "alpha", FALSE, + NULL); + + gimp_drawable_apply_operation (drawable, progress, + C_("undo-type", "Erode"), + node); + g_object_unref (node); + } + else + success = FALSE; +} +CODE + ); +} + sub plug_in_waves { $blurb = 'Distort the image with waves'; @@ -3559,6 +3799,9 @@ CODE plug_in_threshold_alpha plug_in_video plug_in_vinvert + plug_in_vpropagate + plug_in_dilate + plug_in_erode plug_in_waves plug_in_whirl_pinch);