First actual image processing with GEGL! Wheeeee :-)

2007-12-30  Michael Natterer  <mitch@gimp.org>

	First actual image processing with GEGL! Wheeeee :-)

	* app/core/gimpimagemap.[ch]: added code to use gegl instead of the
	old apply_func and apply_data.

	(gimp_image_map_new): add GeglNode parameter that, if passed,
	switches the whole thing to using a gegl graph with this node
	as central processing node.

	* app/tools/gimpimagemaptool.[ch]: add virtual function
	get_operation() which, if implemented, returns a GeglNode to pass
	to gimp_image_map_new(). Added a "Use GEGL" toggle so we can
	switch between legacy and gegl code for the migration period.

	* app/tools/gimpbrightnesscontrasttool.[ch]: implement
	get_operation() and return a brightness-contrast node.

	(gimp_briughtness_contrast_tool_map): set the node's properties
	from the GUI.


svn path=/trunk/; revision=24488
This commit is contained in:
Michael Natterer 2007-12-30 17:47:37 +00:00 committed by Michael Natterer
parent 0d818d9ad3
commit d6ab4d19bd
7 changed files with 423 additions and 94 deletions

View file

@ -1,3 +1,25 @@
2007-12-30 Michael Natterer <mitch@gimp.org>
First actual image processing with GEGL! Wheeeee :-)
* app/core/gimpimagemap.[ch]: added code to use gegl instead of the
old apply_func and apply_data.
(gimp_image_map_new): add GeglNode parameter that, if passed,
switches the whole thing to using a gegl graph with this node
as central processing node.
* app/tools/gimpimagemaptool.[ch]: add virtual function
get_operation() which, if implemented, returns a GeglNode to pass
to gimp_image_map_new(). Added a "Use GEGL" toggle so we can
switch between legacy and gegl code for the migration period.
* app/tools/gimpbrightnesscontrasttool.[ch]: implement
get_operation() and return a brightness-contrast node.
(gimp_briughtness_contrast_tool_map): set the node's properties
from the GUI.
2007-12-30 Sven Neumann <sven@gimp.org>
* app/display/gimpstatusbar.[ch]

View file

