GimpLayer * gimp_image_merge_group_layer (GimpImage *image, GimpGroupLayer *group) { GimpLayer *parent; GimpLayer *layer; gint index; g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); g_return_val_if_fail (GIMP_IS_GROUP_LAYER (group), NULL); g_return_val_if_fail (gimp_item_is_attached (GIMP_ITEM (group)), NULL); g_return_val_if_fail (gimp_item_get_image (GIMP_ITEM (group)) == image, NULL); gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_IMAGE_LAYERS_MERGE, C_("undo-type", "Merge Layer Group")); parent = gimp_layer_get_parent (GIMP_LAYER (group)); index = gimp_item_get_index (GIMP_ITEM (group)); layer = GIMP_LAYER (gimp_item_duplicate (GIMP_ITEM (group), GIMP_TYPE_LAYER)); gimp_object_set_name (GIMP_OBJECT (layer), gimp_object_get_name (group)); gimp_image_remove_layer (image, GIMP_LAYER (group), TRUE, NULL); gimp_image_add_layer (image, layer, parent, index, TRUE); gimp_image_undo_group_end (image); return layer; }
void gimp_create_image_from_buffer (Gimp *gimp, GeglBuffer *buffer) { GimpImage *image; GimpLayer *layer; const Babl *format; g_return_if_fail (GIMP_IS_GIMP (gimp)); g_return_if_fail (GEGL_IS_BUFFER (buffer)); format = gegl_buffer_get_format (buffer); image = gimp_create_image (gimp, gegl_buffer_get_width (buffer), gegl_buffer_get_height (buffer), gimp_babl_format_get_base_type (format), gimp_babl_format_get_precision (format), FALSE); layer = gimp_layer_new_from_buffer (buffer, image, format, "Debug Image", GIMP_OPACITY_OPAQUE, GIMP_NORMAL_MODE); gimp_image_add_layer (image, layer, NULL, -1, FALSE); gimp_create_display (gimp, image, GIMP_UNIT_PIXEL, 1.0); }
void edit_paste_as_new_layer_cmd_callback (GtkAction *action, gpointer data) { Gimp *gimp; GimpImage *image; GimpBuffer *buffer; return_if_no_gimp (gimp, data); return_if_no_image (image, data); buffer = gimp_clipboard_get_buffer (gimp); if (buffer) { GimpLayer *layer; layer = gimp_layer_new_from_buffer (gimp_buffer_get_buffer (buffer), image, gimp_image_get_layer_format (image, TRUE), _("Clipboard"), GIMP_OPACITY_OPAQUE, GIMP_NORMAL_MODE); g_object_unref (buffer); gimp_image_add_layer (image, layer, GIMP_IMAGE_ACTIVE_PARENT, -1, TRUE); gimp_image_flush (image); } else { gimp_message_literal (gimp, NULL, GIMP_MESSAGE_WARNING, _("There is no image data in the clipboard to paste.")); } }
static gint32 create_image (GdkPixbuf *pixbuf, GdkRegion *shape, const gchar *name) { gint32 image; gint32 layer; gdouble xres, yres; gchar *comment; gint width, height; gboolean status; status = gimp_progress_init (_("Importing screenshot")); width = gdk_pixbuf_get_width (pixbuf); height = gdk_pixbuf_get_height (pixbuf); image = gimp_image_new (width, height, GIMP_RGB); gimp_image_undo_disable (image); gimp_get_monitor_resolution (&xres, &yres); gimp_image_set_resolution (image, xres, yres); comment = gimp_get_default_comment (); if (comment) { GimpParasite *parasite; parasite = gimp_parasite_new ("gimp-comment", GIMP_PARASITE_PERSISTENT, strlen (comment) + 1, comment); gimp_image_parasite_attach (image, parasite); gimp_parasite_free (parasite); g_free (comment); } layer = gimp_layer_new_from_pixbuf (image, name ? name : _("Screenshot"), pixbuf, 100, GIMP_NORMAL_MODE, 0.0, 1.0); gimp_image_add_layer (image, layer, 0); if (shape && ! gdk_region_empty (shape)) { image_select_shape (image, shape); if (! gimp_selection_is_empty (image)) { gimp_layer_add_alpha (layer); gimp_edit_clear (layer); gimp_selection_none (image); } } gimp_image_undo_enable (image); return image; }
static void gimp_display_shell_drop_component (GtkWidget *widget, gint x, gint y, GimpImage *image, GimpChannelType component, gpointer data) { GimpDisplayShell *shell = GIMP_DISPLAY_SHELL (data); GimpImage *dest_image = gimp_display_get_image (shell->display); GimpChannel *channel; GimpItem *new_item; const gchar *desc; GIMP_LOG (DND, NULL); if (shell->display->gimp->busy) return; if (! dest_image) { dest_image = gimp_image_new_from_component (image->gimp, image, component); gimp_create_display (dest_image->gimp, dest_image, GIMP_UNIT_PIXEL, 1.0, G_OBJECT (gtk_widget_get_screen (widget)), gimp_widget_get_monitor (widget)); g_object_unref (dest_image); return; } channel = gimp_channel_new_from_component (image, component, NULL, NULL); new_item = gimp_item_convert (GIMP_ITEM (channel), dest_image, GIMP_TYPE_LAYER); g_object_unref (channel); if (new_item) { GimpLayer *new_layer = GIMP_LAYER (new_item); gimp_enum_get_value (GIMP_TYPE_CHANNEL_TYPE, component, NULL, NULL, &desc, NULL); gimp_object_take_name (GIMP_OBJECT (new_layer), g_strdup_printf (_("%s Channel Copy"), desc)); gimp_image_undo_group_start (dest_image, GIMP_UNDO_GROUP_EDIT_PASTE, _("Drop New Layer")); gimp_display_shell_dnd_position_item (shell, image, new_item); gimp_image_add_layer (dest_image, new_layer, GIMP_IMAGE_ACTIVE_PARENT, -1, TRUE); gimp_image_undo_group_end (dest_image); gimp_display_shell_dnd_flush (shell, dest_image); } }
static void gimp_display_shell_drop_pixbuf (GtkWidget *widget, gint x, gint y, GdkPixbuf *pixbuf, gpointer data) { GimpDisplayShell *shell = GIMP_DISPLAY_SHELL (data); GimpImage *image = gimp_display_get_image (shell->display); GimpLayer *new_layer; gboolean has_alpha = FALSE; GIMP_LOG (DND, NULL); if (shell->display->gimp->busy) return; if (! image) { image = gimp_image_new_from_pixbuf (shell->display->gimp, pixbuf, _("Dropped Buffer")); gimp_create_display (image->gimp, image, GIMP_UNIT_PIXEL, 1.0, G_OBJECT (gtk_widget_get_screen (widget)), gimp_widget_get_monitor (widget)); g_object_unref (image); return; } if (gdk_pixbuf_get_n_channels (pixbuf) == 2 || gdk_pixbuf_get_n_channels (pixbuf) == 4) { has_alpha = TRUE; } new_layer = gimp_layer_new_from_pixbuf (pixbuf, image, gimp_image_get_layer_format (image, has_alpha), _("Dropped Buffer"), GIMP_OPACITY_OPAQUE, GIMP_NORMAL_MODE); if (new_layer) { GimpItem *new_item = GIMP_ITEM (new_layer); gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_EDIT_PASTE, _("Drop New Layer")); gimp_display_shell_dnd_position_item (shell, image, new_item); gimp_image_add_layer (image, new_layer, GIMP_IMAGE_ACTIVE_PARENT, -1, TRUE); gimp_image_undo_group_end (image); gimp_display_shell_dnd_flush (shell, image); } }
static void gimp_display_shell_drop_drawable (GtkWidget *widget, gint x, gint y, GimpViewable *viewable, gpointer data) { GimpDisplayShell *shell = GIMP_DISPLAY_SHELL (data); GimpImage *image = gimp_display_get_image (shell->display); GType new_type; GimpItem *new_item; GIMP_LOG (DND, NULL); if (shell->display->gimp->busy) return; if (! image) { image = gimp_image_new_from_drawable (shell->display->gimp, GIMP_DRAWABLE (viewable)); gimp_create_display (shell->display->gimp, image, GIMP_UNIT_PIXEL, 1.0, G_OBJECT (gtk_widget_get_screen (widget)), gimp_widget_get_monitor (widget)); g_object_unref (image); return; } if (GIMP_IS_LAYER (viewable)) new_type = G_TYPE_FROM_INSTANCE (viewable); else new_type = GIMP_TYPE_LAYER; new_item = gimp_item_convert (GIMP_ITEM (viewable), image, new_type); if (new_item) { GimpLayer *new_layer = GIMP_LAYER (new_item); gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_EDIT_PASTE, _("Drop New Layer")); gimp_display_shell_dnd_position_item (shell, image, new_item); gimp_item_set_visible (new_item, TRUE, FALSE); gimp_item_set_linked (new_item, FALSE, FALSE); gimp_image_add_layer (image, new_layer, GIMP_IMAGE_ACTIVE_PARENT, -1, TRUE); gimp_image_undo_group_end (image); gimp_display_shell_dnd_flush (shell, image); } }
static gboolean debug_show_image_graph (GimpImage *source_image) { Gimp *gimp = source_image->gimp; GimpProjectable *projectable = GIMP_PROJECTABLE (source_image); GeglNode *image_graph = gimp_projectable_get_graph (projectable); GeglNode *output_node = gegl_node_get_output_proxy (image_graph, "output"); GimpImage *new_image = NULL; GimpLayer *layer = NULL; GeglNode *introspect = NULL; GeglNode *sink = NULL; GeglBuffer *buffer = NULL; gchar *new_name = NULL; /* Setup and process the introspection graph */ introspect = gegl_node_new_child (NULL, "operation", "gegl:introspect", "node", output_node, NULL); sink = gegl_node_new_child (NULL, "operation", "gegl:buffer-sink", "buffer", &buffer, NULL); gegl_node_link_many (introspect, sink, NULL); gegl_node_process (sink); /* Create a new image of the result */ new_name = g_strdup_printf ("%s GEGL graph", gimp_image_get_display_name (source_image)); new_image = gimp_create_image (gimp, gegl_buffer_get_width (buffer), gegl_buffer_get_height (buffer), GIMP_RGB, GIMP_PRECISION_U8, FALSE); gimp_image_set_uri (new_image, new_name); layer = gimp_layer_new_from_buffer (buffer, new_image, gimp_image_get_layer_format (new_image, TRUE), new_name, 1.0, GIMP_NORMAL_MODE); gimp_image_add_layer (new_image, layer, NULL, 0, FALSE); gimp_create_display (gimp, new_image, GIMP_UNIT_PIXEL, 1.0); /* Cleanup */ g_object_unref (new_image); g_free (new_name); g_object_unref (buffer); g_object_unref (sink); g_object_unref (introspect); g_object_unref (source_image); return FALSE; }
static void preview_update_preview (GimpPreview *preview, GimpDrawable *drawable) { gint x1, y1; gint width, height; gint bpp; guchar *buffer; GimpPixelRgn src_rgn; GimpPixelRgn preview_rgn; gint32 image_id, src_image_id; gint32 preview_id; GimpDrawable *preview_drawable; bpp = gimp_drawable_bpp (drawable->drawable_id); gimp_preview_get_position (preview, &x1, &y1); gimp_preview_get_size (preview, &width, &height); buffer = g_new (guchar, width * height * bpp); gimp_pixel_rgn_init (&src_rgn, drawable, x1, y1, width, height, FALSE, FALSE); gimp_pixel_rgn_get_rect (&src_rgn, buffer, x1, y1, width, height); /* set up gimp drawable for rendering preview into */ src_image_id = gimp_drawable_get_image (drawable->drawable_id); image_id = gimp_image_new (width, height, gimp_image_base_type (src_image_id)); preview_id = gimp_layer_new (image_id, "preview", width, height, gimp_drawable_type (drawable->drawable_id), 100, GIMP_NORMAL_MODE); preview_drawable = gimp_drawable_get (preview_id); gimp_image_add_layer (image_id, preview_id, 0); gimp_layer_set_offsets (preview_id, 0, 0); gimp_pixel_rgn_init (&preview_rgn, preview_drawable, 0, 0, width, height, TRUE, TRUE); gimp_pixel_rgn_set_rect (&preview_rgn, buffer, 0, 0, width, height); gimp_drawable_flush (preview_drawable); gimp_drawable_merge_shadow (preview_id, TRUE); gimp_drawable_update (preview_id, 0, 0, width, height); dog (image_id, preview_drawable, dogvals.inner, dogvals.outer, FALSE); gimp_pixel_rgn_get_rect (&preview_rgn, buffer, 0, 0, width, height); gimp_preview_draw_buffer (preview, buffer, width * bpp); gimp_image_delete (image_id); g_free (buffer); }
/* ----------------------- * p_tri_map_preprocessing * ----------------------- * prepare the tri mask for processing * - have bpp == 1 * - have same size and offset as the input drawable (that is a layer) * - pixel values >= 240 are set to value 240 (MATTING_USER_FOREGROUND) * - in case the input layer already has an alpha channel * all fully transparent (alpha == 0) pixels are also set 0 (MATTING_USER_BACKGROUND) * in the tri map to keep pixels fully transparent. (such pixels typicall do not * have a useful color information in the RGB channels) * * * in case the user provided the tri map as layer or channel that is NOT the layermask of the input layer * we create a new dummy layer with same size and offset as the input layer * and add a layermask to this dummy layer. * The layermask of the dummy layer is then filled with the intersecting grayscale copy * of the user-provided triMap drawable and will be used as tri map in the alpha matting processing. * * returns the dawable Id of the relevant TRI MAP that fulfills the conditons listed above. */ static gint32 p_tri_map_preprocessing (GimpDrawable *drawable, GapFgExtractValues *fgValPtr, gint32 *dummyLayerId) { gint32 prepocessedTriMapLayerId; gint32 inputLayerMaskId; gint32 imageId; *dummyLayerId = -1; imageId = gimp_drawable_get_image(drawable->drawable_id); inputLayerMaskId = gimp_layer_get_mask(drawable->drawable_id); if (fgValPtr->tri_map_drawable_id == inputLayerMaskId) { prepocessedTriMapLayerId = inputLayerMaskId; } else { gint offset_x; gint offset_y; gint32 dummyLayerMaskId; gint32 l_fsel_layer_id; *dummyLayerId = gimp_layer_new(imageId , "DUMMY" , drawable->width , drawable->height , GIMP_RGBA_IMAGE , 100.0 /* full opacity */ , GIMP_NORMAL_MODE /* normal mode */ ); /* get offsets of the input drawable (layer) within the image */ gimp_drawable_offsets (drawable->drawable_id, &offset_x, &offset_y); /* add dummy layer (of same size at same offsets) to the same image */ gimp_image_add_layer(imageId, *dummyLayerId, -1 /* stackposition */ ); gimp_layer_set_offsets(*dummyLayerId, offset_x, offset_y); /* create a new layermask (black is full transparent */ dummyLayerMaskId = gimp_layer_create_mask(*dummyLayerId, GIMP_ADD_BLACK_MASK); gimp_layer_add_mask(*dummyLayerId, dummyLayerMaskId); gimp_edit_copy(fgValPtr->tri_map_drawable_id); l_fsel_layer_id = gimp_edit_paste(dummyLayerMaskId, FALSE); gimp_floating_sel_anchor(l_fsel_layer_id); prepocessedTriMapLayerId = dummyLayerMaskId; } gap_fg_rgn_tri_map_normalize(drawable, prepocessedTriMapLayerId); return(prepocessedTriMapLayerId); } /* end p_tri_map_preprocessing */
void floating_sel_attach (GimpLayer *layer, GimpDrawable *drawable) { GimpImage *image; GimpLayer *floating_sel; g_return_if_fail (GIMP_IS_LAYER (layer)); g_return_if_fail (GIMP_IS_DRAWABLE (drawable)); g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable))); g_return_if_fail (drawable != GIMP_DRAWABLE (layer)); g_return_if_fail (gimp_item_get_image (GIMP_ITEM (layer)) == gimp_item_get_image (GIMP_ITEM (drawable))); image = gimp_item_get_image (GIMP_ITEM (drawable)); floating_sel = gimp_image_floating_sel (image); /* If there is already a floating selection, anchor it */ if (floating_sel) { floating_sel_anchor (floating_sel); /* if we were pasting to the old floating selection, paste now * to the drawable */ if (drawable == (GimpDrawable *) floating_sel) drawable = gimp_image_get_active_drawable (image); } /* set the drawable and allocate a backing store */ gimp_layer_set_lock_alpha (layer, TRUE, FALSE); layer->fs.drawable = drawable; layer->fs.backing_store = tile_manager_new (GIMP_ITEM (layer)->width, GIMP_ITEM (layer)->height, gimp_drawable_bytes (drawable)); /* add the layer to the image */ gimp_image_add_layer (image, layer, 0); /* store the affected area from the drawable in the backing store */ floating_sel_rigor (layer, TRUE); }
void callback_new_mask_button (GtkWidget * button, gpointer data) { gint32 layer_ID; NewLayerData *nl_data = NEW_LAYER_DATA (data); PreviewData *p_data = nl_data->preview_data; GimpImageType image_type; IMAGE_CHECK_ACTION(p_data->image_ID, gtk_dialog_response (GTK_DIALOG (dlg), RESPONSE_FATAL), ); switch (gimp_image_base_type (p_data->image_ID)) { case GIMP_RGB: image_type = GIMP_RGBA_IMAGE; break; case GIMP_GRAY: image_type = GIMP_GRAYA_IMAGE; break; default: return; } gimp_image_undo_group_start (p_data->image_ID); layer_ID = gimp_layer_new (p_data->image_ID, nl_data->name, p_data->old_width, p_data->old_height, image_type, 50, GIMP_NORMAL_MODE); gimp_image_add_layer (p_data->image_ID, layer_ID, -1); gimp_drawable_fill (layer_ID, GIMP_TRANSPARENT_FILL); gimp_layer_translate (layer_ID, p_data->x_off, p_data->y_off); gimp_image_undo_group_end (p_data->image_ID); *(nl_data->layer_ID) = layer_ID; *(nl_data->status) = TRUE; nl_data->preview_data->ui_vals->layer_on_edit_ID = layer_ID; nl_data->preview_data->ui_vals->layer_on_edit_type = nl_data->layer_type; nl_data->preview_data->ui_vals->layer_on_edit_is_new = TRUE; g_free(nl_data); gtk_dialog_response (GTK_DIALOG(dlg), RESPONSE_WORK_ON_AUX_LAYER); }
static gint32 create_new_layer( gint32 img, gint position, const gchar* layername, guint width, guint height, GimpImageBaseType bas_type, GimpDrawable** drawable, GimpPixelRgn* pixel_rgn) { gint32 layer; GimpImageType img_type = GIMP_RGB_IMAGE; /* TODO: add support for GIMP_RGBA_IMAGE in case of RGBA888 */ switch (bas_type) { case GIMP_RGB: img_type = GIMP_RGB_IMAGE; break; case GIMP_GRAY: img_type = GIMP_GRAY_IMAGE; break; case GIMP_INDEXED: img_type = GIMP_INDEXED_IMAGE; break; } if (!layername) { layername = "background"; } layer = gimp_layer_new(img, layername, width, height, img_type, 100, GIMP_NORMAL_MODE); gimp_image_add_layer(img, layer, position); *drawable = gimp_drawable_get(layer); gimp_pixel_rgn_init(pixel_rgn, *drawable, 0, 0, (*drawable)->width, (*drawable)->height, TRUE, FALSE); return layer; }
static gint32 load_image (const gchar *filename) { gint32 image; gint32 layer; GdkPixbuf *pixbuf; gint width; gint height; GError *error = NULL; pixbuf = load_rsvg_pixbuf (filename, &load_vals, &error); if (!pixbuf) { /* Do not rely on librsvg setting GError on failure! */ g_message (_("Could not open '%s' for reading: %s"), gimp_filename_to_utf8 (filename), error ? error->message : _("Unknown reason")); return -1; } gimp_progress_init (_("Rendering SVG")); width = gdk_pixbuf_get_width (pixbuf); height = gdk_pixbuf_get_height (pixbuf); image = gimp_image_new (width, height, GIMP_RGB); gimp_image_undo_disable (image); gimp_image_set_filename (image, filename); gimp_image_set_resolution (image, load_vals.resolution, load_vals.resolution); layer = gimp_layer_new_from_pixbuf (image, _("Rendered SVG"), pixbuf, 100, GIMP_NORMAL_MODE, 0.0, 1.0); gimp_image_add_layer (image, layer, 0); gimp_image_undo_enable (image); return image; }
/* ---------------------------------------- * p_createEmptyEdgeDrawable * ---------------------------------------- * create the (empty) edge drawable as layer of a new image * */ static void p_createEmptyEdgeDrawable(GapEdgeContext *ectx) { ectx->edgeImageId = gimp_image_new(ectx->refDrawable->width , ectx->refDrawable->height , GIMP_GRAY ); ectx->edgeDrawableId = gimp_layer_new(ectx->edgeImageId , "edge" , ectx->refDrawable->width , ectx->refDrawable->height , GIMP_GRAY_IMAGE , 100.0 /* full opacity */ , 0 /* normal mode */ ); gimp_image_add_layer (ectx->edgeImageId, ectx->edgeDrawableId, 0 /* stackposition */ ); ectx->edgeDrawable = gimp_drawable_get(ectx->edgeDrawableId); } /* end p_createEmptyEdgeDrawable */
static gint32 create_new_layer (gint32 image_ID, gint position, const gchar *layername, guint width, guint height, GimpImageBaseType type, GimpDrawable **drawable, GimpPixelRgn *pixel_rgn) { gint32 layer_ID; GimpImageType gdtype = GIMP_RGB_IMAGE; switch (type) { case GIMP_RGB: gdtype = GIMP_RGB_IMAGE; break; case GIMP_GRAY: gdtype = GIMP_GRAY_IMAGE; break; case GIMP_INDEXED: gdtype = GIMP_INDEXED_IMAGE; break; } if (!layername) layername = _("Background"); layer_ID = gimp_layer_new (image_ID, layername, width, height, gdtype, 100, GIMP_NORMAL_MODE); gimp_image_add_layer (image_ID, layer_ID, position); *drawable = gimp_drawable_get (layer_ID); gimp_pixel_rgn_init (pixel_rgn, *drawable, 0, 0, (*drawable)->width, (*drawable)->height, TRUE, FALSE); return layer_ID; }
static GimpLayer * gimp_image_duplicate_layers (GimpImage *image, GimpImage *new_image) { GimpLayer *active_layer = NULL; GList *list; gint count; for (list = gimp_image_get_layer_iter (image), count = 0; list; list = g_list_next (list)) { GimpLayer *layer = list->data; GimpLayer *new_layer; if (gimp_layer_is_floating_sel (layer)) continue; new_layer = GIMP_LAYER (gimp_image_duplicate_item (GIMP_ITEM (layer), new_image)); /* Make sure that if the layer has a layer mask, * its name isn't screwed up */ if (new_layer->mask) gimp_object_set_name (GIMP_OBJECT (new_layer->mask), gimp_object_get_name (layer->mask)); if (gimp_image_get_active_layer (image) == layer) active_layer = new_layer; gimp_image_add_layer (new_image, new_layer, NULL, count++, FALSE); } return active_layer; }
void floating_sel_attach (GimpLayer *layer, GimpDrawable *drawable) { GimpImage *image; GimpLayer *floating_sel; g_return_if_fail (GIMP_IS_LAYER (layer)); g_return_if_fail (GIMP_IS_DRAWABLE (drawable)); g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable))); g_return_if_fail (drawable != GIMP_DRAWABLE (layer)); g_return_if_fail (gimp_item_get_image (GIMP_ITEM (layer)) == gimp_item_get_image (GIMP_ITEM (drawable))); image = gimp_item_get_image (GIMP_ITEM (drawable)); floating_sel = gimp_image_get_floating_selection (image); /* If there is already a floating selection, anchor it */ if (floating_sel) { floating_sel_anchor (floating_sel); /* if we were pasting to the old floating selection, paste now * to the drawable */ if (drawable == (GimpDrawable *) floating_sel) drawable = gimp_image_get_active_drawable (image); } gimp_layer_set_lock_alpha (layer, TRUE, FALSE); gimp_layer_set_floating_sel_drawable (layer, drawable); gimp_image_add_layer (image, layer, NULL, 0, TRUE); }
static void preview_ambient_occlusion_only(gint32 image_ID) { gint32 drawable_ID = -1; gint32 drawableAO_ID = -1; gtk_label_set_text(GTK_LABEL(progress_label), "Mixing Colors"); // preview_diffuse_only(image_ID); preview_normal_only(image_ID); // if (preview_normal_only(image_ID) != NULL) return NULL; drawable_ID = gimp_image_get_active_layer(image_ID); /** Copy active layer. */ /** LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL */ drawableAO_ID = gimp_layer_copy (drawable_ID); /** Add new layer to image. */ gimp_image_add_layer(image_ID, drawableAO_ID, -1); /** Set new layer as active. */ gimp_image_set_active_layer(image_ID, drawableAO_ID); /** * Colors -> Components -> "Channel Mixer" applied * Standard plug-in. Source code ships with GIMP. * * Add the "f" here to signify float in c language. * Removed 0.0 on first param and changed to 0 because boolean. */ /** Explained on line ~1300 of InsaneBump.c */ // if (plug_in_colors_channel_mixer_connector(image_ID, drawableAO_ID, 0, -200.0f, 0.0f, 0.0f, 0.0f, -200.0f, 0.0f, 0.0f, 0.0f, 1.0f) != 1) return; if (plug_in_colors_channel_mixer_connector(image_ID, drawableAO_ID, 0, -1.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f) != 1) return; gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR(progress), 0.87); gimp_desaturate(drawableAO_ID); gimp_levels_stretch(drawableAO_ID); pDrawables.drawable_ao = gimp_drawable_get(drawableAO_ID); gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR(progress), 0.90); }
GimpLayer * text_render (GimpImage *image, GimpDrawable *drawable, GimpContext *context, gint text_x, gint text_y, const gchar *fontname, const gchar *text, gint border, gboolean antialias) { PangoFontDescription *desc; GimpText *gtext; GimpLayer *layer; GimpRGB color; gchar *font; gdouble size; g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); g_return_val_if_fail (drawable == NULL || GIMP_IS_DRAWABLE (drawable), NULL); g_return_val_if_fail (drawable == NULL || gimp_item_is_attached (GIMP_ITEM (drawable)), NULL); g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL); g_return_val_if_fail (fontname != NULL, NULL); g_return_val_if_fail (text != NULL, NULL); if (border < 0) border = 0; desc = pango_font_description_from_string (fontname); size = PANGO_PIXELS (pango_font_description_get_size (desc)); pango_font_description_unset_fields (desc, PANGO_FONT_MASK_SIZE); font = pango_font_description_to_string (desc); pango_font_description_free (desc); gimp_context_get_foreground (context, &color); gtext = g_object_new (GIMP_TYPE_TEXT, "text", text, "font", font, "font-size", size, "antialias", antialias, "border", border, "color", &color, NULL); g_free (font); layer = gimp_text_layer_new (image, gtext); g_object_unref (gtext); if (!layer) return NULL; /* Start a group undo */ gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_TEXT, _("Add Text Layer")); /* Set the layer offsets */ gimp_item_set_offset (GIMP_ITEM (layer), text_x, text_y); /* If there is a selection mask clear it-- * this might not always be desired, but in general, * it seems like the correct behavior. */ if (! gimp_channel_is_empty (gimp_image_get_mask (image))) gimp_channel_clear (gimp_image_get_mask (image), NULL, TRUE); if (drawable == NULL) { /* If the drawable is NULL, create a new layer */ gimp_image_add_layer (image, layer, NULL, -1, TRUE); } else { /* Otherwise, instantiate the text as the new floating selection */ floating_sel_attach (layer, drawable); } /* end the group undo */ gimp_image_undo_group_end (image); return layer; }
static gboolean apply_watermark(watermark_settings settings, image_output out) { gboolean success = TRUE; gint32 layerId; gdouble posX, posY; gint wmwidth, wmheight, wmasc, wmdesc; if (settings->mode) { if (strlen(settings->text) == 0) { return TRUE; } GimpRGB old_foreground, new_foreground; gimp_context_get_foreground(&old_foreground); gimp_rgb_parse_hex (&new_foreground, gdk_color_to_string(&(settings->color)), strlen(gdk_color_to_string(&(settings->color)))); gimp_context_set_foreground(&new_foreground); gimp_text_get_extents_fontname( settings->text, pango_font_description_get_size(settings->font) / PANGO_SCALE, GIMP_PIXELS, pango_font_description_get_family(settings->font), &wmwidth, &wmheight, &wmasc, &wmdesc ); if (settings->position == WM_POS_TL) { posX = 10; posY = 5; } else if (settings->position == WM_POS_TC) { posX = (gimp_image_width(out->image_id) / 2) - (wmwidth / 2); posY = 5; } else if (settings->position == WM_POS_TR) { posX = gimp_image_width(out->image_id) - wmwidth - 10; posY = 5; } else if (settings->position == WM_POS_BL) { posX = 10; posY = gimp_image_height(out->image_id) - wmheight - 5; } else if (settings->position == WM_POS_BC) { posX = (gimp_image_width(out->image_id) / 2) - (wmwidth / 2); posY = gimp_image_height(out->image_id) - wmheight - 5; } else if (settings->position == WM_POS_BR) { posX = gimp_image_width(out->image_id) - wmwidth - 10; posY = gimp_image_height(out->image_id) - wmheight - 5; } else if (settings->position == WM_POS_CL) { posX = 10; posY = (gimp_image_height(out->image_id) / 2) - (wmheight / 2); } else if (settings->position == WM_POS_CR) { posX = gimp_image_width(out->image_id) - wmwidth - 10; posY = (gimp_image_height(out->image_id) / 2) - (wmheight / 2); } else { posX = (gimp_image_width(out->image_id) / 2) - (wmwidth / 2); posY = (gimp_image_height(out->image_id) / 2) - (wmheight / 2); } layerId = gimp_text_fontname( out->image_id, -1, posX, posY, settings->text, -1, TRUE, pango_font_description_get_size(settings->font) / PANGO_SCALE, GIMP_PIXELS, pango_font_description_get_family(settings->font) ); gimp_context_set_foreground(&old_foreground); gimp_layer_set_opacity(layerId, settings->opacity); } else { if (!g_file_test(settings->image_file, G_FILE_TEST_IS_REGULAR)) {//((access(settings->image_file, R_OK) == -1)) { // error, can't access image file return TRUE; } layerId = gimp_file_load_layer( GIMP_RUN_NONINTERACTIVE, out->image_id, settings->image_file ); gimp_layer_set_opacity(layerId, settings->opacity); wmwidth = gimp_drawable_width(layerId); wmheight = gimp_drawable_height(layerId); #if USE_API26 gimp_image_add_layer( out->image_id, layerId, 0 ); #else // starting from 2.8, gimp_image_add_layer is deprecated. // use gimp_image_insert_layer instead gimp_image_insert_layer( out->image_id, layerId, 0, 0 ); #endif if (settings->position == WM_POS_TL) { posX = 10; posY = 10; } else if (settings->position == WM_POS_TC) { posX = (gimp_image_width(out->image_id) / 2) - (wmwidth / 2); posY = 10; } else if (settings->position == WM_POS_TR) { posX = gimp_image_width(out->image_id) - wmwidth - 10; posY = 10; } else if (settings->position == WM_POS_BL) { posX = 10; posY = gimp_image_height(out->image_id) - wmheight - 10; } else if (settings->position == WM_POS_BC) { posX = (gimp_image_width(out->image_id) / 2) - (wmwidth / 2); posY = gimp_image_height(out->image_id) - wmheight - 10; } else if (settings->position == WM_POS_BR) { posX = gimp_image_width(out->image_id) - wmwidth - 10; posY = gimp_image_height(out->image_id) - wmheight - 10; } else if (settings->position == WM_POS_CL) { posX = 10; posY = (gimp_image_height(out->image_id) / 2) - (wmheight / 2); } else if (settings->position == WM_POS_CR) { posX = gimp_image_width(out->image_id) - wmwidth - 10; posY = (gimp_image_height(out->image_id) / 2) - (wmheight / 2); } else { posX = (gimp_image_width(out->image_id) / 2) - (wmwidth / 2); posY = (gimp_image_height(out->image_id) / 2) - (wmheight / 2); } gimp_layer_set_offsets( layerId, posX, posY ); } // refresh all drawables g_free(out->drawable_ids); out->drawable_ids = gimp_image_get_layers(out->image_id, &out->drawable_count); return success; }
static gboolean apply_resize(resize_settings settings, image_output out) { gboolean success = FALSE; gint orig_w, orig_h, final_w, final_h, view_w, view_h; gdouble orig_res_x, orig_res_y; if (settings->change_res) { success = gimp_image_get_resolution( out->image_id, &orig_res_x, &orig_res_y ); if ((settings->new_res_x != orig_res_x) || (settings->new_res_y != orig_res_y)) { // change resolution success = gimp_image_set_resolution( out->image_id, settings->new_res_x, settings->new_res_y ); } } orig_w = gimp_image_width(out->image_id); orig_h = gimp_image_height(out->image_id); if (settings->resize_mode == RESIZE_PERCENT) { if (settings->stretch_mode == STRETCH_ASPECT) { gdouble newpct = min(settings->new_w_pc, settings->new_h_pc); final_w = view_w = round((orig_w * newpct) / 100.0); final_h = view_h = round((orig_h * newpct) / 100.0); } else if (settings->stretch_mode == STRETCH_PADDED) { gdouble newpct = min(settings->new_w_pc, settings->new_h_pc); final_w = round((orig_w * newpct) / 100.0); final_h = round((orig_h * newpct) / 100.0); view_w = round((orig_w * settings->new_w_pc) / 100.0); view_h = round((orig_h * settings->new_h_pc) / 100.0); } else { final_w = view_w = round((orig_w * settings->new_w_pc) / 100.0); final_h = view_h = round((orig_h * settings->new_h_pc) / 100.0); } } else { // user typed exact pixel size if (settings->resize_mode == RESIZE_PIXEL_WIDTH) { view_w = settings->new_w_px; // width is fixed if (settings->stretch_mode == STRETCH_ASPECT) { final_w = view_w; final_h = view_h = round(((float)final_w * orig_h) / orig_w); } else if (settings->stretch_mode == STRETCH_PADDED) { final_w = min(view_w, orig_w); final_h = round(((float)final_w * orig_h) / orig_w); view_h = max(orig_h, final_h); } else { final_w = view_w; final_h = view_h = orig_h; } } else if (settings->resize_mode == RESIZE_PIXEL_HEIGHT) { view_h = settings->new_h_px; // height is fixed if (settings->stretch_mode == STRETCH_ASPECT) { final_h = view_h; final_w = view_w = round(((float)final_h * orig_w) / orig_h); } else if (settings->stretch_mode == STRETCH_PADDED) { final_h = min(view_h, orig_h); final_w = round(((float)final_h * orig_w) / orig_h); view_w = max(orig_w, final_w); } else { final_h = view_h; final_w = view_w = orig_w; } } else { // both dimensions are defined if (settings->stretch_mode == STRETCH_ASPECT) { // Find which new dimension is the smallest percentage of the existing image dimension gdouble newwpct = (float)settings->new_w_px / (float)orig_w; gdouble newhpct = (float)settings->new_h_px / (float)orig_h; gdouble newpct = min(newwpct, newhpct); final_w = view_w = round(orig_w * newpct); final_h = view_h = round(orig_h * newpct); } else if (settings->stretch_mode == STRETCH_PADDED) { // Find which new dimension is the smallest percentage of the existing image dimension gdouble newwpct = (float)settings->new_w_px / (float)orig_w; gdouble newhpct = (float)settings->new_h_px / (float)orig_h; gdouble newpct = min(newwpct, newhpct); final_w = round(orig_w * newpct); final_h = round(orig_h * newpct); view_w = round(orig_w * newwpct); view_h = round(orig_h * newhpct); } else { final_w = view_w = settings->new_w_px; final_h = view_h = settings->new_h_px; } } } // do resize #if USE_API26 success = gimp_image_scale_full ( out->image_id, final_w, final_h, settings->interpolation ); #else // starting from 2.8, gimp_image_scale_full is deprecated. // use gimp_image_scale instead GimpInterpolationType old_interpolation; old_interpolation = gimp_context_get_interpolation(); success = gimp_context_set_interpolation (settings->interpolation); success = gimp_image_scale ( out->image_id, final_w, final_h ); success = gimp_context_set_interpolation (old_interpolation); #endif // add a padding if requested if (settings->stretch_mode == STRETCH_PADDED) { // the padding will be drawn using a coloured layer at the bottom of the image gint32 layerId = gimp_layer_new( out->image_id, "padding_layer", view_w, view_h, GIMP_RGBA_IMAGE, (settings->padding_color_alpha / (float)G_MAXUINT16) * 100, GIMP_NORMAL_MODE ); #if USE_API26 gimp_image_add_layer ( out->image_id, layerId, 0 ); gimp_image_lower_layer_to_bottom(out->image_id, layerId); #else gimp_image_insert_layer( out->image_id, layerId, 0, 0 ); gimp_image_lower_item_to_bottom(out->image_id, layerId); #endif // fill it with the selected color GimpRGB old_background, new_background; gimp_context_get_background(&old_background); gimp_rgb_parse_hex (&new_background, gdk_color_to_string(&(settings->padding_color)), strlen(gdk_color_to_string(&(settings->padding_color)))); gimp_context_set_background(&new_background); gimp_drawable_fill(layerId, GIMP_BACKGROUND_FILL); gimp_context_set_background(&old_background); // move it to the center gimp_layer_translate(layerId, -abs(view_w - final_w) / 2, -abs(view_h - final_h) / 2); // finish changing the canvas size accordingly success = gimp_image_resize_to_layers(out->image_id); } return success; }
static void gimp_display_shell_drop_pixbuf (GtkWidget *widget, gint x, gint y, GdkPixbuf *pixbuf, gpointer data) { GimpDisplayShell *shell = GIMP_DISPLAY_SHELL (data); GimpImage *image = shell->display->image; GimpLayer *new_layer; GimpImageType image_type; gboolean new_image = FALSE; GIMP_LOG (DND, NULL); if (shell->display->gimp->busy) return; switch (gdk_pixbuf_get_n_channels (pixbuf)) { case 1: image_type = GIMP_GRAY_IMAGE; break; case 2: image_type = GIMP_GRAYA_IMAGE; break; case 3: image_type = GIMP_RGB_IMAGE; break; case 4: image_type = GIMP_RGBA_IMAGE; break; break; default: g_return_if_reached (); break; } if (! image) { image = gimp_create_image (shell->display->gimp, gdk_pixbuf_get_width (pixbuf), gdk_pixbuf_get_height (pixbuf), GIMP_IMAGE_TYPE_BASE_TYPE (image_type), FALSE); gimp_create_display (image->gimp, image, GIMP_UNIT_PIXEL, 1.0); g_object_unref (image); gimp_image_undo_disable (image); new_image = TRUE; } new_layer = gimp_layer_new_from_pixbuf (pixbuf, image, image_type, _("Dropped Buffer"), GIMP_OPACITY_OPAQUE, GIMP_NORMAL_MODE); if (new_layer) { GimpItem *new_item = GIMP_ITEM (new_layer); new_item = GIMP_ITEM (new_layer); gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_EDIT_PASTE, _("Drop New Layer")); if (! new_image) gimp_display_shell_dnd_position_item (shell, new_item); gimp_image_add_layer (image, new_layer, -1); gimp_image_undo_group_end (image); gimp_display_shell_dnd_flush (shell, image); } if (new_image) gimp_image_undo_enable (image); }
static GimpLayer * gimp_image_merge_layers (GimpImage *image, GSList *merge_list, GimpContext *context, GimpMergeType merge_type, const gchar *undo_desc) { GList *list; GSList *reverse_list = NULL; PixelRegion src1PR, src2PR, maskPR; PixelRegion *mask; GimpLayer *merge_layer; GimpLayer *layer; GimpLayer *bottom_layer; GimpImageType type; gint count; gint x1, y1, x2, y2; gint x3, y3, x4, y4; CombinationMode operation; gint position; gboolean active[MAX_CHANNELS] = { TRUE, TRUE, TRUE, TRUE }; gint off_x, off_y; gchar *name; g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL); layer = NULL; type = GIMP_RGBA_IMAGE; x1 = y1 = 0; x2 = y2 = 0; bottom_layer = NULL; /* Get the layer extents */ count = 0; while (merge_list) { layer = merge_list->data; gimp_item_offsets (GIMP_ITEM (layer), &off_x, &off_y); switch (merge_type) { case GIMP_EXPAND_AS_NECESSARY: case GIMP_CLIP_TO_IMAGE: if (! count) { x1 = off_x; y1 = off_y; x2 = off_x + gimp_item_width (GIMP_ITEM (layer)); y2 = off_y + gimp_item_height (GIMP_ITEM (layer)); } else { if (off_x < x1) x1 = off_x; if (off_y < y1) y1 = off_y; if ((off_x + gimp_item_width (GIMP_ITEM (layer))) > x2) x2 = (off_x + gimp_item_width (GIMP_ITEM (layer))); if ((off_y + gimp_item_height (GIMP_ITEM (layer))) > y2) y2 = (off_y + gimp_item_height (GIMP_ITEM (layer))); } if (merge_type == GIMP_CLIP_TO_IMAGE) { x1 = CLAMP (x1, 0, gimp_image_get_width (image)); y1 = CLAMP (y1, 0, gimp_image_get_height (image)); x2 = CLAMP (x2, 0, gimp_image_get_width (image)); y2 = CLAMP (y2, 0, gimp_image_get_height (image)); } break; case GIMP_CLIP_TO_BOTTOM_LAYER: if (merge_list->next == NULL) { x1 = off_x; y1 = off_y; x2 = off_x + gimp_item_width (GIMP_ITEM (layer)); y2 = off_y + gimp_item_height (GIMP_ITEM (layer)); } break; case GIMP_FLATTEN_IMAGE: if (merge_list->next == NULL) { x1 = 0; y1 = 0; x2 = gimp_image_get_width (image); y2 = gimp_image_get_height (image); } break; } count ++; reverse_list = g_slist_prepend (reverse_list, layer); merge_list = g_slist_next (merge_list); } if ((x2 - x1) == 0 || (y2 - y1) == 0) return NULL; /* Start a merge undo group. */ gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_IMAGE_LAYERS_MERGE, undo_desc); name = g_strdup (gimp_object_get_name (GIMP_OBJECT (layer))); if (merge_type == GIMP_FLATTEN_IMAGE || gimp_drawable_type (GIMP_DRAWABLE (layer)) == GIMP_INDEXED_IMAGE) { guchar bg[4] = { 0, 0, 0, 0 }; type = GIMP_IMAGE_TYPE_FROM_BASE_TYPE (gimp_image_base_type (image)); merge_layer = gimp_layer_new (image, (x2 - x1), (y2 - y1), type, gimp_object_get_name (GIMP_OBJECT (layer)), GIMP_OPACITY_OPAQUE, GIMP_NORMAL_MODE); if (! merge_layer) { g_warning ("%s: could not allocate merge layer.", G_STRFUNC); return NULL; } GIMP_ITEM (merge_layer)->offset_x = x1; GIMP_ITEM (merge_layer)->offset_y = y1; /* get the background for compositing */ gimp_image_get_background (image, context, gimp_drawable_type (GIMP_DRAWABLE (merge_layer)), bg); /* init the pixel region */ pixel_region_init (&src1PR, gimp_drawable_get_tiles (GIMP_DRAWABLE (merge_layer)), 0, 0, (x2 - x1), (y2 - y1), TRUE); /* set the region to the background color */ color_region (&src1PR, bg); position = 0; } else { /* The final merged layer inherits the name of the bottom most layer * and the resulting layer has an alpha channel whether or not the * original did. Opacity is set to 100% and the MODE is set to normal. */ merge_layer = gimp_layer_new (image, (x2 - x1), (y2 - y1), gimp_drawable_type_with_alpha (GIMP_DRAWABLE (layer)), "merged layer", GIMP_OPACITY_OPAQUE, GIMP_NORMAL_MODE); if (!merge_layer) { g_warning ("%s: could not allocate merge layer", G_STRFUNC); return NULL; } GIMP_ITEM (merge_layer)->offset_x = x1; GIMP_ITEM (merge_layer)->offset_y = y1; /* clear the layer */ pixel_region_init (&src1PR, gimp_drawable_get_tiles (GIMP_DRAWABLE (merge_layer)), 0, 0, (x2 - x1), (y2 - y1), TRUE); clear_region (&src1PR); /* Find the index in the layer list of the bottom layer--we need this * in order to add the final, merged layer to the layer list correctly */ layer = reverse_list->data; position = gimp_container_num_children (image->layers) - gimp_container_get_child_index (image->layers, GIMP_OBJECT (layer)); } bottom_layer = layer; /* Copy the tattoo and parasites of the bottom layer to the new layer */ gimp_item_set_tattoo (GIMP_ITEM (merge_layer), gimp_item_get_tattoo (GIMP_ITEM (bottom_layer))); g_object_unref (GIMP_ITEM (merge_layer)->parasites); GIMP_ITEM (merge_layer)->parasites = gimp_parasite_list_copy (GIMP_ITEM (bottom_layer)->parasites); while (reverse_list) { GimpLayerModeEffects mode; layer = reverse_list->data; /* determine what sort of operation is being attempted and * if it's actually legal... */ operation = gimp_image_merge_layers_get_operation (merge_layer, layer); if (operation == -1) { gimp_layer_add_alpha (layer); /* try again ... */ operation = gimp_image_merge_layers_get_operation (merge_layer, layer); } if (operation == -1) { g_warning ("%s: attempting to merge incompatible layers.", G_STRFUNC); return NULL; } gimp_item_offsets (GIMP_ITEM (layer), &off_x, &off_y); x3 = CLAMP (off_x, x1, x2); y3 = CLAMP (off_y, y1, y2); x4 = CLAMP (off_x + gimp_item_width (GIMP_ITEM (layer)), x1, x2); y4 = CLAMP (off_y + gimp_item_height (GIMP_ITEM (layer)), y1, y2); /* configure the pixel regions */ pixel_region_init (&src1PR, gimp_drawable_get_tiles (GIMP_DRAWABLE (merge_layer)), (x3 - x1), (y3 - y1), (x4 - x3), (y4 - y3), TRUE); pixel_region_init (&src2PR, gimp_drawable_get_tiles (GIMP_DRAWABLE (layer)), (x3 - off_x), (y3 - off_y), (x4 - x3), (y4 - y3), FALSE); if (gimp_layer_get_mask (layer) && gimp_layer_mask_get_apply (layer->mask)) { TileManager *tiles; tiles = gimp_drawable_get_tiles (GIMP_DRAWABLE (layer->mask)); pixel_region_init (&maskPR, tiles, (x3 - off_x), (y3 - off_y), (x4 - x3), (y4 - y3), FALSE); mask = &maskPR; } else { mask = NULL; } /* DISSOLVE_MODE is special since it is the only mode that does not * work on the projection with the lower layer, but only locally on * the layers alpha channel. */ mode = gimp_layer_get_mode (layer); if (layer == bottom_layer && mode != GIMP_DISSOLVE_MODE) mode = GIMP_NORMAL_MODE; combine_regions (&src1PR, &src2PR, &src1PR, mask, NULL, gimp_layer_get_opacity (layer) * 255.999, mode, active, operation); gimp_image_remove_layer (image, layer); reverse_list = g_slist_next (reverse_list); } g_slist_free (reverse_list); /* if the type is flatten, remove all the remaining layers */ if (merge_type == GIMP_FLATTEN_IMAGE) { list = GIMP_LIST (image->layers)->list; while (list) { layer = list->data; list = g_list_next (list); gimp_image_remove_layer (image, layer); } gimp_image_add_layer (image, merge_layer, position); } else { /* Add the layer to the image */ gimp_image_add_layer (image, merge_layer, gimp_container_num_children (image->layers) - position + 1); } /* set the name after the original layers have been removed so we * don't end up with #2 appended to the name */ gimp_object_take_name (GIMP_OBJECT (merge_layer), name); gimp_item_set_visible (GIMP_ITEM (merge_layer), TRUE, TRUE); /* End the merge undo group */ gimp_image_undo_group_end (image); gimp_drawable_update (GIMP_DRAWABLE (merge_layer), 0, 0, gimp_item_width (GIMP_ITEM (merge_layer)), gimp_item_height (GIMP_ITEM (merge_layer))); return merge_layer; }
static GimpLayer * gimp_image_merge_layers (GimpImage *image, GimpContainer *container, GSList *merge_list, GimpContext *context, GimpMergeType merge_type) { GList *list; GSList *reverse_list = NULL; GSList *layers; GimpLayer *merge_layer; GimpLayer *layer; GimpLayer *bottom_layer; GimpParasiteList *parasites; gint count; gint x1, y1, x2, y2; gint off_x, off_y; gint position; gchar *name; GimpLayer *parent; g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL); layer = NULL; x1 = y1 = 0; x2 = y2 = 0; bottom_layer = NULL; parent = gimp_layer_get_parent (merge_list->data); /* Get the layer extents */ count = 0; while (merge_list) { layer = merge_list->data; gimp_item_get_offset (GIMP_ITEM (layer), &off_x, &off_y); switch (merge_type) { case GIMP_EXPAND_AS_NECESSARY: case GIMP_CLIP_TO_IMAGE: if (! count) { x1 = off_x; y1 = off_y; x2 = off_x + gimp_item_get_width (GIMP_ITEM (layer)); y2 = off_y + gimp_item_get_height (GIMP_ITEM (layer)); } else { if (off_x < x1) x1 = off_x; if (off_y < y1) y1 = off_y; if ((off_x + gimp_item_get_width (GIMP_ITEM (layer))) > x2) x2 = (off_x + gimp_item_get_width (GIMP_ITEM (layer))); if ((off_y + gimp_item_get_height (GIMP_ITEM (layer))) > y2) y2 = (off_y + gimp_item_get_height (GIMP_ITEM (layer))); } if (merge_type == GIMP_CLIP_TO_IMAGE) { x1 = CLAMP (x1, 0, gimp_image_get_width (image)); y1 = CLAMP (y1, 0, gimp_image_get_height (image)); x2 = CLAMP (x2, 0, gimp_image_get_width (image)); y2 = CLAMP (y2, 0, gimp_image_get_height (image)); } break; case GIMP_CLIP_TO_BOTTOM_LAYER: if (merge_list->next == NULL) { x1 = off_x; y1 = off_y; x2 = off_x + gimp_item_get_width (GIMP_ITEM (layer)); y2 = off_y + gimp_item_get_height (GIMP_ITEM (layer)); } break; case GIMP_FLATTEN_IMAGE: if (merge_list->next == NULL) { x1 = 0; y1 = 0; x2 = gimp_image_get_width (image); y2 = gimp_image_get_height (image); } break; } count ++; reverse_list = g_slist_prepend (reverse_list, layer); merge_list = g_slist_next (merge_list); } if ((x2 - x1) == 0 || (y2 - y1) == 0) return NULL; /* Start a merge undo group. */ name = g_strdup (gimp_object_get_name (layer)); if (merge_type == GIMP_FLATTEN_IMAGE || (gimp_drawable_is_indexed (GIMP_DRAWABLE (layer)) && ! gimp_drawable_has_alpha (GIMP_DRAWABLE (layer)))) { GeglColor *color; GimpRGB bg; merge_layer = gimp_layer_new (image, (x2 - x1), (y2 - y1), gimp_image_get_layer_format (image, FALSE), gimp_object_get_name (layer), GIMP_OPACITY_OPAQUE, GIMP_NORMAL_MODE); if (! merge_layer) { g_warning ("%s: could not allocate merge layer.", G_STRFUNC); return NULL; } gimp_item_set_offset (GIMP_ITEM (merge_layer), x1, y1); /* get the background for compositing */ gimp_context_get_background (context, &bg); color = gimp_gegl_color_new (&bg); gegl_buffer_set_color (gimp_drawable_get_buffer (GIMP_DRAWABLE (merge_layer)), GEGL_RECTANGLE(0,0,x2-x1,y2-y1), color); g_object_unref (color); position = 0; } else { /* The final merged layer inherits the name of the bottom most layer * and the resulting layer has an alpha channel whether or not the * original did. Opacity is set to 100% and the MODE is set to normal. */ merge_layer = gimp_layer_new (image, (x2 - x1), (y2 - y1), gimp_drawable_get_format_with_alpha (GIMP_DRAWABLE (layer)), "merged layer", GIMP_OPACITY_OPAQUE, GIMP_NORMAL_MODE); if (!merge_layer) { g_warning ("%s: could not allocate merge layer", G_STRFUNC); return NULL; } gimp_item_set_offset (GIMP_ITEM (merge_layer), x1, y1); /* clear the layer */ gegl_buffer_clear (gimp_drawable_get_buffer (GIMP_DRAWABLE (merge_layer)), NULL); /* Find the index in the layer list of the bottom layer--we need this * in order to add the final, merged layer to the layer list correctly */ layer = reverse_list->data; position = gimp_container_get_n_children (container) - gimp_container_get_child_index (container, GIMP_OBJECT (layer)); } bottom_layer = layer; /* Copy the tattoo and parasites of the bottom layer to the new layer */ gimp_item_set_tattoo (GIMP_ITEM (merge_layer), gimp_item_get_tattoo (GIMP_ITEM (bottom_layer))); parasites = gimp_item_get_parasites (GIMP_ITEM (bottom_layer)); parasites = gimp_parasite_list_copy (parasites); gimp_item_set_parasites (GIMP_ITEM (merge_layer), parasites); g_object_unref (parasites); for (layers = reverse_list; layers; layers = g_slist_next (layers)) { GeglBuffer *merge_buffer; GeglBuffer *layer_buffer; GimpApplicator *applicator; GimpLayerModeEffects mode; layer = layers->data; gimp_item_get_offset (GIMP_ITEM (layer), &off_x, &off_y); /* DISSOLVE_MODE is special since it is the only mode that does not * work on the projection with the lower layer, but only locally on * the layers alpha channel. */ mode = gimp_layer_get_mode (layer); if (layer == bottom_layer && mode != GIMP_DISSOLVE_MODE) mode = GIMP_NORMAL_MODE; merge_buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (merge_layer)); layer_buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (layer)); applicator = gimp_applicator_new (NULL, gimp_drawable_get_linear (GIMP_DRAWABLE (layer)), FALSE, FALSE); if (gimp_layer_get_mask (layer) && gimp_layer_get_apply_mask (layer)) { GeglBuffer *mask_buffer; mask_buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (layer->mask)); gimp_applicator_set_mask_buffer (applicator, mask_buffer); gimp_applicator_set_mask_offset (applicator, - (x1 - off_x), - (y1 - off_y)); } gimp_applicator_set_src_buffer (applicator, merge_buffer); gimp_applicator_set_dest_buffer (applicator, merge_buffer); gimp_applicator_set_apply_buffer (applicator, layer_buffer); gimp_applicator_set_apply_offset (applicator, - (x1 - off_x), - (y1 - off_y)); gimp_applicator_set_mode (applicator, gimp_layer_get_opacity (layer), mode); gimp_applicator_blit (applicator, GEGL_RECTANGLE (0, 0, gegl_buffer_get_width (merge_buffer), gegl_buffer_get_height (merge_buffer))); g_object_unref (applicator); gimp_image_remove_layer (image, layer, TRUE, NULL); } g_slist_free (reverse_list); gimp_object_take_name (GIMP_OBJECT (merge_layer), name); gimp_item_set_visible (GIMP_ITEM (merge_layer), TRUE, FALSE); /* if the type is flatten, remove all the remaining layers */ if (merge_type == GIMP_FLATTEN_IMAGE) { list = gimp_image_get_layer_iter (image); while (list) { layer = list->data; list = g_list_next (list); gimp_image_remove_layer (image, layer, TRUE, NULL); } gimp_image_add_layer (image, merge_layer, parent, position, TRUE); } else { /* Add the layer to the image */ gimp_image_add_layer (image, merge_layer, parent, gimp_container_get_n_children (container) - position + 1, TRUE); } gimp_drawable_update (GIMP_DRAWABLE (merge_layer), 0, 0, gimp_item_get_width (GIMP_ITEM (merge_layer)), gimp_item_get_height (GIMP_ITEM (merge_layer))); return merge_layer; }
void ptRun(const gchar* Name, gint NrParameters, const GimpParam* Parameter, gint *nreturn_vals, GimpParam **return_vals) { printf("(%s,%d) '%s'\n",__FILE__,__LINE__,__PRETTY_FUNCTION__); printf("Name : '%s'\n",Name); printf("NrParameters : %d\n",NrParameters); if (!strcmp(Name,"photivoSendToGimp")) { printf("RunMode : %d\n",Parameter[0].data.d_int32); printf("FileName1 : '%s'\n",Parameter[1].data.d_string); printf("FileName2 : '%s'\n",Parameter[2].data.d_string); QFile GimpFile(Parameter[1].data.d_string); bool result = GimpFile.open(QIODevice::ReadOnly | QIODevice::Text); assert(result); QTextStream In(&GimpFile); QString ImageFileName = In.readLine(); QString ExifFileName = In.readLine(); QString ICCFileName = In.readLine(); // Read image FILE *InputFile = fopen(ImageFileName.toLocal8Bit().data(),"rb"); if (!InputFile) { ptLogError(1,ImageFileName.toLocal8Bit().data()); return; // ptError_FileOpen; } short Colors; unsigned short Width; unsigned short Height; unsigned short BitsPerColor; char Buffer[128]; // Extremely naive. Probably just enough for testcases. char *s = fgets(Buffer,127,InputFile); assert ( s ); int n = sscanf(Buffer,"P%hd",&Colors); assert ( 1 == n ); assert(Colors == 6 ); do { s = fgets(Buffer,127,InputFile); assert ( s ); } while (Buffer[0] == '#'); sscanf(Buffer,"%hd %hd",&Width,&Height); s = fgets(Buffer,127,InputFile); assert ( s ); sscanf(Buffer,"%hd",&BitsPerColor); assert(BitsPerColor == 0xffff); Colors = 3; unsigned short (* ImageForGimp)[3] = (unsigned short (*)[3]) CALLOC2(Width*Height,sizeof(*ImageForGimp)); ptMemoryError(ImageForGimp,__FILE__,__LINE__); unsigned short* PpmRow = (unsigned short *) CALLOC2(Width*Height,sizeof(*PpmRow)); ptMemoryError(PpmRow,__FILE__,__LINE__); for (unsigned short Row=0; Row<Height; Row++) { size_t RV = fread(PpmRow,Colors*2,Width,InputFile); if (RV != (size_t) Width) { printf("ReadPpm error. Expected %d bytes. Got %d\n",Width,(int)RV); exit(EXIT_FAILURE); } if (htons(0x55aa) != 0x55aa) { swab((char *)PpmRow,(char *)PpmRow,Width*Colors*2); } for (unsigned short Col=0; Col<Width; Col++) { for (short c=0;c<3;c++) { ImageForGimp[Row*Width+Col][c] = PpmRow[Col*Colors+c]; } } } FREE2(PpmRow); FCLOSE(InputFile); QFile ExifFile(ExifFileName); result = ExifFile.open(QIODevice::ReadOnly); assert(result); qint64 FileSize = ExifFile.size(); QDataStream ExifIn(&ExifFile); char* ExifBuffer = (char *) MALLOC2(FileSize); ptMemoryError(ExifBuffer,__FILE__,__LINE__); unsigned ExifBufferLength = ExifIn.readRawData(ExifBuffer,FileSize); ExifFile.close(); QFile ICCFile(ICCFileName); result = ICCFile.open(QIODevice::ReadOnly); assert(result); qint64 FileSize2 = ICCFile.size(); QDataStream ICCIn(&ICCFile); char* ICCBuffer = (char *) MALLOC2(FileSize2); ptMemoryError(ICCBuffer,__FILE__,__LINE__); unsigned ICCBufferLength = ICCIn.readRawData(ICCBuffer,FileSize2); ICCFile.close(); // And now copy to gimp. gint32 GimpImage = gimp_image_new(Width, Height, GIMP_RGB); assert (GimpImage != -1); gint32 GimpLayer = gimp_layer_new(GimpImage, "BG", Width, Height, GIMP_RGB_IMAGE, 100.0, GIMP_NORMAL_MODE); #if GIMP_MINOR_VERSION<=6 gimp_image_add_layer(GimpImage,GimpLayer,0); #else gimp_image_insert_layer(GimpImage,GimpLayer,0,0); #endif GimpDrawable* Drawable = gimp_drawable_get(GimpLayer); GimpPixelRgn PixelRegion; gimp_pixel_rgn_init(&PixelRegion, Drawable, 0, 0, Drawable->width, Drawable->height, true, false); unsigned short TileHeight = gimp_tile_height(); for (unsigned short Row=0; Row<Height; Row+=TileHeight) { unsigned short NrRows = MIN(Height-Row, (int)TileHeight); guint8* Buffer = g_new(guint8,TileHeight*Width*3); for (unsigned short i=0; i<NrRows; i++) { for (unsigned short j=0; j<Width; j++) { for (short c=0;c<3;c++) { Buffer[3*(i*Width+j)+c] = ImageForGimp[(Row+i)*Width+j][c]>>8; } } } gimp_pixel_rgn_set_rect(&PixelRegion, Buffer, 0, Row, Width, NrRows); g_free(Buffer); } gimp_drawable_flush(Drawable); gimp_drawable_detach(Drawable); FREE2(ImageForGimp); GimpParasite* GimpExifData = gimp_parasite_new("exif-data", GIMP_PARASITE_PERSISTENT, ExifBufferLength, ExifBuffer); gimp_image_parasite_attach(GimpImage,GimpExifData); gimp_parasite_free(GimpExifData); FREE2(ExifBuffer); GimpParasite* GimpICCData = gimp_parasite_new("icc-profile", GIMP_PARASITE_PERSISTENT, ICCBufferLength, ICCBuffer); gimp_image_parasite_attach(GimpImage,GimpICCData); gimp_parasite_free(GimpICCData); FREE2(ICCBuffer); static GimpParam Values[2]; *nreturn_vals = 2; *return_vals = Values; Values[0].type = GIMP_PDB_STATUS; Values[0].data.d_status = GIMP_PDB_SUCCESS; Values[1].type = GIMP_PDB_IMAGE; Values[1].data.d_image = GimpImage; QFile::remove(ImageFileName); QFile::remove(ExifFileName); QFile::remove(ICCFileName); QFile::remove(Parameter[1].data.d_string); }
static void dog (gint32 image_ID, GimpDrawable *drawable, gdouble inner, gdouble outer, gboolean show_progress) { GimpDrawable *drawable1; GimpDrawable *drawable2; gint32 drawable_id = drawable->drawable_id; gint32 layer1; gint32 layer2; gint width, height; gint x1, y1, x2, y2; guchar maxval = 255; gimp_drawable_mask_bounds (drawable_id, &x1, &y1, &x2, &y2); width = (x2 - x1); height = (y2 - y1); gimp_drawable_flush (drawable); layer1 = gimp_layer_copy (drawable_id); gimp_drawable_set_visible (layer1, FALSE); gimp_drawable_set_name (layer1, "dog_scratch_layer1"); gimp_image_add_layer (image_ID, layer1, 0); layer2 = gimp_layer_copy (drawable_id); gimp_drawable_set_visible (layer2, FALSE); gimp_drawable_set_name (layer2, "dog_scratch_layer2"); gimp_image_add_layer (image_ID, layer2, 0); drawable1 = gimp_drawable_get (layer1); drawable2 = gimp_drawable_get (layer2); gauss_rle (drawable1, inner, 0, show_progress); gauss_rle (drawable2, outer, 1, show_progress); compute_difference (drawable, drawable1, drawable2, &maxval); gimp_drawable_detach (drawable1); gimp_drawable_detach (drawable2); gimp_image_remove_layer (image_ID, layer1); gimp_image_remove_layer (image_ID, layer2); gimp_drawable_flush (drawable); gimp_drawable_merge_shadow (drawable_id, TRUE); gimp_drawable_update (drawable_id, x1, y1, width, height); if (dogvals.normalize) { normalize (drawable, maxval); gimp_drawable_flush (drawable); gimp_drawable_merge_shadow (drawable_id, TRUE); gimp_drawable_update (drawable_id, x1, y1, width, height); } if (dogvals.invert) gimp_invert (drawable_id); }
static void gimp_display_shell_drop_drawable (GtkWidget *widget, gint x, gint y, GimpViewable *viewable, gpointer data) { GimpDisplayShell *shell = GIMP_DISPLAY_SHELL (data); GimpImage *image = shell->display->image; GType new_type; GimpItem *new_item; gboolean new_image = FALSE; GIMP_LOG (DND, NULL); if (shell->display->gimp->busy) return; if (! image) { GimpImage *src_image = gimp_item_get_image (GIMP_ITEM (viewable)); GimpDrawable *drawable = GIMP_DRAWABLE (viewable); GimpImageBaseType type; gdouble xres; gdouble yres; type = GIMP_IMAGE_TYPE_BASE_TYPE (gimp_drawable_type (drawable)); image = gimp_create_image (shell->display->gimp, gimp_item_width (GIMP_ITEM (viewable)), gimp_item_height (GIMP_ITEM (viewable)), type, TRUE); gimp_image_undo_disable (image); if (type == GIMP_INDEXED) gimp_image_set_colormap (image, gimp_image_get_colormap (src_image), gimp_image_get_colormap_size (src_image), FALSE); gimp_image_get_resolution (src_image, &xres, &yres); gimp_image_set_resolution (image, xres, yres); gimp_image_set_unit (image, gimp_image_get_unit (src_image)); gimp_create_display (image->gimp, image, GIMP_UNIT_PIXEL, 1.0); g_object_unref (image); new_image = TRUE; } if (GIMP_IS_LAYER (viewable)) new_type = G_TYPE_FROM_INSTANCE (viewable); else new_type = GIMP_TYPE_LAYER; new_item = gimp_item_convert (GIMP_ITEM (viewable), image, new_type); if (new_item) { GimpLayer *new_layer = GIMP_LAYER (new_item); gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_EDIT_PASTE, _("Drop New Layer")); if (! new_image) gimp_display_shell_dnd_position_item (shell, new_item); gimp_item_set_visible (new_item, TRUE, FALSE); gimp_item_set_linked (new_item, FALSE, FALSE); gimp_image_add_layer (image, new_layer, -1); gimp_image_undo_group_end (image); gimp_display_shell_dnd_flush (shell, image); } if (new_image) gimp_image_undo_enable (image); }
GimpLayer * gimp_edit_paste (GimpImage *image, GimpDrawable *drawable, GimpBuffer *paste, gboolean paste_into, gint viewport_x, gint viewport_y, gint viewport_width, gint viewport_height) { GimpLayer *layer; const Babl *format; gint image_width; gint image_height; gint width; gint height; gint offset_x; gint offset_y; gboolean clamp_to_image = TRUE; g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); g_return_val_if_fail (drawable == NULL || GIMP_IS_DRAWABLE (drawable), NULL); g_return_val_if_fail (drawable == NULL || gimp_item_is_attached (GIMP_ITEM (drawable)), NULL); g_return_val_if_fail (GIMP_IS_BUFFER (paste), NULL); /* Make a new layer: if drawable == NULL, * user is pasting into an empty image. */ if (drawable) format = gimp_drawable_get_format_with_alpha (drawable); else format = gimp_image_get_layer_format (image, TRUE); layer = gimp_layer_new_from_buffer (paste, image, format, _("Pasted Layer"), GIMP_OPACITY_OPAQUE, GIMP_NORMAL_MODE); if (! layer) return NULL; image_width = gimp_image_get_width (image); image_height = gimp_image_get_height (image); width = gimp_item_get_width (GIMP_ITEM (layer)); height = gimp_item_get_height (GIMP_ITEM (layer)); if (viewport_width == image_width && viewport_height == image_height) { /* if the whole image is visible, act as if there was no viewport */ viewport_x = 0; viewport_y = 0; viewport_width = 0; viewport_height = 0; } if (drawable) { /* if pasting to a drawable */ gint off_x, off_y; gint x1, y1, x2, y2; gint paste_x, paste_y; gint paste_width, paste_height; gboolean have_mask; gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y); have_mask = gimp_item_mask_bounds (GIMP_ITEM (drawable), &x1, &y1, &x2, &y2); if (! have_mask && /* if we have no mask */ viewport_width > 0 && /* and we have a viewport */ viewport_height > 0 && (width < (x2 - x1) || /* and the paste is smaller than the target */ height < (y2 - y1)) && /* and the viewport intersects with the target */ gimp_rectangle_intersect (viewport_x, viewport_y, viewport_width, viewport_height, off_x, off_y, x2 - x1, y2 - y1, &paste_x, &paste_y, &paste_width, &paste_height)) { /* center on the viewport */ offset_x = paste_x + (paste_width - width) / 2; offset_y = paste_y + (paste_height- height) / 2; } else { /* otherwise center on the target */ offset_x = off_x + ((x1 + x2) - width) / 2; offset_y = off_y + ((y1 + y2) - height) / 2; /* and keep it that way */ clamp_to_image = FALSE; } } else if (viewport_width > 0 && /* if we have a viewport */ viewport_height > 0 && (width < image_width || /* and the paste is */ height < image_height)) /* smaller than the image */ { /* center on the viewport */ offset_x = viewport_x + (viewport_width - width) / 2; offset_y = viewport_y + (viewport_height - height) / 2; } else { /* otherwise center on the image */ offset_x = (image_width - width) / 2; offset_y = (image_height - height) / 2; /* and keep it that way */ clamp_to_image = FALSE; } if (clamp_to_image) { /* Ensure that the pasted layer is always within the image, if it * fits and aligned at top left if it doesn't. (See bug #142944). */ offset_x = MIN (offset_x, image_width - width); offset_y = MIN (offset_y, image_height - height); offset_x = MAX (offset_x, 0); offset_y = MAX (offset_y, 0); } gimp_item_set_offset (GIMP_ITEM (layer), offset_x, offset_y); /* Start a group undo */ gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_EDIT_PASTE, C_("undo-type", "Paste")); /* If there is a selection mask clear it-- * this might not always be desired, but in general, * it seems like the correct behavior. */ if (! gimp_channel_is_empty (gimp_image_get_mask (image)) && ! paste_into) gimp_channel_clear (gimp_image_get_mask (image), NULL, TRUE); /* if there's a drawable, add a new floating selection */ if (drawable) floating_sel_attach (layer, drawable); else gimp_image_add_layer (image, layer, NULL, 0, TRUE); /* end the group undo */ gimp_image_undo_group_end (image); return layer; }
/* --------------------------------- * gap_edgeDetectionByBlurDiff * --------------------------------- */ gint32 gap_edgeDetectionByBlurDiff(gint32 activeDrawableId, gdouble blurRadius, gdouble blurResultRadius , gdouble threshold, gint32 shift, gboolean doLevelsAutostretch , gboolean invert) { gint32 blurLayerId; gint32 edgeLayerId; gint32 imageId; GimpDrawable *edgeDrawable; GimpDrawable *refDrawable; GimpDrawable *blurDrawable; imageId = gimp_drawable_get_image(activeDrawableId); edgeLayerId = gimp_layer_copy(activeDrawableId); gimp_image_add_layer (imageId, edgeLayerId, 0 /* stackposition */ ); edgeDrawable = gimp_drawable_get(edgeLayerId); refDrawable = gimp_drawable_get(activeDrawableId); if(blurRadius > 0.0) { p_call_plug_in_gauss_iir2(imageId, edgeLayerId, blurRadius, blurRadius); } blurDrawable = NULL; // blurLayerId = gimp_layer_copy(edgeLayerId); // gimp_image_add_layer (imageId, blurLayerId, 0 /* stackposition */ ); // blurDrawable = gimp_drawable_get(blurLayerId); p_subtract_ref_layer(imageId, edgeDrawable, refDrawable, threshold, shift, invert); //p_subtract_ref_layer(imageId, edgeDrawable, blurDrawable, threshold, shift, invert); if (doLevelsAutostretch) { gimp_levels_stretch(edgeLayerId); } if(blurResultRadius > 0.0) { p_call_plug_in_gauss_iir2(imageId, edgeLayerId, blurResultRadius, blurResultRadius); } if(refDrawable) { gimp_drawable_detach(refDrawable); } if(edgeDrawable) { gimp_drawable_detach(edgeDrawable); } if(blurDrawable) { gimp_drawable_detach(blurDrawable); } return (edgeLayerId); } /* end gap_edgeDetectionByBlurDiff */