mirror of https://github.com/GNOME/gimp.git
plug-ins, pdb: remove the edge-neon plug-in and add a PDB compat procedure
This commit is contained in:
parent
12bed7be5b
commit
8b08f958ba
|
@ -28,7 +28,7 @@
|
|||
#include "internal-procs.h"
|
||||
|
||||
|
||||
/* 737 procedures registered total */
|
||||
/* 738 procedures registered total */
|
||||
|
||||
void
|
||||
internal_procs_init (GimpPDB *pdb)
|
||||
|
|
|
@ -2505,6 +2505,50 @@ plug_in_mosaic_invoker (GimpProcedure *procedure,
|
|||
error ? *error : NULL);
|
||||
}
|
||||
|
||||
static GimpValueArray *
|
||||
plug_in_neon_invoker (GimpProcedure *procedure,
|
||||
Gimp *gimp,
|
||||
GimpContext *context,
|
||||
GimpProgress *progress,
|
||||
const GimpValueArray *args,
|
||||
GError **error)
|
||||
{
|
||||
gboolean success = TRUE;
|
||||
GimpDrawable *drawable;
|
||||
gdouble radius;
|
||||
gdouble amount;
|
||||
|
||||
drawable = gimp_value_get_drawable (gimp_value_array_index (args, 2), gimp);
|
||||
radius = g_value_get_double (gimp_value_array_index (args, 3));
|
||||
amount = g_value_get_double (gimp_value_array_index (args, 4));
|
||||
|
||||
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;
|
||||
|
||||
node = gegl_node_new_child (NULL,
|
||||
"operation", "gegl:edge-neon",
|
||||
"radius", radius,
|
||||
"amount", amount,
|
||||
NULL);
|
||||
|
||||
gimp_drawable_apply_operation (drawable, progress,
|
||||
C_("undo-type", "Neon"),
|
||||
node);
|
||||
g_object_unref (node);
|
||||
}
|
||||
else
|
||||
success = FALSE;
|
||||
}
|
||||
|
||||
return gimp_procedure_get_return_values (procedure, success,
|
||||
error ? *error : NULL);
|
||||
}
|
||||
|
||||
static GimpValueArray *
|
||||
plug_in_nova_invoker (GimpProcedure *procedure,
|
||||
Gimp *gimp,
|
||||
|
@ -6693,6 +6737,54 @@ register_plug_in_compat_procs (GimpPDB *pdb)
|
|||
gimp_pdb_register_procedure (pdb, procedure);
|
||||
g_object_unref (procedure);
|
||||
|
||||
/*
|
||||
* gimp-plug-in-neon
|
||||
*/
|
||||
procedure = gimp_procedure_new (plug_in_neon_invoker);
|
||||
gimp_object_set_static_name (GIMP_OBJECT (procedure),
|
||||
"plug-in-neon");
|
||||
gimp_procedure_set_static_strings (procedure,
|
||||
"plug-in-neon",
|
||||
"Simulate the glowing boundary of a neon light",
|
||||
"This filter works in a manner similar to the edge plug-in, but uses the first derivative of the gaussian operator to achieve resolution independence. The IIR method of calculating the effect is utilized to keep the processing time constant between large and small standard deviations.",
|
||||
"Compatibility procedure. Please see 'gegl:edge-neon' for credits.",
|
||||
"Compatibility procedure. Please see 'gegl:edge-neon' for credits.",
|
||||
"2019",
|
||||
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,
|
||||
g_param_spec_double ("radius",
|
||||
"radius",
|
||||
"Radius of neon effect (in pixels)",
|
||||
0.0, 1500.0, 0.0,
|
||||
GIMP_PARAM_READWRITE));
|
||||
gimp_procedure_add_argument (procedure,
|
||||
g_param_spec_double ("amount",
|
||||
"amount",
|
||||
"Effect enhancement variable",
|
||||
0.0, 100.0, 0.0,
|
||||
GIMP_PARAM_READWRITE));
|
||||
gimp_pdb_register_procedure (pdb, procedure);
|
||||
g_object_unref (procedure);
|
||||
|
||||
/*
|
||||
* gimp-plug-in-nova
|
||||
*/
|
||||
|
|
|
@ -2482,6 +2482,60 @@ CODE
|
|||
);
|
||||
}
|
||||
|
||||
sub plug_in_neon {
|
||||
$blurb = 'Simulate the glowing boundary of a neon light';
|
||||
|
||||
$help = <<'HELP';
|
||||
This filter works in a manner similar to the edge plug-in, but uses
|
||||
the first derivative of the gaussian operator to achieve resolution
|
||||
independence. The IIR method of calculating the effect is utilized to
|
||||
keep the processing time constant between large and small standard
|
||||
deviations.
|
||||
HELP
|
||||
|
||||
&std_pdb_compat('gegl:edge-neon');
|
||||
$date = '2019';
|
||||
|
||||
@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 => 'radius', type => '0.0 <= float <= 1500.0',
|
||||
desc => 'Radius of neon effect (in pixels)' },
|
||||
{ name => 'amount', type => '0.0 <= float <= 100.0',
|
||||
desc => 'Effect enhancement variable' }
|
||||
);
|
||||
|
||||
%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;
|
||||
|
||||
node = gegl_node_new_child (NULL,
|
||||
"operation", "gegl:edge-neon",
|
||||
"radius", radius,
|
||||
"amount", amount,
|
||||
NULL);
|
||||
|
||||
gimp_drawable_apply_operation (drawable, progress,
|
||||
C_("undo-type", "Neon"),
|
||||
node);
|
||||
g_object_unref (node);
|
||||
}
|
||||
else
|
||||
success = FALSE;
|
||||
}
|
||||
CODE
|
||||
);
|
||||
}
|
||||
|
||||
sub plug_in_nova {
|
||||
$blurb = 'Add a starburst to the image';
|
||||
|
||||
|
@ -4895,6 +4949,7 @@ CODE
|
|||
plug_in_mblur
|
||||
plug_in_mblur_inward
|
||||
plug_in_mosaic
|
||||
plug_in_neon
|
||||
plug_in_nova
|
||||
plug_in_papertile
|
||||
plug_in_photocopy
|
||||
|
|
|
@ -44,8 +44,6 @@
|
|||
/destripe.exe
|
||||
/edge-dog
|
||||
/edge-dog.exe
|
||||
/edge-neon
|
||||
/edge-neon.exe
|
||||
/emboss
|
||||
/emboss.exe
|
||||
/file-aa
|
||||
|
|
|
@ -67,7 +67,6 @@ depth_merge_libexecdir = $(gimpplugindir)/plug-ins/depth-merge
|
|||
despeckle_libexecdir = $(gimpplugindir)/plug-ins/despeckle
|
||||
destripe_libexecdir = $(gimpplugindir)/plug-ins/destripe
|
||||
edge_dog_libexecdir = $(gimpplugindir)/plug-ins/edge-dog
|
||||
edge_neon_libexecdir = $(gimpplugindir)/plug-ins/edge-neon
|
||||
emboss_libexecdir = $(gimpplugindir)/plug-ins/emboss
|
||||
file_aa_libexecdir = $(gimpplugindir)/plug-ins/file-aa
|
||||
file_cel_libexecdir = $(gimpplugindir)/plug-ins/file-cel
|
||||
|
@ -157,7 +156,6 @@ depth_merge_libexec_PROGRAMS = depth-merge
|
|||
despeckle_libexec_PROGRAMS = despeckle
|
||||
destripe_libexec_PROGRAMS = destripe
|
||||
edge_dog_libexec_PROGRAMS = edge-dog
|
||||
edge_neon_libexec_PROGRAMS = edge-neon
|
||||
emboss_libexec_PROGRAMS = emboss
|
||||
file_aa_libexec_PROGRAMS = $(FILE_AA)
|
||||
file_cel_libexec_PROGRAMS = file-cel
|
||||
|
@ -613,23 +611,6 @@ edge_dog_LDADD = \
|
|||
$(INTLLIBS) \
|
||||
$(edge_dog_RC)
|
||||
|
||||
edge_neon_SOURCES = \
|
||||
edge-neon.c
|
||||
|
||||
edge_neon_LDADD = \
|
||||
$(libgimpui) \
|
||||
$(libgimpwidgets) \
|
||||
$(libgimpmodule) \
|
||||
$(libgimp) \
|
||||
$(libgimpmath) \
|
||||
$(libgimpconfig) \
|
||||
$(libgimpcolor) \
|
||||
$(libgimpbase) \
|
||||
$(GTK_LIBS) \
|
||||
$(RT_LIBS) \
|
||||
$(INTLLIBS) \
|
||||
$(edge_neon_RC)
|
||||
|
||||
emboss_SOURCES = \
|
||||
emboss.c
|
||||
|
||||
|
|
|
@ -1,778 +0,0 @@
|
|||
/* GIMP - The GNU Image Manipulation Program
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* Neon filter for GIMP for BIPS
|
||||
* -Spencer Kimball
|
||||
*
|
||||
* This filter works in a manner similar to the "edge"
|
||||
* plug-in, but uses the first derivative of the gaussian
|
||||
* operator to achieve resolution independence. The IIR
|
||||
* method of calculating the effect is utilized to keep
|
||||
* the processing time constant between large and small
|
||||
* standard deviations.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <libgimp/gimp.h>
|
||||
#include <libgimp/gimpui.h>
|
||||
|
||||
#include "libgimp/stdplugins-intl.h"
|
||||
|
||||
|
||||
#define PLUG_IN_PROC "plug-in-neon"
|
||||
#define PLUG_IN_BINARY "edge-neon"
|
||||
#define PLUG_IN_ROLE "gimp-edge-neon"
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
gdouble radius;
|
||||
gdouble amount;
|
||||
} NeonVals;
|
||||
|
||||
|
||||
/*
|
||||
* Function prototypes.
|
||||
*/
|
||||
|
||||
static void query (void);
|
||||
static void run (const gchar *name,
|
||||
gint nparams,
|
||||
const GimpParam *param,
|
||||
gint *nreturn_vals,
|
||||
GimpParam **return_vals);
|
||||
|
||||
static void neon (GimpDrawable *drawable,
|
||||
gdouble radius,
|
||||
gdouble amount,
|
||||
GimpPreview *preview);
|
||||
|
||||
static gboolean neon_dialog (GimpDrawable *drawable);
|
||||
static void neon_preview_update (GimpPreview *preview,
|
||||
GimpDrawable *drawable);
|
||||
|
||||
/*
|
||||
* Gaussian operator helper functions
|
||||
*/
|
||||
static void find_constants (gdouble n_p[],
|
||||
gdouble n_m[],
|
||||
gdouble d_p[],
|
||||
gdouble d_m[],
|
||||
gdouble bd_p[],
|
||||
gdouble bd_m[],
|
||||
gdouble std_dev);
|
||||
static void transfer_pixels (gdouble *src1,
|
||||
gdouble *src2,
|
||||
guchar *dest,
|
||||
gint bytes,
|
||||
gint width);
|
||||
static void combine_to_gradient (guchar *dest,
|
||||
guchar *src2,
|
||||
gint bytes,
|
||||
gint width,
|
||||
gdouble amount);
|
||||
|
||||
|
||||
/***** Local vars *****/
|
||||
|
||||
const GimpPlugInInfo PLUG_IN_INFO =
|
||||
{
|
||||
NULL, /* init */
|
||||
NULL, /* quit */
|
||||
query, /* query */
|
||||
run, /* run */
|
||||
};
|
||||
|
||||
static NeonVals evals =
|
||||
{
|
||||
5.0, /* radius */
|
||||
0.0, /* amount */
|
||||
};
|
||||
|
||||
|
||||
/***** 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 (unused)" },
|
||||
{ GIMP_PDB_DRAWABLE, "drawable", "Input drawable" },
|
||||
{ GIMP_PDB_FLOAT, "radius", "Radius of neon effect (in pixels)" },
|
||||
{ GIMP_PDB_FLOAT, "amount", "Effect enhancement variable (0.0 - 1.0)" },
|
||||
};
|
||||
|
||||
gchar *help_string =
|
||||
"This filter works in a manner similar to the edge "
|
||||
"plug-in, but uses the first derivative of the gaussian "
|
||||
"operator to achieve resolution independence. The IIR "
|
||||
"method of calculating the effect is utilized to keep "
|
||||
"the processing time constant between large and small "
|
||||
"standard deviations.";
|
||||
|
||||
gimp_install_procedure (PLUG_IN_PROC,
|
||||
N_("Simulate the glowing boundary of a neon light"),
|
||||
help_string,
|
||||
"Spencer Kimball",
|
||||
"Bit Specialists, Inc.",
|
||||
"2002",
|
||||
N_("_Neon (legacy)..."),
|
||||
"RGB*, GRAY*",
|
||||
GIMP_PLUGIN,
|
||||
G_N_ELEMENTS (args), 0,
|
||||
args, NULL);
|
||||
|
||||
gimp_plugin_menu_register (PLUG_IN_PROC, "<Image>/Filters/Edge-Detect");
|
||||
}
|
||||
|
||||
static void
|
||||
run (const gchar *name,
|
||||
gint nparams,
|
||||
const GimpParam *param,
|
||||
gint *nreturn_vals,
|
||||
GimpParam **return_vals)
|
||||
{
|
||||
static GimpParam values[2];
|
||||
GimpRunMode run_mode;
|
||||
GimpDrawable *drawable;
|
||||
GimpPDBStatusType status = GIMP_PDB_SUCCESS;
|
||||
|
||||
run_mode = param[0].data.d_int32;
|
||||
|
||||
/* Get the specified drawable */
|
||||
drawable = gimp_drawable_get (param[2].data.d_drawable);
|
||||
|
||||
/* set the tile cache size so that the gaussian blur works well */
|
||||
gimp_tile_cache_ntiles (2 * (MAX (drawable->ntile_rows, drawable->ntile_cols)));
|
||||
|
||||
*nreturn_vals = 1;
|
||||
*return_vals = values;
|
||||
|
||||
values[0].type = GIMP_PDB_STATUS;
|
||||
values[0].data.d_status = status;
|
||||
|
||||
INIT_I18N();
|
||||
|
||||
switch (run_mode)
|
||||
{
|
||||
case GIMP_RUN_INTERACTIVE:
|
||||
/* Possibly retrieve data */
|
||||
gimp_get_data (PLUG_IN_PROC, &evals);
|
||||
|
||||
/* First acquire information with a dialog */
|
||||
if (! neon_dialog (drawable))
|
||||
return;
|
||||
break;
|
||||
|
||||
case GIMP_RUN_NONINTERACTIVE:
|
||||
/* Make sure all the arguments are there! */
|
||||
if (nparams != 5)
|
||||
status = GIMP_PDB_CALLING_ERROR;
|
||||
if (status == GIMP_PDB_SUCCESS)
|
||||
{
|
||||
evals.radius = param[3].data.d_float;
|
||||
evals.amount = param[4].data.d_float;
|
||||
}
|
||||
break;
|
||||
|
||||
case GIMP_RUN_WITH_LAST_VALS:
|
||||
/* Possibly retrieve data */
|
||||
gimp_get_data (PLUG_IN_PROC, &evals);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* make sure the drawable exist and is not indexed */
|
||||
if (gimp_drawable_is_rgb (drawable->drawable_id) ||
|
||||
gimp_drawable_is_gray (drawable->drawable_id))
|
||||
{
|
||||
gimp_progress_init (_("Neon"));
|
||||
|
||||
/* run the neon effect */
|
||||
neon (drawable, evals.radius, evals.amount, NULL);
|
||||
|
||||
if (run_mode != GIMP_RUN_NONINTERACTIVE)
|
||||
gimp_displays_flush ();
|
||||
|
||||
/* Store data */
|
||||
if (run_mode == GIMP_RUN_INTERACTIVE)
|
||||
gimp_set_data (PLUG_IN_PROC, &evals, sizeof (NeonVals));
|
||||
}
|
||||
else
|
||||
{
|
||||
status = GIMP_PDB_EXECUTION_ERROR;
|
||||
*nreturn_vals = 2;
|
||||
values[1].type = GIMP_PDB_STRING;
|
||||
values[1].data.d_string = _("Cannot operate on indexed color images.");
|
||||
}
|
||||
|
||||
values[0].data.d_status = status;
|
||||
|
||||
gimp_drawable_detach (drawable);
|
||||
}
|
||||
|
||||
/**********************************************/
|
||||
/* Neon main */
|
||||
/**********************************************/
|
||||
|
||||
static void
|
||||
neon (GimpDrawable *drawable,
|
||||
gdouble radius,
|
||||
gdouble amount,
|
||||
GimpPreview *preview)
|
||||
{
|
||||
GimpPixelRgn src_rgn, dest_rgn;
|
||||
gint width, height;
|
||||
gint bytes, bpp;
|
||||
gboolean has_alpha;
|
||||
guchar *dest;
|
||||
guchar *src, *src2, *sp_p, *sp_m;
|
||||
gdouble n_p[5], n_m[5];
|
||||
gdouble d_p[5], d_m[5];
|
||||
gdouble bd_p[5], bd_m[5];
|
||||
gdouble *val_p, *val_m, *vp, *vm;
|
||||
gint x, y;
|
||||
gint i, j;
|
||||
gint row, col, b;
|
||||
gint terms;
|
||||
gint progress = 0, max_progress = 1;
|
||||
gint initial_p[4];
|
||||
gint initial_m[4];
|
||||
gdouble std_dev;
|
||||
guchar *preview_buffer1 = NULL;
|
||||
guchar *preview_buffer2 = NULL;
|
||||
|
||||
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 (radius < 1.0)
|
||||
return;
|
||||
|
||||
bytes = drawable->bpp;
|
||||
bpp = bytes;
|
||||
has_alpha = gimp_drawable_has_alpha(drawable->drawable_id);
|
||||
if (has_alpha)
|
||||
bpp--;
|
||||
|
||||
val_p = g_new (gdouble, MAX (width, height) * bytes);
|
||||
val_m = g_new (gdouble, MAX (width, height) * bytes);
|
||||
|
||||
src = g_new (guchar, MAX (width, height) * bytes);
|
||||
src2 = g_new (guchar, MAX (width, height) * bytes);
|
||||
dest = g_new (guchar, MAX (width, height) * bytes);
|
||||
|
||||
gimp_pixel_rgn_init (&src_rgn, drawable,
|
||||
0, 0, drawable->width, drawable->height, FALSE, FALSE);
|
||||
|
||||
if (preview)
|
||||
{
|
||||
preview_buffer1 = g_new (guchar, width * height * bytes);
|
||||
preview_buffer2 = g_new (guchar, width * height * bytes);
|
||||
}
|
||||
else
|
||||
{
|
||||
gimp_pixel_rgn_init (&dest_rgn, drawable,
|
||||
0, 0, drawable->width, drawable->height, TRUE, TRUE);
|
||||
|
||||
progress = 0;
|
||||
max_progress = (radius < 1.0 ) ? 0 : width * height * radius * 2;
|
||||
}
|
||||
|
||||
/* First the vertical pass */
|
||||
radius = fabs (radius) + 1.0;
|
||||
std_dev = sqrt (-(radius * radius) / (2 * log (1.0 / 255.0)));
|
||||
|
||||
/* derive the constants for calculating the gaussian from the std dev */
|
||||
find_constants (n_p, n_m, d_p, d_m, bd_p, bd_m, std_dev);
|
||||
|
||||
for (col = 0; col < width; col++)
|
||||
{
|
||||
memset (val_p, 0, height * bytes * sizeof (gdouble));
|
||||
memset (val_m, 0, height * bytes * sizeof (gdouble));
|
||||
|
||||
gimp_pixel_rgn_get_col (&src_rgn, src, col + x, y, height);
|
||||
|
||||
sp_p = src;
|
||||
sp_m = src + (height - 1) * bytes;
|
||||
vp = val_p;
|
||||
vm = val_m + (height - 1) * bytes;
|
||||
|
||||
/* Set up the first vals */
|
||||
for (i = 0; i < bytes; i++)
|
||||
{
|
||||
initial_p[i] = sp_p[i];
|
||||
initial_m[i] = sp_m[i];
|
||||
}
|
||||
|
||||
for (row = 0; row < height; row++)
|
||||
{
|
||||
gdouble *vpptr, *vmptr;
|
||||
|
||||
terms = (row < 4) ? row : 4;
|
||||
|
||||
for (b = 0; b < bpp; b++)
|
||||
{
|
||||
vpptr = vp + b; vmptr = vm + b;
|
||||
|
||||
for (i = 0; i <= terms; i++)
|
||||
{
|
||||
*vpptr += n_p[i] * sp_p[(-i * bytes) + b] -
|
||||
d_p[i] * vp[(-i * bytes) + b];
|
||||
*vmptr += n_m[i] * sp_m[(i * bytes) + b] -
|
||||
d_m[i] * vm[(i * bytes) + b];
|
||||
}
|
||||
|
||||
for (j = i; j <= 4; j++)
|
||||
{
|
||||
*vpptr += (n_p[j] - bd_p[j]) * initial_p[b];
|
||||
*vmptr += (n_m[j] - bd_m[j]) * initial_m[b];
|
||||
}
|
||||
}
|
||||
if (has_alpha)
|
||||
{
|
||||
vp[bpp] = sp_p[bpp];
|
||||
vm[bpp] = sp_m[bpp];
|
||||
}
|
||||
|
||||
sp_p += bytes;
|
||||
sp_m -= bytes;
|
||||
vp += bytes;
|
||||
vm -= bytes;
|
||||
}
|
||||
|
||||
transfer_pixels (val_p, val_m, dest, bytes, height);
|
||||
|
||||
if (preview)
|
||||
{
|
||||
for (row = 0 ; row < height ; row++)
|
||||
memcpy (preview_buffer1 + (row * width + col) * bytes,
|
||||
dest + bytes * row,
|
||||
bytes);
|
||||
}
|
||||
else
|
||||
{
|
||||
gimp_pixel_rgn_set_col (&dest_rgn, dest, col + x, y, height);
|
||||
|
||||
progress += height * radius;
|
||||
|
||||
if ((col % 20) == 0)
|
||||
gimp_progress_update ((double) progress / (double) max_progress);
|
||||
}
|
||||
}
|
||||
|
||||
/* Now the horizontal pass */
|
||||
gimp_pixel_rgn_init (&src_rgn, drawable,
|
||||
0, 0, drawable->width, drawable->height, FALSE, FALSE);
|
||||
|
||||
for (row = 0; row < height; row++)
|
||||
{
|
||||
memset (val_p, 0, width * bytes * sizeof (gdouble));
|
||||
memset (val_m, 0, width * bytes * sizeof (gdouble));
|
||||
|
||||
gimp_pixel_rgn_get_row (&src_rgn, src, x, row + y, width);
|
||||
if (preview)
|
||||
{
|
||||
memcpy (src2,
|
||||
preview_buffer1 + row * width * bytes,
|
||||
width * bytes);
|
||||
}
|
||||
else
|
||||
{
|
||||
gimp_pixel_rgn_get_row (&dest_rgn, src2, x, row + y, width);
|
||||
}
|
||||
|
||||
sp_p = src;
|
||||
sp_m = src + (width - 1) * bytes;
|
||||
vp = val_p;
|
||||
vm = val_m + (width - 1) * bytes;
|
||||
|
||||
/* Set up the first vals */
|
||||
for (i = 0; i < bytes; i++)
|
||||
{
|
||||
initial_p[i] = sp_p[i];
|
||||
initial_m[i] = sp_m[i];
|
||||
}
|
||||
|
||||
for (col = 0; col < width; col++)
|
||||
{
|
||||
gdouble *vpptr, *vmptr;
|
||||
|
||||
terms = (col < 4) ? col : 4;
|
||||
|
||||
for (b = 0; b < bpp; b++)
|
||||
{
|
||||
vpptr = vp + b; vmptr = vm + b;
|
||||
|
||||
for (i = 0; i <= terms; i++)
|
||||
{
|
||||
*vpptr += n_p[i] * sp_p[(-i * bytes) + b] -
|
||||
d_p[i] * vp[(-i * bytes) + b];
|
||||
*vmptr += n_m[i] * sp_m[(i * bytes) + b] -
|
||||
d_m[i] * vm[(i * bytes) + b];
|
||||
}
|
||||
|
||||
for (j = i; j <= 4; j++)
|
||||
{
|
||||
*vpptr += (n_p[j] - bd_p[j]) * initial_p[b];
|
||||
*vmptr += (n_m[j] - bd_m[j]) * initial_m[b];
|
||||
}
|
||||
}
|
||||
if (has_alpha)
|
||||
{
|
||||
vp[bpp] = sp_p[bpp];
|
||||
vm[bpp] = sp_m[bpp];
|
||||
}
|
||||
|
||||
sp_p += bytes;
|
||||
sp_m -= bytes;
|
||||
vp += bytes;
|
||||
vm -= bytes;
|
||||
}
|
||||
|
||||
transfer_pixels (val_p, val_m, dest, bytes, width);
|
||||
|
||||
combine_to_gradient (dest, src2, bytes, width, amount);
|
||||
|
||||
if (preview)
|
||||
{
|
||||
memcpy (preview_buffer2 + row * width * bytes,
|
||||
dest,
|
||||
width * bytes);
|
||||
}
|
||||
else
|
||||
{
|
||||
gimp_pixel_rgn_set_row (&dest_rgn, dest, x, row + y, width);
|
||||
|
||||
progress += width * radius;
|
||||
if ((row % 20) == 0)
|
||||
gimp_progress_update ((double) progress / (double) max_progress);
|
||||
}
|
||||
}
|
||||
|
||||
if (preview)
|
||||
{
|
||||
gimp_preview_draw_buffer (preview, preview_buffer2, width * bytes);
|
||||
g_free (preview_buffer1);
|
||||
g_free (preview_buffer2);
|
||||
}
|
||||
else
|
||||
{
|
||||
gimp_progress_update (1.0);
|
||||
/* now, merge horizontal and vertical into a magnitude */
|
||||
gimp_pixel_rgn_init (&src_rgn, drawable,
|
||||
0, 0, drawable->width, drawable->height,
|
||||
FALSE, TRUE);
|
||||
|
||||
/* merge the shadow, update the drawable */
|
||||
gimp_drawable_flush (drawable);
|
||||
gimp_drawable_merge_shadow (drawable->drawable_id, TRUE);
|
||||
gimp_drawable_update (drawable->drawable_id,
|
||||
x, y, width, height);
|
||||
}
|
||||
/* free up buffers */
|
||||
g_free (val_p);
|
||||
g_free (val_m);
|
||||
g_free (src);
|
||||
g_free (src2);
|
||||
g_free (dest);
|
||||
}
|
||||
|
||||
static void
|
||||
transfer_pixels (gdouble *src1,
|
||||
gdouble *src2,
|
||||
guchar *dest,
|
||||
gint bytes,
|
||||
gint width)
|
||||
{
|
||||
gint b;
|
||||
gint bend = bytes * width;
|
||||
gdouble sum;
|
||||
|
||||
for (b = 0; b < bend; b++)
|
||||
{
|
||||
sum = *src1++ + *src2++;
|
||||
|
||||
if (sum > 255)
|
||||
sum = 255;
|
||||
else if (sum < 0)
|
||||
sum = 0;
|
||||
|
||||
*dest++ = (guchar) sum;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
combine_to_gradient (guchar *dest,
|
||||
guchar *src2,
|
||||
gint bytes,
|
||||
gint width,
|
||||
gdouble amount)
|
||||
{
|
||||
gint b;
|
||||
gint bend = bytes * width;
|
||||
gdouble h, v;
|
||||
gdouble sum;
|
||||
gdouble scale = (1.0 + 9.0 * amount);
|
||||
|
||||
for (b = 0; b < bend; b++)
|
||||
{
|
||||
/* scale result */
|
||||
h = *src2++;
|
||||
v = *dest;
|
||||
|
||||
sum = sqrt (h*h + v*v) * scale;
|
||||
|
||||
if (sum > 255)
|
||||
sum = 255;
|
||||
else if (sum < 0)
|
||||
sum = 0;
|
||||
|
||||
*dest++ = (guchar) sum;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
find_constants (gdouble n_p[],
|
||||
gdouble n_m[],
|
||||
gdouble d_p[],
|
||||
gdouble d_m[],
|
||||
gdouble bd_p[],
|
||||
gdouble bd_m[],
|
||||
gdouble std_dev)
|
||||
{
|
||||
gdouble a0, a1, b0, b1, c0, c1, w0, w1;
|
||||
gdouble w0n, w1n, cos0, cos1, sin0, sin1, b0n, b1n;
|
||||
|
||||
/* coefficients for Gaussian 1st derivative filter */
|
||||
a0 = 0.6472;
|
||||
a1 = 4.531;
|
||||
b0 = 1.527;
|
||||
b1 = 1.516;
|
||||
c0 = -0.6494;
|
||||
c1 = -0.9557;
|
||||
w0 = 0.6719;
|
||||
w1 = 2.072;
|
||||
|
||||
/* coefficients for Gaussian filter */
|
||||
/*
|
||||
a0 = 1.68;
|
||||
a1 = 3.735;
|
||||
b0 = 1.783;
|
||||
b1 = 1.723;
|
||||
c0 = -0.6803;
|
||||
c1 = -0.2598;
|
||||
w0 = 0.6318;
|
||||
w1 = 1.997;
|
||||
*/
|
||||
|
||||
/* coefficients for filter */
|
||||
w0n = w0 / std_dev;
|
||||
w1n = w1 / std_dev;
|
||||
cos0 = cos (w0n);
|
||||
cos1 = cos (w1n);
|
||||
sin0 = sin (w0n);
|
||||
sin1 = sin (w1n);
|
||||
b0n = b0 / std_dev;
|
||||
b1n = b1 / std_dev;
|
||||
|
||||
/*
|
||||
gdouble div;
|
||||
div = sqrt (2 * G_PI) * std_dev;
|
||||
a0 = a0 / div;
|
||||
a1 = a1 / div;
|
||||
c0 = c0 / div;
|
||||
c1 = c1 / div;
|
||||
*/
|
||||
|
||||
n_p[4] = 0.0;
|
||||
n_p[3] = exp (-b1n - 2 * b0n) * (c1 * sin1 - cos1 * c0) + exp (-b0n - 2 * b1n) * (a1 * sin0 - cos0 * a0);
|
||||
n_p[2] = 2 * exp (-b0n - b1n) * ((a0 + c0) * cos1 * cos0 - cos1 * a1 * sin0 - cos0 * c1 * sin1) + c0 * exp (-2 * b0n) + a0 * exp (-2 * b1n);
|
||||
n_p[1] = exp (-b1n) * (c1 * sin1 - (c0 + 2 * a0) * cos1) + exp (-b0n) * (a1 * sin0 - (2 * c0 + a0) * cos0);
|
||||
n_p[0] = a0 + c0;
|
||||
|
||||
d_p[4] = exp (-2 * b0n - 2 * b1n);
|
||||
d_p[3] = -2 * cos0 * exp (-b0n - 2 * b1n) - 2 * cos1 * exp (-b1n - 2 * b0n);
|
||||
d_p[2] = 4 * cos1 * cos0 * exp (-b0n - b1n) + exp (-2 * b1n) + exp (-2 * b0n);
|
||||
d_p[1] = -2 * exp (-b1n) * cos1 - 2 * exp (-b0n) * cos0;
|
||||
d_p[0] = 0.0;
|
||||
|
||||
/* For first derivative */
|
||||
n_m[4] = d_p[4] * n_p[0] - n_p[4];
|
||||
n_m[3] = d_p[3] * n_p[0] - n_p[3];
|
||||
n_m[2] = d_p[2] * n_p[0] - n_p[2];
|
||||
n_m[1] = d_p[1] * n_p[0] - n_p[1];
|
||||
n_m[0] = 0.0;
|
||||
|
||||
/* For gaussian operator */
|
||||
/*
|
||||
n_m[4] = n_p[4] - d_p[4] * n_p[0];
|
||||
n_m[3] = n_p[3] - d_p[3] * n_p[0];
|
||||
n_m[2] = n_p[2] - d_p[2] * n_p[0];
|
||||
n_m[1] = n_p[1] - d_p[1] * n_p[0];
|
||||
n_m[0] = 0.0;
|
||||
*/
|
||||
|
||||
d_m[4] = d_p[4];
|
||||
d_m[3] = d_p[3];
|
||||
d_m[2] = d_p[2];
|
||||
d_m[1] = d_p[1];
|
||||
d_m[0] = d_p[0];
|
||||
|
||||
{
|
||||
gint i;
|
||||
gdouble sum_n_p, sum_n_m, sum_d;
|
||||
gdouble a, b;
|
||||
|
||||
sum_n_p = 0.0;
|
||||
sum_n_m = 0.0;
|
||||
sum_d = 0.0;
|
||||
|
||||
for (i = 0; i <= 4; i++)
|
||||
{
|
||||
sum_n_p += n_p[i];
|
||||
sum_n_m += n_m[i];
|
||||
sum_d += d_p[i];
|
||||
}
|
||||
|
||||
a = sum_n_p / (1 + sum_d);
|
||||
b = sum_n_m / (1 + sum_d);
|
||||
|
||||
for (i = 0; i <= 4; i++)
|
||||
{
|
||||
bd_p[i] = d_p[i] * a;
|
||||
bd_m[i] = d_m[i] * b;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************/
|
||||
/* Dialog */
|
||||
/*******************************************************/
|
||||
|
||||
static gboolean
|
||||
neon_dialog (GimpDrawable *drawable)
|
||||
{
|
||||
GtkWidget *dialog;
|
||||
GtkWidget *main_vbox;
|
||||
GtkWidget *preview;
|
||||
GtkWidget *grid;
|
||||
GtkAdjustment *scale_data;
|
||||
gboolean run;
|
||||
|
||||
gimp_ui_init (PLUG_IN_BINARY, FALSE);
|
||||
|
||||
dialog = gimp_dialog_new (_("Neon Detection"), PLUG_IN_ROLE,
|
||||
NULL, 0,
|
||||
gimp_standard_help_func, PLUG_IN_PROC,
|
||||
|
||||
_("_Cancel"), GTK_RESPONSE_CANCEL,
|
||||
_("_OK"), GTK_RESPONSE_OK,
|
||||
|
||||
NULL);
|
||||
|
||||
gimp_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_from_drawable_id (drawable->drawable_id);
|
||||
gtk_box_pack_start (GTK_BOX (main_vbox), preview, TRUE, TRUE, 0);
|
||||
gtk_widget_show (preview);
|
||||
|
||||
g_signal_connect (preview, "invalidated",
|
||||
G_CALLBACK (neon_preview_update),
|
||||
drawable);
|
||||
|
||||
grid = gtk_grid_new ();
|
||||
gtk_grid_set_row_spacing (GTK_GRID (grid), 6);
|
||||
gtk_grid_set_column_spacing (GTK_GRID (grid), 6);
|
||||
gtk_box_pack_start (GTK_BOX (main_vbox), grid, FALSE, FALSE, 0);
|
||||
gtk_widget_show (grid);
|
||||
|
||||
/* Label, scale, entry for evals.radius */
|
||||
scale_data = gimp_scale_entry_new (GTK_GRID (grid), 0, 0,
|
||||
_("_Radius:"), 100, 8,
|
||||
evals.radius, 0.0, 64.0, 1, 10, 2,
|
||||
FALSE, 0.0,
|
||||
8 * MAX (drawable->width, drawable->height),
|
||||
NULL, NULL);
|
||||
|
||||
g_signal_connect (scale_data, "value-changed",
|
||||
G_CALLBACK (gimp_double_adjustment_update),
|
||||
&evals.radius);
|
||||
g_signal_connect_swapped (scale_data, "value-changed",
|
||||
G_CALLBACK (gimp_preview_invalidate),
|
||||
preview);
|
||||
|
||||
/* Label, scale, entry for evals.amount */
|
||||
scale_data = gimp_scale_entry_new (GTK_GRID (grid), 0, 1,
|
||||
_("_Amount:"), 100, 8,
|
||||
evals.amount, 0.0, 1.0, 0.01, 0.1, 2,
|
||||
TRUE, 0, 0,
|
||||
NULL, NULL);
|
||||
|
||||
g_signal_connect (scale_data, "value-changed",
|
||||
G_CALLBACK (gimp_double_adjustment_update),
|
||||
&evals.amount);
|
||||
g_signal_connect_swapped (scale_data, "value-changed",
|
||||
G_CALLBACK (gimp_preview_invalidate),
|
||||
preview);
|
||||
|
||||
gtk_widget_show (dialog);
|
||||
|
||||
run = (gimp_dialog_run (GIMP_DIALOG (dialog)) == GTK_RESPONSE_OK);
|
||||
|
||||
gtk_widget_destroy (dialog);
|
||||
|
||||
return run;
|
||||
}
|
||||
|
||||
static void
|
||||
neon_preview_update (GimpPreview *preview,
|
||||
GimpDrawable *drawable)
|
||||
{
|
||||
neon (drawable,
|
||||
evals.radius,
|
||||
evals.amount,
|
||||
preview);
|
||||
}
|
|
@ -19,7 +19,6 @@ depth_merge_RC = depth-merge.rc.o
|
|||
despeckle_RC = despeckle.rc.o
|
||||
destripe_RC = destripe.rc.o
|
||||
edge_dog_RC = edge-dog.rc.o
|
||||
edge_neon_RC = edge-neon.rc.o
|
||||
emboss_RC = emboss.rc.o
|
||||
file_aa_RC = file-aa.rc.o
|
||||
file_cel_RC = file-cel.rc.o
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
'despeckle' => { ui => 1, gegl => 1 },
|
||||
'destripe' => { ui => 1, gegl => 1 },
|
||||
'edge-dog' => { ui => 1 },
|
||||
'edge-neon' => { ui => 1 },
|
||||
'emboss' => { ui => 1 },
|
||||
'file-aa' => { ui => 1, gegl => 1, optional => 1, libs => 'AA_LIBS' },
|
||||
'file-cel' => { ui => 1, gegl => 1 },
|
||||
|
|
|
@ -25,7 +25,6 @@ plug-ins/common/depth-merge.c
|
|||
plug-ins/common/despeckle.c
|
||||
plug-ins/common/destripe.c
|
||||
plug-ins/common/edge-dog.c
|
||||
plug-ins/common/edge-neon.c
|
||||
plug-ins/common/emboss.c
|
||||
plug-ins/common/file-aa.c
|
||||
plug-ins/common/file-cel.c
|
||||
|
|
Loading…
Reference in New Issue