plug-ins: port blinds to GEGL

Found another unfinished result of boredom from years ago.
Stupid 8-bit only port.
This commit is contained in:
Michael Natterer 2019-06-27 13:21:56 +02:00
parent c3752ba743
commit 4c4abf7fc4
3 changed files with 114 additions and 99 deletions

View file

@ -300,6 +300,7 @@ blinds_LDADD = \
$(libgimpcolor) \ $(libgimpcolor) \
$(libgimpbase) \ $(libgimpbase) \
$(GTK_LIBS) \ $(GTK_LIBS) \
$(GEGL_LIBS) \
$(RT_LIBS) \ $(RT_LIBS) \
$(INTLLIBS) \ $(INTLLIBS) \
$(blinds_RC) $(blinds_RC)

View file

@ -57,11 +57,6 @@ typedef struct data
gboolean bg_trans; gboolean bg_trans;
} BlindVals; } BlindVals;
/* Array to hold each size of fans. And no there are not each the
* same size (rounding errors...)
*/
static gint fanwidths[MAX_FANS];
static void query (void); static void query (void);
static void run (const gchar *name, static void run (const gchar *name,
@ -70,19 +65,18 @@ static void run (const gchar *name,
gint *nreturn_vals, gint *nreturn_vals,
GimpParam **return_vals); GimpParam **return_vals);
static gboolean blinds_dialog (GimpDrawable *drawable); static gboolean blinds_dialog (gint32 drawable_id);
static void dialog_update_preview (GimpDrawable *drawable, static void dialog_update_preview (gpointer drawable_id,
GimpPreview *preview); GimpPreview *preview);
static void apply_blinds (GimpDrawable *drawable); static void apply_blinds (gint32 drawable_id);
const GimpPlugInInfo PLUG_IN_INFO =
{ /* Array to hold each size of fans. And no there are not each the
NULL, /* init_proc */ * same size (rounding errors...)
NULL, /* quit_proc */ */
query, /* query_proc */
run, /* run_proc */ static gint fanwidths[MAX_FANS];
};
/* Values when first invoked */ /* Values when first invoked */
static BlindVals bvals = static BlindVals bvals =
@ -93,8 +87,18 @@ static BlindVals bvals =
FALSE FALSE
}; };
const GimpPlugInInfo PLUG_IN_INFO =
{
NULL, /* init_proc */
NULL, /* quit_proc */
query, /* query_proc */
run, /* run_proc */
};
MAIN () MAIN ()
static void static void
query (void) query (void)
{ {
@ -130,13 +134,12 @@ run (const gchar *name,
GimpParam **return_vals) GimpParam **return_vals)
{ {
static GimpParam values[1]; static GimpParam values[1];
GimpDrawable *drawable; gint32 drawable_id;
GimpRunMode run_mode; GimpRunMode run_mode;
GimpPDBStatusType status = GIMP_PDB_SUCCESS; GimpPDBStatusType status = GIMP_PDB_SUCCESS;
run_mode = param[0].data.d_int32;
INIT_I18N (); INIT_I18N ();
gegl_init (NULL, NULL);
*nreturn_vals = 1; *nreturn_vals = 1;
*return_vals = values; *return_vals = values;
@ -144,22 +147,21 @@ run (const gchar *name,
values[0].type = GIMP_PDB_STATUS; values[0].type = GIMP_PDB_STATUS;
values[0].data.d_status = status; values[0].data.d_status = status;
drawable = gimp_drawable_get (param[2].data.d_drawable); run_mode = param[0].data.d_int32;
drawable_id = param[2].data.d_drawable;
switch (run_mode) switch (run_mode)
{ {
case GIMP_RUN_INTERACTIVE: case GIMP_RUN_INTERACTIVE:
gimp_get_data (PLUG_IN_PROC, &bvals); gimp_get_data (PLUG_IN_PROC, &bvals);
if (! blinds_dialog (drawable)) if (! blinds_dialog (drawable_id))
{
gimp_drawable_detach (drawable);
return; return;
}
break; break;
case GIMP_RUN_NONINTERACTIVE: case GIMP_RUN_NONINTERACTIVE:
if (nparams != 7) if (nparams != 7)
status = GIMP_PDB_CALLING_ERROR; status = GIMP_PDB_CALLING_ERROR;
if (status == GIMP_PDB_SUCCESS) if (status == GIMP_PDB_SUCCESS)
{ {
bvals.angledsp = param[3].data.d_int32; bvals.angledsp = param[3].data.d_int32;
@ -177,12 +179,12 @@ run (const gchar *name,
break; break;
} }
if (gimp_drawable_is_rgb (drawable->drawable_id) || if (gimp_drawable_is_rgb (drawable_id) ||
gimp_drawable_is_gray (drawable->drawable_id)) gimp_drawable_is_gray (drawable_id))
{ {
gimp_progress_init (_("Adding blinds")); gimp_progress_init (_("Adding blinds"));
apply_blinds (drawable); apply_blinds (drawable_id);
if (run_mode != GIMP_RUN_NONINTERACTIVE) if (run_mode != GIMP_RUN_NONINTERACTIVE)
gimp_displays_flush (); gimp_displays_flush ();
@ -196,13 +198,11 @@ run (const gchar *name,
} }
values[0].data.d_status = status; values[0].data.d_status = status;
gimp_drawable_detach (drawable);
} }
static gboolean static gboolean
blinds_dialog (GimpDrawable *drawable) blinds_dialog (gint32 drawable_id)
{ {
GtkWidget *dialog; GtkWidget *dialog;
GtkWidget *main_vbox; GtkWidget *main_vbox;
@ -240,13 +240,13 @@ blinds_dialog (GimpDrawable *drawable)
main_vbox, TRUE, TRUE, 0); main_vbox, TRUE, TRUE, 0);
gtk_widget_show (main_vbox); gtk_widget_show (main_vbox);
preview = gimp_aspect_preview_new_from_drawable_id (drawable->drawable_id); preview = gimp_aspect_preview_new_from_drawable_id (drawable_id);
gtk_box_pack_start (GTK_BOX (main_vbox), preview, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (main_vbox), preview, TRUE, TRUE, 0);
gtk_widget_show (preview); gtk_widget_show (preview);
g_signal_connect_swapped (preview, "invalidated", g_signal_connect_swapped (preview, "invalidated",
G_CALLBACK (dialog_update_preview), G_CALLBACK (dialog_update_preview),
drawable); GINT_TO_POINTER (drawable_id));
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12); hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, FALSE, 0);
@ -291,7 +291,7 @@ blinds_dialog (GimpDrawable *drawable)
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), bvals.bg_trans); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), bvals.bg_trans);
if (!gimp_drawable_has_alpha (drawable->drawable_id)) if (! gimp_drawable_has_alpha (drawable_id))
{ {
gtk_widget_set_sensitive (toggle, FALSE); gtk_widget_set_sensitive (toggle, FALSE);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), FALSE); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), FALSE);
@ -442,9 +442,10 @@ blindsapply (guchar *srow,
} }
static void static void
dialog_update_preview (GimpDrawable *drawable, dialog_update_preview (gpointer drawable_ptr,
GimpPreview *preview) GimpPreview *preview)
{ {
gint32 drawable_id = GPOINTER_TO_INT (drawable_ptr);
gint y; gint y;
guchar *p, *buffer, *cache; guchar *p, *buffer, *cache;
GimpRGB background; GimpRGB background;
@ -452,8 +453,7 @@ dialog_update_preview (GimpDrawable *drawable,
gint width, height, bpp; gint width, height, bpp;
gimp_preview_get_size (preview, &width, &height); gimp_preview_get_size (preview, &width, &height);
bpp = gimp_drawable_bpp (drawable->drawable_id); cache = gimp_drawable_get_thumbnail_data (drawable_id,
cache = gimp_drawable_get_thumbnail_data (drawable->drawable_id,
&width, &height, &bpp); &width, &height, &bpp);
p = cache; p = cache;
@ -462,7 +462,15 @@ dialog_update_preview (GimpDrawable *drawable,
if (bvals.bg_trans) if (bvals.bg_trans)
gimp_rgb_set_alpha (&background, 0.0); gimp_rgb_set_alpha (&background, 0.0);
gimp_drawable_get_color_uchar (drawable->drawable_id, &background, bg); if (gimp_drawable_is_gray (drawable_id))
{
bg[0] = gimp_rgb_luminance_uchar (&background);
gimp_rgba_get_uchar (&background, NULL, NULL, NULL, bg + 3);
}
else
{
gimp_rgba_get_uchar (&background, bg, bg + 1, bg + 2, bg + 3);
}
buffer = g_new (guchar, width * height * bpp); buffer = g_new (guchar, width * height * bpp);
@ -549,11 +557,13 @@ dialog_update_preview (GimpDrawable *drawable,
#define STEP 40 #define STEP 40
static void static void
apply_blinds (GimpDrawable *drawable) apply_blinds (gint32 drawable_id)
{ {
GimpPixelRgn des_rgn; GeglBuffer *src_buffer;
GimpPixelRgn src_rgn; GeglBuffer *dest_buffer;
const Babl *format;
guchar *src_rows, *des_rows; guchar *src_rows, *des_rows;
gint bytes;
gint x, y; gint x, y;
GimpRGB background; GimpRGB background;
guchar bg[4]; guchar bg[4];
@ -565,20 +575,25 @@ apply_blinds (GimpDrawable *drawable)
if (bvals.bg_trans) if (bvals.bg_trans)
gimp_rgb_set_alpha (&background, 0.0); gimp_rgb_set_alpha (&background, 0.0);
gimp_drawable_get_color_uchar (drawable->drawable_id, &background, bg); gimp_rgba_get_uchar (&background, bg, bg + 1, bg + 2, bg + 3);
if (! gimp_drawable_mask_intersect (drawable->drawable_id, if (! gimp_drawable_mask_intersect (drawable_id,
&sel_x1, &sel_y1, &sel_x1, &sel_y1,
&sel_width, &sel_height)) &sel_width, &sel_height))
return; return;
gimp_pixel_rgn_init (&src_rgn, drawable, if (gimp_drawable_has_alpha (drawable_id))
sel_x1, sel_y1, sel_width, sel_height, FALSE, FALSE); format = babl_format ("R'G'B'A u8");
gimp_pixel_rgn_init (&des_rgn, drawable, else
sel_x1, sel_y1, sel_width, sel_height, TRUE, TRUE); format = babl_format ("R'G'B' u8");
src_rows = g_new (guchar, MAX (sel_width, sel_height) * 4 * STEP); bytes = babl_format_get_bytes_per_pixel (format);
des_rows = g_new (guchar, MAX (sel_width, sel_height) * 4 * STEP);
src_buffer = gimp_drawable_get_buffer (drawable_id);
dest_buffer = gimp_drawable_get_shadow_buffer (drawable_id);
src_rows = g_new (guchar, MAX (sel_width, sel_height) * bytes * STEP);
des_rows = g_new (guchar, MAX (sel_width, sel_height) * bytes * STEP);
if (bvals.orientation == GIMP_ORIENTATION_VERTICAL) if (bvals.orientation == GIMP_ORIENTATION_VERTICAL)
{ {
@ -587,30 +602,28 @@ apply_blinds (GimpDrawable *drawable)
gint rr; gint rr;
gint step; gint step;
if((y + STEP) > sel_height) if ((y + STEP) > sel_height)
step = sel_height - y; step = sel_height - y;
else else
step = STEP; step = STEP;
gimp_pixel_rgn_get_rect (&src_rgn, gegl_buffer_get (src_buffer,
src_rows, GEGL_RECTANGLE (sel_x1, sel_y1 + y,
sel_x1, sel_width, step), 1.0,
sel_y1 + y, format, src_rows,
sel_width, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
step);
/* OK I could make this better */ /* OK I could make this better */
for (rr = 0; rr < STEP; rr++) for (rr = 0; rr < STEP; rr++)
blindsapply (src_rows + (sel_width * rr * src_rgn.bpp), blindsapply (src_rows + (sel_width * rr * bytes),
des_rows + (sel_width * rr * src_rgn.bpp), des_rows + (sel_width * rr * bytes),
sel_width, src_rgn.bpp, bg); sel_width, bytes, bg);
gimp_pixel_rgn_set_rect (&des_rgn, gegl_buffer_set (dest_buffer,
des_rows, GEGL_RECTANGLE (sel_x1, sel_y1 + y,
sel_x1, sel_width, step), 0,
sel_y1 + y, format, des_rows,
sel_width, GEGL_AUTO_ROWSTRIDE);
step);
gimp_progress_update ((double) y / (double) sel_height); gimp_progress_update ((double) y / (double) sel_height);
} }
@ -623,13 +636,13 @@ apply_blinds (GimpDrawable *drawable)
* rows. Make row 0 invalid so we can find it again! * rows. Make row 0 invalid so we can find it again!
*/ */
gint i; gint i;
gint *sr = g_new (gint, sel_height * 4); gint *sr = g_new (gint, sel_height * bytes);
gint *dr = g_new (gint, sel_height * 4); gint *dr = g_new (gint, sel_height * bytes);
guchar *dst = g_new (guchar, STEP * 4); guchar *dst = g_new (guchar, STEP * bytes);
guchar dummybg[4]; guchar dummybg[4];
memset (dummybg, 0, 4); memset (dummybg, 0, 4);
memset (dr, 0, sel_height * 4); /* all dr rows are background rows */ memset (dr, 0, sel_height * bytes); /* all dr rows are background rows */
for (y = 0; y < sel_height; y++) for (y = 0; y < sel_height; y++)
{ {
sr[y] = y+1; sr[y] = y+1;
@ -647,9 +660,9 @@ apply_blinds (GimpDrawable *drawable)
{ {
int j; int j;
guchar *bgdst; guchar *bgdst;
bgdst = &dst[i * src_rgn.bpp]; bgdst = &dst[i * bytes];
for (j = 0 ; j < src_rgn.bpp; j++) for (j = 0 ; j < bytes; j++)
{ {
bgdst[j] = bg[j]; bgdst[j] = bg[j];
} }
@ -666,12 +679,11 @@ apply_blinds (GimpDrawable *drawable)
else else
step = STEP; step = STEP;
gimp_pixel_rgn_get_rect (&src_rgn, gegl_buffer_get (src_buffer,
src_rows, GEGL_RECTANGLE (sel_x1 + x, sel_y1,
sel_x1 + x, step, sel_height), 1.0,
sel_y1, format, src_rows,
step, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
sel_height);
/* OK I could make this better */ /* OK I could make this better */
for (rr = 0; rr < sel_height; rr++) for (rr = 0; rr < sel_height; rr++)
@ -684,18 +696,17 @@ apply_blinds (GimpDrawable *drawable)
else else
{ {
/* Draw line from src */ /* Draw line from src */
p = src_rows + (step * src_rgn.bpp * (dr[rr] - 1)); p = src_rows + (step * bytes * (dr[rr] - 1));
} }
memcpy (des_rows + (rr * step * src_rgn.bpp), p, memcpy (des_rows + (rr * step * bytes), p,
step * src_rgn.bpp); step * bytes);
} }
gimp_pixel_rgn_set_rect (&des_rgn, gegl_buffer_set (dest_buffer,
des_rows, GEGL_RECTANGLE (sel_x1 + x, sel_y1,
sel_x1 + x, step, sel_height), 0,
sel_y1, format, des_rows,
step, GEGL_AUTO_ROWSTRIDE);
sel_height);
gimp_progress_update ((double) x / (double) sel_width); gimp_progress_update ((double) x / (double) sel_width);
} }
@ -708,9 +719,12 @@ apply_blinds (GimpDrawable *drawable)
g_free (src_rows); g_free (src_rows);
g_free (des_rows); g_free (des_rows);
g_object_unref (src_buffer);
g_object_unref (dest_buffer);
gimp_progress_update (1.0); gimp_progress_update (1.0);
gimp_drawable_flush (drawable);
gimp_drawable_merge_shadow (drawable->drawable_id, TRUE); gimp_drawable_merge_shadow (drawable_id, TRUE);
gimp_drawable_update (drawable->drawable_id, gimp_drawable_update (drawable_id,
sel_x1, sel_y1, sel_width, sel_height); sel_x1, sel_y1, sel_width, sel_height);
} }

View file

@ -2,7 +2,7 @@
'align-layers' => { ui => 1 }, 'align-layers' => { ui => 1 },
'animation-optimize' => {}, 'animation-optimize' => {},
# FIXME 'animation-play' => { ui => 1, gegl => 1 }, # FIXME 'animation-play' => { ui => 1, gegl => 1 },
'blinds' => { ui => 1 }, 'blinds' => { ui => 1, gegl => 1 },
'blur' => {}, 'blur' => {},
'border-average' => { ui => 1, gegl => 1 }, 'border-average' => { ui => 1, gegl => 1 },
'busy-dialog' => { ui => 1, gegl => 1 }, 'busy-dialog' => { ui => 1, gegl => 1 },