@ -19,6 +19,7 @@
#include "config.h"
#include <glib-object.h>
#include <gegl.h>
#include "core-types.h"
@ -53,11 +54,20 @@ struct _GimpImageMap
TileManager *undo_tiles;
gint undo_offset_x;
gint undo_offset_y;
GimpImageMapApplyFunc apply_func;
gpointer user_data;
gpointer apply_data;
PixelRegion srcPR;
PixelRegion destPR;
PixelRegionIterator *PRI;
GeglNode *gegl;
GeglNode *input;
GeglNode *shift;
GeglNode *operation;
GeglNode *output;
GeglProcessor *processor;
guint idle_id;
};
@ -77,6 +87,9 @@ static gboolean gimp_image_map_get_pixel_at (GimpPickable *pickable,
guchar *pixel);
static gboolean gimp_image_map_do (GimpImageMap *image_map);
static void gimp_image_map_data_written (GObject *operation,
const GeglRectangle *extent,
GimpImageMap *image_map);
G_DEFINE_TYPE_WITH_CODE (GimpImageMap, gimp_image_map, GIMP_TYPE_OBJECT,
@ -125,7 +138,7 @@ gimp_image_map_init (GimpImageMap *image_map)
image_map->undo_offset_x = 0;
image_map->undo_offset_y = 0;
image_map->apply_func = NULL;
image_map->user_data = NULL;
image_map->apply_data = NULL;
image_map->PRI = NULL;
image_map->idle_id = 0;
}
@ -163,9 +176,33 @@ gimp_image_map_finalize (GObject *object)
g_source_remove (image_map->idle_id);
image_map->idle_id = 0;
if (image_map->processor)
{
g_object_unref (image_map->processor);
image_map->processor = NULL;
}
if (image_map->PRI)
{
pixel_regions_process_stop (image_map->PRI);
image_map->PRI = NULL;
}
}
if (image_map->gegl)
{
g_object_unref (image_map->gegl);
image_map->gegl = NULL;
image_map->input = NULL;
image_map->shift = NULL;
image_map->output = NULL;
}
if (image_map->operation)
{
g_object_unref (image_map->operation);
image_map->operation = NULL;
}
if (image_map->drawable)
{
@ -254,18 +291,23 @@ gimp_image_map_get_pixel_at (GimpPickable *pickable,
GimpImageMap *
gimp_image_map_new (GimpDrawable *drawable,
const gchar *undo_desc)
const gchar *undo_desc,
GeglNode *operation)
{
GimpImageMap *image_map;
g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);
g_return_val_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)), NULL);
g_return_val_if_fail (operation == NULL || GEGL_IS_NODE (operation), NULL);
image_map = g_object_new (GIMP_TYPE_IMAGE_MAP, NULL);
image_map->drawable = g_object_ref (drawable);
image_map->undo_desc = g_strdup (undo_desc);
if (operation)
image_map->operation = g_object_ref (operation);
gimp_viewable_preview_freeze (GIMP_VIEWABLE (drawable));
return image_map;
@ -285,7 +327,7 @@ gimp_image_map_apply (GimpImageMap *image_map,
g_return_if_fail (apply_func != NULL);
image_map->apply_func = apply_func;
image_map->user_data = apply_data;
image_map->apply_data = apply_data;
/* If we're still working, remove the timer */
if (image_map->idle_id)
@ -293,9 +335,18 @@ gimp_image_map_apply (GimpImageMap *image_map,
g_source_remove (image_map->idle_id);
image_map->idle_id = 0;
if (image_map->processor)
{
g_object_unref (image_map->processor);
image_map->processor = NULL;
}
if (image_map->PRI)
{
pixel_regions_process_stop (image_map->PRI);
image_map->PRI = NULL;
}
}
/* Make sure the drawable is still valid */
if (! gimp_item_is_attached (GIMP_ITEM (image_map->drawable)))
@ -359,6 +410,77 @@ gimp_image_map_apply (GimpImageMap *image_map,
image_map->undo_offset_y = y;
}
if (image_map->operation)
{
GeglRectangle rect;
if (! image_map->gegl)
{
GObject *sink_operation;
image_map->gegl = gegl_node_new ();
image_map->input =
gegl_node_new_child (image_map->gegl,
"operation", "gimp-tilemanager-source",
NULL);
image_map->shift =
gegl_node_new_child (image_map->gegl,
"operation", "shift",
NULL);
#ifdef __GNUC__
#warning FIXME: gegl_node_add_child() needs to be public
#endif
gegl_node_add_child (image_map->gegl, image_map->operation);
image_map->output =
gegl_node_new_child (image_map->gegl,
"operation", "gimp-tilemanager-sink",
NULL);
g_object_get (image_map->output,
"gegl-operation", &sink_operation,
NULL);
g_signal_connect (sink_operation, "data-written",
G_CALLBACK (gimp_image_map_data_written),
image_map);
g_object_unref (sink_operation);
gegl_node_link_many (image_map->input,
image_map->shift,
image_map->operation,
image_map->output,
NULL);
}
gegl_node_set (image_map->input,
"tile-manager", image_map->undo_tiles,
NULL);
gegl_node_set (image_map->shift,
"x", (gdouble) x,
"y", (gdouble) y,
NULL);
gegl_node_set (image_map->output,
"tile-manager",
gimp_drawable_get_shadow_tiles (image_map->drawable),
NULL);
rect.x = x;
rect.y = y;
rect.width = width;
rect.height = height;
image_map->processor = gegl_node_new_processor (image_map->output,
&rect);
}
else
{
/* Configure the src from the drawable data */
pixel_region_init (&image_map->srcPR, image_map->undo_tiles,
0, 0, width, height, FALSE);
@ -372,6 +494,7 @@ gimp_image_map_apply (GimpImageMap *image_map,
image_map->PRI = pixel_regions_register (2,
&image_map->srcPR,
&image_map->destPR);
}
/* Start the intermittant work procedure */
image_map->idle_id = g_idle_add ((GSourceFunc) gimp_image_map_do, image_map);
@ -425,9 +548,18 @@ gimp_image_map_clear (GimpImageMap *image_map)
g_source_remove (image_map->idle_id);
image_map->idle_id = 0;
if (image_map->processor)
{
g_object_unref (image_map->processor);
image_map->processor = NULL;
}
if (image_map->PRI)
{
pixel_regions_process_stop (image_map->PRI);
image_map->PRI = NULL;
}
}
/* Make sure the drawable is still valid */
if (! gimp_item_is_attached (GIMP_ITEM (image_map->drawable)))
@ -485,7 +617,6 @@ static gboolean
gimp_image_map_do (GimpImageMap *image_map)
{
GimpImage *image;
gint i;
if (! gimp_item_is_attached (GIMP_ITEM (image_map->drawable)))
{
@ -496,6 +627,26 @@ gimp_image_map_do (GimpImageMap *image_map)
image = gimp_item_get_image (GIMP_ITEM (image_map->drawable));
if (image_map->gegl)
{
gboolean result = gegl_processor_work (image_map->processor, NULL);
if (! result)
{
g_object_unref (image_map->processor);
image_map->processor = NULL;
image_map->idle_id = 0;
g_signal_emit (image_map, image_map_signals[FLUSH], 0);
return FALSE;
}
}
else
{
gint i;
/* Process up to 16 tiles in one go. This reduces the overhead
* caused by updating the display while the imagemap is being
* applied and gives us a tiny speedup.
@ -516,11 +667,12 @@ gimp_image_map_do (GimpImageMap *image_map)
x - image_map->undo_offset_x,
y - image_map->undo_offset_y,
w, h, FALSE);
pixel_region_init (&destPR, gimp_drawable_get_tiles (image_map->drawable),
pixel_region_init (&destPR,
gimp_drawable_get_tiles (image_map->drawable),
x, y, w, h, TRUE);
copy_region (&srcPR, &destPR);
image_map->apply_func (image_map->user_data,
image_map->apply_func (image_map->apply_data,
&image_map->srcPR,
&image_map->destPR);
@ -546,8 +698,55 @@ gimp_image_map_do (GimpImageMap *image_map)
return FALSE;
}
}
}
g_signal_emit (image_map, image_map_signals[FLUSH], 0);
return TRUE;
}
static void
gimp_image_map_data_written (GObject *operation,
const GeglRectangle *extent,
GimpImageMap *image_map)
{
GimpImage *image;
PixelRegion srcPR;
PixelRegion destPR;
#if 0
g_print ("%s: rect = { %d, %d, %d, %d }\n",
G_STRFUNC, extent->x, extent->y, extent->width, extent->height);
#endif
image = gimp_item_get_image (GIMP_ITEM (image_map->drawable));
/* Reset to initial drawable conditions. */
pixel_region_init (&srcPR, image_map->undo_tiles,
extent->x - image_map->undo_offset_x,
extent->y - image_map->undo_offset_y,
extent->width,
extent->height,
FALSE);
pixel_region_init (&destPR, gimp_drawable_get_tiles (image_map->drawable),
extent->x, extent->y,
extent->width, extent->height,
TRUE);
copy_region (&srcPR, &destPR);
/* Apply the result of the gegl graph. */
pixel_region_init (&srcPR, image->shadow,
extent->x, extent->y,
extent->width, extent->height,
FALSE);
gimp_drawable_apply_region (image_map->drawable, &srcPR,
FALSE, NULL,
GIMP_OPACITY_OPAQUE, GIMP_REPLACE_MODE,
NULL,
extent->x, extent->y);
gimp_drawable_update (image_map->drawable,
extent->x, extent->y,
extent->width, extent->height);
}

View file

@ -56,7 +56,8 @@ struct _GimpImageMapClass
GType gimp_image_map_get_type (void) G_GNUC_CONST;
GimpImageMap * gimp_image_map_new (GimpDrawable *drawable,
const gchar *undo_desc);
const gchar *undo_desc,
GeglNode *operation);
void gimp_image_map_apply (GimpImageMap *image_map,
GimpImageMapApplyFunc apply_func,

View file

@ -18,6 +18,7 @@
#include "config.h"
#include <gegl.h>
#include <gtk/gtk.h>
#include "libgimpwidgets/gimpwidgets.h"
@ -69,6 +70,8 @@ static void gimp_brightness_contrast_tool_motion (GimpTool
GdkModifierType state,
GimpDisplay *display);
static GeglNode *
gimp_brightness_contrast_tool_get_operation (GimpImageMapTool *image_map_tool);
static void gimp_brightness_contrast_tool_map (GimpImageMapTool *image_map_tool);
static void gimp_brightness_contrast_tool_dialog (GimpImageMapTool *image_map_tool);
static void gimp_brightness_contrast_tool_reset (GimpImageMapTool *image_map_tool);
@ -118,6 +121,7 @@ gimp_brightness_contrast_tool_class_init (GimpBrightnessContrastToolClass *klass
im_tool_class->shell_desc = _("Adjust Brightness and Contrast");
im_tool_class->get_operation = gimp_brightness_contrast_tool_get_operation;
im_tool_class->map = gimp_brightness_contrast_tool_map;
im_tool_class->dialog = gimp_brightness_contrast_tool_dialog;
im_tool_class->reset = gimp_brightness_contrast_tool_reset;
@ -136,6 +140,12 @@ gimp_brightness_contrast_tool_finalize (GObject *object)
{
GimpBrightnessContrastTool *bc_tool = GIMP_BRIGHTNESS_CONTRAST_TOOL (object);
if (bc_tool->bc_node)
{
g_object_unref (bc_tool->bc_node);
bc_tool->bc_node = NULL;
}
if (bc_tool->lut)
{
gimp_lut_free (bc_tool->lut);
@ -175,11 +185,42 @@ gimp_brightness_contrast_tool_initialize (GimpTool *tool,
return TRUE;
}
static GeglNode *
gimp_brightness_contrast_tool_get_operation (GimpImageMapTool *im_tool)
{
GimpBrightnessContrastTool *bc_tool = GIMP_BRIGHTNESS_CONTRAST_TOOL (im_tool);
if (! bc_tool->bc_node)
{
bc_tool->bc_node = g_object_new (GEGL_TYPE_NODE,
"operation", "brightness-contrast",
NULL);
}
return bc_tool->bc_node;
}
static void
gimp_brightness_contrast_tool_map (GimpImageMapTool *im_tool)
{
GimpBrightnessContrastTool *bc_tool = GIMP_BRIGHTNESS_CONTRAST_TOOL (im_tool);
if (bc_tool->bc_node)
{
gdouble brightness;
gdouble contrast;
brightness = bc_tool->brightness / 127.0;
contrast = (bc_tool->contrast < 0 ?
(bc_tool->contrast + 127.0) / 127.0 :
bc_tool->contrast * 4.0 / 127.0 + 1);
gegl_node_set (bc_tool->bc_node,
"brightness", brightness,
"contrast", contrast,
NULL);
}
brightness_contrast_lut_setup (bc_tool->lut,
bc_tool->brightness / 255.0,
bc_tool->contrast / 127.0,

View file

@ -44,6 +44,7 @@ struct _GimpBrightnessContrastTool
gdouble brightness;
gdouble contrast;
GimpLut *lut;
GeglNode *bc_node;
/* dialog */
GtkAdjustment *brightness_data;

View file

@ -21,6 +21,7 @@
#include <errno.h>
#include <glib/gstdio.h>
#include <gegl.h>
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
@ -77,6 +78,8 @@ static void gimp_image_map_tool_map (GimpImageMapTool *im_tool);
static void gimp_image_map_tool_dialog (GimpImageMapTool *im_tool);
static void gimp_image_map_tool_reset (GimpImageMapTool *im_tool);
static void gimp_image_map_tool_create_map (GimpImageMapTool *im_tool);
static void gimp_image_map_tool_flush (GimpImageMap *image_map,
GimpImageMapTool *im_tool);
@ -101,6 +104,8 @@ static void gimp_image_map_tool_settings_dialog (GimpImageMapTool *im_tool,
static void gimp_image_map_tool_notify_preview (GObject *config,
GParamSpec *pspec,
GimpImageMapTool *im_tool);
static void gimp_image_map_tool_gegl_toggled (GtkWidget *toggle,
GimpImageMapTool *im_tool);
G_DEFINE_TYPE (GimpImageMapTool, gimp_image_map_tool, GIMP_TYPE_COLOR_TOOL)
@ -240,6 +245,23 @@ gimp_image_map_tool_initialize (GimpTool *tool,
G_CALLBACK (gimp_image_map_tool_notify_preview),
image_map_tool, 0);
if (GIMP_IMAGE_MAP_TOOL_GET_CLASS (image_map_tool)->get_operation)
{
image_map_tool->use_gegl = TRUE;
toggle = gtk_check_button_new_with_label ("Use GEGL");
gtk_box_pack_end (GTK_BOX (image_map_tool->main_vbox), toggle,
FALSE, FALSE, 0);
gtk_widget_show (toggle);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle),
image_map_tool->use_gegl);
g_signal_connect (toggle, "toggled",
G_CALLBACK (gimp_image_map_tool_gegl_toggled),
image_map_tool);
}
if (klass->load_dialog_title)
{
image_map_tool->load_button =
@ -313,11 +335,8 @@ gimp_image_map_tool_initialize (GimpTool *tool,
gtk_widget_show (image_map_tool->shell);
image_map_tool->drawable = drawable;
image_map_tool->image_map = gimp_image_map_new (drawable, tool_info->blurb);
g_signal_connect (image_map_tool->image_map, "flush",
G_CALLBACK (gimp_image_map_tool_flush),
image_map_tool);
gimp_image_map_tool_create_map (image_map_tool);
return TRUE;
}
@ -416,6 +435,29 @@ gimp_image_map_tool_reset (GimpImageMapTool *tool)
GIMP_IMAGE_MAP_TOOL_GET_CLASS (tool)->reset (tool);
}
static void
gimp_image_map_tool_create_map (GimpImageMapTool *tool)
{
GeglNode *operation = NULL;
if (tool->image_map)
{
gimp_image_map_clear (tool->image_map);
g_object_unref (tool->image_map);
}
if (tool->use_gegl)
operation = GIMP_IMAGE_MAP_TOOL_GET_CLASS (tool)->get_operation (tool);
tool->image_map = gimp_image_map_new (tool->drawable,
GIMP_TOOL (tool)->tool_info->blurb,
operation);
g_signal_connect (tool->image_map, "flush",
G_CALLBACK (gimp_image_map_tool_flush),
tool);
}
static gboolean
gimp_image_map_tool_settings_load (GimpImageMapTool *tool,
gpointer file,
@ -796,3 +838,18 @@ gimp_image_map_tool_settings_dialog (GimpImageMapTool *tool,
gtk_widget_show (tool->settings_dialog);
}
static void
gimp_image_map_tool_gegl_toggled (GtkWidget *toggle,
GimpImageMapTool *im_tool)
{
im_tool->use_gegl = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (toggle));
gimp_tool_control_set_preserve (GIMP_TOOL (im_tool)->control, TRUE);
gimp_image_map_tool_create_map (im_tool);
gimp_tool_control_set_preserve (GIMP_TOOL (im_tool)->control, FALSE);
gimp_image_map_tool_preview (im_tool);
}

View file

@ -19,6 +19,10 @@
#ifndef __GIMP_IMAGE_MAP_TOOL_H__
#define __GIMP_IMAGE_MAP_TOOL_H__
#ifdef __GNUC__
#warning FIXME: dont include gegl.h here
#endif
#include <gegl.h>
#include "gimpcolortool.h"
@ -50,6 +54,9 @@ struct _GimpImageMapTool
/* settings file dialog */
GtkWidget *settings_dialog;
/* temp hack */
gboolean use_gegl;
};
struct _GimpImageMapToolClass
@ -64,6 +71,7 @@ struct _GimpImageMapToolClass
const gchar *save_dialog_title;
/* virtual functions */
GeglNode * (* get_operation) (GimpImageMapTool *image_map_tool);
void (* map) (GimpImageMapTool *image_map_tool);
void (* dialog) (GimpImageMapTool *image_map_tool);
void (* reset) (GimpImageMapTool *image_map_tool);