[gimp] plug-ins: as a proof-of-concept, port despeckle to GimpProcedureConfig
- From: Michael Natterer <mitch src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] plug-ins: as a proof-of-concept, port despeckle to GimpProcedureConfig
- Date: Fri, 20 Sep 2019 10:56:56 +0000 (UTC)
commit df62d087982ce26d2b5ddf1aee5f6457fa3f54f6
Author: Michael Natterer <mitch gimp org>
Date: Fri Sep 20 12:54:50 2019 +0200
plug-ins: as a proof-of-concept, port despeckle to GimpProcedureConfig
Its entire dialog and execution are now based on object properties and
widgets are views on the properties. Also add a "Reset" button.
plug-ins/common/despeckle.c | 480 ++++++++++++++++++++++++++------------------
1 file changed, 284 insertions(+), 196 deletions(-)
---
diff --git a/plug-ins/common/despeckle.c b/plug-ins/common/despeckle.c
index 9351a87a4f..09e3d4ba73 100644
--- a/plug-ins/common/despeckle.c
+++ b/plug-ins/common/despeckle.c
@@ -45,13 +45,11 @@
#define FILTER_ADAPTIVE 0x01
#define FILTER_RECURSIVE 0x02
-#define despeckle_radius (despeckle_vals[0]) /* diameter of filter */
-#define filter_type (despeckle_vals[1]) /* filter type */
-#define black_level (despeckle_vals[2]) /* Black level */
-#define white_level (despeckle_vals[3]) /* White level */
-
/* List that stores pixels falling in to the same luma bucket */
-#define MAX_LIST_ELEMS SQR(2 * MAX_RADIUS + 1)
+#define MAX_LIST_ELEMS SQR(2 * MAX_RADIUS + 1)
+
+#define RESPONSE_RESET 1
+
typedef struct
{
@@ -101,23 +99,32 @@ static GimpValueArray * despeckle_run (GimpProcedure *proced
const GimpValueArray *args,
gpointer run_data);
-static void despeckle (void);
-static void despeckle_median (guchar *src,
+static void despeckle (GimpDrawable *drawable,
+ GObject *config);
+static void despeckle_median (GObject *config,
+ guchar *src,
guchar *dst,
gint width,
gint height,
gint bpp,
- gint radius,
gboolean preview);
-static gboolean despeckle_dialog (void);
+static gboolean despeckle_dialog (GimpDrawable *drawable,
+ GObject *config);
-static void dialog_adaptive_callback (GtkWidget *widget,
- gpointer data);
-static void dialog_recursive_callback (GtkWidget *widget,
- gpointer data);
+static void dialog_adaptive_callback (GtkWidget *button,
+ GObject *config);
+static void dialog_adaptive_notify (GObject *config,
+ const GParamSpec *pspec,
+ GtkWidget *button);
+static void dialog_recursive_callback (GtkWidget *button,
+ GObject *config);
+static void dialog_recursive_notify (GObject *config,
+ const GParamSpec *pspec,
+ GtkWidget *button);
-static void preview_update (GtkWidget *preview);
+static void preview_update (GtkWidget *preview,
+ GObject *config);
G_DEFINE_TYPE (Despeckle, despeckle, GIMP_TYPE_PLUG_IN)
@@ -132,18 +139,6 @@ static gint histrest; /* From min to max */
static DespeckleHistogram histogram;
-static GtkWidget *preview; /* Preview widget */
-static GimpDrawable *drawable = NULL; /* Current drawable */
-
-
-static gint despeckle_vals[4] =
-{
- 3, /* Default value for the diameter */
- FILTER_ADAPTIVE, /* Default value for the filter type */
- 7, /* Default value for the black level */
- 248 /* Default value for the white level */
-};
-
static void
despeckle_class_init (DespeckleClass *klass)
@@ -227,61 +222,40 @@ static GimpValueArray *
despeckle_run (GimpProcedure *procedure,
GimpRunMode run_mode,
GimpImage *image,
- GimpDrawable *_drawable,
+ GimpDrawable *drawable,
const GimpValueArray *args,
gpointer run_data)
{
+ GimpProcedureConfig *config;
+
INIT_I18N ();
gegl_init (NULL, NULL);
- drawable = _drawable;
-
- switch (run_mode)
+ if (! gimp_drawable_is_rgb (drawable) &&
+ ! gimp_drawable_is_gray (drawable))
{
- case GIMP_RUN_INTERACTIVE :
- gimp_get_data (PLUG_IN_PROC, &despeckle_radius);
+ return gimp_procedure_new_return_values (procedure,
+ GIMP_PDB_EXECUTION_ERROR,
+ NULL);
+ }
+
+ config = gimp_procedure_create_config (procedure);
+ gimp_procedure_config_begin_run (config, run_mode, args);
- if (gimp_drawable_is_rgb (drawable) ||
- gimp_drawable_is_gray (drawable))
+ if (run_mode == GIMP_RUN_INTERACTIVE)
+ {
+ if (! despeckle_dialog (drawable, G_OBJECT (config)))
{
- if (! despeckle_dialog ())
- {
- return gimp_procedure_new_return_values (procedure,
- GIMP_PDB_CANCEL,
- NULL);
- }
+ return gimp_procedure_new_return_values (procedure,
+ GIMP_PDB_CANCEL,
+ NULL);
}
- break;
-
- case GIMP_RUN_NONINTERACTIVE:
- despeckle_radius = GIMP_VALUES_GET_INT (args, 0);
- filter_type = GIMP_VALUES_GET_INT (args, 1);
- black_level = GIMP_VALUES_GET_INT (args, 2);
- white_level = GIMP_VALUES_GET_INT (args, 3);
- break;
-
- case GIMP_RUN_WITH_LAST_VALS:
- gimp_get_data (PLUG_IN_PROC, despeckle_vals);
- break;
}
- if (gimp_drawable_is_rgb (drawable) ||
- gimp_drawable_is_gray (drawable))
- {
- despeckle ();
+ despeckle (drawable, G_OBJECT (config));
- if (run_mode != GIMP_RUN_NONINTERACTIVE)
- gimp_displays_flush ();
-
- if (run_mode == GIMP_RUN_INTERACTIVE)
- gimp_set_data (PLUG_IN_PROC, despeckle_vals, sizeof (despeckle_vals));
- }
- else
- {
- return gimp_procedure_new_return_values (procedure,
- GIMP_PDB_EXECUTION_ERROR,
- NULL);
- }
+ gimp_procedure_config_end_run (config, run_mode);
+ g_object_unref (config);
return gimp_procedure_new_return_values (procedure, GIMP_PDB_SUCCESS, NULL);
}
@@ -335,8 +309,28 @@ pixel_copy (guchar *dest,
* accordingly.
*/
+static const Babl *
+get_u8_format (GimpDrawable *drawable)
+{
+ if (gimp_drawable_is_rgb (drawable))
+ {
+ if (gimp_drawable_has_alpha (drawable))
+ return babl_format ("R'G'B'A u8");
+ else
+ return babl_format ("R'G'B' u8");
+ }
+ else
+ {
+ if (gimp_drawable_has_alpha (drawable))
+ return babl_format ("Y'A u8");
+ else
+ return babl_format ("Y' u8");
+ }
+}
+
static void
-despeckle (void)
+despeckle (GimpDrawable *drawable,
+ GObject *config)
{
GeglBuffer *src_buffer;
GeglBuffer *dest_buffer;
@@ -351,21 +345,7 @@ despeckle (void)
&x, &y, &width, &height))
return;
- if (gimp_drawable_is_rgb (drawable))
- {
- if (gimp_drawable_has_alpha (drawable))
- format = babl_format ("R'G'B'A u8");
- else
- format = babl_format ("R'G'B' u8");
- }
- else
- {
- if (gimp_drawable_has_alpha (drawable))
- format = babl_format ("Y'A u8");
- else
- format = babl_format ("Y' u8");
- }
-
+ format = get_u8_format (drawable);
img_bpp = babl_format_get_bytes_per_pixel (format);
src_buffer = gimp_drawable_get_buffer (drawable);
@@ -378,7 +358,8 @@ despeckle (void)
format, src,
GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
- despeckle_median (src, dst, width, height, img_bpp, despeckle_radius, FALSE);
+ despeckle_median (config,
+ src, dst, width, height, img_bpp, FALSE);
gegl_buffer_set (dest_buffer, GEGL_RECTANGLE (x, y, width, height), 0,
format, dst,
@@ -395,16 +376,18 @@ despeckle (void)
}
static gboolean
-despeckle_dialog (void)
+despeckle_dialog (GimpDrawable *drawable,
+ GObject *config)
{
- GtkWidget *dialog;
- GtkWidget *main_vbox;
- GtkWidget *vbox;
- GtkWidget *grid;
- GtkWidget *frame;
- GtkWidget *button;
- GtkAdjustment *adj;
- gboolean run;
+ GtkWidget *dialog;
+ GtkWidget *main_vbox;
+ GtkWidget *preview;
+ GtkWidget *vbox;
+ GtkWidget *grid;
+ GtkWidget *frame;
+ GtkWidget *button;
+ gint filter_type;
+ gboolean run;
gimp_ui_init (PLUG_IN_BINARY, TRUE);
@@ -412,6 +395,7 @@ despeckle_dialog (void)
NULL, 0,
gimp_standard_help_func, PLUG_IN_PROC,
+ _("_Reset"), RESPONSE_RESET,
_("_Cancel"), GTK_RESPONSE_CANCEL,
_("_OK"), GTK_RESPONSE_OK,
@@ -434,9 +418,11 @@ despeckle_dialog (void)
gtk_box_pack_start (GTK_BOX (main_vbox), preview, TRUE, TRUE, 0);
gtk_widget_show (preview);
+ g_object_set_data (config, "drawable", drawable);
+
g_signal_connect (preview, "invalidated",
G_CALLBACK (preview_update),
- NULL);
+ config);
frame = gimp_frame_new (_("Median"));
gtk_box_pack_start (GTK_BOX (main_vbox), frame, FALSE, FALSE, 0);
@@ -446,6 +432,8 @@ despeckle_dialog (void)
gtk_container_add (GTK_CONTAINER (frame), vbox);
gtk_widget_show (vbox);
+ g_object_get (config, "type", &filter_type, NULL);
+
button = gtk_check_button_new_with_mnemonic (_("_Adaptive"));
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
@@ -454,7 +442,10 @@ despeckle_dialog (void)
g_signal_connect (button, "toggled",
G_CALLBACK (dialog_adaptive_callback),
- NULL);
+ config);
+ g_signal_connect (config, "notify::type",
+ G_CALLBACK (dialog_adaptive_notify),
+ button);
button = gtk_check_button_new_with_mnemonic (_("R_ecursive"));
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
@@ -464,7 +455,10 @@ despeckle_dialog (void)
g_signal_connect (button, "toggled",
G_CALLBACK (dialog_recursive_callback),
- NULL);
+ config);
+ g_signal_connect (config, "notify::type",
+ G_CALLBACK (dialog_recursive_notify),
+ button);
grid = gtk_grid_new ();
gtk_grid_set_row_spacing (GTK_GRID (grid), 6);
@@ -476,53 +470,52 @@ despeckle_dialog (void)
* Box size (diameter) control...
*/
- adj = gimp_scale_entry_new (GTK_GRID (grid), 0, 0,
- _("_Radius:"), SCALE_WIDTH, ENTRY_WIDTH,
- despeckle_radius, 1, MAX_RADIUS, 1, 5, 0,
- TRUE, 0, 0,
- NULL, NULL);
- g_signal_connect (adj, "value-changed",
- G_CALLBACK (gimp_int_adjustment_update),
- &despeckle_radius);
- g_signal_connect_swapped (adj, "value-changed",
- G_CALLBACK (gimp_preview_invalidate),
- preview);
+ gimp_prop_scale_entry_new (config, "radius",
+ GTK_GRID (grid), 0, 0,
+ _("_Radius:"),
+ 1, 5, 0,
+ FALSE, 0, 0);
/*
* Black level control...
*/
- adj = gimp_scale_entry_new (GTK_GRID (grid), 0, 1,
- _("_Black level:"), SCALE_WIDTH, ENTRY_WIDTH,
- black_level, -1, 255, 1, 8, 0,
- TRUE, 0, 0,
- NULL, NULL);
- g_signal_connect (adj, "value-changed",
- G_CALLBACK (gimp_int_adjustment_update),
- &black_level);
- g_signal_connect_swapped (adj, "value-changed",
- G_CALLBACK (gimp_preview_invalidate),
- preview);
+ gimp_prop_scale_entry_new (config, "black",
+ GTK_GRID (grid), 0, 1,
+ _("_Black level:"),
+ 1, 8, 0,
+ FALSE, 0, 0);
/*
* White level control...
*/
- adj = gimp_scale_entry_new (GTK_GRID (grid), 0, 2,
- _("_White level:"), SCALE_WIDTH, ENTRY_WIDTH,
- white_level, 0, 256, 1, 8, 0,
- TRUE, 0, 0,
- NULL, NULL);
- g_signal_connect (adj, "value-changed",
- G_CALLBACK (gimp_int_adjustment_update),
- &white_level);
- g_signal_connect_swapped (adj, "value-changed",
+ gimp_prop_scale_entry_new (config, "white",
+ GTK_GRID (grid), 0, 2,
+ _("_White level:"),
+ 1, 8, 0,
+ FALSE, 0, 0);
+
+ g_signal_connect_swapped (config, "notify",
G_CALLBACK (gimp_preview_invalidate),
preview);
gtk_widget_show (dialog);
- run = (gimp_dialog_run (GIMP_DIALOG (dialog)) == GTK_RESPONSE_OK);
+ while (TRUE)
+ {
+ gint response = gimp_dialog_run (GIMP_DIALOG (dialog));
+
+ if (response == RESPONSE_RESET)
+ {
+ gimp_config_reset (GIMP_CONFIG (config));
+ }
+ else
+ {
+ run = (response == GTK_RESPONSE_OK);
+ break;
+ }
+ }
gtk_widget_destroy (dialog);
@@ -530,34 +523,20 @@ despeckle_dialog (void)
}
static void
-preview_update (GtkWidget *widget)
+preview_update (GtkWidget *widget,
+ GObject *config)
{
- GimpPreview *preview = GIMP_PREVIEW (widget);
- GeglBuffer *src_buffer;
- const Babl *format;
- guchar *dst;
- guchar *src;
- gint img_bpp;
- gint x1,y1;
- gint width, height;
-
- preview = GIMP_PREVIEW (widget);
-
- if (gimp_drawable_is_rgb (drawable))
- {
- if (gimp_drawable_has_alpha (drawable))
- format = babl_format ("R'G'B'A u8");
- else
- format = babl_format ("R'G'B' u8");
- }
- else
- {
- if (gimp_drawable_has_alpha (drawable))
- format = babl_format ("Y'A u8");
- else
- format = babl_format ("Y' u8");
- }
-
+ GimpPreview *preview = GIMP_PREVIEW (widget);
+ GimpDrawable *drawable = g_object_get_data (config, "drawable");
+ GeglBuffer *src_buffer;
+ const Babl *format;
+ guchar *dst;
+ guchar *src;
+ gint img_bpp;
+ gint x1,y1;
+ gint width, height;
+
+ format = get_u8_format (drawable);
img_bpp = babl_format_get_bytes_per_pixel (format);
gimp_preview_get_size (preview, &width, &height);
@@ -572,7 +551,8 @@ preview_update (GtkWidget *widget)
format, src,
GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
- despeckle_median (src, dst, width, height, img_bpp, despeckle_radius, TRUE);
+ despeckle_median (config,
+ src, dst, width, height, img_bpp, TRUE);
gimp_preview_draw_buffer (preview, dst, width * img_bpp);
@@ -583,29 +563,94 @@ preview_update (GtkWidget *widget)
}
static void
-dialog_adaptive_callback (GtkWidget *widget,
- gpointer data)
+dialog_adaptive_callback (GtkWidget *button,
+ GObject *config)
{
- if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)))
+ gint filter_type;
+
+ g_object_get (config, "type", &filter_type, NULL);
+
+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)))
filter_type |= FILTER_ADAPTIVE;
else
filter_type &= ~FILTER_ADAPTIVE;
- gimp_preview_invalidate (GIMP_PREVIEW (preview));
+ g_signal_handlers_block_by_func (config,
+ dialog_adaptive_notify,
+ button);
+
+ g_object_set (config, "type", filter_type, NULL);
+
+ g_signal_handlers_unblock_by_func (config,
+ dialog_adaptive_notify,
+ button);
}
static void
-dialog_recursive_callback (GtkWidget *widget,
- gpointer data)
+dialog_adaptive_notify (GObject *config,
+ const GParamSpec *pspec,
+ GtkWidget *button)
{
- if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)))
+ gint filter_type;
+
+ g_object_get (config, "type", &filter_type, NULL);
+
+ g_signal_handlers_block_by_func (button,
+ dialog_adaptive_callback,
+ config);
+
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
+ (filter_type & FILTER_ADAPTIVE) != 0);
+
+ g_signal_handlers_unblock_by_func (button,
+ dialog_adaptive_callback,
+ config);
+}
+
+static void
+dialog_recursive_callback (GtkWidget *button,
+ GObject *config)
+{
+ gint filter_type;
+
+ g_object_get (config, "type", &filter_type, NULL);
+
+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)))
filter_type |= FILTER_RECURSIVE;
else
filter_type &= ~FILTER_RECURSIVE;
- gimp_preview_invalidate (GIMP_PREVIEW (preview));
+ g_signal_handlers_block_by_func (config,
+ dialog_recursive_notify,
+ button);
+
+ g_object_set (config, "type", filter_type, NULL);
+
+ g_signal_handlers_unblock_by_func (config,
+ dialog_recursive_notify,
+ button);
}
+static void
+dialog_recursive_notify (GObject *config,
+ const GParamSpec *pspec,
+ GtkWidget *button)
+{
+ gint filter_type;
+
+ g_object_get (config, "type", &filter_type, NULL);
+
+ g_signal_handlers_block_by_func (button,
+ dialog_recursive_callback,
+ config);
+
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
+ (filter_type & FILTER_RECURSIVE) != 0);
+
+ g_signal_handlers_unblock_by_func (button,
+ dialog_recursive_callback,
+ config);
+}
static inline void
list_add_elem (PixelsList *list,
@@ -688,6 +733,8 @@ histogram_get_median (DespeckleHistogram *hist,
static inline void
add_val (DespeckleHistogram *hist,
+ gint black_level,
+ gint white_level,
const guchar *src,
gint width,
gint bpp,
@@ -698,22 +745,24 @@ add_val (DespeckleHistogram *hist,
const gint value = pixel_luminance (src + pos, bpp);
if (value > black_level && value < white_level)
- {
- histogram_add (hist, value, src + pos);
- histrest++;
- }
+ {
+ histogram_add (hist, value, src + pos);
+ histrest++;
+ }
else
- {
- if (value <= black_level)
- hist0++;
+ {
+ if (value <= black_level)
+ hist0++;
- if (value >= white_level)
- hist255++;
- }
+ if (value >= white_level)
+ hist255++;
+ }
}
static inline void
del_val (DespeckleHistogram *hist,
+ gint black_level,
+ gint white_level,
const guchar *src,
gint width,
gint bpp,
@@ -724,22 +773,24 @@ del_val (DespeckleHistogram *hist,
const gint value = pixel_luminance (src + pos, bpp);
if (value > black_level && value < white_level)
- {
- histogram_remove (hist, value);
- histrest--;
- }
+ {
+ histogram_remove (hist, value);
+ histrest--;
+ }
else
- {
- if (value <= black_level)
- hist0--;
+ {
+ if (value <= black_level)
+ hist0--;
- if (value >= white_level)
- hist255--;
- }
+ if (value >= white_level)
+ hist255--;
+ }
}
static inline void
add_vals (DespeckleHistogram *hist,
+ gint black_level,
+ gint white_level,
const guchar *src,
gint width,
gint bpp,
@@ -758,13 +809,17 @@ add_vals (DespeckleHistogram *hist,
{
for (x = xmin; x <= xmax; x++)
{
- add_val (hist, src, width, bpp, x, y);
+ add_val (hist,
+ black_level, white_level,
+ src, width, bpp, x, y);
}
}
}
static inline void
del_vals (DespeckleHistogram *hist,
+ gint black_level,
+ gint white_level,
const guchar *src,
gint width,
gint bpp,
@@ -783,13 +838,17 @@ del_vals (DespeckleHistogram *hist,
{
for (x = xmin; x <= xmax; x++)
{
- del_val (hist, src, width, bpp, x, y);
+ del_val (hist,
+ black_level, white_level,
+ src, width, bpp, x, y);
}
}
}
static inline void
update_histogram (DespeckleHistogram *hist,
+ gint black_level,
+ gint white_level,
const guchar *src,
gint width,
gint bpp,
@@ -803,13 +862,23 @@ update_histogram (DespeckleHistogram *hist,
/* assuming that box is moving either right or down */
del_vals (hist,
+ black_level, white_level,
src, width, bpp, hist->xmin, hist->ymin, xmin - 1, hist->ymax);
- del_vals (hist, src, width, bpp, xmin, hist->ymin, xmax, ymin - 1);
- del_vals (hist, src, width, bpp, xmin, ymax + 1, xmax, hist->ymax);
+ del_vals (hist,
+ black_level, white_level,
+ src, width, bpp, xmin, hist->ymin, xmax, ymin - 1);
+ del_vals (hist,
+ black_level, white_level,
+ src, width, bpp, xmin, ymax + 1, xmax, hist->ymax);
- add_vals (hist, src, width, bpp, hist->xmax + 1, ymin, xmax, ymax);
- add_vals (hist, src, width, bpp, xmin, ymin, hist->xmax, hist->ymin - 1);
add_vals (hist,
+ black_level, white_level,
+ src, width, bpp, hist->xmax + 1, ymin, xmax, ymax);
+ add_vals (hist,
+ black_level, white_level,
+ src, width, bpp, xmin, ymin, hist->xmax, hist->ymin - 1);
+ add_vals (hist,
+ black_level, white_level,
src, width, bpp, hist->xmin, hist->ymax + 1, hist->xmax, ymax);
hist->xmin = xmin;
@@ -819,14 +888,18 @@ update_histogram (DespeckleHistogram *hist,
}
static void
-despeckle_median (guchar *src,
+despeckle_median (GObject *config,
+ guchar *src,
guchar *dst,
gint width,
gint height,
gint bpp,
- gint radius,
gboolean preview)
{
+ gint radius;
+ gint filter_type;
+ gint black_level;
+ gint white_level;
guint progress;
guint max_progress;
gint x, y;
@@ -837,6 +910,13 @@ despeckle_median (guchar *src,
gint xmin;
gint xmax;
+ g_object_get (config,
+ "radius", &radius,
+ "type", &filter_type,
+ "black", &black_level,
+ "white", &white_level,
+ NULL);
+
memset (&histogram, 0, sizeof(histogram));
progress = 0;
max_progress = width * height;
@@ -861,6 +941,7 @@ despeckle_median (guchar *src,
histogram.xmax = xmax;
histogram.ymax = ymax;
add_vals (&histogram,
+ black_level, white_level,
src, width, bpp,
histogram.xmin, histogram.ymin,
histogram.xmax, histogram.ymax);
@@ -875,6 +956,7 @@ despeckle_median (guchar *src,
xmax = MIN (width - 1, x + adapt_radius);
update_histogram (&histogram,
+ black_level, white_level,
src, width, bpp, xmin, ymin, xmax, ymax);
pos = (x + (y * width)) * bpp;
@@ -882,9 +964,15 @@ despeckle_median (guchar *src,
if (filter_type & FILTER_RECURSIVE)
{
- del_val (&histogram, src, width, bpp, x, y);
+ del_val (&histogram,
+ black_level, white_level,
+ src, width, bpp, x, y);
+
pixel_copy (src + pos, pixel, bpp);
- add_val (&histogram, src, width, bpp, x, y);
+
+ add_val (&histogram,
+ black_level, white_level,
+ src, width, bpp, x, y);
}
pixel_copy (dst + pos, pixel, bpp);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]