static void do_texture_press () { gimp_image_delete (preview_image); preview_image = gimp_image_duplicate(image_ID); border (preview_image); preview_update (preview); }
/* -------------------------- * p_create_corpus_layer * -------------------------- * create the corpus layer that builds the reference pattern * for the resynthesizer call. The reference pattern is built * as duplicate of the original image reduced to the area around the current selection. * (grown by corpus_border_radius) * Note that the duplicate image has a selection, that includes the gorwn area * around the orignal selection, but EXCLUDES the original selection * (that is the area holding the object that has to be replaced * by pattern of the surrounding area) * returns the layer_id of the reference pattern. */ static gint32 p_create_corpus_layer(gint32 image_id, gint32 drawable_id, TransValues *val_ptr) { gint32 dup_image_id; gint32 channel_id; gint32 channel_2_id; GimpRGB bck_color; GimpRGB white_opaque_color; /* gboolean has_selection; */ gboolean non_empty; gint x1, y1, x2, y2; gint32 active_layer_stackposition; gint32 active_dup_layer_id; active_layer_stackposition = gap_layer_get_stackposition(image_id, drawable_id); dup_image_id = gimp_image_duplicate(image_id); channel_id = gimp_selection_save(dup_image_id); gimp_selection_grow(dup_image_id, val_ptr->corpus_border_radius); gimp_selection_invert(dup_image_id); gimp_context_get_background(&bck_color); channel_2_id = gimp_selection_save(dup_image_id); gimp_image_select_item(dup_image_id, GIMP_CHANNEL_OP_REPLACE, channel_id); gimp_rgba_set_uchar (&white_opaque_color, 255, 255, 255, 255); gimp_context_set_background(&white_opaque_color); gimp_edit_clear(channel_2_id); gimp_context_set_background(&bck_color); /* restore original background color */ gimp_selection_load(channel_2_id); gimp_selection_invert(dup_image_id); /* has_selection = */ gimp_selection_bounds(dup_image_id, &non_empty, &x1, &y1, &x2, &y2); gimp_image_crop(dup_image_id, (x2 - x1), (y2 - y1), x1, y1); gimp_selection_invert(dup_image_id); active_dup_layer_id = gap_layer_get_id_by_stackposition(dup_image_id, active_layer_stackposition); if (1==0) { /* debug code shows the duplicate image by adding a display */ gimp_display_new(dup_image_id); } return (active_dup_layer_id); } /* end p_create_corpus_layer */
gint webx_indexed_target_get_image (WebxIndexedTarget *indexed, WebxTargetInput *input, gint *layer) { gint tmp_image; gint tmp_layer; gint *layers; gint num_layers; gchar *custom_palette; gint num_colors; gboolean converted; g_return_val_if_fail (WEBX_IS_INDEXED_TARGET (indexed), -1); if (indexed->palette_type == GIMP_REUSE_PALETTE) { *layer = input->indexed_layer; return input->indexed_image; } custom_palette = indexed->custom_palette; if (! custom_palette) custom_palette = ""; tmp_image = input->rgb_image; tmp_layer = input->rgb_layer; num_colors = indexed->num_colors; if (num_colors == 256 && gimp_drawable_has_alpha (tmp_layer)) num_colors = 255; tmp_image = gimp_image_duplicate (tmp_image); converted = gimp_image_convert_indexed (tmp_image, indexed->dither_type, indexed->palette_type, num_colors, indexed->alpha_dither, indexed->remove_unused, custom_palette); if (! converted) { gimp_image_delete (tmp_image); *layer = -1; return -1; } layers = gimp_image_get_layers (tmp_image, &num_layers); g_assert (num_layers == 1); tmp_layer = layers[0]; indexed->image = tmp_image; indexed->layer = tmp_layer; *layer= tmp_layer; return tmp_image; }
static void webx_pipeline_create_background (WebxPipeline *pipeline) { g_return_if_fail (WEBX_IS_PIPELINE (pipeline)); if (gimp_drawable_is_rgb (pipeline->rgb_layer)) { pipeline->background = webx_drawable_to_pixbuf (pipeline->rgb_layer); } else { /* pipeline->rgb_image is still original image, which can be non rgb (as we create background early in pipeline). */ gint duplicate = gimp_image_duplicate (pipeline->rgb_image); gimp_image_undo_disable (duplicate); pipeline->background = webx_image_to_pixbuf (duplicate); gimp_image_delete (duplicate); } }
/* --------------------------------------- * gap_pview_render_f_from_image_duplicate * --------------------------------------- * render preview widget from image. * This procedure creates a temorary copy of the image * for rendering of the preview. * NOTE: if the caller wants to render a temporary image * that is not needed anymore after the rendering, * the procedure gap_pview_render_f_from_image should be used * to avoid duplicating of the image. * * hint: call gtk_widget_queue_draw(pv_ptr->da_widget); * after this procedure to make the changes appear on screen. */ void gap_pview_render_f_from_image_duplicate (GapPView *pv_ptr , gint32 image_id , gint32 flip_request , gint32 flip_status ) { gint32 dup_image_id; dup_image_id = gimp_image_duplicate(image_id); gimp_image_undo_disable (dup_image_id); gap_pview_render_f_from_image(pv_ptr , dup_image_id , flip_request , flip_status ); gimp_image_delete(dup_image_id); } /* end gap_pview_render_f_from_image_duplicate */
void image_duplicate_cmd_callback (GtkAction *action, gpointer data) { GimpDisplay *display; GimpDisplayShell *shell; GimpImage *new_image; return_if_no_display (display, data); shell = GIMP_DISPLAY_SHELL (display->shell); new_image = gimp_image_duplicate (display->image); gimp_create_display (new_image->gimp, new_image, shell->unit, gimp_zoom_model_get_factor (shell->zoom)); g_object_unref (new_image); }
GimpImage * gimp_edit_paste_as_new_image (Gimp *gimp, GimpObject *paste) { GimpImage *image = NULL; g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL); g_return_val_if_fail (GIMP_IS_IMAGE (paste) || GIMP_IS_BUFFER (paste), NULL); if (GIMP_IS_IMAGE (paste)) { image = gimp_image_duplicate (GIMP_IMAGE (paste)); } else if (GIMP_IS_BUFFER (paste)) { image = gimp_image_new_from_buffer (gimp, GIMP_BUFFER (paste)); } return image; }
static void guillotine (gint32 image_ID) { gint guide; gint image_width; gint image_height; gboolean guides_found = FALSE; GList *hguides, *hg; GList *vguides, *vg; image_width = gimp_image_width (image_ID); image_height = gimp_image_height (image_ID); hguides = g_list_append (NULL, GINT_TO_POINTER (0)); hguides = g_list_append (hguides, GINT_TO_POINTER (image_height)); vguides = g_list_append (NULL, GINT_TO_POINTER (0)); vguides = g_list_append (vguides, GINT_TO_POINTER (image_width)); for (guide = gimp_image_find_next_guide (image_ID, 0); guide > 0; guide = gimp_image_find_next_guide (image_ID, guide)) { gint position = gimp_image_get_guide_position (image_ID, guide); switch (gimp_image_get_guide_orientation (image_ID, guide)) { case GIMP_ORIENTATION_HORIZONTAL: if (! g_list_find (hguides, GINT_TO_POINTER (position))) { hguides = g_list_insert_sorted (hguides, GINT_TO_POINTER (position), guide_sort_func); guides_found = TRUE; } break; case GIMP_ORIENTATION_VERTICAL: if (! g_list_find (vguides, GINT_TO_POINTER (position))) { vguides = g_list_insert_sorted (vguides, GINT_TO_POINTER (position), guide_sort_func); guides_found = TRUE; } break; case GIMP_ORIENTATION_UNKNOWN: g_assert_not_reached (); break; } } if (guides_found) { gchar *filename; gint h, v, hpad, vpad; gint x, y; gchar *hformat; gchar *format; filename = gimp_image_get_filename (image_ID); if (!filename) filename = g_strdup (_("Untitled")); /* get the number horizontal and vertical slices */ h = g_list_length (hguides); v = g_list_length (vguides); /* need the number of digits of h and v for the padding */ hpad = log10(h) + 1; vpad = log10(v) + 1; /* format for the x-y coordinates in the filename */ hformat = g_strdup_printf ("%%0%i", MAX (hpad, vpad)); format = g_strdup_printf ("-%si-%si", hformat, hformat); /* Do the actual dup'ing and cropping... this isn't a too naive a * way to do this since we got copy-on-write tiles, either. */ for (y = 0, hg = hguides; hg && hg->next; y++, hg = hg->next) { for (x = 0, vg = vguides; vg && vg->next; x++, vg = vg->next) { gint32 new_image = gimp_image_duplicate (image_ID); GString *new_filename; gchar *fileextension; gchar *fileindex; gint pos; if (new_image == -1) { g_warning ("Couldn't create new image."); return; } gimp_image_undo_disable (new_image); gimp_image_crop (new_image, GPOINTER_TO_INT (vg->next->data) - GPOINTER_TO_INT (vg->data), GPOINTER_TO_INT (hg->next->data) - GPOINTER_TO_INT (hg->data), GPOINTER_TO_INT (vg->data), GPOINTER_TO_INT (hg->data)); new_filename = g_string_new (filename); /* show the rough coordinates of the image in the title */ fileindex = g_strdup_printf (format, x, y); /* get the position of the file extension - last . in filename */ fileextension = strrchr (new_filename->str, '.'); pos = fileextension - new_filename->str; /* insert the coordinates before the extension */ g_string_insert (new_filename, pos, fileindex); g_free (fileindex); gimp_image_set_filename (new_image, new_filename->str); g_string_free (new_filename, TRUE); while ((guide = gimp_image_find_next_guide (new_image, 0))) gimp_image_delete_guide (new_image, guide); gimp_image_undo_enable (new_image); gimp_display_new (new_image); } } g_free (filename); g_free (hformat); g_free (format); } g_list_free (hguides); g_list_free (vguides); }
static gboolean webx_pipeline_check_update (WebxPipeline *pipeline) { gint *layers; gint num_layers; gint i; g_return_val_if_fail (WEBX_IS_PIPELINE (pipeline), FALSE); if (pipeline->rgb_image != -1) { gimp_image_delete (pipeline->rgb_image); pipeline->rgb_image = -1; } if (pipeline->indexed_image != -1) { gimp_image_delete (pipeline->indexed_image); pipeline->indexed_image = -1; } if (pipeline->background) { g_object_unref (pipeline->background); pipeline->background = NULL; } pipeline->rgb_image = gimp_image_duplicate (pipeline->user_image); gimp_image_undo_disable (pipeline->rgb_image); pipeline->rgb_layer = gimp_image_merge_visible_layers (pipeline->rgb_image, GIMP_CLIP_TO_IMAGE); /* make sure there is only one layer, where all visible layers were merged */ layers = gimp_image_get_layers (pipeline->rgb_image, &num_layers); for (i = 0; i < num_layers; i++) { if (layers[i] != pipeline->rgb_layer) gimp_image_remove_layer (pipeline->rgb_image, layers[i]); } g_free (layers); /* we don't want layer to be smaller than image */ gimp_layer_resize_to_image_size (pipeline->rgb_layer); gimp_image_scale (pipeline->rgb_image, pipeline->resize_width, pipeline->resize_height); webx_pipeline_create_background (pipeline); pipeline->crop_offsx *= pipeline->crop_scale_x; pipeline->crop_offsy *= pipeline->crop_scale_y; pipeline->crop_width *= pipeline->crop_scale_x; pipeline->crop_height *= pipeline->crop_scale_y; pipeline->crop_scale_x = 1.0; pipeline->crop_scale_y = 1.0; webx_pipeline_crop_clip (pipeline); if (pipeline->crop_width != pipeline->resize_width || pipeline->crop_height != pipeline->resize_height ) { gimp_image_crop (pipeline->rgb_image, pipeline->crop_width, pipeline->crop_height, pipeline->crop_offsx, pipeline->crop_offsy); } if (gimp_drawable_is_indexed (pipeline->rgb_layer)) { pipeline->indexed_image = gimp_image_duplicate (pipeline->rgb_image); gimp_image_undo_disable (pipeline->indexed_image); pipeline->indexed_layer = gimp_image_merge_visible_layers (pipeline->indexed_image, GIMP_CLIP_TO_IMAGE); } else { pipeline->indexed_image = -1; pipeline->indexed_layer = -1; } if ( ! gimp_drawable_is_rgb (pipeline->rgb_layer)) gimp_image_convert_rgb (pipeline->rgb_image); return TRUE; }
/* Compose a roll film image from several images */ static gint32 film (void) { gint width, height; guchar *hole; gint film_height, film_width; gint picture_width, picture_height; gint picture_space, picture_x0, picture_y0; gint hole_offset, hole_width, hole_height, hole_space, hole_x; gint number_height, num_images, num_pictures; gint j, k, picture_count; gdouble f; gint num_layers; gint32 *image_ID_src, image_ID_dst, layer_ID_src, layer_ID_dst; gint image_ID_tmp; gint32 *layers; GimpDrawable *drawable_dst; GimpPixelRgn pixel_rgn_dst; gint new_layer; gint floating_sel; /* initialize */ layers = NULL; num_images = filmvals.num_images; image_ID_src = filmvals.image; if (num_images <= 0) return (-1); gimp_context_push (); gimp_context_set_foreground (&filmvals.number_color); gimp_context_set_background (&filmvals.film_color); if (filmvals.keep_height) /* Search maximum picture height */ { picture_height = 0; for (j = 0; j < num_images; j++) { height = gimp_image_height (image_ID_src[j]); if (height > picture_height) picture_height = height; } film_height = (int)(picture_height / filmvals.picture_height + 0.5); filmvals.film_height = film_height; } else { film_height = filmvals.film_height; picture_height = (int)(film_height * filmvals.picture_height + 0.5); } picture_space = (int)(film_height * filmvals.picture_space + 0.5); picture_y0 = (film_height - picture_height)/2; number_height = film_height * filmvals.number_height; /* Calculate total film width */ film_width = 0; num_pictures = 0; for (j = 0; j < num_images; j++) { layers = gimp_image_get_layers (image_ID_src[j], &num_layers); /* Get scaled image size */ width = gimp_image_width (image_ID_src[j]); height = gimp_image_height (image_ID_src[j]); f = ((double)picture_height) / (double)height; picture_width = width * f; for (k = 0; k < num_layers; k++) { if (gimp_layer_is_floating_sel (layers[k])) continue; film_width += (picture_space/2); /* Leading space */ film_width += picture_width; /* Scaled image width */ film_width += (picture_space/2); /* Trailing space */ num_pictures++; } g_free (layers); } #ifdef FILM_DEBUG g_printerr ("film_height = %d, film_width = %d\n", film_height, film_width); g_printerr ("picture_height = %d, picture_space = %d, picture_y0 = %d\n", picture_height, picture_space, picture_y0); g_printerr ("Number of pictures = %d\n", num_pictures); #endif image_ID_dst = create_new_image (_("Untitled"), (guint) film_width, (guint) film_height, GIMP_RGB_IMAGE, &layer_ID_dst, &drawable_dst, &pixel_rgn_dst); /* Fill film background */ gimp_drawable_fill (layer_ID_dst, GIMP_FILL_BACKGROUND); /* Draw all the holes */ hole_offset = film_height * filmvals.hole_offset; hole_width = film_height * filmvals.hole_width; hole_height = film_height * filmvals.hole_height; hole_space = film_height * filmvals.hole_space; hole_x = hole_space / 2; #ifdef FILM_DEBUG g_printerr ("hole_x %d hole_offset %d hole_width %d hole_height %d hole_space %d\n", hole_x, hole_offset, hole_width, hole_height, hole_space ); #endif hole = create_hole_rgb (hole_width, hole_height); if (hole) { while (hole_x < film_width) { draw_hole_rgb (drawable_dst, hole_x, hole_offset, hole_width, hole_height, hole); draw_hole_rgb (drawable_dst, hole_x, film_height-hole_offset-hole_height, hole_width, hole_height, hole); hole_x += hole_width + hole_space; } g_free (hole); } gimp_drawable_detach (drawable_dst); /* Compose all images and layers */ picture_x0 = 0; picture_count = 0; for (j = 0; j < num_images; j++) { image_ID_tmp = gimp_image_duplicate (image_ID_src[j]); width = gimp_image_width (image_ID_tmp); height = gimp_image_height (image_ID_tmp); f = ((gdouble) picture_height) / (gdouble) height; picture_width = width * f; if (gimp_image_base_type (image_ID_tmp) != GIMP_RGB) gimp_image_convert_rgb (image_ID_tmp); gimp_image_scale (image_ID_tmp, picture_width, picture_height); layers = gimp_image_get_layers (image_ID_tmp, &num_layers); for (k = 0; k < num_layers; k++) { if (gimp_layer_is_floating_sel (layers[k])) continue; picture_x0 += picture_space / 2; layer_ID_src = layers[k]; gimp_layer_resize_to_image_size (layer_ID_src); new_layer = gimp_layer_new_from_drawable (layer_ID_src, image_ID_dst); gimp_image_insert_layer (image_ID_dst, new_layer, -1, -1); gimp_layer_set_offsets (new_layer, picture_x0, picture_y0); /* Draw picture numbers */ if ((number_height > 0) && (filmvals.number_pos[0] || filmvals.number_pos[1])) { if (filmvals.number_pos[0]) draw_number (layer_ID_dst, filmvals.number_start + picture_count, picture_x0 + picture_width/2, (hole_offset-number_height)/2, number_height); if (filmvals.number_pos[1]) draw_number (layer_ID_dst, filmvals.number_start + picture_count, picture_x0 + picture_width/2, film_height - (hole_offset + number_height)/2, number_height); } picture_x0 += picture_width + (picture_space/2); gimp_progress_update (((gdouble) (picture_count + 1)) / (gdouble) num_pictures); picture_count++; } g_free (layers); gimp_image_delete (image_ID_tmp); } gimp_progress_update (1.0); gimp_image_flatten (image_ID_dst); /* Drawing text/numbers leaves us with a floating selection. Stop it */ floating_sel = gimp_image_get_floating_sel (image_ID_dst); if (floating_sel != -1) gimp_floating_sel_anchor (floating_sel); gimp_context_pop (); return image_ID_dst; }
static gboolean border_dialog (gint32 image_ID, GimpDrawable *drawable) { GtkWidget *dialog; GtkWidget *main_hbox; GtkWidget *middle_vbox; GtkWidget *right_vbox; GtkWidget *label; gboolean run; gimp_ui_init (PLUG_IN_BINARY, FALSE); dialog = gimp_dialog_new ("Simple Border", PLUG_IN_ROLE, NULL, 0, gimp_standard_help_func, PLUG_IN_PROC, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OK, GTK_RESPONSE_OK, NULL); gimp_window_set_transient (GTK_WINDOW (dialog)); gtk_widget_show (dialog); main_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12); gtk_container_set_border_width (GTK_CONTAINER (main_hbox), 12); gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), main_hbox, TRUE, TRUE, 0); gtk_widget_show (main_hbox); middle_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12); gtk_container_set_border_width (GTK_CONTAINER (middle_vbox), 12); gtk_box_pack_start (GTK_BOX (main_hbox), middle_vbox, TRUE, TRUE, 0); gtk_widget_show (middle_vbox); right_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12); gtk_container_set_border_width (GTK_CONTAINER (right_vbox), 12); gtk_widget_set_size_request (right_vbox, 320, -1); gtk_box_pack_start (GTK_BOX (main_hbox), right_vbox, TRUE, TRUE, 0); gtk_widget_show (right_vbox); /* preview */ label = gtk_label_new ("Preview"); gtk_box_pack_start (GTK_BOX (middle_vbox), label, FALSE, FALSE, 0); gtk_widget_show (label); preview_image = gimp_image_duplicate(image_ID); preview = gtk_image_new(); preview_update (preview); gtk_box_pack_start (GTK_BOX (middle_vbox), preview, TRUE, TRUE, 0); gtk_widget_show (preview); /* textures */ label = gtk_label_new ("Textures"); gtk_box_pack_start (GTK_BOX (right_vbox), label, FALSE, FALSE, 0); gtk_widget_show (label); GtkWidget *notebook = gtk_notebook_new (); gtk_box_pack_start (GTK_BOX (right_vbox), notebook, FALSE, FALSE, 0); gtk_notebook_set_scrollable (GTK_NOTEBOOK (notebook), TRUE); gtk_widget_show (notebook); create_texture_page (GTK_NOTEBOOK (notebook), "Top", textures, G_N_ELEMENTS (textures)); run = (gimp_dialog_run (GIMP_DIALOG (dialog)) == GTK_RESPONSE_OK); gtk_widget_destroy (dialog); return run; }
/** * gimp_export_image: * @image_ID: Pointer to the image_ID. * @drawable_ID: Pointer to the drawable_ID. * @format_name: The (short) name of the image_format (e.g. JPEG or GIF). * @capabilities: What can the image_format do? * * Takes an image and a drawable to be saved together with a * description of the capabilities of the image_format. If the * type of image doesn't match the capabilities of the format * a dialog is opened that informs the user that the image has * to be exported and offers to do the necessary conversions. * * If the user chooses to export the image, a copy is created. * This copy is then converted, the image_ID and drawable_ID * are changed to point to the new image and the procedure returns * GIMP_EXPORT_EXPORT. The save_plugin has to take care of deleting the * created image using gimp_image_delete() when it has saved it. * * If the user chooses to Ignore the export problem, the image_ID * and drawable_ID is not altered, GIMP_EXPORT_IGNORE is returned and * the save_plugin should try to save the original image. If the * user chooses Cancel, GIMP_EXPORT_CANCEL is returned and the * save_plugin should quit itself with status %GIMP_PDB_CANCEL. * * If @format_name is NULL, no dialogs will be shown and this function * will behave as if the user clicked on the 'Export' button, if a * dialog would have been shown. * * Returns: An enum of #GimpExportReturn describing the user_action. **/ GimpExportReturn gimp_export_image (gint32 *image_ID, gint32 *drawable_ID, const gchar *format_name, GimpExportCapabilities capabilities) { GSList *actions = NULL; GimpImageBaseType type; gint32 i; gint32 n_layers; gint32 *layers; gboolean interactive = FALSE; gboolean added_flatten = FALSE; gboolean has_layer_masks = FALSE; gboolean background_has_alpha = TRUE; GimpExportReturn retval = GIMP_EXPORT_CANCEL; g_return_val_if_fail (*image_ID > -1 && *drawable_ID > -1, FALSE); /* do some sanity checks */ if (capabilities & GIMP_EXPORT_NEEDS_ALPHA) capabilities |= GIMP_EXPORT_CAN_HANDLE_ALPHA; if (capabilities & GIMP_EXPORT_CAN_HANDLE_LAYERS_AS_ANIMATION) capabilities |= GIMP_EXPORT_CAN_HANDLE_LAYERS; if (capabilities & GIMP_EXPORT_CAN_HANDLE_LAYER_MASKS) capabilities |= GIMP_EXPORT_CAN_HANDLE_LAYERS; if (capabilities & GIMP_EXPORT_CAN_HANDLE_LAYERS) capabilities |= GIMP_EXPORT_CAN_HANDLE_ALPHA; if (format_name && g_getenv ("GIMP_INTERACTIVE_EXPORT")) interactive = TRUE; /* ask for confirmation if the user is not saving a layer (see bug #51114) */ if (interactive && ! gimp_item_is_layer (*drawable_ID) && ! (capabilities & GIMP_EXPORT_CAN_HANDLE_LAYERS)) { if (gimp_item_is_layer_mask (*drawable_ID)) { retval = confirm_save_dialog (_("You are about to save a layer mask as %s.\n" "This will not save the visible layers."), format_name); } else if (gimp_item_is_channel (*drawable_ID)) { retval = confirm_save_dialog (_("You are about to save a channel (saved selection) as %s.\n" "This will not save the visible layers."), format_name); } else { /* this should not happen */ g_warning ("%s: unknown drawable type!", G_STRFUNC); } /* cancel - the user can then select an appropriate layer to save */ if (retval == GIMP_EXPORT_CANCEL) return GIMP_EXPORT_CANCEL; } /* check alpha and layer masks */ layers = gimp_image_get_layers (*image_ID, &n_layers); for (i = 0; i < n_layers; i++) { if (gimp_drawable_has_alpha (layers[i])) { if (! (capabilities & GIMP_EXPORT_CAN_HANDLE_ALPHA)) { actions = g_slist_prepend (actions, &export_action_flatten); added_flatten = TRUE; break; } } else { /* If this is the last layer, it's visible and has no alpha * channel, then the image has a "flat" background */ if (i == n_layers - 1 && gimp_item_get_visible (layers[i])) background_has_alpha = FALSE; if (capabilities & GIMP_EXPORT_NEEDS_ALPHA) { actions = g_slist_prepend (actions, &export_action_add_alpha); break; } } } if (! added_flatten) { for (i = 0; i < n_layers; i++) { if (gimp_layer_get_mask (layers[i]) != -1) has_layer_masks = TRUE; } } if (! added_flatten) { gint32 n_children; gint32 *children; children = gimp_item_get_children (layers[0], &n_children); /* check if layer size != canvas size, opacity != 100%, or offsets != 0 */ if (n_layers == 1 && ! children && gimp_item_is_layer (*drawable_ID) && ! (capabilities & GIMP_EXPORT_CAN_HANDLE_LAYERS)) { gint offset_x; gint offset_y; gimp_drawable_offsets (*drawable_ID, &offset_x, &offset_y); if ((gimp_layer_get_opacity (*drawable_ID) < 100.0) || (gimp_image_width (*image_ID) != gimp_drawable_width (*drawable_ID)) || (gimp_image_height (*image_ID) != gimp_drawable_height (*drawable_ID)) || offset_x || offset_y) { if (capabilities & GIMP_EXPORT_CAN_HANDLE_ALPHA) { actions = g_slist_prepend (actions, &export_action_merge_single); } else { actions = g_slist_prepend (actions, &export_action_flatten); } } } /* check multiple layers */ else if (n_layers > 1) { if (capabilities & GIMP_EXPORT_CAN_HANDLE_LAYERS_AS_ANIMATION) { if (background_has_alpha || capabilities & GIMP_EXPORT_NEEDS_ALPHA) actions = g_slist_prepend (actions, &export_action_animate_or_merge); else actions = g_slist_prepend (actions, &export_action_animate_or_flatten); } else if (! (capabilities & GIMP_EXPORT_CAN_HANDLE_LAYERS)) { if (capabilities & GIMP_EXPORT_NEEDS_ALPHA) actions = g_slist_prepend (actions, &export_action_merge); else actions = g_slist_prepend (actions, &export_action_merge_or_flatten); } } /* check for a single toplevel layer group */ else if (children) { if (! (capabilities & GIMP_EXPORT_CAN_HANDLE_LAYERS)) { if (capabilities & GIMP_EXPORT_NEEDS_ALPHA) actions = g_slist_prepend (actions, &export_action_merge); else actions = g_slist_prepend (actions, &export_action_merge_or_flatten); } } g_free (children); /* check layer masks */ if (has_layer_masks && ! (capabilities & GIMP_EXPORT_CAN_HANDLE_LAYER_MASKS)) actions = g_slist_prepend (actions, &export_action_apply_masks); } g_free (layers); /* check the image type */ type = gimp_image_base_type (*image_ID); switch (type) { case GIMP_RGB: if (! (capabilities & GIMP_EXPORT_CAN_HANDLE_RGB)) { if ((capabilities & GIMP_EXPORT_CAN_HANDLE_INDEXED) && (capabilities & GIMP_EXPORT_CAN_HANDLE_GRAY)) actions = g_slist_prepend (actions, &export_action_convert_indexed_or_grayscale); else if (capabilities & GIMP_EXPORT_CAN_HANDLE_INDEXED) actions = g_slist_prepend (actions, &export_action_convert_indexed); else if (capabilities & GIMP_EXPORT_CAN_HANDLE_GRAY) actions = g_slist_prepend (actions, &export_action_convert_grayscale); else if (capabilities & GIMP_EXPORT_CAN_HANDLE_BITMAP) actions = g_slist_prepend (actions, &export_action_convert_bitmap); } break; case GIMP_GRAY: if (! (capabilities & GIMP_EXPORT_CAN_HANDLE_GRAY)) { if ((capabilities & GIMP_EXPORT_CAN_HANDLE_RGB) && (capabilities & GIMP_EXPORT_CAN_HANDLE_INDEXED)) actions = g_slist_prepend (actions, &export_action_convert_rgb_or_indexed); else if (capabilities & GIMP_EXPORT_CAN_HANDLE_RGB) actions = g_slist_prepend (actions, &export_action_convert_rgb); else if (capabilities & GIMP_EXPORT_CAN_HANDLE_INDEXED) actions = g_slist_prepend (actions, &export_action_convert_indexed); else if (capabilities & GIMP_EXPORT_CAN_HANDLE_BITMAP) actions = g_slist_prepend (actions, &export_action_convert_bitmap); } break; case GIMP_INDEXED: if (! (capabilities & GIMP_EXPORT_CAN_HANDLE_INDEXED)) { if ((capabilities & GIMP_EXPORT_CAN_HANDLE_RGB) && (capabilities & GIMP_EXPORT_CAN_HANDLE_GRAY)) actions = g_slist_prepend (actions, &export_action_convert_rgb_or_grayscale); else if (capabilities & GIMP_EXPORT_CAN_HANDLE_RGB) actions = g_slist_prepend (actions, &export_action_convert_rgb); else if (capabilities & GIMP_EXPORT_CAN_HANDLE_GRAY) actions = g_slist_prepend (actions, &export_action_convert_grayscale); else if (capabilities & GIMP_EXPORT_CAN_HANDLE_BITMAP) { gint n_colors; g_free (gimp_image_get_colormap (*image_ID, &n_colors)); if (n_colors > 2) actions = g_slist_prepend (actions, &export_action_convert_bitmap); } } break; } if (actions) { actions = g_slist_reverse (actions); if (interactive) retval = export_dialog (actions, format_name); else retval = GIMP_EXPORT_EXPORT; } else { retval = GIMP_EXPORT_IGNORE; } if (retval == GIMP_EXPORT_EXPORT) { GSList *list; *image_ID = gimp_image_duplicate (*image_ID); *drawable_ID = gimp_image_get_active_layer (*image_ID); gimp_image_undo_disable (*image_ID); for (list = actions; list; list = list->next) { export_action_perform (list->data, *image_ID, drawable_ID); } } g_slist_free (actions); return retval; }
/* ------------------------------------------------------- * gap_image_set_selection_from_selection_or_drawable * ------------------------------------------------------- * create a selection in the specified image_id. * The selection is a scaled copy of the selection in another image, * referred by ref_drawable_id, or a Grayscale copy of the specified ref_drawable_id * (in case the referred image has no selection or the flag force_from_drawable is TRUE) * * - operates on a duplicate of the image referred by ref_drawable_id. * - this duplicate is scaled to same size as specified image_id * * return TRUE in case the selection was successfully created . */ gboolean gap_image_set_selection_from_selection_or_drawable(gint32 image_id, gint32 ref_drawable_id , gboolean force_from_drawable) { gint32 l_aux_channel_id; gint32 ref_image_id; gint32 work_drawable_id; /* the duplicate of the layer that is used as selction mask */ gint32 dup_image_id; gboolean has_selection; gboolean non_empty; gint x1, y1, x2, y2; if ((image_id < 0) || (ref_drawable_id < 0)) { return (FALSE); } ref_image_id = gimp_item_get_image(ref_drawable_id); if (ref_image_id < 0) { printf("ref_drawable_id does not refer to a valid image layer_id:%d\n", (int)ref_drawable_id); return (FALSE); } dup_image_id = gimp_image_duplicate(ref_image_id); if (dup_image_id < 0) { printf("duplicating of image failed, referred souce image_id:%d\n", (int)ref_image_id); return (FALSE); } /* clear undo stack */ if (gimp_image_undo_is_enabled(dup_image_id)) { gimp_image_undo_disable(dup_image_id); } if ((gimp_image_width(image_id) != gimp_image_width(dup_image_id)) || (gimp_image_height(image_id) != gimp_image_height(dup_image_id))) { if(gap_debug) { printf("scaling tmp image_id: %d\n", (int)dup_image_id); } gimp_image_scale(dup_image_id, gimp_image_width(image_id), gimp_image_height(image_id)); } has_selection = gimp_selection_bounds(ref_image_id, &non_empty, &x1, &y1, &x2, &y2); if ((has_selection) && (non_empty) && (force_from_drawable != TRUE)) { /* use scaled copy of the already exisating selection in the referred image */ work_drawable_id = gimp_image_get_selection(dup_image_id); } else { gint32 active_layer_stackposition; /* create selection as gray copy of the alt_selection layer */ active_layer_stackposition = gap_layer_get_stackposition(ref_image_id, ref_drawable_id); if(gimp_image_base_type(dup_image_id) != GIMP_GRAY) { if(gap_debug) { printf("convert to GRAYSCALE tmp image_id: %d\n", (int)dup_image_id); } gimp_image_convert_grayscale(dup_image_id); } work_drawable_id = gap_layer_get_id_by_stackposition(dup_image_id, active_layer_stackposition); gimp_layer_resize_to_image_size (work_drawable_id); } gimp_selection_all(image_id); //l_sel_channel_id = gimp_image_get_selection(image_id); l_aux_channel_id = gimp_selection_save(image_id); /* copy the work drawable (layer or channel) into the selection channel * the work layer is a grayscale copy GRAY or GRAYA of the alt_selection layer * that is already scaled and resized to fit the size of the target image * the work channel is the scaled selection of the image refred by ref_drawable_id * * copying is done into an auxiliary channel from where we regulary load the selection. * this is done because subseqent queries of the selection boudaries will deliver * full channel size rectangle after a direct copy into the selection. */ gap_layer_copy_picked_channel (l_aux_channel_id /* dst_drawable_id*/ , 0 /* dst_channel_pick */ , work_drawable_id /* src_drawable_id */ , 0 /* src_channel_pick */ , FALSE /* gboolean shadow */ ); gimp_image_select_item(image_id, GIMP_CHANNEL_OP_REPLACE, l_aux_channel_id); gimp_image_remove_channel(image_id, l_aux_channel_id); gap_image_delete_immediate(dup_image_id); return (TRUE); } /* end gap_image_set_selection_from_selection_or_drawable */
/* ---------------------------- * gap_frame_fetch_dup_image * ---------------------------- * returns merged or selected layer_id * (that is the only visible layer in temporary created scratch image) * the caller is resonsible to delete the scratch image when processing is done. * this can be done by calling gap_frame_fetch_delete_list_of_duplicated_images() */ gint32 gap_frame_fetch_dup_image(gint32 ffetch_user_id ,const char *filename /* full filename of the image (already contains framenr) */ ,gint32 stackpos /* 0 pick layer on top of stack, -1 merge visible layers */ ,gboolean addToCache /* enable caching */ ) { gint32 resulting_layer; gint32 image_id; gint32 dup_image_id; resulting_layer = -1; dup_image_id = -1; image_id = p_load_cache_image(filename, ffetch_user_id, addToCache); if (image_id < 0) { return(-1); } if (stackpos < 0) { dup_image_id = gimp_image_duplicate(image_id); gap_frame_fetch_remove_parasite(dup_image_id); resulting_layer = gap_image_merge_visible_layers(dup_image_id, GIMP_CLIP_TO_IMAGE); } else { gint l_nlayers; gint32 *l_layers_list; l_layers_list = gimp_image_get_layers(image_id, &l_nlayers); if(l_layers_list != NULL) { if (stackpos < l_nlayers) { gint32 src_layer_id; gdouble l_xresoulution, l_yresoulution; gint32 l_unit; src_layer_id = l_layers_list[stackpos]; dup_image_id = gimp_image_new (gimp_image_width(image_id) , gimp_image_height(image_id) , gimp_image_base_type(image_id) ); gimp_image_get_resolution(image_id, &l_xresoulution, &l_yresoulution); gimp_image_set_resolution(dup_image_id, l_xresoulution, l_yresoulution); l_unit = gimp_image_get_unit(image_id); gimp_image_set_unit(dup_image_id, l_unit); resulting_layer = gap_layer_copy_to_image (dup_image_id, src_layer_id); } g_free (l_layers_list); } } p_add_image_to_list_of_duplicated_images(dup_image_id, ffetch_user_id); if (addToCache != TRUE) { GimpParasite *l_parasite; l_parasite = gimp_image_parasite_find(image_id, GAP_IMAGE_CACHE_PARASITE); if(l_parasite) { gimp_parasite_free(l_parasite); } else { /* the original image is not cached * (delete it because the caller gets the preprocessed duplicate) */ gap_image_delete_immediate(image_id); } } return(resulting_layer); } /* end gap_frame_fetch_dup_image */
static gboolean webx_jpeg_target_save_image (WebxTarget *widget, WebxTargetInput *input, const gchar *file_name) { WebxJpegTarget *jpeg; GimpParam *return_vals; gint n_return_vals; gint32 image; gint32 layer; gint32 save_image; gint32 save_layer; gboolean save_res; jpeg = WEBX_JPEG_TARGET (widget); image = input->rgb_image; layer = input->rgb_layer; if (gimp_drawable_has_alpha (layer) || jpeg->strip_exif) { /* jpeg doesn't support alpha */ save_image = gimp_image_duplicate (image); gimp_image_undo_disable (image); save_layer = gimp_image_flatten (save_image); if (jpeg->strip_exif) { gimp_image_parasite_detach (save_image, "exif-data"); gimp_image_parasite_detach (save_image, "gimp-metadata"); } } else { save_image = image; save_layer = layer; } return_vals = gimp_run_procedure ("file-jpeg-save", &n_return_vals, GIMP_PDB_INT32, GIMP_RUN_NONINTERACTIVE, GIMP_PDB_IMAGE, save_image, GIMP_PDB_DRAWABLE, save_layer, GIMP_PDB_STRING, file_name, GIMP_PDB_STRING, file_name, GIMP_PDB_FLOAT, jpeg->quality, GIMP_PDB_FLOAT, jpeg->smoothing, GIMP_PDB_INT32, (gint)jpeg->optimize, GIMP_PDB_INT32, (gint)jpeg->progressive, GIMP_PDB_STRING, "", GIMP_PDB_INT32, jpeg->subsmp, GIMP_PDB_INT32, (gint)jpeg->baseline, GIMP_PDB_INT32, jpeg->restart, GIMP_PDB_INT32, jpeg->dct, GIMP_PDB_END); if (return_vals[0].data.d_int32 == GIMP_PDB_SUCCESS) save_res = TRUE; else save_res = FALSE; gimp_destroy_params (return_vals, n_return_vals); if (gimp_drawable_has_alpha (layer)) { gimp_image_delete (save_image); } return save_res; }