 |
| GimpChat Member |
 |
Joined: Oct 31, 2020 Posts: 2013
|
Grok made a GEGL plugin inspired by Pixelitor's "Radial Waves" but simpler. It still does a very similar effect. Notice the preview image showing it distorting a gradient. Attachment:
raydistortion_grok.png [ 241.54 KiB | Viewed 3007 times ]
I did not make this plugin. Grok did, I just instructed it. I have no idea how to write math like this. Explained simply this plugin is like GEGL Waves (gegl:waves) but it uses a uneven star shape instead of circular water ripples. In theory it could be done with other shapes too Attachment:
linux_binaries_gegl_plugin.zip [7.36 KiB]
Downloaded 84 times
Attachment:
windows_binaries_gegl_plugin.zip [42.29 KiB]
Downloaded 293 times
Code here /* 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]> * 2025 Grok and DeepSeek with Beaver's help */
#include "config.h" #include <glib/gi18n-lib.h> #include <gegl.h> #include <gegl-plugin.h> #include <math.h>
#ifdef GEGL_PROPERTIES
property_double (center_x, _("Center X"), 0.5) description (_("Horizontal center of the effect (relative to image width, 0.0 to 1.0)")) value_range (0.0, 1.0) ui_meta ("unit", "relative-coordinate") ui_meta ("direction", "x")
property_double (center_y, _("Center Y"), 0.5) description (_("Vertical center of the effect (relative to image height, 0.0 to 1.0)")) value_range (0.0, 1.0) ui_meta ("unit", "relative-coordinate") ui_meta ("direction", "y")
property_int (angular_division, _("Star Points"), 30) description (_("Number of points in the uneven star shape for the ray distortion")) value_range (6, 50)
property_double (wavelength, _("Ray Length"), 60.0) description (_("Length of the rays in pixels")) value_range (1.0, 200.0)
property_double (amplitude, _("Ray Intensity"), 10.0) description (_("Strength of the rays in pixels")) value_range (0.0, 100.0)
property_double (phase, _("Phase"), 0.0) description (_("Phase shift of the effect in degrees")) value_range (0.0, 360.0) ui_meta ("unit", "degree")
#else
#define GEGL_OP_FILTER #define GEGL_OP_NAME raydistortion #define GEGL_OP_C_SOURCE raydis.c
#include "gegl-op.h"
static void prepare (GeglOperation *operation) { const Babl *format = babl_format ("RGBA float"); gegl_operation_set_format (operation, "input", format); gegl_operation_set_format (operation, "output", format); }
static GeglRectangle get_bounding_box (GeglOperation *operation) { GeglRectangle *in_rect = gegl_operation_source_get_bounding_box (operation, "input"); if (!in_rect) return gegl_rectangle_infinite_plane (); return *in_rect; }
static GeglRectangle get_required_for_output (GeglOperation *operation, const gchar *input_pad, const GeglRectangle *roi) { GeglProperties *o = GEGL_PROPERTIES (operation); GeglRectangle result = *roi;
/* Expand the region of interest to account for the maximum displacement */ gdouble max_displacement = o->amplitude; result.x -= max_displacement; result.y -= max_displacement; result.width += 2 * max_displacement; result.height += 2 * max_displacement;
GeglRectangle *in_rect = gegl_operation_source_get_bounding_box (operation, "input"); if (in_rect) gegl_rectangle_intersect (&result, &result, in_rect);
return result; }
/* Function to mirror coordinates within image bounds */ static gdouble mirror_coordinate (gdouble coord, gdouble min, gdouble max) { gdouble range = max - min; if (range <= 0) return min; /* Avoid division by zero */
/* Normalize coordinate to range [min, max) */ gdouble normalized = coord - min; gdouble mod = fmod (normalized, 2 * range);
/* Mirror by reflecting across the boundaries */ if (mod < 0) mod += 2 * range; /* Handle negative values */ if (mod < range) return min + mod; /* Forward direction */ else return min + (2 * range - mod); /* Reflected direction */ }
static gboolean process (GeglOperation *operation, GeglBuffer *input, GeglBuffer *output, const GeglRectangle *result, gint level) { GeglProperties *o = GEGL_PROPERTIES (operation); const Babl *format = babl_format ("RGBA float"); gfloat *output_pixel = g_new (gfloat, 4); gdouble phase_rad = o->phase * G_PI / 180.0;
/* Get image dimensions for relative coordinates and mirroring */ GeglRectangle *in_rect = gegl_operation_source_get_bounding_box (operation, "input"); gdouble center_x = o->center_x * in_rect->width + in_rect->x; gdouble center_y = o->center_y * in_rect->height + in_rect->y; gdouble min_x = in_rect->x; gdouble max_x = in_rect->x + in_rect->width; gdouble min_y = in_rect->y; gdouble max_y = in_rect->y + in_rect->height;
for (gint y = result->y; y < result->y + result->height; y++) { for (gint x = result->x; x < result->x + result->width; x++) { /* Calculate radial distance and angle from center */ gdouble dx = x - center_x; gdouble dy = y - center_y; gdouble distance = sqrt (dx * dx + dy * dy); gdouble theta = atan2 (dy, dx); /* Angle in radians */
/* Compute ray distortion effect with uneven star shape */ gdouble src_x = x; gdouble src_y = y;
/* Create an uneven star shape using a deterministic method */ gdouble base_points = o->angular_division; gdouble irregularity = sin (theta * base_points); /* Deterministic unevenness */ gdouble varied_points = base_points + irregularity * 0.5; /* Reduced variation for subtlety */ gdouble angular_segment = floor (theta * varied_points / (2.0 * G_PI)) * (2.0 * G_PI) / varied_points; gdouble segment_factor = cos (theta - angular_segment); segment_factor = pow (segment_factor, 4.0); /* Sharpen the rays for distortion effect */
/* Apply the effect directly */ gdouble displacement = sin (theta * base_points + phase_rad); /* Fluctuating based on angle */
/* Apply displacement radially, scaled by amplitude and segment factor */ gdouble dist = distance == 0.0 ? 1.0 : distance; gdouble offset = o->amplitude * displacement * segment_factor * (distance / o->wavelength); src_x = x - offset * (dx / dist); /* Pull pixels toward the center for ray distortion effect */ src_y = y - offset * (dy / dist);
/* Mirror coordinates to stay within image bounds */ src_x = mirror_coordinate (src_x, min_x, max_x); src_y = mirror_coordinate (src_y, min_y, max_y);
/* Sample input at the displaced coordinates */ gegl_buffer_sample (input, src_x, src_y, NULL, output_pixel, format, GEGL_SAMPLER_LINEAR, GEGL_ABYSS_CLAMP);
GeglRectangle pixel_rect = {x, y, 1, 1}; gegl_buffer_set (output, &pixel_rect, 0, format, output_pixel, GEGL_AUTO_ROWSTRIDE); } }
g_free (output_pixel); return TRUE; }
static void gegl_op_class_init (GeglOpClass *klass) { GeglOperationClass *operation_class = GEGL_OPERATION_CLASS (klass); GeglOperationFilterClass *filter_class = GEGL_OPERATION_FILTER_CLASS (klass);
operation_class->prepare = prepare; operation_class->get_bounding_box = get_bounding_box; operation_class->get_required_for_output = get_required_for_output; filter_class->process = process;
gegl_operation_class_set_keys (operation_class, "name", "ai/lb:ray-distortion", "title", _("Ray Distortion"), "reference-hash", "raydistortion2025", "description", _("Distort the image with uneven star rays"), "gimp:menu-path", "<Image>/Filters/AI GEGL", "gimp:menu-label", _("Ray Distortion..."), NULL); }
#endif
LOCATION TO PUT BINARIES Windows C:\Users\(USERNAME)\AppData\Local\gegl-0.4\plug-ins Linux ~/.local/share/gegl-0.4/plug-ins Linux (Flatpak includes Chromebook)~/.var/app/org.gimp.GIMP/data/gegl-0.4/plug-ins
Last edited by contrast_ on Thu May 22, 2025 10:53 pm, edited 1 time in total.
|
|