It is currently Sat Jul 06, 2024 7:15 pm


All times are UTC - 5 hours [ DST ]



Post new topic Reply to topic  [ 9 posts ] 
Author Message
 Post subject: GEGL Pixel Text - plugin download
PostPosted: Thu Nov 23, 2023 6:23 pm  (#1) 
Offline
GimpChat Member
User avatar

Joined: Oct 31, 2020
Posts: 1457
This plugin is released. Download here
https://github.com/LinuxBeaver/Gimp-Pix ... imp_plugin


EVERYTHING BELOW ON THE FIRST PAGE IS JUST DOCUMENTATION OF THIS PLUGINS DEVELOPMENT THAT WAS INTENTIONALLY PROCRASTINATED.


This thread exist for an up and coming Gimp GEGL plugin called "Pixel Text" here is a preview of its graph.

Attachment:
pasted_image417.png
pasted_image417.png [ 104.83 KiB | Viewed 32436 times ]


This one has an extra drop shadow.
Attachment:
pasted_image415.png
pasted_image415.png [ 1.41 MiB | Viewed 32436 times ]


Here is the syntax itself to create this in GEGL Graph


id=0 src-atop aux=[ ref=0 layer src=image_path_here.png/jpg  ]

pixelize size-x=14 size-y=14
median-blur radius=0
id=1 dst-over aux=[ ref=1 translate x=5 y=4 levels out-high=0.2 saturation scale=1
id=x multiply aux=[ ref=x emboss depth=40 elevation=10] ]
gegl:opacity value=2
median-blur radius=0


The node "multiply" can be swapped with "overlay"

The GEGL .c format for this is

srcatop = gegl:src-atop, (alpha lock and normal blend mode combined)
pixel = gegl:pixelize
fix = gegl:median-blur radius=0 (this fixes glitches by resetting gegl:opacity's shenigans)
idref = gegl:nop (This makes a bookmark of an image in the middle of a graph and calls it later)
behind = gegl:dst-over (this is the behind blend mode in GEGL)
idref2 = gegl:nop (This makes a bookmark of an image in the middle of a graph and calls it later)
multiply = gegl:multiply
opacity = gegl:opacity (This does something called hyper opacity which is opacity about 100% and it creates a known glitch)
fix2 = median-blur radius=0 (this fixes glitches by resetting gegl:opacity's shenigans)
emboss = gegl:emboss
levels = gegl:levels
layer = gegl:layer (This node calls gegl:layer src=) which is the image file upload.

THESE ARE THE NODES IN THE ASSUMED CORRECT ORDER NOT TESTED YET
input, srcatop, pixel, fix, idref, behind. idref2, multiply, opacity, fix2, output
srcatop connects to layer
behind connects to levels
multiply connects to -emboss
idred2, -emboss


The bottom line is this thread exist so we can learn together how to make GEGL plugins and hopefully some OTHER THEN ME makes one. I will update this thread as the development of this plugin continues. It will be developing in real time and once the development is down the download will be on an edited first post.


Last edited by contrast_ on Fri Dec 15, 2023 6:48 pm, edited 3 times in total.

Share on Facebook Share on Twitter Share on Orkut Share on Digg Share on MySpace Share on Delicious Share on Technorati
Top
 Post subject: Re: GEGL Pixel Text (In Development)
PostPosted: Sat Nov 25, 2023 3:16 pm  (#2) 
Offline
GimpChat Member
User avatar

Joined: Oct 31, 2020
Posts: 1457
Here is a GEGL filter in development.
Read the notes in *//* on the individual code to see how the nodes connect or what the operations do

This is the part of Pixel Text's graph that contains all the node names only. Node names can be anything in any particular order.

typedef struct
{
GeglNode *input;
GeglNode *pixel;
GeglNode *fix;
GeglNode *fix2;
GeglNode *behind;
GeglNode *alphalock;
GeglNode *offset;
GeglNode *levels;
GeglNode *saturation;
GeglNode *multiply;
GeglNode *overlay;
GeglNode *idref;
GeglNode *idref2;
GeglNode *overlay;
GeglNode *opacity;
GeglNode *output;
}State;



And this is the part where we have to relist the nodes with their given names in a different way, with the option to add paramaters like gegl:median-blur "radius=0", radius=0 was the parameter. The node names have to correspond to the names given above but the gegl operation name must be a valid gegl operation like gegl:emboss.



/*This is where the nodes are listed (again) with the option to define some properties, They do not have to be listed in correct order*/

/*This node is Gimp's pixelize filter and does most of the work in making the text style"*/
  state->pixel = gegl_node_new_child (gegl,
                                  "operation", "gegl:pixelize",
                                  NULL);

/*These two fix nodes are median blur's at 0 radius that fix a bug relating to gegl:opacity corrupting the alpha channel"*/
  state->fix = gegl_node_new_child (gegl,
                                  "operation", "gegl:median-blur", "radius", 0,
                                  NULL);



  state->fix2 = gegl_node_new_child (gegl,
                                  "operation", "gegl:median-blur", "radius", 0,
                                  NULL);

/*DST Over is a GEGL blend mode that does the same thing as Gimp's behind blend mode."*/

  state->behind = gegl_node_new_child (gegl,
                                  "operation", "gegl:dst-over",
                                  NULL);

/*SRC-ATOP is a GEGL exclusive blend mode that does something LIKE Gimp's "lock alpha channel" option. This blend mode is unique to GEGL"*/

  state->alphalock = gegl_node_new_child (gegl,
                                  "operation", "gegl:src-atop",
                                  NULL);

/*This node "translate" is a gegl move tool similar to "offset"*/

  state->offset = gegl_node_new_child (gegl,
                                  "operation", "gegl:translate", "x", 5, "y", 4,
                                  NULL);

  state->levels = gegl_node_new_child (gegl,
                                  "operation", "gegl:levels", "out-high", 0.2,
                                  NULL);

  state->saturation = gegl_node_new_child (gegl,
                                  "operation", "gegl:saturation", "scale", 1.1,
                                  NULL);

/*These two nodes multiply and overlay will be called to replace "blendmodechange"*/
  state->multiply = gegl_node_new_child (gegl,
                                  "operation", "gegl:multiply",
                                  NULL);

  state->overlay = gegl_node_new_child (gegl,
                                  "operation", "gegl:overlay",
                                  NULL);
/*These two nop nodes function as independent id and refs*/


  state->idref1 = gegl_node_new_child (gegl,
                                  "operation", "gegl:nop",
                                  NULL);


  state->idref2 = gegl_node_new_child (gegl,
                                  "operation", "gegl:nop",
                                  NULL);

  state->emboss = gegl_node_new_child (gegl,
                                  "operation", "gegl:emboss",
                                  NULL);


  state->opacity = gegl_node_new_child (gegl,
                                  "operation", "gegl:opacity", "value", 2.0,
                                  NULL);



This is where the GEGL Graph itself is and the node "blendmodechange" is the only node without a state-> as it will either be multiply or overlay depending on what the user chooses.


static void
update_graph (GeglOperation *operation)
{
  GeglProperties *o = GEGL_PROPERTIES (operation);
  State *state = o->user_data;
  if (!state) return;

/* This is where the stateless blendmodechange gets swapped for multiply or overlay.
"switchblendmode will be its property name in the GUI" */
  GeglNode *blendmodechange = state->multiply; /* the default node is multiply  */
  switch (o->switchblendmode) {
    case BLEND_MODE_TYPE_OVERLAY: blendmodechange = state->overlay; break;
    case BLEND_MODE_TYPE_MULTIPLY: blendmodechange = state->multiply; break;
default: blendmodechange = state->overlay;

/* This is the GEGL Graph itself and nodes do have to be in the correct order.

"blendmodechange" lacks a state-> because it will be either or blend mode we want (overlay or multiply)*/
  gegl_node_link_many (state->input, state->alphalock, state->pixel, state->fix, state->idref1, state->behind, state->idref2, blendmodechange, state->opacity, state->fix2, state->output, NULL);
  gegl_node_link_many (state->idref2, emboss  NULL);
/*idref2 also know as gegl:nop connects to emboss because it is the last node in the second link_many. It is sending a image of the graph's current state to be embossed. That is why it is seen
before and after "blend mode change"*/
  gegl_node_connect_from (state->idref2, "aux", state->emboss, "output");
/*blendmodechange the only node without a state-> is connecting to emboss so it can be a blend mode switcher of either "gegl:overlay or gegl:multiply"*/
  gegl_node_connect_from (blendmodechange, "aux", state->emboss, "output");
/*The lock alpha channel blend mode (gegl:src-atop) is connecting to gegl:layer src=imagepathhere.jpg for an image file upload ability*/
  gegl_node_connect_from (state->alphalock, "aux", state->layer, "output");
/*Idref1 (The first gegl:nop) exist to make a duplicate of pixelize's effect and put it behind the original image and then tweak it with levels and saturation to darken it.
It connects to levels because that is the last node.*/
  gegl_node_link_many (state->idref1, state->saturation, state->levels,  NULL);
  gegl_node_connect_from (state->behind, "aux", state->levels, "output");



This is the entire code so far and it does NOT work and does NOT compile

/* 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 <pippin@gimp.org>
* 2023, - Pixel Text, Beaver


Test this filter without installing by pasting this syntax into Gimp's GEGL graph. This filter works best with an image file upload


id=0 src-atop aux=[ ref=0 layer src=/home/USERNAME/Pictures/Magic/pattern_fills/pattern_plaid-pattern-2_1_3_0-0_0_1__ff8ab3_00e1ff.png   ]

pixelize size-x=14 size-y=14
median-blur radius=0
id=1 dst-over aux=[ ref=1 translate x=5 y=4 levels out-high=0.2 saturation scale=1
id=x multiply aux=[ ref=x emboss depth=40 elevation=10] ]
gegl:opacity value=2
median-blur radius=0

*/

#include "config.h"
#include <glib/gi18n-lib.h>

#ifdef GEGL_PROPERTIES

/* This is Properties (part 1) where properties are shown in the GUI based on their definitions in Properties (part two)

THEY ARE NOT YET DEFINED*/


property_double (yourpropertyname, _("Name for GUI"), 0.0)
   description (_("description"))
   value_range (0.0, 20.0)
   ui_range    (0.24, 20.0)
   ui_gamma    (3.0)



#else

#define GEGL_OP_META
#define GEGL_OP_NAME     pixel_text
#define GEGL_OP_C_SOURCE pixel_text.c

#include "gegl-op.h"

/*This is where the nodes are listed without any properties defined. They do not have to be listed in correct order. */
typedef struct
{
GeglNode *input;
GeglNode *pixel;
GeglNode *fix;
GeglNode *fix2;
GeglNode *behind;
GeglNode *alphalock;
GeglNode *offset;
GeglNode *levels;
GeglNode *saturation;
GeglNode *multiply;
GeglNode *overlay;
GeglNode *idref;
GeglNode *idref2;
GeglNode *overlay;
GeglNode *opacity;
GeglNode *output;
}State;

static void attach (GeglOperation *operation)
{
  GeglNode *gegl = operation->node;
  GeglNode *input, *output;

  state->input    = gegl_node_get_input_proxy (gegl, "input");
  state->output   = gegl_node_get_output_proxy (gegl, "output");




/*This is where the nodes are listed (again) with the option to define some properties, They do not have to be listed in correct order*/

/*This node is Gimp's pixelize filter and does most of the work in making the text style"*/
  state->pixel = gegl_node_new_child (gegl,
                                  "operation", "gegl:pixelize",
                                  NULL);

/*These two fix nodes are median blur's at 0 radius that fix a bug relating to gegl:opacity corrupting the alpha channel"*/
  state->fix = gegl_node_new_child (gegl,
                                  "operation", "gegl:median-blur", "radius", 0,
                                  NULL);



  state->fix2 = gegl_node_new_child (gegl,
                                  "operation", "gegl:median-blur", "radius", 0,
                                  NULL);

/*DST Over is a GEGL blend mode that does the same thing as Gimp's behind blend mode."*/

  state->behind = gegl_node_new_child (gegl,
                                  "operation", "gegl:dst-over",
                                  NULL);

/*SRC-ATOP is a GEGL exclusive blend mode that does something LIKE Gimp's "lock alpha channel" option. This blend mode is unique to GEGL"*/

  state->alphalock = gegl_node_new_child (gegl,
                                  "operation", "gegl:src-atop",
                                  NULL);

/*This node "translate" is a gegl move tool similar to "offset"*/

  state->offset = gegl_node_new_child (gegl,
                                  "operation", "gegl:translate", "x", 5, "y", 4,
                                  NULL);

  state->levels = gegl_node_new_child (gegl,
                                  "operation", "gegl:levels", "out-high", 0.2,
                                  NULL);

  state->saturation = gegl_node_new_child (gegl,
                                  "operation", "gegl:saturation", "scale", 1.1,
                                  NULL);

/*These two nodes multiply and overlay will be called to replace "blendmodechange"*/
  state->multiply = gegl_node_new_child (gegl,
                                  "operation", "gegl:multiply",
                                  NULL);

  state->overlay = gegl_node_new_child (gegl,
                                  "operation", "gegl:overlay",
                                  NULL);
/*These two nop nodes function as independent id and refs*/


  state->idref1 = gegl_node_new_child (gegl,
                                  "operation", "gegl:nop",
                                  NULL);


  state->idref2 = gegl_node_new_child (gegl,
                                  "operation", "gegl:nop",
                                  NULL);

  state->emboss = gegl_node_new_child (gegl,
                                  "operation", "gegl:emboss",
                                  NULL);


  state->opacity = gegl_node_new_child (gegl,
                                  "operation", "gegl:opacity", "value", 2.0,
                                  NULL);



/* This is Properties (part 2) where properties are defined

THEY ARE NOT YET DEFINED*/
gegl_operation_meta_redirect (operation, "yourproperty", opname, "propertyname");

}

static void
update_graph (GeglOperation *operation)
{
  GeglProperties *o = GEGL_PROPERTIES (operation);
  State *state = o->user_data;
  if (!state) return;

/* This is where the stateless blendmodechange gets swapped for multiply or overlay.
"switchblendmode will be its property name in the GUI" */
  GeglNode *blendmodechange = state->multiply; /* the default node is multiply  */
  switch (o->switchblendmode) {
    case BLEND_MODE_TYPE_OVERLAY: blendmodechange = state->overlay; break;
    case BLEND_MODE_TYPE_MULTIPLY: blendmodechange = state->multiply; break;
default: blendmodechange = state->overlay;

/* This is the GEGL Graph itself and nodes do have to be in the correct order.

"blendmodechange" lacks a state-> because it will be either or blend mode we want (overlay or multiply)*/
  gegl_node_link_many (state->input, state->alphalock, state->pixel, state->fix, state->idref1, state->behind, state->idref2, blendmodechange, state->opacity, state->fix2, state->output, NULL);
  gegl_node_link_many (state->idref2, emboss  NULL);
/*idref2 also know as gegl:nop connects to emboss because it is the last node in the second link_many. It is sending a image of the graph's current state to be embossed. That is why it is seen
before and after "blend mode change"*/
  gegl_node_connect_from (state->idref2, "aux", state->emboss, "output");
/*blendmodechange the only node without a state-> is connecting to emboss so it can be a blend mode switcher of either "gegl:overlay or gegl:multiply"*/
  gegl_node_connect_from (blendmodechange, "aux", state->emboss, "output");
/*The lock alpha channel blend mode (gegl:src-atop) is connecting to gegl:layer src=imagepathhere.jpg for an image file upload ability*/
  gegl_node_connect_from (state->alphalock, "aux", state->layer, "output");
/*Idref1 (The first gegl:nop) exist to make a duplicate of pixelize's effect and put it behind the original image and then tweak it with levels and saturation to darken it.
It connects to levels because that is the last node.*/
  gegl_node_link_many (state->idref1, state->saturation, state->levels,  NULL);
  gegl_node_connect_from (state->behind, "aux", state->levels, "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,
/* This is where the operation name, title name, description, menu path and menu label go.*/
    "name",        "lb:pixel-text",
    "title",       _("Pixel Text"),
    "reference-hash", "action52avgnmeme",
    "description", _("Make retro gaming text"),
    "gimp:menu-path", "<Image>/Filters/Text Styling/",
    "gimp:menu-label", _("Pixel Text..."),
    NULL);
}

#endif


Top
 Post subject: Re: GEGL Pixel Text (In Development)
PostPosted: Sat Nov 25, 2023 11:10 pm  (#3) 
Offline
GimpChat Member
User avatar

Joined: Oct 31, 2020
Posts: 1457
The GUI options are coming about

These are four sliders so far, Pixelize, Blend Mode Choice, Depth and Elevation.

property_double (pixelize, _("Pixelize Meter"), 14.0)
   description (_("Pixelization of the text."))
   value_range (1.0, 25.0)
   ui_range    (0.24, 25.0)
   ui_gamma    (3.0)



enum_start (emboss_blend_pixel)
   enum_value (BLEND_MODE_TYPE_OVERLAY,    "overlay",    N_("Overlay"))
   enum_value (BLEND_MODE_TYPE_MULTIPLY,  "multiply",  N_("Multiply"))
enum_end (embossblendpixel)

property_enum (switchblendmode, _("Blend mode of Emboss"),
               embossblendpixel, emboss_blend_pixel,
               BLEND_MODE_TYPE_OVERLAY)
  description (_("Select a scale algorithm. No Halo works best on scaling down images less then half and LoHalo works best on scaling down images more then half."))


property_double (depth, _("Emboss Depth"), 40.0)
   description (_("Emboss Depth for the emboss effecting the text."))
   value_range (10.0, 60.0)
   ui_range    (10.0, 60.0)
   ui_gamma    (3.0)


property_double (elevation, _("Emboss Elevation"), 40.0)
   description (_("Emboss Elevation for the emboss effecting the text."))
   value_range (10.0, 60.0)
   ui_range    (10.0, 60.0)
   ui_gamma    (3.0)


All sliders but "switchblendmode/embossblendpixel" correspond to this section of the .c file


gegl:pixelize's size-x and size-y parameter are combined into one slider meaning this one slider controls both x and y together in synch. X and Y of gegl:pixelize will not be separate sliders in this filter.

gegl_operation_meta_redirect (operation, "pixelize", state->pixel, "size-x");
gegl_operation_meta_redirect (operation, "pixelize", state->pixel, "size-y");
gegl_operation_meta_redirect (operation, "depth", state->emboss, "depth");
gegl_operation_meta_redirect (operation, "elevation", state->emboss, "elevation");


Switchblendmode/embossblendpixel corresponds to this section of the .c file. Only two blend modes can be choosen "gegl:overlay and gegl:multiply"

/* This is where the stateless blendmodechange gets swapped for multiply or overlay.
"switchblendmode will be its property name in the GUI" */
  GeglNode *blendmodechange = state->multiply; /* the default node is multiply  */
  switch (o->switchblendmode) {
    case BLEND_MODE_TYPE_OVERLAY: blendmodechange = state->overlay; break;
    case BLEND_MODE_TYPE_MULTIPLY: blendmodechange = state->multiply; break;
default: blendmodechange = state->overlay;


We are not done making the filter yet and this code will NOT compile

/* 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 <pippin@gimp.org>
* 2023, - Pixel Text, Beaver


Test this filter without installing by pasting this syntax into Gimp's GEGL graph. This filter works best with an image file upload


id=0 src-atop aux=[ ref=0 layer src=/home/USERNAME/Pictures/Magic/pattern_fills/pattern_plaid-pattern-2_1_3_0-0_0_1__ff8ab3_00e1ff.png   ]

pixelize size-x=14 size-y=14
median-blur radius=0
id=1 dst-over aux=[ ref=1 translate x=5 y=4 levels out-high=0.2 saturation scale=1
id=x multiply aux=[ ref=x emboss depth=40 elevation=10] ]
gegl:opacity value=2
median-blur radius=0

*/

#include "config.h"
#include <glib/gi18n-lib.h>

#ifdef GEGL_PROPERTIES

/* This is Properties (part 1) where properties are shown in the GUI based on their definitions in Properties (part two)*/



property_double (pixelize, _("Pixelize Meter"), 14.0)
   description (_("Pixelization of the text."))
   value_range (1.0, 25.0)
   ui_range    (0.24, 25.0)
   ui_gamma    (3.0)



enum_start (emboss_blend_pixel)
   enum_value (BLEND_MODE_TYPE_OVERLAY,    "overlay",    N_("Overlay"))
   enum_value (BLEND_MODE_TYPE_MULTIPLY,  "multiply",  N_("Multiply"))
enum_end (embossblendpixel)

property_enum (switchblendmode, _("Blend mode of Emboss"),
               embossblendpixel, emboss_blend_pixel,
               BLEND_MODE_TYPE_OVERLAY)
  description (_("Select a scale algorithm. No Halo works best on scaling down images less then half and LoHalo works best on scaling down images more then half."))


property_double (depth, _("Emboss Depth"), 40.0)
   description (_("Emboss Depth for the emboss effecting the text."))
   value_range (10.0, 60.0)
   ui_range    (10.0, 60.0)
   ui_gamma    (3.0)


property_double (elevation, _("Emboss Elevation"), 40.0)
   description (_("Emboss Elevation for the emboss effecting the text."))
   value_range (10.0, 60.0)
   ui_range    (10.0, 60.0)
   ui_gamma    (3.0)

#else

#define GEGL_OP_META
#define GEGL_OP_NAME     pixel_text
#define GEGL_OP_C_SOURCE pixel_text.c

#include "gegl-op.h"

/*This is where the nodes are listed without any properties defined. They do not have to be listed in correct order. */
typedef struct
{
GeglNode *input;
GeglNode *pixel;
GeglNode *fix;
GeglNode *fix2;
GeglNode *behind;
GeglNode *alphalock;
GeglNode *offset;
GeglNode *levels;
GeglNode *saturation;
GeglNode *multiply;
GeglNode *overlay;
GeglNode *idref;
GeglNode *idref2;
GeglNode *overlay;
GeglNode *opacity;
GeglNode *output;
}State;

static void attach (GeglOperation *operation)
{
  GeglNode *gegl = operation->node;
  GeglNode *input, *output;

  state->input    = gegl_node_get_input_proxy (gegl, "input");
  state->output   = gegl_node_get_output_proxy (gegl, "output");




/*This is where the nodes are listed (again) with the option to define some properties, They do not have to be listed in correct order*/

/*This node is Gimp's pixelize filter and does most of the work in making the text style"*/
  state->pixel = gegl_node_new_child (gegl,
                                  "operation", "gegl:pixelize",
                                  NULL);

/*These two fix nodes are median blur's at 0 radius that fix a bug relating to gegl:opacity corrupting the alpha channel"*/
  state->fix = gegl_node_new_child (gegl,
                                  "operation", "gegl:median-blur", "radius", 0,
                                  NULL);



  state->fix2 = gegl_node_new_child (gegl,
                                  "operation", "gegl:median-blur", "radius", 0,
                                  NULL);

/*DST Over is a GEGL blend mode that does the same thing as Gimp's behind blend mode."*/

  state->behind = gegl_node_new_child (gegl,
                                  "operation", "gegl:dst-over",
                                  NULL);

/*SRC-ATOP is a GEGL exclusive blend mode that does something LIKE Gimp's "lock alpha channel" option. This blend mode is unique to GEGL"*/

  state->alphalock = gegl_node_new_child (gegl,
                                  "operation", "gegl:src-atop",
                                  NULL);

/*This node "translate" is a gegl move tool similar to "offset"*/

  state->offset = gegl_node_new_child (gegl,
                                  "operation", "gegl:translate", "x", 5, "y", 4,
                                  NULL);

  state->levels = gegl_node_new_child (gegl,
                                  "operation", "gegl:levels", "out-high", 0.2,
                                  NULL);

  state->saturation = gegl_node_new_child (gegl,
                                  "operation", "gegl:saturation", "scale", 1.1,
                                  NULL);

/*These two nodes multiply and overlay will be called to replace "blendmodechange"*/
  state->multiply = gegl_node_new_child (gegl,
                                  "operation", "gegl:multiply",
                                  NULL);

  state->overlay = gegl_node_new_child (gegl,
                                  "operation", "gegl:overlay",
                                  NULL);
/*These two nop nodes function as independent id and refs*/


  state->idref1 = gegl_node_new_child (gegl,
                                  "operation", "gegl:nop",
                                  NULL);


  state->idref2 = gegl_node_new_child (gegl,
                                  "operation", "gegl:nop",
                                  NULL);

  state->emboss = gegl_node_new_child (gegl,
                                  "operation", "gegl:emboss",
                                  NULL);


  state->opacity = gegl_node_new_child (gegl,
                                  "operation", "gegl:opacity", "value", 2.0,
                                  NULL);

/* This is Properties (part 2) where properties are defined

These are sliders to control the pixelize x and y sliders as one.*/
gegl_operation_meta_redirect (operation, "pixelize", state->pixel, "size-x");
gegl_operation_meta_redirect (operation, "pixelize", state->pixel, "size-y");
gegl_operation_meta_redirect (operation, "depth", state->emboss, "depth");
gegl_operation_meta_redirect (operation, "elevation", state->emboss, "elevation");

}

static void
update_graph (GeglOperation *operation)
{
  GeglProperties *o = GEGL_PROPERTIES (operation);
  State *state = o->user_data;
  if (!state) return;

/* This is where the stateless blendmodechange gets swapped for multiply or overlay.
"switchblendmode will be its property name in the GUI" */
  GeglNode *blendmodechange = state->multiply; /* the default node is multiply  */
  switch (o->switchblendmode) {
    case BLEND_MODE_TYPE_OVERLAY: blendmodechange = state->overlay; break;
    case BLEND_MODE_TYPE_MULTIPLY: blendmodechange = state->multiply; break;
default: blendmodechange = state->overlay;

/* This is the GEGL Graph itself and nodes do have to be in the correct order.

"blendmodechange" lacks a state-> because it will be either or blend mode we want (overlay or multiply)*/
  gegl_node_link_many (state->input, state->alphalock, state->pixel, state->fix, state->idref1, state->behind, state->idref2, blendmodechange, state->opacity, state->fix2, state->output, NULL);
  gegl_node_link_many (state->idref2, emboss  NULL);
/*idref2 also know as gegl:nop connects to emboss because it is the last node in the second link_many. It is sending a image of the graph's current state to be embossed. That is why it is seen
before and after "blend mode change"*/
  gegl_node_connect_from (state->idref2, "aux", state->emboss, "output");
/*blendmodechange the only node without a state-> is connecting to emboss so it can be a blend mode switcher of either "gegl:overlay or gegl:multiply"*/
  gegl_node_connect_from (blendmodechange, "aux", state->emboss, "output");
/*The lock alpha channel blend mode (gegl:src-atop) is connecting to gegl:layer src=imagepathhere.jpg for an image file upload ability*/
  gegl_node_connect_from (state->alphalock, "aux", state->layer, "output");
/*Idref1 (The first gegl:nop) exist to make a duplicate of pixelize's effect and put it behind the original image and then tweak it with levels and saturation to darken it.
It connects to levels because that is the last node.*/
  gegl_node_link_many (state->idref1, state->saturation, state->levels,  NULL);
  gegl_node_connect_from (state->behind, "aux", state->levels, "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,
/* This is where the operation name, title name, description, menu path and menu label go.*/
    "name",        "lb:pixel-text",
    "title",       _("Pixel Text"),
    "reference-hash", "action52avgnmeme",
    "description", _("Make retro gaming text"),
    "gimp:menu-path", "<Image>/Filters/Text Styling/",
    "gimp:menu-label", _("Pixel Text..."),
    NULL);
}

#endif


Top
 Post subject: Re: GEGL Pixel Text (In Development)
PostPosted: Sun Dec 03, 2023 12:55 am  (#4) 
Offline
GimpChat Member
User avatar

Joined: Oct 31, 2020
Posts: 1457
No changes have been made since last post but the code has been organized in the sense that the { } symbols, and things like

static void update_graph (GeglOperation *operation)
{
  GeglProperties *o = GEGL_PROPERTIES (operation);
  State *state = o->user_data;
  if (!state) return;


have been put in the correct place, where as before they were present but in thw wrong area.


This compiles and is mostly complete. All it needs is a few more sliders.

/* 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 <pippin@gimp.org>
* 2023, - Pixel Text, Beaver


Test this filter without installing by pasting this syntax into Gimp's GEGL graph. This filter works best with an image file upload


id=0 src-atop aux=[ ref=0 layer src=/home/USERNAME/Pictures/Magic/pattern_fills/pattern_plaid-pattern-2_1_3_0-0_0_1__ff8ab3_00e1ff.png   ]

pixelize size-x=14 size-y=14
median-blur radius=0
id=1 dst-over aux=[ ref=1 translate x=5 y=4 levels out-high=0.2 saturation scale=1
id=x multiply aux=[ ref=x emboss depth=40 elevation=10] ]
gegl:opacity value=2
median-blur radius=0
*/


#include "config.h"
#include <glib/gi18n-lib.h>

#ifdef GEGL_PROPERTIES


/* This is Properties (part 1) where properties are shown in the GUI based on their definitions in Properties (part two)*/

property_double (pixelize, _("Pixelize Meter"), 14.0)
   description (_("Pixelization of the text."))
   value_range (1.0, 25.0)
   ui_range    (0.24, 25.0)
   ui_gamma    (3.0)

enum_start (emboss_blend_pixel)
   enum_value (BLEND_MODE_TYPE_OVERLAY,    "overlay",    N_("Overlay"))
   enum_value (BLEND_MODE_TYPE_MULTIPLY,  "multiply",  N_("Multiply"))
enum_end (embossblendpixel)

property_enum (switchblendmode, _("Blend mode of Emboss"),
               embossblendpixel, emboss_blend_pixel,
               BLEND_MODE_TYPE_OVERLAY)
  description (_("Select a scale algorithm. No Halo works best on scaling down images less then half and LoHalo works best on scaling down images more then half."))


property_double (depth, _("Emboss Depth"), 40.0)
   description (_("Emboss Depth for the emboss effecting the text."))
   value_range (10.0, 60.0)
   ui_range    (10.0, 60.0)
   ui_gamma    (3.0)


property_double (elevation, _("Emboss Elevation"), 40.0)
   description (_("Emboss Elevation for the emboss effecting the text."))
   value_range (10.0, 60.0)
   ui_range    (10.0, 60.0)
   ui_gamma    (3.0)

#else

#define GEGL_OP_META
#define GEGL_OP_NAME     pixel_text
#define GEGL_OP_C_SOURCE pixel_text.c

#include "gegl-op.h"

/*This is where the nodes are listed without any properties defined. They do not have to be listed in correct order. */
typedef struct
{
GeglNode *input;
GeglNode *output;
GeglNode *pixel;
GeglNode *fix;
GeglNode *fix2;
GeglNode *behind;
GeglNode *alphalock;
GeglNode *offset;
GeglNode *levels;
GeglNode *saturation;
GeglNode *multiply;
GeglNode *overlay;
GeglNode *idref1;
GeglNode *idref2;
GeglNode *opacity;
GeglNode *emboss;
GeglNode *layer;
}State;

static void attach (GeglOperation *operation)
{
  GeglNode *gegl = operation->node;
  GeglProperties *o = GEGL_PROPERTIES (operation);

  State *state = o->user_data = g_malloc0 (sizeof (State));

  state->input    = gegl_node_get_input_proxy (gegl, "input");
  state->output   = gegl_node_get_output_proxy (gegl, "output");

/*This is where the nodes are listed (again) with the option to define some properties, They do not have to be listed in correct order*/

/*This node is Gimp's pixelize filter and does most of the work in making the text style"*/
  state->pixel = gegl_node_new_child (gegl,
                                  "operation", "gegl:pixelize",
                                  NULL);

/*These two fix nodes are median blur's at 0 radius that fix a bug relating to gegl:opacity corrupting the alpha channel"*/
  state->fix = gegl_node_new_child (gegl,
                                  "operation", "gegl:median-blur", "radius", 0,
                                  NULL);

  state->fix2 = gegl_node_new_child (gegl,
                                  "operation", "gegl:median-blur", "radius", 0,
                                  NULL);

/*DST Over is a GEGL blend mode that does the same thing as Gimp's behind blend mode."*/

  state->behind = gegl_node_new_child (gegl,
                                  "operation", "gegl:dst-over",
                                  NULL);

/*SRC-ATOP is a GEGL exclusive blend mode that does something LIKE Gimp's "lock alpha channel" option. This blend mode is unique to GEGL"*/

  state->alphalock = gegl_node_new_child (gegl,
                                  "operation", "gegl:src-atop",
                                  NULL);

/*This node "translate" is a gegl move tool similar to "offset"*/

  state->offset = gegl_node_new_child (gegl,
                                  "operation", "gegl:translate", "x", 5.0, "y", 4.0,
                                  NULL);

  state->levels = gegl_node_new_child (gegl,
                                  "operation", "gegl:levels", "out-high", 0.2,
                                  NULL);

  state->saturation = gegl_node_new_child (gegl,
                                  "operation", "gegl:saturation", "scale", 1.1,
                                  NULL);

/*These two nodes multiply and overlay will be called to replace "blendmodechange"*/
  state->multiply = gegl_node_new_child (gegl,
                                  "operation", "gegl:multiply",
                                  NULL);

  state->overlay = gegl_node_new_child (gegl,
                                  "operation", "gegl:overlay",
                                  NULL);
/*These two nop nodes function as independent id and refs*/


  state->idref1 = gegl_node_new_child (gegl,
                                  "operation", "gegl:nop",
                                  NULL);


  state->idref2 = gegl_node_new_child (gegl,
                                  "operation", "gegl:nop",
                                  NULL);

  state->emboss = gegl_node_new_child (gegl,
                                  "operation", "gegl:emboss",
                                  NULL);

  state->layer = gegl_node_new_child (gegl,
                                  "operation", "gegl:layer",
                                  NULL);

  state->opacity = gegl_node_new_child (gegl,
                                  "operation", "gegl:opacity", "value", 2.0,
                                  NULL);

/* This is Properties (part 2) where properties are defined

These are sliders to control the pixelize x and y sliders as one.*/
gegl_operation_meta_redirect (operation, "pixelize", state->pixel, "size-x");
gegl_operation_meta_redirect (operation, "pixelize", state->pixel, "size-y");
gegl_operation_meta_redirect (operation, "depth", state->emboss, "depth");
gegl_operation_meta_redirect (operation, "elevation", state->emboss, "elevation");
}

static void update_graph (GeglOperation *operation)
{
  GeglProperties *o = GEGL_PROPERTIES (operation);
  State *state = o->user_data;
  if (!state) return;



/* This is where the stateless blendmodechange gets swapped for multiply or overlay.
"switchblendmode will be its property name in the GUI" */
  GeglNode *blendmodechange = state->multiply; /* the default node is multiply  */
  switch (o->switchblendmode) {
    case BLEND_MODE_TYPE_OVERLAY: blendmodechange = state->overlay; break;
    case BLEND_MODE_TYPE_MULTIPLY: blendmodechange = state->multiply; break;
default: blendmodechange = state->overlay;
}

/* This is the GEGL Graph itself and nodes do have to be in the correct order.

"blendmodechange" lacks a state-> because it will be either or blend mode we want (overlay or multiply)*/
  gegl_node_link_many (state->input, state->alphalock, state->pixel, state->fix, state->idref1, state->behind, state->idref2, blendmodechange, state->opacity, state->fix2, state->output, NULL);

  gegl_node_link_many (state->idref2, state->emboss,  NULL);
/*idref2 also know as gegl:nop connects to emboss because it is the last node in the second link_many. It is sending a image of the graph's current state to be embossed. That is why it is seen
before and after "blend mode change"*/
  gegl_node_connect_from (state->idref2, "aux", state->emboss, "output");
/*blendmodechange the only node without a state-> is connecting to emboss so it can be a blend mode switcher of either "gegl:overlay or gegl:multiply"*/
  gegl_node_connect_from (blendmodechange, "aux", state->emboss, "output");
/*The lock alpha channel blend mode (gegl:src-atop) is connecting to gegl:layer src=imagepathhere.jpg for an image file upload ability*/
  gegl_node_connect_from (state->alphalock, "aux", state->layer, "output");
/*Idref1 (The first gegl:nop) exist to make a duplicate of pixelize's effect and put it behind the original image and then tweak it with levels and saturation to darken it.
It connects to levels because that is the last node.*/
  gegl_node_link_many (state->idref1, state->saturation, state->levels,  NULL);
  gegl_node_connect_from (state->behind, "aux", state->levels, "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,
/* This is where the operation name, title name, description, menu path and menu label go.*/
    "name",        "lb:pixel-text",
    "title",       _("Pixel Text"),
    "reference-hash", "action52avgnmeme",
    "description", _("Make retro gaming text"),
    "gimp:menu-path", "<Image>/Filters/Text Styling/",
    "gimp:menu-label", _("Pixel Text..."),
    NULL);
}

#endif


Its missing some of its GUI sliders that I planned., but the blend mode switcher, pixelize slider and emboss features work.
Image

This filter is NOT yet complete.


Top
 Post subject: Re: GEGL Pixel Text (In Development)
PostPosted: Wed Dec 06, 2023 5:11 pm  (#5) 
Offline
GimpChat Member
User avatar

Joined: Oct 31, 2020
Posts: 1457
Attachment:
pixel_text_progress.png
pixel_text_progress.png [ 347.75 KiB | Viewed 32252 times ]


New properties were added for GUI sliders

property_double (x, _("Move Pixel Shadow Horizontal"), 5.0)
    description (_("Horizontal Movability of the Pixel Text's tail end"))
    ui_range (-6.0, 6.0)
    ui_meta ("unit", "pixel-distance")
    ui_meta ("axis", "x")

property_double (y, _("Move Pixel Shadow Vertical"), 4.0)
    description (_("Vertical Movability of the Pixel Text's tail end"))
    ui_range (-6.0, 6.0)
    ui_meta ("unit", "pixel-distance")
    ui_meta ("axis", "y")

property_file_path(image, _("Image overlay"), "")
    description (_("Optional image file overlay to be put over the text text. Source image file path (png, jpg, raw, svg, bmp, tif, ...)"))




gegl_operation_meta_redirect (operation, "x", state->offset, "x");
gegl_operation_meta_redirect (operation, "y", state->offset, "y");
gegl_operation_meta_redirect (operation, "image", state->layer, "src");


That correspond to
  state->offset = gegl_node_new_child (gegl,
                                  "operation", "gegl:translate",
                                  NULL);



and

  state->layer = gegl_node_new_child (gegl,
                                  "operation", "gegl:layer",
                                  NULL);


and the node state->offset calling gegl:translate.

GEGL Translate is a GEGL only move tool, and it was inserted in the graph. I forgot to do that earlier.

The only difference of this graph from last time is the new state->offset node. Below is the GEGL Graph in a way that .c understands.

/* This is the GEGL Graph itself and nodes do have to be in the correct order.

"blendmodechange" lacks a state-> because it will be either or blend mode we want (overlay or multiply)*/
  gegl_node_link_many (state->input, state->alphalock, state->pixel, state->fix, state->idref1, state->behind, state->idref2, blendmodechange, state->opacity, state->fix2, state->output, NULL);

  gegl_node_link_many (state->idref2, state->emboss,  NULL);
/*idref2 also know as gegl:nop connects to emboss because it is the last node in the second link_many. It is sending a image of the graph's current state to be embossed. That is why it is seen
before and after "blend mode change"*/
  gegl_node_connect_from (state->idref2, "aux", state->emboss, "output");
/*blendmodechange the only node without a state-> is connecting to emboss so it can be a blend mode switcher of either "gegl:overlay or gegl:multiply"*/
  gegl_node_connect_from (blendmodechange, "aux", state->emboss, "output");
/*The lock alpha channel blend mode (gegl:src-atop) is connecting to gegl:layer src=imagepathhere.jpg for an image file upload ability*/
  gegl_node_connect_from (state->alphalock, "aux", state->layer, "output");
/*Idref1 (The first gegl:nop) exist to make a duplicate of pixelize's effect and put it behind the original image and then tweak it with levels and saturation to darken it.
It connects to levels because that is the last node.*/
  gegl_node_link_many (state->idref1,  state->offset, state->saturation, state->levels,  NULL);
  gegl_node_connect_from (state->behind, "aux", state->levels, "output");
}



Here is the full code it does compile and is almost but not entirely complete

/* 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 <pippin@gimp.org>
* 2023, - Pixel Text, Beaver


Test this filter without installing by pasting this syntax into Gimp's GEGL graph. This filter works best with an image file upload


id=0 src-atop aux=[ ref=0 layer src=/home/USERNAME/Pictures/Magic/pattern_fills/pattern_plaid-pattern-2_1_3_0-0_0_1__ff8ab3_00e1ff.png   ]

pixelize size-x=14 size-y=14
median-blur radius=0
id=1 dst-over aux=[ ref=1 translate x=5 y=4 levels out-high=0.2 saturation scale=1
id=x multiply aux=[ ref=x emboss depth=40 elevation=10] ]
gegl:opacity value=2
median-blur radius=0
*/


#include "config.h"
#include <glib/gi18n-lib.h>

#ifdef GEGL_PROPERTIES


/* This is Properties (part 1) where properties are shown in the GUI based on their definitions in Properties (part two)*/

property_double (pixelize, _("Controll the Pixelize Effect"), 14.0)
   description (_("Pixelization of the text."))
   value_range (1.0, 25.0)
   ui_range    (0.24, 25.0)
   ui_gamma    (3.0)

enum_start (emboss_blend_pixel)
   enum_value (BLEND_MODE_TYPE_OVERLAY,    "overlay",    N_("Overlay"))
   enum_value (BLEND_MODE_TYPE_MULTIPLY,  "multiply",  N_("Multiply"))
enum_end (embossblendpixel)

property_enum (switchblendmode, _("Blend mode of Pixel Shadow Emboss"),
               embossblendpixel, emboss_blend_pixel,
               BLEND_MODE_TYPE_OVERLAY)
  description (_("Select a scale algorithm. No Halo works best on scaling down images less then half and LoHalo works best on scaling down images more then half."))


property_double (depth, _("Pixel Shadow Emboss Depth"), 40.0)
   description (_("Emboss Depth for the emboss effecting the text."))
   value_range (1.0, 60.0)
   ui_range    (1.0, 60.0)
   ui_gamma    (3.0)


property_double (elevation, _("Pixel Shadow Emboss Elevation"), 40.0)
   description (_("Emboss Elevation for the emboss effecting the text."))
   value_range (0.0, 60.0)
   ui_range    (0.0, 60.0)
   ui_gamma    (3.0)

property_double (x, _("Move Pixel Shadow Horizontal"), 5.0)
    description (_("Horizontal Movability of the Pixel Text's tail end"))
    ui_range (-6.0, 6.0)
    ui_meta ("unit", "pixel-distance")
    ui_meta ("axis", "x")

property_double (y, _("Move Pixel Shadow Vertical"), 4.0)
    description (_("Vertical Movability of the Pixel Text's tail end"))
    ui_range (-6.0, 6.0)
    ui_meta ("unit", "pixel-distance")
    ui_meta ("axis", "y")

property_file_path(image, _("Image overlay"), "")
    description (_("Optional image file overlay to be put over the text text. Source image file path (png, jpg, raw, svg, bmp, tif, ...)"))


#else

#define GEGL_OP_META
#define GEGL_OP_NAME     pixel_text
#define GEGL_OP_C_SOURCE pixel_text.c

#include "gegl-op.h"

/*This is where the nodes are listed without any properties defined. They do not have to be listed in correct order. */
typedef struct
{
GeglNode *input;
GeglNode *output;
GeglNode *pixel;
GeglNode *fix;
GeglNode *fix2;
GeglNode *behind;
GeglNode *alphalock;
GeglNode *offset;
GeglNode *levels;
GeglNode *saturation;
GeglNode *multiply;
GeglNode *overlay;
GeglNode *idref1;
GeglNode *idref2;
GeglNode *opacity;
GeglNode *emboss;
GeglNode *layer;
}State;

static void attach (GeglOperation *operation)
{
  GeglNode *gegl = operation->node;
  GeglProperties *o = GEGL_PROPERTIES (operation);

  State *state = o->user_data = g_malloc0 (sizeof (State));

  state->input    = gegl_node_get_input_proxy (gegl, "input");
  state->output   = gegl_node_get_output_proxy (gegl, "output");

/*This is where the nodes are listed (again) with the option to define some properties, They do not have to be listed in correct order*/

/*This node is Gimp's pixelize filter and does most of the work in making the text style"*/
  state->pixel = gegl_node_new_child (gegl,
                                  "operation", "gegl:pixelize",
                                  NULL);

/*These two fix nodes are median blur's at 0 radius that fix a bug relating to gegl:opacity corrupting the alpha channel"*/
  state->fix = gegl_node_new_child (gegl,
                                  "operation", "gegl:median-blur", "radius", 0,
                                  NULL);

  state->fix2 = gegl_node_new_child (gegl,
                                  "operation", "gegl:median-blur", "radius", 0,
                                  NULL);

/*DST Over is a GEGL blend mode that does the same thing as Gimp's behind blend mode."*/

  state->behind = gegl_node_new_child (gegl,
                                  "operation", "gegl:dst-over",
                                  NULL);

/*SRC-ATOP is a GEGL exclusive blend mode that does something LIKE Gimp's "lock alpha channel" option. This blend mode is unique to GEGL"*/

  state->alphalock = gegl_node_new_child (gegl,
                                  "operation", "gegl:src-atop",
                                  NULL);

/*This node "translate" is a gegl move tool similar to "offset"*/

  state->offset = gegl_node_new_child (gegl,
                                  "operation", "gegl:translate",
                                  NULL);

  state->levels = gegl_node_new_child (gegl,
                                  "operation", "gegl:levels", "out-high", 0.2,
                                  NULL);

  state->saturation = gegl_node_new_child (gegl,
                                  "operation", "gegl:saturation", "scale", 1.1,
                                  NULL);

/*These two nodes multiply and overlay will be called to replace "blendmodechange"*/
  state->multiply = gegl_node_new_child (gegl,
                                  "operation", "gegl:multiply",
                                  NULL);

  state->overlay = gegl_node_new_child (gegl,
                                  "operation", "gegl:overlay",
                                  NULL);
/*These two nop nodes function as independent id and refs*/


  state->idref1 = gegl_node_new_child (gegl,
                                  "operation", "gegl:nop",
                                  NULL);


  state->idref2 = gegl_node_new_child (gegl,
                                  "operation", "gegl:nop",
                                  NULL);

  state->emboss = gegl_node_new_child (gegl,
                                  "operation", "gegl:emboss",
                                  NULL);

  state->layer = gegl_node_new_child (gegl,
                                  "operation", "gegl:layer",
                                  NULL);

  state->opacity = gegl_node_new_child (gegl,
                                  "operation", "gegl:opacity", "value", 2.0,
                                  NULL);

/* This is Properties (part 2) where properties are defined

These are sliders to control the pixelize x and y sliders as one.*/
gegl_operation_meta_redirect (operation, "pixelize", state->pixel, "size-x");
gegl_operation_meta_redirect (operation, "pixelize", state->pixel, "size-y");
gegl_operation_meta_redirect (operation, "depth", state->emboss, "depth");
gegl_operation_meta_redirect (operation, "elevation", state->emboss, "elevation");
gegl_operation_meta_redirect (operation, "x", state->offset, "x");
gegl_operation_meta_redirect (operation, "y", state->offset, "y");
gegl_operation_meta_redirect (operation, "image", state->layer, "src");
}

static void update_graph (GeglOperation *operation)
{
  GeglProperties *o = GEGL_PROPERTIES (operation);
  State *state = o->user_data;
  if (!state) return;



/* This is where the stateless blendmodechange gets swapped for multiply or overlay.
"switchblendmode will be its property name in the GUI" */
  GeglNode *blendmodechange = state->multiply; /* the default node is multiply  */
  switch (o->switchblendmode) {
    case BLEND_MODE_TYPE_OVERLAY: blendmodechange = state->overlay; break;
    case BLEND_MODE_TYPE_MULTIPLY: blendmodechange = state->multiply; break;
default: blendmodechange = state->overlay;
}

/* This is the GEGL Graph itself and nodes do have to be in the correct order.

"blendmodechange" lacks a state-> because it will be either or blend mode we want (overlay or multiply)*/
  gegl_node_link_many (state->input, state->alphalock, state->pixel, state->fix, state->idref1, state->behind, state->idref2, blendmodechange, state->opacity, state->fix2, state->output, NULL);

  gegl_node_link_many (state->idref2, state->emboss,  NULL);
/*idref2 also know as gegl:nop connects to emboss because it is the last node in the second link_many. It is sending a image of the graph's current state to be embossed. That is why it is seen
before and after "blend mode change"*/
  gegl_node_connect_from (state->idref2, "aux", state->emboss, "output");
/*blendmodechange the only node without a state-> is connecting to emboss so it can be a blend mode switcher of either "gegl:overlay or gegl:multiply"*/
  gegl_node_connect_from (blendmodechange, "aux", state->emboss, "output");
/*The lock alpha channel blend mode (gegl:src-atop) is connecting to gegl:layer src=imagepathhere.jpg for an image file upload ability*/
  gegl_node_connect_from (state->alphalock, "aux", state->layer, "output");
/*Idref1 (The first gegl:nop) exist to make a duplicate of pixelize's effect and put it behind the original image and then tweak it with levels and saturation to darken it.
It connects to levels because that is the last node.*/
  gegl_node_link_many (state->idref1,  state->offset, state->saturation, state->levels,  NULL);
  gegl_node_connect_from (state->behind, "aux", state->levels, "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,
/* This is where the operation name, title name, description, menu path and menu label go.*/
    "name",        "lb:pixel-text",
    "title",       _("Pixel Text"),
    "reference-hash", "action52avgnmeme",
    "description", _("Make retro gaming text"),
    "gimp:menu-path", "<Image>/Filters/Text Styling/",
    "gimp:menu-label", _("Pixel Text..."),
    NULL);
}

#endif


Top
 Post subject: Re: GEGL Pixel Text (In Development)
PostPosted: Wed Dec 06, 2023 5:35 pm  (#6) 
Offline
GimpChat Member
User avatar

Joined: Oct 31, 2020
Posts: 1457
When running Pixel Text in Gimp we get this warning. I have seen this many times in development. It means that a slider is beyond its parameters.
Attachment:
warning_slider_beyond_limits.png
warning_slider_beyond_limits.png [ 4.81 KiB | Viewed 32251 times ]


In example, gegl:emboss depth=100 is the max parameter of gegl:emboss and gegl:emboss depth=1 is the lowest. The range is 0-100. Anything higher or lower will be an invalid parameter and trigger this error. Lets look through the source code to find the cause of the error.


...After a few minutes of me looking at the code...
Pixelize cannot be below 1 or any decimal number because it is an integer only property.


Here is the warning trigger

Attachment:
invalid.png
invalid.png [ 72.93 KiB | Viewed 32251 times ]



Decimals are numbers with points, in example (0.5,1.5,2.5,3.5,4.5) and integers are whole numbers (1,2,3,4 or two billion and twenty eight) if it has a point like 100.3, its a decimal.


In good practice we can do this. This does not fix a trigger warning but it is a good practice that I usually don't do.


Attachment:
good_practice.png
good_practice.png [ 92.2 KiB | Viewed 32251 times ]



Now lets restart Gimp, load the plugin, and see if the error is there.

Image

Its fixed and here is the updated code. Oh yeah I should mention that I got another 1 time error about all GEGL presets for pixel text breaking, This is because we changed GUI properties from decimal to integer and that erases all presets. Its not big deal because this plugin is not even released yet.

This is the new one time error that means all presets for said plugin are corrupted and will be deleted. No big deal it will never appear again.
Error while parsing '/home/contrast/.var/app/org.gimp.GIMP/config/GIMP/2.10/filters/GimpGegl-lb-pixel-text-config.settings' in line 5: unexpected number '5.515', expected number (integer) - fatal parse error



Here is the updated source code that does compile but is not yet complete

/* 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 <pippin@gimp.org>
* 2023, - Pixel Text, Beaver


Test this filter without installing by pasting this syntax into Gimp's GEGL graph. This filter works best with an image file upload


id=0 src-atop aux=[ ref=0 layer src=/home/USERNAME/Pictures/Magic/pattern_fills/pattern_plaid-pattern-2_1_3_0-0_0_1__ff8ab3_00e1ff.png   ]

pixelize size-x=14 size-y=14
median-blur radius=0
id=1 dst-over aux=[ ref=1 translate x=5 y=4 levels out-high=0.2 saturation scale=1
id=x multiply aux=[ ref=x emboss depth=40 elevation=10] ]
gegl:opacity value=2
median-blur radius=0
*/


#include "config.h"
#include <glib/gi18n-lib.h>

#ifdef GEGL_PROPERTIES


/* This is Properties (part 1) where properties are shown in the GUI based on their definitions in Properties (part two)*/

property_int (pixelize, _("Controll the Pixelize Effect"), 14)
   description (_("Pixelization of the text."))
   value_range (1, 25)
   ui_gamma    (3.0)

enum_start (emboss_blend_pixel)
   enum_value (BLEND_MODE_TYPE_OVERLAY,    "overlay",    N_("Overlay"))
   enum_value (BLEND_MODE_TYPE_MULTIPLY,  "multiply",  N_("Multiply"))
enum_end (embossblendpixel)

property_enum (switchblendmode, _("Blend mode of Pixel Shadow Emboss"),
               embossblendpixel, emboss_blend_pixel,
               BLEND_MODE_TYPE_OVERLAY)
  description (_("Select a scale algorithm. No Halo works best on scaling down images less then half and LoHalo works best on scaling down images more then half."))


property_int (depth, _("Pixel Shadow Emboss Depth"), 40)
   description (_("Emboss Depth for the emboss effecting the text."))
   value_range (1, 60)
   ui_range    (1, 60)
   ui_gamma    (3.0)


property_double (elevation, _("Pixel Shadow Emboss Elevation"), 40.0)
   description (_("Emboss Elevation for the emboss effecting the text."))
   value_range (0.0, 60.0)
   ui_range    (0.0, 60.0)
   ui_gamma    (3.0)

property_double (x, _("Move Pixel Shadow Horizontal"), 5.0)
    description (_("Horizontal Movability of the Pixel Text's tail end"))
    ui_range (-6.0, 6.0)
    ui_meta ("unit", "pixel-distance")
    ui_meta ("axis", "x")

property_double (y, _("Move Pixel Shadow Vertical"), 4.0)
    description (_("Vertical Movability of the Pixel Text's tail end"))
    ui_range (-6.0, 6.0)
    ui_meta ("unit", "pixel-distance")
    ui_meta ("axis", "y")

property_file_path(image, _("Image overlay"), "")
    description (_("Optional image file overlay to be put over the text text. Source image file path (png, jpg, raw, svg, bmp, tif, ...)"))


#else

#define GEGL_OP_META
#define GEGL_OP_NAME     pixel_text
#define GEGL_OP_C_SOURCE pixel_text.c

#include "gegl-op.h"

/*This is where the nodes are listed without any properties defined. They do not have to be listed in correct order. */
typedef struct
{
GeglNode *input;
GeglNode *output;
GeglNode *pixel;
GeglNode *fix;
GeglNode *fix2;
GeglNode *behind;
GeglNode *alphalock;
GeglNode *offset;
GeglNode *levels;
GeglNode *saturation;
GeglNode *multiply;
GeglNode *overlay;
GeglNode *idref1;
GeglNode *idref2;
GeglNode *opacity;
GeglNode *emboss;
GeglNode *layer;
}State;

static void attach (GeglOperation *operation)
{
  GeglNode *gegl = operation->node;
  GeglProperties *o = GEGL_PROPERTIES (operation);

  State *state = o->user_data = g_malloc0 (sizeof (State));

  state->input    = gegl_node_get_input_proxy (gegl, "input");
  state->output   = gegl_node_get_output_proxy (gegl, "output");

/*This is where the nodes are listed (again) with the option to define some properties, They do not have to be listed in correct order*/

/*This node is Gimp's pixelize filter and does most of the work in making the text style"*/
  state->pixel = gegl_node_new_child (gegl,
                                  "operation", "gegl:pixelize",
                                  NULL);

/*These two fix nodes are median blur's at 0 radius that fix a bug relating to gegl:opacity corrupting the alpha channel"*/
  state->fix = gegl_node_new_child (gegl,
                                  "operation", "gegl:median-blur", "radius", 0,
                                  NULL);

  state->fix2 = gegl_node_new_child (gegl,
                                  "operation", "gegl:median-blur", "radius", 0,
                                  NULL);

/*DST Over is a GEGL blend mode that does the same thing as Gimp's behind blend mode."*/

  state->behind = gegl_node_new_child (gegl,
                                  "operation", "gegl:dst-over",
                                  NULL);

/*SRC-ATOP is a GEGL exclusive blend mode that does something LIKE Gimp's "lock alpha channel" option. This blend mode is unique to GEGL"*/

  state->alphalock = gegl_node_new_child (gegl,
                                  "operation", "gegl:src-atop",
                                  NULL);

/*This node "translate" is a gegl move tool similar to "offset"*/

  state->offset = gegl_node_new_child (gegl,
                                  "operation", "gegl:translate",
                                  NULL);

  state->levels = gegl_node_new_child (gegl,
                                  "operation", "gegl:levels", "out-high", 0.2,
                                  NULL);

  state->saturation = gegl_node_new_child (gegl,
                                  "operation", "gegl:saturation", "scale", 1.1,
                                  NULL);

/*These two nodes multiply and overlay will be called to replace "blendmodechange"*/
  state->multiply = gegl_node_new_child (gegl,
                                  "operation", "gegl:multiply",
                                  NULL);

  state->overlay = gegl_node_new_child (gegl,
                                  "operation", "gegl:overlay",
                                  NULL);
/*These two nop nodes function as independent id and refs*/


  state->idref1 = gegl_node_new_child (gegl,
                                  "operation", "gegl:nop",
                                  NULL);


  state->idref2 = gegl_node_new_child (gegl,
                                  "operation", "gegl:nop",
                                  NULL);

  state->emboss = gegl_node_new_child (gegl,
                                  "operation", "gegl:emboss",
                                  NULL);

  state->layer = gegl_node_new_child (gegl,
                                  "operation", "gegl:layer",
                                  NULL);

  state->opacity = gegl_node_new_child (gegl,
                                  "operation", "gegl:opacity", "value", 2.0,
                                  NULL);

/* This is Properties (part 2) where properties are defined

These are sliders to control the pixelize x and y sliders as one.*/
gegl_operation_meta_redirect (operation, "pixelize", state->pixel, "size-x");
gegl_operation_meta_redirect (operation, "pixelize", state->pixel, "size-y");
gegl_operation_meta_redirect (operation, "depth", state->emboss, "depth");
gegl_operation_meta_redirect (operation, "elevation", state->emboss, "elevation");
gegl_operation_meta_redirect (operation, "x", state->offset, "x");
gegl_operation_meta_redirect (operation, "y", state->offset, "y");
gegl_operation_meta_redirect (operation, "image", state->layer, "src");
}

static void update_graph (GeglOperation *operation)
{
  GeglProperties *o = GEGL_PROPERTIES (operation);
  State *state = o->user_data;
  if (!state) return;



/* This is where the stateless blendmodechange gets swapped for multiply or overlay.
"switchblendmode will be its property name in the GUI" */
  GeglNode *blendmodechange = state->multiply; /* the default node is multiply  */
  switch (o->switchblendmode) {
    case BLEND_MODE_TYPE_OVERLAY: blendmodechange = state->overlay; break;
    case BLEND_MODE_TYPE_MULTIPLY: blendmodechange = state->multiply; break;
default: blendmodechange = state->overlay;
}

/* This is the GEGL Graph itself and nodes do have to be in the correct order.

"blendmodechange" lacks a state-> because it will be either or blend mode we want (overlay or multiply)*/
  gegl_node_link_many (state->input, state->alphalock, state->pixel, state->fix, state->idref1, state->behind, state->idref2, blendmodechange, state->opacity, state->fix2, state->output, NULL);

  gegl_node_link_many (state->idref2, state->emboss,  NULL);
/*idref2 also know as gegl:nop connects to emboss because it is the last node in the second link_many. It is sending a image of the graph's current state to be embossed. That is why it is seen
before and after "blend mode change"*/
  gegl_node_connect_from (state->idref2, "aux", state->emboss, "output");
/*blendmodechange the only node without a state-> is connecting to emboss so it can be a blend mode switcher of either "gegl:overlay or gegl:multiply"*/
  gegl_node_connect_from (blendmodechange, "aux", state->emboss, "output");
/*The lock alpha channel blend mode (gegl:src-atop) is connecting to gegl:layer src=imagepathhere.jpg for an image file upload ability*/
  gegl_node_connect_from (state->alphalock, "aux", state->layer, "output");
/*Idref1 (The first gegl:nop) exist to make a duplicate of pixelize's effect and put it behind the original image and then tweak it with levels and saturation to darken it.
It connects to levels because that is the last node.*/
  gegl_node_link_many (state->idref1,  state->offset, state->saturation, state->levels,  NULL);
  gegl_node_connect_from (state->behind, "aux", state->levels, "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,
/* This is where the operation name, title name, description, menu path and menu label go.*/
    "name",        "lb:pixel-text",
    "title",       _("Pixel Text"),
    "reference-hash", "action52avgnmeme",
    "description", _("Make retro gaming text"),
    "gimp:menu-path", "<Image>/Filters/Text Styling/",
    "gimp:menu-label", _("Pixel Text..."),
    NULL);
}

#endif


Top
 Post subject: Re: GEGL Pixel Text (In Development)
PostPosted: Wed Dec 06, 2023 5:51 pm  (#7) 
Offline
GimpChat Member
User avatar

Joined: Oct 31, 2020
Posts: 1457
Let's rename sliders in GEGL.


Attachment:
pasted_image024.png
pasted_image024.png [ 84.75 KiB | Viewed 32251 times ]


Under is where name changes are happening
Attachment:
rename.png
rename.png [ 72.58 KiB | Viewed 32251 times ]



Now lets recompile
Attachment:
renaming_worked.png
renaming_worked.png [ 54.18 KiB | Viewed 32251 times ]


Now comes the hard part, we have to make two modes for this filter (original color mode, and user defined color mode)
currently this uses whatever original color was in Gimp but we can tell it to use any color by having a gegl:color-overlay node that kicks beginning when the user selects a from a drop down list.


Top
 Post subject: Re: GEGL Pixel Text (In Development)
PostPosted: Fri Dec 15, 2023 5:55 pm  (#8) 
Offline
GimpChat Member
User avatar

Joined: Oct 31, 2020
Posts: 1457
This filter could have been developed in a few hours, it is my fault for taking half a month. I got distracted with other things like bash/AI powered GEGL filters and real life. Seriously this is the longest procrastination on any GEGL filter I ever made.

Now its time to finalize this filter. It turns out there was a error in the graph that was fixed.

Error (emboss being put inside a nop called idref2)
[code]  gegl_node_connect_from (idref2, "aux", state->emboss, "output");[/code]


Correct (emboss being put inside overlay or multiply)
  gegl_node_connect_from (blendmodechange, "aux", state->emboss, "output");



Now that the error is fixed let's see the changes to the GEGL Graph area and the update settings we added to it.

This is where the blend mode changes from either overlay or multiply. This is the same as last time. It is default on Overlay
  GeglNode *blendmodechange = state->multiply; /* the default node is multiply  */
  switch (o->switchblendmode) {
    case BLEND_MODE_TYPE_OVERLAY: blendmodechange = state->overlay; break;
    case BLEND_MODE_TYPE_MULTIPLY: blendmodechange = state->multiply; break;
default: blendmodechange = state->overlay;


This is where the node gegl:color-overlay kicks in or gets disabled

It selects either gegl:nop or gegl:color-overlay depending on the users selection on the drop down list.
/* This is where the stateless colorsetting gets swapped for default color mode or any color mode.*/
  GeglNode *colorsetting = state->nopcolor;
  switch (o->colorpolicy) {
    case NOP_COLOR: colorsetting = state->nopcolor; break;
    case COLOR_ANY: colorsetting = state->color; break;
default: colorsetting = state->nopcolor;


Finally, this is the final GEGL Graph.

  gegl_node_link_many (state->input, colorsetting, state->alphalock, state->pixel, state->fix, state->idref1, state->behind, state->idref2, blendmodechange, state->opacity, state->fix2, state->output, NULL);

  gegl_node_link_many (state->idref2, state->emboss,  NULL);
/*idref2 also know as gegl:nop connects to emboss because it is the last node in the second link_many. It is sending a image of the graph's current state to be embossed. That is why it is seen
before and after "blend mode change"*/
  gegl_node_connect_from (blendmodechange, "aux", state->emboss, "output");
/*blendmodechange the only node without a state-> is connecting to emboss so it can be a blend mode switcher of either "gegl:overlay or gegl:multiply"*/
  gegl_node_connect_from (blendmodechange, "aux", state->emboss, "output");
/*The lock alpha channel blend mode (gegl:src-atop) is connecting to gegl:layer src=imagepathhere.jpg for an image file upload ability*/
  gegl_node_connect_from (state->alphalock, "aux", state->layer, "output");
/*Idref1 (The first gegl:nop) exist to make a duplicate of pixelize's effect and put it behind the original image and then tweak it with levels and saturation to darken it.
It connects to levels because that is the last node.*/
  gegl_node_link_many (state->idref1,  state->offset, state->saturation, state->levels,  NULL);
  gegl_node_connect_from (state->behind, "aux", state->levels, "output");
}


This filter would be released now, but there is a problem of a new discovery.

NEW DISCOVERY MADE several minutes ago
A gaussian blur before anything and my "glass over text plugin + gegl:pixelize" after ward creates bettereffect.
Attachment:
2023-12-15_17-14.png
2023-12-15_17-14.png [ 477.48 KiB | Viewed 30633 times ]


Full Code of plugin that is technically complete. Consider this a stable.

/* 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 <pippin@gimp.org>
* 2023, - Pixel Text, Beaver


Test this filter without installing by pasting this syntax into Gimp's GEGL graph. This filter works best with an image file upload


id=0 src-atop aux=[ ref=0 layer src=/home/USERNAME/Pictures/Magic/pattern_fills/pattern_plaid-pattern-2_1_3_0-0_0_1__ff8ab3_00e1ff.png   ]

pixelize size-x=14 size-y=14
median-blur radius=0
id=1 dst-over aux=[ ref=1 translate x=5 y=4 levels out-high=0.2 saturation scale=1
id=x multiply aux=[ ref=x emboss depth=40 elevation=10] ]
gegl:opacity value=2
median-blur radius=0
*/


#include "config.h"
#include <glib/gi18n-lib.h>

#ifdef GEGL_PROPERTIES

enum_start (color_mode)
   enum_value (NOP_COLOR,    "nocolor",    N_("Original color mode"))
   enum_value (COLOR_ANY,  "color",  N_("Color overlay mode"))
enum_end (colormode)


property_enum (colorpolicy, _("Color Policy:"),
               colormode, color_mode,
               NOP_COLOR)
  description (_("Setting to keep the original image color or replace the original color with any color you want."))


property_color  (color, _("Color"), "#fe7e00")
ui_meta ("visible", "colorpolicy {color}")


/* This is Properties (part 1) where properties are shown in the GUI based on their definitions in Properties (part two)*/

property_int (pixelize, _("Control the Pixelize Effect"), 6)
   description (_("Pixelization of the text from gegl:pixelize ."))
   value_range (1, 25)
   ui_gamma    (3.0)

property_int (depth, _("Pixel Shadow Emboss Depth"), 40)
   description (_("Emboss Depth for the emboss effecting the text."))
   value_range (1, 60)
   ui_range    (1, 60)
   ui_gamma    (3.0)

property_double (elevation, _("Pixel Shadow Emboss Elevation"), 14.0)
   description (_("Emboss Elevation for the emboss effecting the text."))
   value_range (0.0, 60.0)
   ui_range    (0.0, 60.0)
   ui_gamma    (3.0)

property_double (x, _("X Pixel Shadow"), 5.0)
    description (_("Horizontal Movability of the Pixel Text's opaque shadow"))
    ui_range (-6.0, 6.0)
    ui_meta ("unit", "pixel-distance")
    ui_meta ("axis", "x")

property_double (y, _("Y Pixel Shadow"), 4.0)
    description (_("Vertical Movability of the Pixel Text's opaque shadow"))
    ui_range (-6.0, 6.0)
    ui_meta ("unit", "pixel-distance")
    ui_meta ("axis", "y")

property_file_path(image, _("Image overlay"), "")
    description (_("Optional image file overlay to be put over the text. Source image file path (png, jpg, raw, svg, bmp, tif, ...)"))

enum_start (emboss_blend_pixel)
   enum_value (BLEND_MODE_TYPE_OVERLAY,    "overlay",    N_("Overlay"))
   enum_value (BLEND_MODE_TYPE_MULTIPLY,  "multiply",  N_("Multiply"))
enum_end (embossblendpixel)

property_enum (switchblendmode, _("Blend mode of Pixel Text:"),
               embossblendpixel, emboss_blend_pixel,
               BLEND_MODE_TYPE_OVERLAY)
  description (_("Blend mode of pixel text filter"))


#else

#define GEGL_OP_META
#define GEGL_OP_NAME     pixel_text
#define GEGL_OP_C_SOURCE pixel_text.c

#include "gegl-op.h"

/*This is where the nodes are listed without any properties defined. They do not have to be listed in correct order. */
typedef struct
{
GeglNode *input;
GeglNode *output;
GeglNode *pixel;
GeglNode *nopcolor;
GeglNode *color;
GeglNode *fix;
GeglNode *fix2;
GeglNode *behind;
GeglNode *alphalock;
GeglNode *offset;
GeglNode *levels;
GeglNode *saturation;
GeglNode *multiply;
GeglNode *overlay;
GeglNode *idref1;
GeglNode *idref2;
GeglNode *opacity;
GeglNode *emboss;
GeglNode *layer;
}State;

static void attach (GeglOperation *operation)
{
  GeglNode *gegl = operation->node;
  GeglProperties *o = GEGL_PROPERTIES (operation);

  State *state = o->user_data = g_malloc0 (sizeof (State));

  state->input    = gegl_node_get_input_proxy (gegl, "input");
  state->output   = gegl_node_get_output_proxy (gegl, "output");

/*This is where the nodes are listed (again) with the option to define some properties, They do not have to be listed in correct order*/

/*This node is Gimp's pixelize filter and does most of the work in making the text style"*/
  state->pixel = gegl_node_new_child (gegl,
                                  "operation", "gegl:pixelize",
                                  NULL);

/*These two fix nodes are median blur's at 0 radius that fix a bug relating to gegl:opacity corrupting the alpha channel"*/
  state->fix = gegl_node_new_child (gegl,
                                  "operation", "gegl:median-blur", "radius", 0,
                                  NULL);

  state->fix2 = gegl_node_new_child (gegl,
                                  "operation", "gegl:median-blur", "radius", 0,
                                  NULL);

/*DST Over is a GEGL blend mode that does the same thing as Gimp's behind blend mode."*/

  state->behind = gegl_node_new_child (gegl,
                                  "operation", "gegl:dst-over",
                                  NULL);

/*SRC-ATOP is a GEGL exclusive blend mode that does something LIKE Gimp's "lock alpha channel" option. This blend mode is unique to GEGL"*/

  state->alphalock = gegl_node_new_child (gegl,
                                  "operation", "gegl:src-atop",
                                  NULL);

/*This node "translate" is a gegl move tool similar to "offset"*/

  state->offset = gegl_node_new_child (gegl,
                                  "operation", "gegl:translate",
                                  NULL);

  state->levels = gegl_node_new_child (gegl,
                                  "operation", "gegl:levels", "out-high", 0.2,
                                  NULL);

  state->saturation = gegl_node_new_child (gegl,
                                  "operation", "gegl:saturation", "scale", 1.1,
                                  NULL);

/*These two nodes multiply and overlay will be called to replace "blendmodechange"*/
  state->multiply = gegl_node_new_child (gegl,
                                  "operation", "gegl:multiply",
                                  NULL);

  state->overlay = gegl_node_new_child (gegl,
                                  "operation", "gegl:overlay",
                                  NULL);
/*These two nop nodes function as independent id and refs*/


  state->idref1 = gegl_node_new_child (gegl,
                                  "operation", "gegl:nop",
                                  NULL);

  state->idref2 = gegl_node_new_child (gegl,
                                  "operation", "gegl:nop",
                                  NULL);

  state->nopcolor = gegl_node_new_child (gegl,
                                  "operation", "gegl:nop",
                                  NULL);

  state->color = gegl_node_new_child (gegl,
                                  "operation", "gegl:color-overlay",
                                  NULL);

  state->emboss = gegl_node_new_child (gegl,
                                  "operation", "gegl:emboss",
                                  NULL);

  state->layer = gegl_node_new_child (gegl,
                                  "operation", "gegl:layer",
                                  NULL);

  state->opacity = gegl_node_new_child (gegl,
                                  "operation", "gegl:opacity", "value", 2.0,
                                  NULL);

/* This is Properties (part 2) where properties are defined

These are sliders to control the pixelize x and y sliders as one.*/
gegl_operation_meta_redirect (operation, "pixelize", state->pixel, "size-x");
gegl_operation_meta_redirect (operation, "pixelize", state->pixel, "size-y");
gegl_operation_meta_redirect (operation, "depth", state->emboss, "depth");
gegl_operation_meta_redirect (operation, "elevation", state->emboss, "elevation");
gegl_operation_meta_redirect (operation, "x", state->offset, "x");
gegl_operation_meta_redirect (operation, "y", state->offset, "y");
gegl_operation_meta_redirect (operation, "image", state->layer, "src");
gegl_operation_meta_redirect (operation, "color", state->color, "value");
}


static void
update_graph (GeglOperation *operation)
{
  GeglProperties *o = GEGL_PROPERTIES (operation);
  State *state = o->user_data;
  if (!state) return;

/* This is where the stateless blendmodechange gets swapped for multiply or overlay.
"switchblendmode will be its property name in the GUI" */
  GeglNode *blendmodechange = state->multiply; /* the default node is multiply  */
  switch (o->switchblendmode) {
    case BLEND_MODE_TYPE_OVERLAY: blendmodechange = state->overlay; break;
    case BLEND_MODE_TYPE_MULTIPLY: blendmodechange = state->multiply; break;
default: blendmodechange = state->overlay;

}

/* This is where the stateless colorsetting gets swapped for default color mode or any color mode.*/
  GeglNode *colorsetting = state->nopcolor;
  switch (o->colorpolicy) {
    case NOP_COLOR: colorsetting = state->nopcolor; break;
    case COLOR_ANY: colorsetting = state->color; break;
default: colorsetting = state->nopcolor;
}


/* This is the GEGL Graph itself and nodes do have to be in the correct order.

"blendmodechange" lacks a state-> because it will be either or blend mode we want (overlay or multiply)*/
  gegl_node_link_many (state->input, colorsetting, state->alphalock, state->pixel, state->fix, state->idref1, state->behind, state->idref2, blendmodechange, state->opacity, state->fix2, state->output, NULL);

  gegl_node_link_many (state->idref2, state->emboss,  NULL);
/*idref2 also know as gegl:nop connects to emboss because it is the last node in the second link_many. It is sending a image of the graph's current state to be embossed. That is why it is seen
before and after "blend mode change"*/
  gegl_node_connect_from (blendmodechange, "aux", state->emboss, "output");
/*blendmodechange the only node without a state-> is connecting to emboss so it can be a blend mode switcher of either "gegl:overlay or gegl:multiply"*/
  gegl_node_connect_from (blendmodechange, "aux", state->emboss, "output");
/*The lock alpha channel blend mode (gegl:src-atop) is connecting to gegl:layer src=imagepathhere.jpg for an image file upload ability*/
  gegl_node_connect_from (state->alphalock, "aux", state->layer, "output");
/*Idref1 (The first gegl:nop) exist to make a duplicate of pixelize's effect and put it behind the original image and then tweak it with levels and saturation to darken it.
It connects to levels because that is the last node.*/
  gegl_node_link_many (state->idref1,  state->offset, state->saturation, state->levels,  NULL);
  gegl_node_connect_from (state->behind, "aux", state->levels, "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,
/* This is where the operation name, title name, description, menu path and menu label go.*/
    "name",        "lb:pixel-text",
    "title",       _("Pixel Text"),
    "reference-hash", "action52avgnmeme",
    "description", _("Make retro gaming text"),
    "gimp:menu-path", "<Image>/Filters/Text Styling/",
    "gimp:menu-label", _("Pixel Text..."),
    NULL);
}

#endif


Top
 Post subject: Re: GEGL Pixel Text - plugin download
PostPosted: Fri Dec 15, 2023 6:50 pm  (#9) 
Offline
GimpChat Member
User avatar

Joined: Oct 31, 2020
Posts: 1457
Pixel text binary downloads on Github have been released. I did not yet add the glass over text or gaussian blur at the start of the graph

https://github.com/LinuxBeaver/Gimp-Pix ... imp_plugin

Everything listed above is documentation of how this plugin was made.

Attachment:
pixels_ready.png
pixels_ready.png [ 379.79 KiB | Viewed 30573 times ]


Attachment:
pixels_ready_2.png
pixels_ready_2.png [ 278.55 KiB | Viewed 30573 times ]


Top
Post new topic Reply to topic  [ 9 posts ] 

All times are UTC - 5 hours [ DST ]


   Similar Topics   Replies 
No new posts Attachment(s) GEGL ROYAL TEXT plugin (download provided)

11

No new posts Attachment(s) GEGL Ocean Caustics (plugin download)

6

No new posts Attachment(s) GEGL Ring Bevel Plugin Download

14

No new posts Attachment(s) GEGL Sparkle effect plugin - download provided

5

No new posts Attachment(s) GEGL Text Style Collection - plugin with many fancy text styles

14



* Login  



Powered by phpBB3 © phpBB Group