diff --git a/app/pdb/internal-procs.c b/app/pdb/internal-procs.c index 3ae9b07dd3..96a9e83284 100644 --- a/app/pdb/internal-procs.c +++ b/app/pdb/internal-procs.c @@ -28,7 +28,7 @@ #include "internal-procs.h" -/* 690 procedures registered total */ +/* 692 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 051c6aa898..c49c8bd14c 100644 --- a/app/pdb/plug-in-compat-cmds.c +++ b/app/pdb/plug-in-compat-cmds.c @@ -259,6 +259,164 @@ plug_in_cubism_invoker (GimpProcedure *procedure, error ? *error : NULL); } +static GimpValueArray * +plug_in_mblur_invoker (GimpProcedure *procedure, + Gimp *gimp, + GimpContext *context, + GimpProgress *progress, + const GimpValueArray *args, + GError **error) +{ + gboolean success = TRUE; + GimpDrawable *drawable; + gint32 type; + gdouble length; + gdouble angle; + gdouble center_x; + gdouble center_y; + + drawable = gimp_value_get_drawable (gimp_value_array_index (args, 2), gimp); + type = g_value_get_int (gimp_value_array_index (args, 3)); + length = g_value_get_double (gimp_value_array_index (args, 4)); + angle = g_value_get_double (gimp_value_array_index (args, 5)); + center_x = g_value_get_double (gimp_value_array_index (args, 6)); + center_y = g_value_get_double (gimp_value_array_index (args, 7)); + + 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 = NULL; + + if (type == 0) + { + node = gegl_node_new_child (NULL, + "operation", "gegl:motion-blur-linear", + "length", length, + "angle", angle, + NULL); + } + else if (type == 1) + { + node = gegl_node_new_child (NULL, + "operation", "gegl:motion-blur-circular", + "center-x", center_x, + "center-y", center_y, + "angle", angle, + NULL); + } + else if (type == 2) + { + gdouble factor = CLAMP (length / 256.0, 0.0, 1.0); + node = gegl_node_new_child (NULL, + "operation", "gegl:motion-blur-zoom", + "center-x", center_x, + "center-y", center_y, + "factor", factor, + NULL); + } + + if (node != NULL) + { + gimp_drawable_apply_operation (drawable, progress, + C_("undo-type", "Motion Blur"), + node); + + g_object_unref (node); + } + else + success = FALSE; + + } + else + success = FALSE; + } + + return gimp_procedure_get_return_values (procedure, success, + error ? *error : NULL); +} + +static GimpValueArray * +plug_in_mblur_inward_invoker (GimpProcedure *procedure, + Gimp *gimp, + GimpContext *context, + GimpProgress *progress, + const GimpValueArray *args, + GError **error) +{ + gboolean success = TRUE; + GimpDrawable *drawable; + gint32 type; + gdouble length; + gdouble angle; + gdouble center_x; + gdouble center_y; + + drawable = gimp_value_get_drawable (gimp_value_array_index (args, 2), gimp); + type = g_value_get_int (gimp_value_array_index (args, 3)); + length = g_value_get_double (gimp_value_array_index (args, 4)); + angle = g_value_get_double (gimp_value_array_index (args, 5)); + center_x = g_value_get_double (gimp_value_array_index (args, 6)); + center_y = g_value_get_double (gimp_value_array_index (args, 7)); + + 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 = NULL; + + if (type == 0) + { + node = gegl_node_new_child (NULL, + "operation", "gegl:motion-blur-linear", + "length", length, + "angle", angle, + NULL); + } + else if (type == 1) + { + node = gegl_node_new_child (NULL, + "operation", "gegl:motion-blur-circular", + "center-x", center_x, + "center-y", center_y, + "angle", angle, + NULL); + } + else if (type == 2) + { + gdouble factor = CLAMP (-length / (256.0 - length), -10.0, 0.0); + node = gegl_node_new_child (NULL, + "operation", "gegl:motion-blur-zoom", + "center-x", center_x, + "center-y", center_y, + "factor", factor, + NULL); + } + + if (node != NULL) + { + gimp_drawable_apply_operation (drawable, progress, + C_("undo-type", "Motion Blur"), + node); + + g_object_unref (node); + } + else + success = FALSE; + + } + else + success = FALSE; + } + + return gimp_procedure_get_return_values (procedure, success, + error ? *error : NULL); +} + static GimpValueArray * plug_in_pixelize_invoker (GimpProcedure *procedure, Gimp *gimp, @@ -1100,6 +1258,138 @@ register_plug_in_compat_procs (GimpPDB *pdb) gimp_pdb_register_procedure (pdb, procedure); g_object_unref (procedure); + /* + * gimp-plug-in-mblur + */ + procedure = gimp_procedure_new (plug_in_mblur_invoker); + gimp_object_set_static_name (GIMP_OBJECT (procedure), + "plug-in-mblur"); + gimp_procedure_set_static_strings (procedure, + "plug-in-mblur", + "Simulate movement using directional blur", + "This plug-in simulates the effect seen when photographing a moving object at a slow shutter speed. Done by adding multiple displaced copies.", + "Compatibility procedure. Please see 'gegl:motion-blur-linear, -zoom, -cirular' for credits.", + "Compatibility procedure. Please see 'gegl:motion-blur-linear, -zoom, -cirular' for credits.", + "2013", + 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 ("type", + "type", + "Type of motion blur { LINEAR (0), RADIAL (1), ZOOM (2) }", + 0, 2, 0, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + g_param_spec_double ("length", + "length", + "Length", + -G_MAXDOUBLE, G_MAXDOUBLE, 0, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + g_param_spec_double ("angle", + "angle", + "Angle", + 0, 360, 0, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + g_param_spec_double ("center-x", + "center x", + "Center X", + -G_MAXDOUBLE, G_MAXDOUBLE, 0, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + g_param_spec_double ("center-y", + "center y", + "Center Y", + -G_MAXDOUBLE, G_MAXDOUBLE, 0, + GIMP_PARAM_READWRITE)); + gimp_pdb_register_procedure (pdb, procedure); + g_object_unref (procedure); + + /* + * gimp-plug-in-mblur-inward + */ + procedure = gimp_procedure_new (plug_in_mblur_inward_invoker); + gimp_object_set_static_name (GIMP_OBJECT (procedure), + "plug-in-mblur-inward"); + gimp_procedure_set_static_strings (procedure, + "plug-in-mblur-inward", + "Simulate movement using directional blur", + "This procedure is equivalent to plug-in-mblur but performs the zoom blur inward instead of outward.", + "Compatibility procedure. Please see 'gegl:motion-blur-linear, -zoom, -cirular' for credits.", + "Compatibility procedure. Please see 'gegl:motion-blur-linear, -zoom, -cirular' for credits.", + "2013", + 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 ("type", + "type", + "Type of motion blur { LINEAR (0), RADIAL (1), ZOOM (2) }", + 0, 2, 0, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + g_param_spec_double ("length", + "length", + "Length", + -G_MAXDOUBLE, G_MAXDOUBLE, 0, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + g_param_spec_double ("angle", + "angle", + "Angle", + 0, 360, 0, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + g_param_spec_double ("center-x", + "center x", + "Center X", + -G_MAXDOUBLE, G_MAXDOUBLE, 0, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + g_param_spec_double ("center-y", + "center y", + "Center Y", + -G_MAXDOUBLE, G_MAXDOUBLE, 0, + GIMP_PARAM_READWRITE)); + gimp_pdb_register_procedure (pdb, procedure); + g_object_unref (procedure); + /* * gimp-plug-in-pixelize */ diff --git a/plug-ins/common/.gitignore b/plug-ins/common/.gitignore index c240c4633f..d6db89a77a 100644 --- a/plug-ins/common/.gitignore +++ b/plug-ins/common/.gitignore @@ -22,8 +22,6 @@ /blur-gauss.exe /blur-gauss-selective /blur-gauss-selective.exe -/blur-motion -/blur-motion.exe /border-average /border-average.exe /bump-map diff --git a/plug-ins/common/Makefile.am b/plug-ins/common/Makefile.am index c983dff5da..85aeb995ff 100644 --- a/plug-ins/common/Makefile.am +++ b/plug-ins/common/Makefile.am @@ -54,7 +54,6 @@ libexec_PROGRAMS = \ blur \ blur-gauss \ blur-gauss-selective \ - blur-motion \ border-average \ bump-map \ cartoon \ @@ -377,23 +376,6 @@ blur_gauss_selective_LDADD = \ $(INTLLIBS) \ $(blur_gauss_selective_RC) -blur_motion_SOURCES = \ - blur-motion.c - -blur_motion_LDADD = \ - $(libgimpui) \ - $(libgimpwidgets) \ - $(libgimpmodule) \ - $(libgimp) \ - $(libgimpmath) \ - $(libgimpconfig) \ - $(libgimpcolor) \ - $(libgimpbase) \ - $(GTK_LIBS) \ - $(RT_LIBS) \ - $(INTLLIBS) \ - $(blur_motion_RC) - border_average_SOURCES = \ border-average.c @@ -722,7 +704,6 @@ decompose_LDADD = \ $(libgimpcolor) \ $(libgimpbase) \ $(GTK_LIBS) \ - $(GEGL_LIBS) \ $(RT_LIBS) \ $(INTLLIBS) \ $(decompose_RC) diff --git a/plug-ins/common/blur-motion.c b/plug-ins/common/blur-motion.c deleted file mode 100644 index bed7d9d63d..0000000000 --- a/plug-ins/common/blur-motion.c +++ /dev/null @@ -1,1160 +0,0 @@ -/* GIMP - The GNU Image Manipulation Program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * Motion Blur plug-in for GIMP 0.99 - * Copyright (C) 1997 Daniel Skarda (0rfelyus@atrey.karlin.mff.cuni.cz) - * - * This plug-in is port of Motion Blur plug-in for GIMP 0.54 by - * Thorsten Martinsen - * Copyright (C) 1996 Torsten Martinsen - * Bresenham algorithm stuff hacked from HP2xx written by - * Heinz W. Werntges - * Changes for version 1.11/1.12 Copyright (C) 1996 Federico Mena Quintero - * quartic@polloux.fciencias.unam.mx - * - * I also used some code from Whirl and Pinch plug-in by Federico Mena Quintero - * (federico@nuclecu.unam.mx) - * - * Copyright (C) 2007 Joerg Gittinger (sw@gittingerbox.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 . - */ - -#include "config.h" - -#include - -#include -#include - -#include "libgimp/stdplugins-intl.h" - - -#define PLUG_IN_PROC "plug-in-mblur" -#define PLUG_IN_PROC_INWARD "plug-in-mblur-inward" -#define PLUG_IN_BINARY "blur-motion" -#define PLUG_IN_ROLE "gimp-blur-motion" -#define PLUG_IN_VERSION "May 2007, 1.3" - - -#define MBLUR_LENGTH_MAX 256.0 - - -typedef enum -{ - MBLUR_LINEAR, - MBLUR_RADIAL, - MBLUR_ZOOM, - MBLUR_MAX = MBLUR_ZOOM -} MBlurType; - - -typedef struct -{ - gint32 mblur_type; - gint32 length; - gint32 angle; - gdouble center_x; - gdouble center_y; - gboolean blur_outward; -} mblur_vals_t; - - -/***** Prototypes *****/ - -static void query (void); -static void run (const gchar *name, - gint nparams, - const GimpParam *param, - gint *nreturn_vals, - GimpParam **return_vals); - -static void mblur (GimpDrawable *drawable, - GimpPreview *preview); -static void mblur_linear (GimpDrawable *drawable, - GimpPreview *preview, - gint x1, - gint y1, - gint width, - gint height); -static void mblur_radial (GimpDrawable *drawable, - GimpPreview *preview, - gint x1, - gint y1, - gint width, - gint height); -static void mblur_zoom (GimpDrawable *drawable, - GimpPreview *preview, - gint x1, - gint y1, - gint width, - gint height); - -static gboolean mblur_dialog (gint32 image_ID, - GimpDrawable *drawable); - -/***** Variables *****/ - -const GimpPlugInInfo PLUG_IN_INFO = -{ - NULL, /* init_proc */ - NULL, /* quit_proc */ - query, /* query_proc */ - run /* run_proc */ -}; - -static mblur_vals_t mbvals = -{ - MBLUR_LINEAR, /* mblur_type */ - 5, /* length */ - 10, /* radius */ - 100000.0, /* center_x */ - 100000.0, /* center_y */ - TRUE /* blur_outward */ -}; - - -static GtkObject *length = NULL; -static GtkObject *angle = NULL; -static GtkWidget *center = NULL; -static GtkWidget *dir_button = NULL; -static GtkWidget *preview = NULL; - -static gint img_width, img_height, img_bpp; -static gboolean has_alpha; - -/***** Functions *****/ - -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" }, - { GIMP_PDB_DRAWABLE, "drawable", "Input drawable" }, - { GIMP_PDB_INT32, "type", "Type of motion blur { LINEAR (0), RADIAL (1), ZOOM (2) }" }, - { GIMP_PDB_INT32, "length", "Length" }, - { GIMP_PDB_INT32, "angle", "Angle" }, - { GIMP_PDB_FLOAT, "center-x", "Center X (optional)" }, - { GIMP_PDB_FLOAT, "center-y", "Center Y (optional)" }, - }; - - gimp_install_procedure (PLUG_IN_PROC, - N_("Simulate movement using directional blur"), - "This plug-in simulates the effect seen when " - "photographing a moving object at a slow shutter " - "speed. Done by adding multiple displaced copies.", - "Torsten Martinsen, Federico Mena Quintero, Daniel Skarda, Joerg Gittinger", - "Torsten Martinsen, Federico Mena Quintero, Daniel Skarda, Joerg Gittinger", - PLUG_IN_VERSION, - N_("_Motion Blur..."), - "RGB*, GRAY*", - GIMP_PLUGIN, - G_N_ELEMENTS (args), 0, - args, NULL); - - gimp_install_procedure (PLUG_IN_PROC_INWARD, - N_("Simulate movement using directional blur"), - "This procedure is equivalent to plug-in-mblur but " - "performs the zoom blur inward instead of outward.", - "Torsten Martinsen, Federico Mena Quintero, Daniel Skarda, Joerg Gittinger", - "Torsten Martinsen, Federico Mena Quintero, Daniel Skarda, Joerg Gittinger", - PLUG_IN_VERSION, - N_("_Motion Blur..."), - "RGB*, GRAY*", - GIMP_PLUGIN, - G_N_ELEMENTS (args), 0, - args, NULL); - - gimp_plugin_menu_register (PLUG_IN_PROC, "/Filters/Blur"); -} - -static void -run (const gchar *name, - gint nparams, - const GimpParam *param, - gint *nreturn_vals, - GimpParam **return_vals) -{ - static GimpParam values[1]; - GimpRunMode run_mode; - GimpPDBStatusType status; - GimpDrawable *drawable; - gint x1, y1, x2, y2; - - INIT_I18N (); - - status = GIMP_PDB_SUCCESS; - run_mode = param[0].data.d_int32; - - *nreturn_vals = 1; - *return_vals = values; - - values[0].type = GIMP_PDB_STATUS; - values[0].data.d_status = status; - - /* Get the active drawable info */ - - drawable = gimp_drawable_get (param[2].data.d_drawable); - - img_width = gimp_drawable_width (drawable->drawable_id); - img_height = gimp_drawable_height (drawable->drawable_id); - img_bpp = gimp_drawable_bpp (drawable->drawable_id); - - gimp_drawable_mask_bounds (drawable->drawable_id, &x1, &y1, &x2, &y2); - - mbvals.center_x = (gdouble) (x1 + x2 - 1) / 2.0; - mbvals.center_y = (gdouble) (y1 + y2 - 1) / 2.0; - - /* Set the tile cache size */ - gimp_tile_cache_ntiles (2 * drawable->ntile_cols); - - switch (run_mode) - { - case GIMP_RUN_INTERACTIVE: - /* Possibly retrieve data */ - gimp_get_data (PLUG_IN_PROC, &mbvals); - - /* Get information from the dialog */ - if (! mblur_dialog (param[1].data.d_image, drawable)) - return; - break; - - case GIMP_RUN_NONINTERACTIVE: - if (strcmp (name, PLUG_IN_PROC_INWARD) == 0) - mbvals.blur_outward = FALSE; - - if (nparams == 8) - { - mbvals.center_x = param[6].data.d_float; - mbvals.center_y = param[7].data.d_float; - } - else if (nparams != 6) - { - status = GIMP_PDB_CALLING_ERROR; - } - - if (status == GIMP_PDB_SUCCESS) - { - mbvals.mblur_type = param[3].data.d_int32; - mbvals.length = param[4].data.d_int32; - mbvals.angle = param[5].data.d_int32; - } - - if ((mbvals.mblur_type < 0) || (mbvals.mblur_type > MBLUR_MAX)) - status= GIMP_PDB_CALLING_ERROR; - break; - - case GIMP_RUN_WITH_LAST_VALS: - /* Possibly retrieve data */ - gimp_get_data (PLUG_IN_PROC, &mbvals); - break; - - default: - break; - } - - /* Blur the image */ - - if ((status == GIMP_PDB_SUCCESS) && - (gimp_drawable_is_rgb(drawable->drawable_id) || - gimp_drawable_is_gray(drawable->drawable_id))) - { - - /* Run! */ - has_alpha = gimp_drawable_has_alpha (drawable->drawable_id); - mblur (drawable, NULL); - - /* If run mode is interactive, flush displays */ - if (run_mode != GIMP_RUN_NONINTERACTIVE) - gimp_displays_flush (); - - /* Store data */ - if (run_mode == GIMP_RUN_INTERACTIVE) - gimp_set_data (PLUG_IN_PROC, &mbvals, sizeof (mblur_vals_t)); - } - else if (status == GIMP_PDB_SUCCESS) - status = GIMP_PDB_EXECUTION_ERROR; - - values[0].data.d_status = status; - - gimp_drawable_detach (drawable); -} - -static void -mblur_linear (GimpDrawable *drawable, - GimpPreview *preview, - gint x1, - gint y1, - gint width, - gint height) -{ - GimpPixelRgn dest_rgn; - GimpPixelFetcher *pft; - gpointer pr; - GimpRGB background; - - guchar *dest; - guchar *d; - guchar pixel[4]; - gint32 sum[4]; - gint progress, max_progress; - gint c, p; - gint x, y, i, n; - gint dx, dy, px, py, swapdir, err, e, s1, s2; - - gimp_pixel_rgn_init (&dest_rgn, drawable, - x1, y1, width, height, (preview == NULL), TRUE); - - pft = gimp_pixel_fetcher_new (drawable, FALSE); - - gimp_context_get_background (&background); - gimp_pixel_fetcher_set_bg_color (pft, &background); - - progress = 0; - max_progress = width * height; - - n = mbvals.length; - px = (gdouble) n * cos (mbvals.angle / 180.0 * G_PI); - py = (gdouble) n * sin (mbvals.angle / 180.0 * G_PI); - - /* - * Initialization for Bresenham algorithm: - * dx = abs(x2-x1), s1 = sign(x2-x1) - * dy = abs(y2-y1), s2 = sign(y2-y1) - */ - if ((dx = px) != 0) - { - if (dx < 0) - { - dx = -dx; - s1 = -1; - } - else - s1 = 1; - } - else - s1 = 0; - - if ((dy = py) != 0) - { - if (dy < 0) - { - dy = -dy; - s2 = -1; - } - else - s2 = 1; - } - else - s2 = 0; - - if (dy > dx) - { - swapdir = dx; - dx = dy; - dy = swapdir; - swapdir = 1; - } - else - swapdir = 0; - - dy *= 2; - err = dy - dx; /* Initial error term */ - dx *= 2; - - for (pr = gimp_pixel_rgns_register (1, &dest_rgn), p = 0; - pr != NULL; - pr = gimp_pixel_rgns_process (pr), p++) - { - dest = dest_rgn.data; - - for (y = dest_rgn.y; y < dest_rgn.y + dest_rgn.h; y++) - { - d = dest; - - for (x = dest_rgn.x; x < dest_rgn.x + dest_rgn.w; x++) - { - gint xx, yy; - - xx = x; - yy = y; - e = err; - - for (c = 0; c < img_bpp; c++) - sum[c]= 0; - - for (i = 0; i < n; ) - { - gimp_pixel_fetcher_get_pixel (pft, xx, yy, pixel); - - if (has_alpha) - { - gint32 alpha = pixel[img_bpp-1]; - - sum[img_bpp-1] += alpha; - for (c = 0; c < img_bpp-1; c++) - sum[c] += pixel[c] * alpha; - } - else - { - for (c = 0; c < img_bpp; c++) - sum[c] += pixel[c]; - } - i++; - - while (e >= 0 && dx) - { - if (swapdir) - xx += s1; - else - yy += s2; - e -= dx; - } - - if (swapdir) - yy += s2; - else - xx += s1; - - e += dy; - - if ((xx < x1) || (xx >= x1 + width) || - (yy < y1) || (yy >= y1 + height)) - break; - } - - if (i == 0) - { - gimp_pixel_fetcher_get_pixel (pft, xx, yy, d); - } - else - { - if (has_alpha) - { - gint32 alpha = sum[img_bpp-1]; - - if ((d[img_bpp-1] = alpha/i) != 0) - { - for (c = 0; c < img_bpp-1; c++) - d[c] = sum[c] / alpha; - } - } - else - { - for (c = 0; c < img_bpp; c++) - d[c] = sum[c] / i; - } - } - - d += dest_rgn.bpp; - } - - dest += dest_rgn.rowstride; - } - - if (preview) - { - gimp_drawable_preview_draw_region (GIMP_DRAWABLE_PREVIEW (preview), - &dest_rgn); - } - else - { - progress += dest_rgn.w * dest_rgn.h; - - if ((p % 8) == 0) - gimp_progress_update ((gdouble) progress / max_progress); - } - } - - gimp_pixel_fetcher_destroy (pft); -} - - -static void -mblur_radial (GimpDrawable *drawable, - GimpPreview *preview, - gint x1, - gint y1, - gint width, - gint height) -{ - GimpPixelRgn dest_rgn; - GimpPixelFetcher *pft; - gpointer pr; - GimpRGB background; - - gdouble center_x; - gdouble center_y; - guchar *dest; - guchar *d; - guchar pixel[4]; - guchar p1[4], p2[4], p3[4], p4[4]; - gint32 sum[4]; - - gint progress, max_progress, c; - - gint x, y, i, p, n, count; - gdouble angle, theta, r, xr, yr; - gdouble phi, phi_start, s_val, c_val; - gdouble dx, dy; - - /* initialize */ - - center_x = mbvals.center_x; - center_y = mbvals.center_y; - - gimp_pixel_rgn_init (&dest_rgn, drawable, - x1, y1, width, height, (preview == NULL), TRUE); - - pft = gimp_pixel_fetcher_new (drawable, FALSE); - - gimp_context_get_background (&background); - gimp_pixel_fetcher_set_bg_color (pft, &background); - - progress = 0; - max_progress = width * height; - - angle = gimp_deg_to_rad (mbvals.angle); - - for (pr = gimp_pixel_rgns_register (1, &dest_rgn), p = 0; - pr != NULL; - pr = gimp_pixel_rgns_process (pr), p++) - { - dest = dest_rgn.data; - - for (y = dest_rgn.y; y < dest_rgn.y + dest_rgn.h; y++) - { - d = dest; - - for (x = dest_rgn.x; x < dest_rgn.x + dest_rgn.w; x++) - { - gdouble xx = 0.0; - gdouble yy = 0.0; - - xr = (gdouble) x - center_x; - yr = (gdouble) y - center_y; - - r = sqrt (SQR (xr) + SQR (yr)); - n = r * angle; - - if (angle == 0.0) - { - gimp_pixel_fetcher_get_pixel (pft, x, y, d); - d += dest_rgn.bpp; - continue; - } - - /* ensure quality with small angles */ - if (n < 3) - n = 3; /* always use at least 3 (interpolation) steps */ - - /* limit loop count due to performanc reasons */ - if (n > 100) - n = 100 + sqrt (n-100); - - if (xr != 0.0) - { - phi = atan(yr/xr); - if (xr < 0.0) - phi = G_PI + phi; - - } - else - { - if (yr >= 0.0) - phi = G_PI_2; - else - phi = -G_PI_2; - } - - for (c = 0; c < img_bpp; c++) - sum[c] = 0; - - if (n == 1) - phi_start = phi; - else - phi_start = phi + angle/2.0; - - theta = angle / (gdouble)n; - count = 0; - - for (i = 0; i < n; i++) - { - s_val = sin (phi_start - (gdouble) i * theta); - c_val = cos (phi_start - (gdouble) i * theta); - - xx = center_x + r * c_val; - yy = center_y + r * s_val; - - if ((yy < y1) || (yy >= y1 + height) || - (xx < x1) || (xx >= x1 + width)) - continue; - - ++count; - if ((xx + 1 < x1 + width) && (yy + 1 < y1 + height)) - { - dx = xx - floor (xx); - dy = yy - floor (yy); - - gimp_pixel_fetcher_get_pixel (pft, xx, yy, p1); - gimp_pixel_fetcher_get_pixel (pft, xx+1, yy, p2); - gimp_pixel_fetcher_get_pixel (pft, xx, yy+1, p3); - gimp_pixel_fetcher_get_pixel (pft, xx+1, yy+1, p4); - - for (c = 0; c < img_bpp; c++) - { - pixel[c] = (((gdouble) p1[c] * (1.0-dx) + - (gdouble) p2[c] * dx) * (1.0-dy) + - ((gdouble) p3[c] * (1.0-dx) + - (gdouble) p4[c] * dx) * dy); - } - } - else - { - gimp_pixel_fetcher_get_pixel (pft, xx+.5, yy+.5, pixel); - } - - if (has_alpha) - { - gint32 alpha = pixel[img_bpp-1]; - - sum[img_bpp-1] += alpha; - - for (c = 0; c < img_bpp-1; c++) - sum[c] += pixel[c] * alpha; - } - else - { - for (c = 0; c < img_bpp; c++) - sum[c] += pixel[c]; - } - } - - if (count == 0) - { - gimp_pixel_fetcher_get_pixel (pft, xx, yy, d); - } - else - { - if (has_alpha) - { - gint32 alpha = sum[img_bpp-1]; - - if ((d[img_bpp-1] = alpha/count) != 0) - { - for (c = 0; c < img_bpp-1; c++) - d[c] = sum[c] / alpha; - } - } - else - { - for (c = 0; c < img_bpp; c++) - d[c] = sum[c] / count; - } - } - - d += dest_rgn.bpp; - } - - dest += dest_rgn.rowstride; - } - - if (preview) - { - gimp_drawable_preview_draw_region (GIMP_DRAWABLE_PREVIEW (preview), - &dest_rgn); - } - else - { - progress += dest_rgn.w * dest_rgn.h; - - if ((p % 8) == 0) - gimp_progress_update ((gdouble) progress / max_progress); - } - } - - gimp_pixel_fetcher_destroy (pft); - -} - - -static void -mblur_zoom (GimpDrawable *drawable, - GimpPreview *preview, - gint x1, - gint y1, - gint width, - gint height) -{ - GimpPixelRgn dest_rgn; - GimpPixelFetcher *pft; - gpointer pr; - GimpRGB background; - - gdouble center_x; - gdouble center_y; - guchar *dest, *d; - guchar pixel[4]; - guchar p1[4], p2[4], p3[4], p4[4]; - gint32 sum[4]; - - gint progress, max_progress; - gint x, y, i, n, p, c; - gdouble xx_start, xx_end, yy_start, yy_end; - gdouble dxx, dyy; - gdouble dx, dy; - gint xy_len; - gdouble f, r; - gint drawable_x1, drawable_y1; - gint drawable_x2, drawable_y2; - - /* initialize */ - - center_x = mbvals.center_x; - center_y = mbvals.center_y; - - gimp_drawable_mask_bounds (drawable->drawable_id, - &drawable_x1, &drawable_y1, - &drawable_x2, &drawable_y2); - gimp_pixel_rgn_init (&dest_rgn, drawable, - x1, y1, width, height, (preview == NULL), TRUE); - - pft = gimp_pixel_fetcher_new (drawable, FALSE); - - gimp_context_get_background (&background); - gimp_pixel_fetcher_set_bg_color (pft, &background); - - progress = 0; - max_progress = width * height; - - n = mbvals.length; - - if (n == 0) - n = 1; - - r = sqrt (SQR (drawable->width / 2) + SQR (drawable->height / 2)); - n = ((gdouble) n * r / MBLUR_LENGTH_MAX); - f = (r-n)/r; - - for (pr = gimp_pixel_rgns_register (1, &dest_rgn), p = 0; - pr != NULL; - pr = gimp_pixel_rgns_process (pr), p++) - { - dest = dest_rgn.data; - - for (y = dest_rgn.y; y < dest_rgn.y + dest_rgn.h; y++) - { - d = dest; - - for (x = dest_rgn.x; x < dest_rgn.x + dest_rgn.w; x++) - { - gdouble xx, yy; - - for (c = 0; c < img_bpp; c++) - sum[c] = 0; - - xx_start = x; - yy_start = y; - - if (mbvals.blur_outward) - { - xx_end = center_x + ((gdouble) x - center_x) * f; - yy_end = center_y + ((gdouble) y - center_y) * f; - } - else - { - xx_end = center_x + ((gdouble) x - center_x) * (1.0/f); - yy_end = center_y + ((gdouble) y - center_y) * (1.0/f); - } - - xy_len = sqrt (SQR (xx_end-xx_start) + SQR (yy_end-yy_start)) + 1; - - if (xy_len < 3) - xy_len = 3; - - dxx = (xx_end - xx_start) / (gdouble) xy_len; - dyy = (yy_end - yy_start) / (gdouble) xy_len; - - xx = xx_start; - yy = yy_start; - - for (i = 0; i < xy_len; i++) - { - if ((yy < drawable_y1) || (yy >= drawable_y2) || - (xx < drawable_x1) || (xx >= drawable_x2)) - break; - - if ((xx+1 < drawable_x2) && (yy+1 < drawable_y2)) - { - dx = xx - floor (xx); - dy = yy - floor (yy); - - gimp_pixel_fetcher_get_pixel (pft, xx, yy, p1); - gimp_pixel_fetcher_get_pixel (pft, xx+1, yy, p2); - gimp_pixel_fetcher_get_pixel (pft, xx, yy+1, p3); - gimp_pixel_fetcher_get_pixel (pft, xx+1, yy+1, p4); - - for (c = 0; c < img_bpp; c++) - { - pixel[c] = (((gdouble)p1[c] * (1.0-dx) + - (gdouble)p2[c] * dx) * (1.0-dy) + - ((gdouble)p3[c] * (1.0-dx) + - (gdouble)p4[c] * dx) * dy); - } - } - else - { - gimp_pixel_fetcher_get_pixel (pft, xx+.5, yy+.5, pixel); - } - - if (has_alpha) - { - gint32 alpha = pixel[img_bpp-1]; - - sum[img_bpp-1] += alpha; - - for (c = 0; c < img_bpp-1; c++) - sum[c] += pixel[c] * alpha; - } - else - { - for (c = 0; c < img_bpp; c++) - sum[c] += pixel[c]; - } - - xx += dxx; - yy += dyy; - } - - if (i == 0) - { - gimp_pixel_fetcher_get_pixel (pft, xx, yy, d); - } - else - { - if (has_alpha) - { - gint32 alpha = sum[img_bpp-1]; - - if ((d[img_bpp-1] = alpha/i) != 0) - { - for (c = 0; c < img_bpp-1; c++) - d[c] = sum[c] / alpha; - } - } - else - { - for (c = 0; c < img_bpp; c++) - d[c] = sum[c] / i; - } - } - - d += dest_rgn.bpp; - } - - dest += dest_rgn.rowstride; - } - - if (preview) - { - gimp_drawable_preview_draw_region (GIMP_DRAWABLE_PREVIEW (preview), - &dest_rgn); - } - else - { - progress += dest_rgn.w * dest_rgn.h; - - if ((p % 8) == 0) - gimp_progress_update ((gdouble) progress / max_progress); - } - } - - gimp_pixel_fetcher_destroy (pft); -} - -static void -mblur (GimpDrawable *drawable, - GimpPreview *preview) -{ - gint x, y; - gint width, height; - - if (preview) - { - gimp_preview_get_position (preview, &x, &y); - gimp_preview_get_size (preview, &width, &height); - } - else if (! gimp_drawable_mask_intersect (drawable->drawable_id, - &x, &y, &width, &height)) - { - return; - } - - if (! preview) - gimp_progress_init (_("Motion blurring")); - - switch (mbvals.mblur_type) - { - case MBLUR_LINEAR: - mblur_linear (drawable, preview, x, y, width, height); - break; - - case MBLUR_RADIAL: - mblur_radial (drawable, preview, x, y, width, height); - break; - - case MBLUR_ZOOM: - mblur_zoom (drawable, preview, x, y, width, height); - break; - - default: - break; - } - - if (! preview) - { - gimp_progress_update (1.0); - - gimp_drawable_flush (drawable); - gimp_drawable_merge_shadow (drawable->drawable_id, TRUE); - gimp_drawable_update (drawable->drawable_id, x, y, width, height); - } -} - -/**************************************** - * UI - ****************************************/ - -static void -mblur_set_sensitivity (void) -{ - if (!length || !angle || !center || !dir_button) - return; /* Not initialized yet */ - - switch (mbvals.mblur_type) - { - case MBLUR_LINEAR: - gimp_scale_entry_set_sensitive (length, TRUE); - gimp_scale_entry_set_sensitive (angle, TRUE); - gtk_widget_set_sensitive (center, FALSE); - gtk_widget_set_sensitive (dir_button, FALSE); - break; - - case MBLUR_RADIAL: - gimp_scale_entry_set_sensitive (length, FALSE); - gimp_scale_entry_set_sensitive (angle, TRUE); - gtk_widget_set_sensitive (center, TRUE); - gtk_widget_set_sensitive (dir_button, FALSE); - break; - - case MBLUR_ZOOM: - gimp_scale_entry_set_sensitive (length, TRUE); - gimp_scale_entry_set_sensitive (angle, FALSE); - gtk_widget_set_sensitive (center, TRUE); - gtk_widget_set_sensitive (dir_button, TRUE); - break; - - default: - break; - } -} - -static void -mblur_radio_button_update (GtkWidget *widget, - gpointer data) -{ - gimp_radio_button_update (widget, data); - mblur_set_sensitivity (); - gimp_preview_invalidate (GIMP_PREVIEW (preview)); -} - -static void -mblur_center_update (GimpSizeEntry *entry) -{ - mbvals.center_x = gimp_size_entry_get_refval (entry, 0); - mbvals.center_y = gimp_size_entry_get_refval (entry, 1); -} - -static gboolean -mblur_dialog (gint32 image_ID, - GimpDrawable *drawable) -{ - GtkWidget *dialog; - GtkWidget *main_vbox; - GtkWidget *hbox; - GtkWidget *vbox; - GtkWidget *frame; - GtkWidget *table; - GtkWidget *entry; - GtkWidget *spinbutton; - GtkWidget *button; - GtkObject *adj; - gdouble xres, yres; - gboolean run; - - gimp_ui_init (PLUG_IN_BINARY, FALSE); - - dialog = gimp_dialog_new (_("Motion Blur"), PLUG_IN_ROLE, - NULL, 0, - gimp_standard_help_func, PLUG_IN_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 (mblur), - 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); - - frame = gimp_int_radio_group_new (TRUE, _("Blur Type"), - G_CALLBACK (mblur_radio_button_update), - &mbvals.mblur_type, mbvals.mblur_type, - - C_("blur-type", "_Linear"), MBLUR_LINEAR, NULL, - C_("blur-type", "_Radial"), MBLUR_RADIAL, NULL, - C_("blur-type", "_Zoom"), MBLUR_ZOOM, NULL, - - NULL); - - gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, FALSE, 0); - gtk_widget_show (frame); - - center = gimp_frame_new (_("Blur Center")); - gtk_box_pack_start (GTK_BOX (hbox), center, FALSE, FALSE, 0); - gtk_widget_show (center); - - vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12); - gtk_container_add (GTK_CONTAINER (center), vbox); - gtk_widget_show (vbox); - - gimp_image_get_resolution (image_ID, &xres, &yres); - - entry = gimp_size_entry_new (1, - GIMP_UNIT_PIXEL, "%a", - TRUE, FALSE, FALSE, 5, - GIMP_SIZE_ENTRY_UPDATE_SIZE); - gtk_table_set_row_spacings (GTK_TABLE (entry), 2); - gtk_table_set_col_spacing (GTK_TABLE (entry), 0, 6); - gtk_table_set_col_spacing (GTK_TABLE (entry), 2, 6); - gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0); - gtk_widget_show (entry); - - g_signal_connect (entry, "value-changed", - G_CALLBACK (mblur_center_update), - NULL); - g_signal_connect_swapped (entry, "value-changed", - G_CALLBACK (gimp_preview_invalidate), - preview); - - spinbutton = gimp_spin_button_new (&adj, 1, 0, 1, 1, 10, 0, 1, 2); - gimp_size_entry_add_field (GIMP_SIZE_ENTRY (entry), - GTK_SPIN_BUTTON (spinbutton), NULL); - gtk_table_attach_defaults (GTK_TABLE (entry), spinbutton, 1, 2, 0, 1); - gtk_widget_show (spinbutton); - - gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (entry), 0, xres, TRUE); - gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (entry), 0, mbvals.center_x); - gimp_size_entry_attach_label (GIMP_SIZE_ENTRY (entry), - _("_X:"), 0, 0, 0.0); - - gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (entry), 1, yres, TRUE); - gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (entry), 1, mbvals.center_y); - gimp_size_entry_attach_label (GIMP_SIZE_ENTRY (entry), - _("_Y:"), 1, 0, 0.0); - - button = gtk_check_button_new_with_mnemonic (_("Blur _outward")); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), - mbvals.blur_outward); - gtk_box_pack_start (GTK_BOX (main_vbox), button, FALSE, FALSE, 0); - gtk_widget_show (button); - g_signal_connect (button, "toggled", - G_CALLBACK (gimp_toggle_button_update), - &mbvals.blur_outward); - g_signal_connect_swapped (button, "toggled", - G_CALLBACK (gimp_preview_invalidate), - preview); - dir_button = button; - - frame = gimp_frame_new (_("Blur Parameters")); - gtk_box_pack_start (GTK_BOX (main_vbox), frame, FALSE, FALSE, 0); - gtk_widget_show (frame); - - table = gtk_table_new (2, 3, FALSE); - gtk_table_set_col_spacings (GTK_TABLE (table), 6); - gtk_table_set_row_spacings (GTK_TABLE (table), 6); - gtk_container_add (GTK_CONTAINER (frame), table); - gtk_widget_show (table); - - length = gimp_scale_entry_new (GTK_TABLE (table), 0, 0, - _("L_ength:"), 150, 3, - mbvals.length, 1.0, MBLUR_LENGTH_MAX, 1.0, 8.0, 0, - TRUE, 0, 0, - NULL, NULL); - - g_signal_connect (length, "value-changed", - G_CALLBACK (gimp_int_adjustment_update), - &mbvals.length); - g_signal_connect_swapped (length, "value-changed", - G_CALLBACK (gimp_preview_invalidate), - preview); - - angle = gimp_scale_entry_new (GTK_TABLE (table), 0, 1, - _("_Angle:"), 150, 3, - mbvals.angle, 0.0, 360.0, 1.0, 15.0, 0, - TRUE, 0, 0, - NULL, NULL); - - g_signal_connect (angle, "value-changed", - G_CALLBACK (gimp_int_adjustment_update), - &mbvals.angle); - g_signal_connect_swapped (angle, "value-changed", - G_CALLBACK (gimp_preview_invalidate), - preview); - - mblur_set_sensitivity (); - - gtk_widget_show (dialog); - - run = (gimp_dialog_run (GIMP_DIALOG (dialog)) == GTK_RESPONSE_OK); - - gtk_widget_destroy (dialog); - - return run; -} diff --git a/plug-ins/common/gimprc.common b/plug-ins/common/gimprc.common index e98010039f..cad83352fb 100644 --- a/plug-ins/common/gimprc.common +++ b/plug-ins/common/gimprc.common @@ -8,7 +8,6 @@ blinds_RC = blinds.rc.o blur_RC = blur.rc.o blur_gauss_RC = blur-gauss.rc.o blur_gauss_selective_RC = blur-gauss-selective.rc.o -blur_motion_RC = blur-motion.rc.o border_average_RC = border-average.rc.o bump_map_RC = bump-map.rc.o cartoon_RC = cartoon.rc.o diff --git a/plug-ins/common/plugin-defs.pl b/plug-ins/common/plugin-defs.pl index 9f76a78c12..14e30eda24 100644 --- a/plug-ins/common/plugin-defs.pl +++ b/plug-ins/common/plugin-defs.pl @@ -9,7 +9,6 @@ 'blur' => {}, 'blur-gauss' => { ui => 1 }, 'blur-gauss-selective' => { ui => 1, cflags => 'MMX_EXTRA_CFLAGS' }, - 'blur-motion' => { ui => 1 }, 'border-average' => { ui => 1 }, 'bump-map' => { ui => 1 }, 'cartoon' => { ui => 1 }, diff --git a/po-plug-ins/POTFILES.in b/po-plug-ins/POTFILES.in index b6afce83e3..d25bb0c6db 100644 --- a/po-plug-ins/POTFILES.in +++ b/po-plug-ins/POTFILES.in @@ -16,7 +16,6 @@ plug-ins/common/blinds.c plug-ins/common/blur.c plug-ins/common/blur-gauss.c plug-ins/common/blur-gauss-selective.c -plug-ins/common/blur-motion.c plug-ins/common/border-average.c plug-ins/common/bump-map.c plug-ins/common/cartoon.c diff --git a/tools/pdbgen/pdb/plug_in_compat.pdb b/tools/pdbgen/pdb/plug_in_compat.pdb index c5ae60994c..7ecfd1998f 100644 --- a/tools/pdbgen/pdb/plug_in_compat.pdb +++ b/tools/pdbgen/pdb/plug_in_compat.pdb @@ -245,6 +245,179 @@ CODE ); } +sub plug_in_mblur { + $blurb = 'Simulate movement using directional blur'; + + $help = <<'HELP'; +This plug-in simulates the effect seen when +photographing a moving object at a slow shutter +speed. Done by adding multiple displaced copies. +HELP + + &std_pdb_compat('gegl:motion-blur-linear, -zoom, -cirular'); + $date = '2013'; + + @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 => 'type', type => '0 <= int32 <= 2', + desc => 'Type of motion blur { LINEAR (0), RADIAL (1), ZOOM (2) }' }, + { name => 'length', type => 'float', + desc => 'Length' }, + { name => 'angle', type => '0 <= float <= 360', + desc => 'Angle' }, + { name => 'center_x', type => 'float', + desc => 'Center X' }, + { name => 'center_y', type => 'float', + desc => 'Center Y' } + ); + + %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 = NULL; + + if (type == 0) + { + node = gegl_node_new_child (NULL, + "operation", "gegl:motion-blur-linear", + "length", length, + "angle", angle, + NULL); + } + else if (type == 1) + { + node = gegl_node_new_child (NULL, + "operation", "gegl:motion-blur-circular", + "center-x", center_x, + "center-y", center_y, + "angle", angle, + NULL); + } + else if (type == 2) + { + gdouble factor = CLAMP (length / 256.0, 0.0, 1.0); + node = gegl_node_new_child (NULL, + "operation", "gegl:motion-blur-zoom", + "center-x", center_x, + "center-y", center_y, + "factor", factor, + NULL); + } + + if (node != NULL) + { + gimp_drawable_apply_operation (drawable, progress, + C_("undo-type", "Motion Blur"), + node); + + g_object_unref (node); + } + else + success = FALSE; + + } + else + success = FALSE; +} +CODE + ); +} + +sub plug_in_mblur_inward { + $blurb = 'Simulate movement using directional blur'; + + $help = <<'HELP'; +This procedure is equivalent to plug-in-mblur but +performs the zoom blur inward instead of outward. +HELP + + &std_pdb_compat('gegl:motion-blur-linear, -zoom, -cirular'); + $date = '2013'; + + @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 => 'type', type => '0 <= int32 <= 2', + desc => 'Type of motion blur { LINEAR (0), RADIAL (1), ZOOM (2) }' }, + { name => 'length', type => 'float', + desc => 'Length' }, + { name => 'angle', type => '0 <= float <= 360', + desc => 'Angle' }, + { name => 'center_x', type => 'float', + desc => 'Center X' }, + { name => 'center_y', type => 'float', + desc => 'Center Y' } + ); + + %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 = NULL; + + if (type == 0) + { + node = gegl_node_new_child (NULL, + "operation", "gegl:motion-blur-linear", + "length", length, + "angle", angle, + NULL); + } + else if (type == 1) + { + node = gegl_node_new_child (NULL, + "operation", "gegl:motion-blur-circular", + "center-x", center_x, + "center-y", center_y, + "angle", angle, + NULL); + } + else if (type == 2) + { + gdouble factor = CLAMP (-length / (256.0 - length), -10.0, 0.0); + node = gegl_node_new_child (NULL, + "operation", "gegl:motion-blur-zoom", + "center-x", center_x, + "center-y", center_y, + "factor", factor, + NULL); + } + + if (node != NULL) + { + gimp_drawable_apply_operation (drawable, progress, + C_("undo-type", "Motion Blur"), + node); + + g_object_unref (node); + } + else + success = FALSE; + + } + else + success = FALSE; +} +CODE + ); +} + sub plug_in_pixelize { $blurb = 'Simplify image into an array of solid-colored squares'; @@ -1040,6 +1213,8 @@ CODE plug_in_autocrop_layer plug_in_colortoalpha plug_in_cubism + plug_in_mblur + plug_in_mblur_inward plug_in_pixelize plug_in_pixelize2 plug_in_polar_coords