 |
| GimpChat Member |
 |
Joined: Oct 31, 2020 Posts: 2025
|
Inner Glow is getting an update soon to do two new things1. Solve it's conflict with gegl_command.py (for the past two weeks it broke it) 2. Work on adjustment layer groups in Gimp 2.99.19 -- Inner Glow will still have all its new fancy features One can test the update before I push it by compiling this /* This file is an image processing operation for GEGL * * GEGL is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * * GEGL 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with GEGL; if not, see <https://www.gnu.org/licenses/>. * * Copyright 2006 Øyvind Kolås <[email protected]> * 2022 Beaver (GEGL inner glow) */
/*GEGL Inner Glow is a stand alone plugin but it is also part of GEGL Effects. The stand alone version does more then the GEGL Effects implementation of it. */
/* Recreation of Inner Glow's GEGL Graph. May not be 100% accurate but you can test it without installing this way.
id=0 src-in aux=[ ref=0 id=1 dst-atop aux=[ ref=1 distance-transform ] xor srgb=true aux=[ ref=1 ] color-overlay value=#000000 dropshadow x=0 y=0 grow-radius=5 color-overlay value=#ff0000 ] median-blur radius=3 alpha-percentile=94 crop
*/
#include "config.h" #include <glib/gi18n-lib.h>
#ifdef GEGL_PROPERTIES /*This is a list of the default inner glow plugin and its modern successors.*/
enum_start (inner_glow_list) enum_value (DEFAULT_IG, "default", N_("Default Inner Glow")) enum_value (INVERT_TRANSPARENCY_IG, "invert", N_("Invert Transparency")) enum_value (DEFAULT_IG_IMAGE_UPLOAD, "defaultimage", N_("Image Upload")) enum_value (INVERT_TRANSPARENCY_IG_IMAGE_UPLOAD, "invertimage", N_("Image Upload with Inverted Transparency")) enum_value (FEB_2024_IG, "feb2024", N_("Feb 2024 Inner Glow")) enum_value (GRAINY_IG, "grainy", N_("Grainy Inner Glow")) enum_value (BEVEL_IG, "beveled", N_("Beveled Inner Glow")) enum_end (innerglowlist)
property_enum (mode, _("Mode:"), innerglowlist, inner_glow_list, DEFAULT_IG) description (_("Change the default mode of Inner Glow to an alternative mode where inner glow inverts transparency and or allows image file uploads over it."))
enum_start (gegl_blend_mode_typeig) enum_value (GEGL_BLEND_MODE_TYPE_HARDLIGHT, "hardlight", N_("Hard Light")) enum_value (GEGL_BLEND_MODE_TYPE_MULTIPLY, "multiply", N_("Multiply")) enum_value (GEGL_BLEND_MODE_TYPE_SCREEN, "screen", N_("Screen")) enum_value (GEGL_BLEND_MODE_TYPE_GRAINMERGE, "grainmerge", N_("Grain Merge")) enum_end (GeglBlendModeTypeig0)
property_enum (bevelblendmode, _("Emboss blend mode:"), GeglBlendModeTypeig0, gegl_blend_mode_typeig, GEGL_BLEND_MODE_TYPE_HARDLIGHT) ui_meta ("visible", "mode {beveled }" )
/*This is GEGL syntax I wrote to invert transparency. Its operation is gegl:gegl and it represents a GEGL Graph inside a GEGL Graph. please know distance transform is only here for filling the entire image with content. i could have used other nodes like "solid-noise, cell-noise, ect... but distance transform was the fastest. gegl:color was faster but broke the graph */ #define GRAPHUSEDBYINNERGLOW \ " id=1 dst-atop aux=[ ref=1 distance-transform ] xor srgb=true aux=[ ref=1 ] color-overlay value=#000000 "\
#define GRAPHUSEDBYINNERGLOW2 \ " id=1 src-out aux=[ color value=black] crop aux=[ ref=1 ] "\
/*On June 24 2023 I finally figured out how to bake in GEGL Graphs*/
/*This is an enum list for the base shape of inner stroke/shadow/glow. It should not be renamed.*/ enum_start (gegl_dropshadow_grow_shapeig) enum_value (GEGL_DROPSHADOW_GROW_SHAPE_SQUAREig, "squareig", N_("Square")) enum_value (GEGL_DROPSHADOW_GROW_SHAPE_CIRCLEig, "circleig", N_("Circle")) enum_value (GEGL_DROPSHADOW_GROW_SHAPE_DIAMONDig, "diamondig", N_("Diamond")) enum_end (GeglDropshadowGrowShapeig)
property_enum (grow_shape, _("Grow shape"), GeglDropshadowGrowShapeig, gegl_dropshadow_grow_shapeig, GEGL_DROPSHADOW_GROW_SHAPE_CIRCLEig) description (_("The shape to expand or contract the shadow in"))
property_double (x, _("X"), 0.0) description (_("Horizontal shadow offset")) ui_range (-20.0, 20.0) value_range (-20.0, 20.0) ui_steps (1, 2) ui_meta ("axis", "x")
property_double (y, _("Y"), 0.0) description (_("Vertical shadow offset")) ui_range (-20.0, 20.0) value_range (-20.0, 20.0) ui_steps (1, 2) ui_meta ("axis", "y")
property_double (radius, _("Blur radius"), 9) value_range (0.0, 60.0) ui_range (0.0, 40.0) ui_steps (1, 5) ui_gamma (1.5) ui_meta ("unit", "pixel-distance")
property_double (grow_radius, _("Grow radius"), 4.0) value_range (1, 40.0) ui_range (1, 30.0) ui_digits (0) ui_steps (1, 5) ui_gamma (1.5) ui_meta ("unit", "pixel-distance") description (_("The distance to expand the shadow before blurring. When using inverted modes this setting needs to be at a reasonable degree for it's effect to be noticable."))
property_double (noise, _("Increase Noise"), 60.0) value_range (10.0, 100.0) ui_meta ("visible", "mode {grainy }" )
property_double (noiserepeat, _("Repetition of noise"), 8.0) value_range (5.0, 100.0) ui_meta ("visible", "mode {grainy }" )
property_seed (seed, _("Noise seed"), rand) ui_meta ("visible", "mode {grainy }" )
property_double (opacity, _("Opacity"), 1.2) value_range (0.0, 2.0) ui_steps (0.01, 0.10)
property_color (value2, _("Color"), "#fbff00") description (_("The color to paint over the input")) ui_meta ("role", "color-primary") ui_meta ("visible", "!mode {defaultimage, invertimage }" )
property_double (fixoutline, _("Median to fix non-effected pixels on edges"), 60) value_range (50, 100) description (_("Due to a bug I can't solve, not all pixels will be effected by inner glow. Median blur solves that problem.'")) ui_meta ("visible", "!mode {feb2024, grainy, beveled }" )
property_int (fixoutline2, _("Median to fix non-effected pixels on edges 2"), 1) value_range (0, 5) description (_("Due to a bug I can't solve, not all pixels will be effected by inner glow. Median blur solves that problem.")) ui_meta ("visible", "mode {grainy, feb2024, beveled }" )
property_file_path (image, _("Upload image file"), "") description (_("Upload image file for inner Glow")) ui_meta ("visible", "!mode {default, grainy, feb2024, beveled, invert }" )
property_double (imageblur, _("Blur image uploaded"), 0.0) value_range (0.0, 20.0) description (_("Blur image file upload only")) ui_meta ("visible", "!mode {default, invert, grainy, beveled, feb2024 }" )
property_boolean (clippolicy, _("Clip setting (bug trade off)"), TRUE) description (_("Enable or disable the inner glow's clip. When disabled it will create a border bug when blur radius is high. When enabled it will clip Gimp's layers to image size setting."))
#else
#define GEGL_OP_META #define GEGL_OP_NAME inner_glow #define GEGL_OP_C_SOURCE inner-glow.c
#include "gegl-op.h"
typedef struct { GeglNode *input; GeglNode *it; GeglNode *it2; GeglNode *src; GeglNode *pick; GeglNode *shadow; GeglNode *shadowopacitymax; GeglNode *color; GeglNode *color2; GeglNode *median2; GeglNode *medianset; GeglNode *in; GeglNode *in2; GeglNode *in3; GeglNode *in4; GeglNode *ingrainy; GeglNode *c2arevision; GeglNode *out; GeglNode *blurimage; GeglNode *idref; GeglNode *idref2; GeglNode *idref3; GeglNode *crop; GeglNode *atop; GeglNode *image; GeglNode *multiplybevel; GeglNode *screenbevel; GeglNode *hardlightbevel; GeglNode *grainmergebevel; GeglNode *nothing; GeglNode *output; }State;
static void attach (GeglOperation *operation) { GeglNode *gegl = operation->node; GeglProperties *o = GEGL_PROPERTIES (operation);
State *state = o->user_data = g_malloc0 (sizeof (State)); GeglColor *hidden_color = gegl_color_new ("#00ffffAA"); state->input = gegl_node_get_input_proxy (gegl, "input"); state->output = gegl_node_get_output_proxy (gegl, "output");
state->it = gegl_node_new_child (gegl, "operation", "gegl:gegl", "string", GRAPHUSEDBYINNERGLOW, NULL);
state->it2 = gegl_node_new_child (gegl, "operation", "gegl:gegl", "string", GRAPHUSEDBYINNERGLOW2, NULL); /*On June 24 2023 I finally figured out how to bake in GEGL Graphs At Nov 20 2023 I learned that two nodes can call the same graph, also this graph inverts transparency.*/
state->in = gegl_node_new_child (gegl, "operation", "gegl:src-in", NULL);
state->in2 = gegl_node_new_child (gegl, "operation", "gegl:src-in", NULL);
state->in3 = gegl_node_new_child (gegl, "operation", "gegl:src-in", NULL);
state->in4 = gegl_node_new_child (gegl, "operation", "gegl:src-in", NULL);
state->ingrainy = gegl_node_new_child (gegl, "operation", "gegl:src-in", NULL);
state->out = gegl_node_new_child (gegl, "operation", "gegl:src-out", NULL);
state->src = gegl_node_new_child (gegl, "operation", "gegl:src", NULL);
state->pick = gegl_node_new_child (gegl, "operation", "gegl:noise-pick", NULL);
state->atop = gegl_node_new_child (gegl, "operation", "gegl:src-atop", NULL);
state->image = gegl_node_new_child (gegl, "operation", "gegl:layer", NULL);
state->idref3 = gegl_node_new_child (gegl, "operation", "gegl:nop", NULL);
state->idref2 = gegl_node_new_child (gegl, "operation", "gegl:nop", NULL);
state->idref = gegl_node_new_child (gegl, "operation", "gegl:nop", NULL);
state->crop = gegl_node_new_child (gegl, "operation", "gegl:crop", NULL); /*This node was added November 20 2023 to fix another border bug that happens with layer to image size, where inner glow goes OUTSIDE the selection some how. This is a bug with Gimp internally but somehow crop fixes it.*/
state->blurimage = gegl_node_new_child (gegl, "operation", "gegl:gaussian-blur", NULL);
state->shadow = gegl_node_new_child (gegl, "operation", "gegl:dropshadow", NULL);
#define opacitymax \ " median-blur radius=0 opacity value=2 median-blur radius=0 "\
state->shadowopacitymax = gegl_node_new_child (gegl, "operation", "gegl:gegl", "string", opacitymax, NULL);
state->color = gegl_node_new_child (gegl, "operation", "gegl:color-overlay", "value", hidden_color, NULL); /*This is a trick to bake in color nodes*/
state->color2 = gegl_node_new_child (gegl, "operation", "gegl:color-overlay", NULL);
state->median2 = gegl_node_new_child (gegl, "operation", "gegl:median-blur", "radius", 1, NULL);
state->medianset = gegl_node_new_child (gegl, "operation", "gegl:median-blur", "radius", 1, "alpha-percentile", 100.0, NULL);
#define screen \ " id=1 screen aux=[ ref=1 emboss opacity value=0.7 ] "\
state->screenbevel = gegl_node_new_child (gegl, "operation", "gegl:gegl", "string", screen, NULL);
#define hardlight \ " id=1 hard-light aux=[ ref=1 emboss opacity value=0.2 ] "\
state->hardlightbevel = gegl_node_new_child (gegl, "operation", "gegl:gegl", "string", hardlight, NULL);
#define grainmerge \ " id=1 gimp:layer-mode layer-mode=grain-merge blend-space=rgb-perceptual aux=[ ref=1 emboss opacity value=0.5 ] "\
state->grainmergebevel = gegl_node_new_child (gegl, "operation", "gegl:gegl", "string", grainmerge, NULL); #define multiply \ " id=1 gimp:layer-mode layer-mode=multiply aux=[ ref=1 emboss opacity value=0.5 ] "\
state->multiplybevel = gegl_node_new_child (gegl, "operation", "gegl:gegl", "string", multiply, NULL);
#define c2afeb2024 \ " color-to-alpha color=black transparency-threshold=0 opacity-threshold=1 "\
state->c2arevision = gegl_node_new_child (gegl, "operation", "gegl:gegl", "string", c2afeb2024, NULL);
state->nothing = gegl_node_new_child (gegl, "operation", "gegl:dst", NULL);
gegl_operation_meta_redirect (operation, "grow_radius", state->shadow, "grow-radius"); gegl_operation_meta_redirect (operation, "radius", state->shadow, "radius"); gegl_operation_meta_redirect (operation, "opacity", state->shadow, "opacity"); gegl_operation_meta_redirect (operation, "grow-shape", state->shadow, "grow-shape"); gegl_operation_meta_redirect (operation, "value2", state->color2, "value"); gegl_operation_meta_redirect (operation, "x", state->shadow, "x"); gegl_operation_meta_redirect (operation, "y", state->shadow, "y"); gegl_operation_meta_redirect (operation, "fixoutline", state->median2, "alpha-percentile"); gegl_operation_meta_redirect (operation, "fixoutline2", state->medianset, "radius"); gegl_operation_meta_redirect (operation, "image", state->image, "src"); gegl_operation_meta_redirect (operation, "imageblur", state->blurimage, "std-dev-x"); gegl_operation_meta_redirect (operation, "imageblur", state->blurimage, "std-dev-y"); gegl_operation_meta_redirect (operation, "noise", state->pick, "pct-random"); gegl_operation_meta_redirect (operation, "noiserepeat", state->pick, "repeat"); gegl_operation_meta_redirect (operation, "seed", state->pick, "seed");
}
static void update_graph (GeglOperation *operation) { GeglProperties *o = GEGL_PROPERTIES (operation); State *state = o->user_data; if (!state) return;
GeglNode *usethis = state->multiplybevel; /* the blend mode switcher for the bevel applying to inner glow*/ GeglNode *crop; if (o->clippolicy) crop = state->crop; if (!o->clippolicy) crop = state->nothing;
switch (o->bevelblendmode) { case GEGL_BLEND_MODE_TYPE_MULTIPLY: usethis = state->multiplybevel; break; case GEGL_BLEND_MODE_TYPE_GRAINMERGE: usethis = state->grainmergebevel; break; case GEGL_BLEND_MODE_TYPE_HARDLIGHT: usethis = state->hardlightbevel; break; case GEGL_BLEND_MODE_TYPE_SCREEN: usethis = state->screenbevel; break; default: usethis = state->multiplybevel; }
switch (o->mode) { break; case DEFAULT_IG: gegl_node_link_many (state->input, state->it, state->shadow, state->color, state->in, state->median2, state->color2, crop, state->output, NULL); gegl_node_connect (state->in, "aux", state->input, "output"); gegl_node_connect (state->crop, "aux", state->input, "output"); break; case INVERT_TRANSPARENCY_IG: gegl_node_link_many (state->input, state->it, state->shadow, state->it2, state->color, state->in, state->median2, state->color2, crop, state->output, NULL); gegl_node_connect (state->in, "aux", state->input, "output"); gegl_node_connect (state->crop, "aux", state->input, "output"); break; case DEFAULT_IG_IMAGE_UPLOAD: gegl_node_link_many (state->input, state->it, state->shadow, state->color, state->in, state->median2, state->color2, state->idref, state->atop, crop, state->output, NULL); gegl_node_link_many (state->idref, state->image, state->blurimage, NULL); gegl_node_connect (state->in, "aux", state->input, "output"); gegl_node_connect (state->atop, "aux", state->blurimage, "output"); gegl_node_connect (state->crop, "aux", state->input, "output"); break; case INVERT_TRANSPARENCY_IG_IMAGE_UPLOAD: gegl_node_link_many (state->input, state->it, state->shadow, state->it2, state->color, state->in, state->median2, state->color2, state->idref, state->atop, crop, state->output, NULL); gegl_node_link_many (state->idref, state->image, state->blurimage, NULL); gegl_node_connect (state->in, "aux", state->input, "output"); gegl_node_connect (state->atop, "aux", state->blurimage, "output"); gegl_node_connect (state->crop, "aux", state->input, "output"); break; case FEB_2024_IG: gegl_node_link_many (state->input, state->medianset, state->idref, state->in2, crop, state->output, NULL); gegl_node_link_many (state->idref, state->it2, state->shadow, state->color2, NULL); gegl_node_connect (state->in2, "aux", state->color2, "output"); gegl_node_connect (state->crop, "aux", state->input, "output"); break; case GRAINY_IG: /*This is median blur followed by GEGL's src-in blend mode and a crop*/ gegl_node_link_many (state->input, state->medianset, state->idref3, state->in3, crop, state->output, NULL); /*Inside the src in blend mode we have a gegl graph, drop shadow, color overlay and another src-in blend mode*/ gegl_node_connect (state->in3, "aux", state->ingrainy, "output"); gegl_node_link_many (state->idref3, state->it2, state->shadow, state->color2, state->idref2, state->ingrainy, NULL); /*Inside the second src in blend mode with have the pick filter.*/ gegl_node_connect (state->ingrainy, "aux", state->pick, "output"); gegl_node_link_many (state->idref2, state->pick, NULL); gegl_node_connect (state->crop, "aux", state->input, "output"); break; case BEVEL_IG: gegl_node_link_many (state->input, state->medianset, state->idref, state->in4, crop, state->output, NULL); gegl_node_link_many (state->idref, state->it2, state->shadow, state->color2, usethis, NULL); gegl_node_connect (state->in4, "aux", usethis, "output"); gegl_node_connect (state->crop, "aux", state->input, "output"); } }
static void gegl_op_class_init (GeglOpClass *klass) { GeglOperationClass *operation_class; GeglOperationMetaClass *operation_meta_class = GEGL_OPERATION_META_CLASS (klass); operation_class = GEGL_OPERATION_CLASS (klass);
operation_class->attach = attach; operation_meta_class->update = update_graph;
gegl_operation_class_set_keys (operation_class, "name", "lb:innerglow", "title", _("Inner Glow (to blend)"), "reference-hash", "g3do6aaoo1100g0fjf25sb2ac", "description", _("GEGL does an inner glow effect. For this filter to work you need to use the 'Normal' or other blending options. Or a duplicate layer on top. " ""), "gimp:menu-path", "<Image>/Filters/Text Styling", "gimp:menu-label", _("Inner Glow (to blend)..."), NULL); }
#endif
|
|