plug-ins: port contrast-retinex to GEGL, stupid 8-bit port only

(cherry picked from commit 0e23d7262b)
This commit is contained in:
Michael Natterer
2019-07-11 12:17:01 +02:00
parent c484a0c17b
commit 1ad7cbbb73
3 changed files with 62 additions and 44 deletions

View File

@ -547,6 +547,7 @@ contrast_retinex_LDADD = \
$(libgimpcolor) \ $(libgimpcolor) \
$(libgimpbase) \ $(libgimpbase) \
$(GTK_LIBS) \ $(GTK_LIBS) \
$(GEGL_LIBS) \
$(RT_LIBS) \ $(RT_LIBS) \
$(INTLLIBS) \ $(INTLLIBS) \
$(contrast_retinex_RC) $(contrast_retinex_RC)

View File

@ -81,8 +81,10 @@ static void run (const gchar *name,
GimpParam **return_vals); GimpParam **return_vals);
/* Gimp */ /* Gimp */
static gboolean retinex_dialog (GimpDrawable *drawable); static gboolean retinex_dialog (gint32 drawable_ID);
static void retinex (GimpDrawable *drawable, static void retinex (gint32 drawable_ID,
GimpPreview *preview);
static void retinex_preview (gpointer drawable_ID,
GimpPreview *preview); GimpPreview *preview);
static void retinex_scales_distribution (gfloat *scales, static void retinex_scales_distribution (gfloat *scales,
@ -180,14 +182,13 @@ run (const gchar *name,
GimpParam **return_vals) GimpParam **return_vals)
{ {
static GimpParam values[1]; static GimpParam values[1];
GimpDrawable *drawable;
GimpRunMode run_mode; GimpRunMode run_mode;
gint32 drawable_ID;
GimpPDBStatusType status = GIMP_PDB_SUCCESS; GimpPDBStatusType status = GIMP_PDB_SUCCESS;
gint x, y, width, height; gint x, y, width, height;
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;
@ -195,21 +196,19 @@ 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;
if (! gimp_drawable_mask_intersect (drawable->drawable_id, if (! gimp_drawable_mask_intersect (drawable_ID,
&x, &y, &width, &height) || &x, &y, &width, &height) ||
width < MIN_GAUSSIAN_SCALE || width < MIN_GAUSSIAN_SCALE ||
height < MIN_GAUSSIAN_SCALE) height < MIN_GAUSSIAN_SCALE)
{ {
status = GIMP_PDB_EXECUTION_ERROR; status = GIMP_PDB_EXECUTION_ERROR;
gimp_drawable_detach (drawable);
values[0].data.d_status = status; values[0].data.d_status = status;
return; return;
} }
gimp_tile_cache_ntiles (2 * (drawable->width / gimp_tile_width () + 1));
switch (run_mode) switch (run_mode)
{ {
case GIMP_RUN_INTERACTIVE: case GIMP_RUN_INTERACTIVE:
@ -217,7 +216,7 @@ run (const gchar *name,
gimp_get_data (PLUG_IN_PROC, &rvals); gimp_get_data (PLUG_IN_PROC, &rvals);
/* First acquire information with a dialog */ /* First acquire information with a dialog */
if (! retinex_dialog (drawable)) if (! retinex_dialog (drawable_ID))
return; return;
break; break;
@ -244,12 +243,12 @@ run (const gchar *name,
break; break;
} }
if ((status == GIMP_PDB_SUCCESS) && if (status == GIMP_PDB_SUCCESS &&
(gimp_drawable_is_rgb (drawable->drawable_id))) (gimp_drawable_is_rgb (drawable_ID)))
{ {
gimp_progress_init (_("Retinex")); gimp_progress_init (_("Retinex"));
retinex (drawable, NULL); retinex (drawable_ID, NULL);
if (run_mode != GIMP_RUN_NONINTERACTIVE) if (run_mode != GIMP_RUN_NONINTERACTIVE)
gimp_displays_flush (); gimp_displays_flush ();
@ -263,14 +262,12 @@ run (const gchar *name,
status = GIMP_PDB_EXECUTION_ERROR; status = GIMP_PDB_EXECUTION_ERROR;
} }
gimp_drawable_detach (drawable);
values[0].data.d_status = status; values[0].data.d_status = status;
} }
static gboolean static gboolean
retinex_dialog (GimpDrawable *drawable) retinex_dialog (gint32 drawable_ID)
{ {
GtkWidget *dialog; GtkWidget *dialog;
GtkWidget *main_vbox; GtkWidget *main_vbox;
@ -304,13 +301,13 @@ retinex_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_zoom_preview_new_from_drawable_id (drawable->drawable_id); preview = gimp_zoom_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 (retinex), G_CALLBACK (retinex_preview),
drawable); GINT_TO_POINTER (drawable_ID));
table = gtk_table_new (4, 3, FALSE); table = gtk_table_new (4, 3, FALSE);
gtk_table_set_col_spacings (GTK_TABLE (table), 6); gtk_table_set_col_spacings (GTK_TABLE (table), 6);
@ -386,16 +383,16 @@ retinex_dialog (GimpDrawable *drawable)
* Applies the algorithm * Applies the algorithm
*/ */
static void static void
retinex (GimpDrawable *drawable, retinex (gint32 drawable_ID,
GimpPreview *preview) GimpPreview *preview)
{ {
gint x, y, width, height; GeglBuffer *src_buffer;
gint size, bytes; GeglBuffer *dest_buffer;
guchar *src = NULL; const Babl *format;
guchar *psrc = NULL; guchar *src = NULL;
GimpPixelRgn dst_rgn, src_rgn; guchar *psrc = NULL;
gint x, y, width, height;
bytes = drawable->bpp; gint size, bytes;
/* /*
* Get the size of the current image or its selection. * Get the size of the current image or its selection.
@ -407,13 +404,20 @@ retinex (GimpDrawable *drawable,
} }
else else
{ {
if (! gimp_drawable_mask_intersect (drawable->drawable_id, if (! gimp_drawable_mask_intersect (drawable_ID,
&x, &y, &width, &height)) &x, &y, &width, &height))
return; return;
if (gimp_drawable_has_alpha (drawable_ID))
format = babl_format ("R'G'B'A u8");
else
format = babl_format ("R'G'B' u8");
bytes = babl_format_get_bytes_per_pixel (format);
/* Allocate memory */ /* Allocate memory */
size = width * height * bytes; size = width * height * bytes;
src = g_try_malloc (sizeof (guchar) * size); src = g_try_malloc (sizeof (guchar) * size);
if (src == NULL) if (src == NULL)
{ {
@ -424,10 +428,11 @@ retinex (GimpDrawable *drawable,
memset (src, 0, sizeof (guchar) * size); memset (src, 0, sizeof (guchar) * size);
/* Fill allocated memory with pixel data */ /* Fill allocated memory with pixel data */
gimp_pixel_rgn_init (&src_rgn, drawable, src_buffer = gimp_drawable_get_buffer (drawable_ID);
x, y, width, height,
FALSE, FALSE); gegl_buffer_get (src_buffer, GEGL_RECTANGLE (x, y, width, height), 1.0,
gimp_pixel_rgn_get_rect (&src_rgn, src, x, y, width, height); format, src,
GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
} }
/* /*
@ -442,27 +447,39 @@ retinex (GimpDrawable *drawable,
} }
else else
{ {
gimp_pixel_rgn_init (&dst_rgn, drawable, dest_buffer = gimp_drawable_get_shadow_buffer (drawable_ID);
x, y, width, height,
TRUE, TRUE); gegl_buffer_set (dest_buffer, GEGL_RECTANGLE (x, y, width, height), 0,
gimp_pixel_rgn_set_rect (&dst_rgn, psrc, x, y, width, height); format, psrc,
GEGL_AUTO_ROWSTRIDE);
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_ID, TRUE);
gimp_drawable_merge_shadow (drawable->drawable_id, TRUE); gimp_drawable_update (drawable_ID, x, y, width, height);
gimp_drawable_update (drawable->drawable_id, x, y, width, height);
} }
g_free (src); g_free (src);
} }
static void
retinex_preview (gpointer drawable_ID,
GimpPreview *preview)
{
retinex (GPOINTER_TO_INT (drawable_ID), preview);
}
/* /*
* calculate scale values for desired distribution. * calculate scale values for desired distribution.
*/ */
static void static void
retinex_scales_distribution(gfloat* scales, gint nscales, gint mode, gint s) retinex_scales_distribution (gfloat *scales,
gint nscales,
gint mode,
gint s)
{ {
if (nscales == 1) if (nscales == 1)
{ /* For one filter we choose the median scale */ { /* For one filter we choose the median scale */

View File

@ -15,7 +15,7 @@
'colormap-remap' => { ui => 1, gegl => 1 }, 'colormap-remap' => { ui => 1, gegl => 1 },
'compose' => { ui => 1, gegl => 1 }, 'compose' => { ui => 1, gegl => 1 },
'contrast-normalize' => {}, 'contrast-normalize' => {},
'contrast-retinex' => { ui => 1 }, 'contrast-retinex' => { ui => 1, gegl => 1 },
'crop-zealous' => { gegl => 1 }, 'crop-zealous' => { gegl => 1 },
'curve-bend' => { ui => 1, gegl => 1 }, 'curve-bend' => { ui => 1, gegl => 1 },
'decompose' => { ui => 1, gegl => 1 }, 'decompose' => { ui => 1, gegl => 1 },