/* ============================================================================ * gap_image_merge_visible_layers * merge visible layer an return layer_id of the resulting merged layer. * (with workaround, for empty images return transparent layer) * ============================================================================ */ gint32 gap_image_merge_visible_layers(gint32 image_id, GimpMergeType mergemode) { GimpImageBaseType l_type; guint l_width, l_height; gint32 l_layer_id; /* get info about the image */ l_width = gimp_image_width(image_id); l_height = gimp_image_height(image_id); l_type = gimp_image_base_type(image_id); l_type = (l_type * 2); /* convert from GimpImageBaseType to GimpImageType */ /* add 2 full transparent dummy layers at top * (because gimp_image_merge_visible_layers complains * if there are less than 2 visible layers) */ l_layer_id = gimp_layer_new(image_id, "dummy", l_width, l_height, l_type, 0.0, /* Opacity full transparent */ 0); /* NORMAL */ gimp_image_insert_layer(image_id, l_layer_id, 0, 0); l_layer_id = gimp_layer_new(image_id, "dummy", 10, 10, l_type, 0.0, /* Opacity full transparent */ 0); /* NORMAL */ gimp_image_insert_layer(image_id, l_layer_id, 0, 0); return gimp_image_merge_visible_layers (image_id, mergemode); } /* end gap_image_merge_visible_layers */
/* ============================================================================ * gap_image_new_with_layer_of_samesize * ============================================================================ * create empty image * if layer_id is NOT NULL then create one full transparent layer at full image size * and return the layer_id */ gint32 gap_image_new_with_layer_of_samesize(gint32 old_image_id, gint32 *layer_id) { GimpImageBaseType l_type; guint l_width; guint l_height; gint32 new_image_id; gdouble l_xresoulution, l_yresoulution; gint32 l_unit; /* create empty image */ l_width = gimp_image_width(old_image_id); l_height = gimp_image_height(old_image_id); l_type = gimp_image_base_type(old_image_id); l_unit = gimp_image_get_unit(old_image_id); gimp_image_get_resolution(old_image_id, &l_xresoulution, &l_yresoulution); new_image_id = gimp_image_new(l_width, l_height,l_type); gimp_image_set_resolution(new_image_id, l_xresoulution, l_yresoulution); gimp_image_set_unit(new_image_id, l_unit); if(layer_id) { l_type = (l_type * 2); /* convert from GimpImageBaseType to GimpImageType */ *layer_id = gimp_layer_new(new_image_id, "dummy", l_width, l_height, l_type, 0.0, /* Opacity full transparent */ 0); /* NORMAL */ gimp_image_insert_layer(new_image_id, *layer_id, 0, 0); } return (new_image_id); } /* end gap_image_new_with_layer_of_samesize */
void gap_image_prevent_empty_image(gint32 image_id) { GimpImageBaseType l_type; guint l_width, l_height; gint32 l_layer_id; gint l_nlayers; gint32 *l_layers_list; l_layers_list = gimp_image_get_layers(image_id, &l_nlayers); if(l_layers_list != NULL) { g_free (l_layers_list); } else l_nlayers = 0; if(l_nlayers == 0) { /* the resulting image has no layer, add a transparent dummy layer */ /* get info about the image */ l_width = gimp_image_width(image_id); l_height = gimp_image_height(image_id); l_type = gimp_image_base_type(image_id); l_type = (l_type * 2); /* convert from GimpImageBaseType to GimpImageType */ /* add a transparent dummy layer */ l_layer_id = gimp_layer_new(image_id, "dummy", l_width, l_height, l_type, 0.0, /* Opacity full transparent */ 0); /* NORMAL */ gimp_image_insert_layer(image_id, l_layer_id, 0, 0); } } /* end gap_image_prevent_empty_image */
void gimp_image_set_colormap (GimpImage *image, const guchar *colormap, gint n_colors, gboolean push_undo) { g_return_if_fail (GIMP_IS_IMAGE (image)); g_return_if_fail (colormap != NULL || n_colors == 0); g_return_if_fail (n_colors >= 0 && n_colors <= 256); if (push_undo) gimp_image_undo_push_image_colormap (image, _("Set Colormap")); if (image->colormap) memset (image->colormap, 0, GIMP_IMAGE_COLORMAP_SIZE); if (colormap) { if (! image->colormap) image->colormap = g_new0 (guchar, GIMP_IMAGE_COLORMAP_SIZE); memcpy (image->colormap, colormap, n_colors * 3); } else if (! gimp_image_base_type (image) == GIMP_INDEXED) { if (image->colormap) g_free (image->colormap); image->colormap = NULL; } image->n_colors = n_colors; gimp_image_colormap_changed (image, -1); }
int p_constraint_proc_sel1(gchar *proc_name) { int l_rc; GimpImageBaseType l_base_type; /* here we should check, if proc_name * can operate on the current Imagetype (RGB, INDEXED, GRAY) * if not, 0 should be returned. * * I did not find a way to do this with the PDB Interface of gimp 0.99.16 */ return 1; l_rc = 0; /* 0 .. set Apply Button in_sensitive */ l_base_type =gimp_image_base_type(g_current_image_id); switch(l_base_type) { case GIMP_RGB: case GIMP_GRAY: case GIMP_INDEXED: l_rc = 1; break; } return l_rc; }
static void palette_import_image_changed (GimpContext *context, GimpImage *image, ImportDialog *dialog) { if (dialog->image) { g_signal_handlers_disconnect_by_func (dialog->image, palette_import_layer_changed, dialog); g_signal_handlers_disconnect_by_func (dialog->image, palette_import_mask_changed, dialog); } dialog->image = image; if (dialog->import_type == IMAGE_IMPORT) { gboolean sensitive = FALSE; if (image) { gchar *label; label = g_strdup_printf ("%s-%d", gimp_image_get_display_name (image), gimp_image_get_ID (image)); gtk_entry_set_text (GTK_ENTRY (dialog->entry), label); g_free (label); palette_import_make_palette (dialog); if (gimp_image_base_type (image) != GIMP_INDEXED) sensitive = TRUE; } gtk_widget_set_sensitive (dialog->sample_merged_toggle, sensitive); gtk_widget_set_sensitive (dialog->selection_only_toggle, sensitive); gimp_scale_entry_set_sensitive (GTK_OBJECT (dialog->threshold), sensitive); gimp_scale_entry_set_sensitive (GTK_OBJECT (dialog->num_colors), sensitive); } if (dialog->image) { g_signal_connect (dialog->image, "active-layer-changed", G_CALLBACK (palette_import_layer_changed), dialog); g_signal_connect (dialog->image, "mask-changed", G_CALLBACK (palette_import_mask_changed), dialog); } }
static void export_convert_bitmap (gint32 image_ID, gint32 *drawable_ID) { if (gimp_image_base_type (image_ID) == GIMP_INDEXED) gimp_image_convert_rgb (image_ID); gimp_image_convert_indexed (image_ID, GIMP_FS_DITHER, GIMP_MAKE_PALETTE, 2, FALSE, 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); }
gboolean gimp_pdb_image_is_base_type (GimpImage *image, GimpImageBaseType type, GError **error) { g_return_val_if_fail (GIMP_IS_IMAGE (image), FALSE); g_return_val_if_fail (error == NULL || *error == NULL, FALSE); if (gimp_image_base_type (image) == type) return TRUE; g_set_error (error, GIMP_PDB_ERROR, GIMP_PDB_INVALID_ARGUMENT, _("Image '%s' (%d) is of type '%s', " "but an image of type '%s' is expected"), gimp_image_get_display_name (image), gimp_image_get_ID (image), gimp_pdb_enum_value_get_nick (GIMP_TYPE_IMAGE_BASE_TYPE, gimp_image_base_type (image)), gimp_pdb_enum_value_get_nick (GIMP_TYPE_IMAGE_BASE_TYPE, type)); return FALSE; }
static void gimp_image_undo_constructed (GObject *object) { GimpImageUndo *image_undo = GIMP_IMAGE_UNDO (object); GimpImage *image; if (G_OBJECT_CLASS (parent_class)->constructed) G_OBJECT_CLASS (parent_class)->constructed (object); image = GIMP_UNDO (object)->image; switch (GIMP_UNDO (object)->undo_type) { case GIMP_UNDO_IMAGE_TYPE: image_undo->base_type = gimp_image_base_type (image); break; case GIMP_UNDO_IMAGE_SIZE: image_undo->width = gimp_image_get_width (image); image_undo->height = gimp_image_get_height (image); break; case GIMP_UNDO_IMAGE_RESOLUTION: gimp_image_get_resolution (image, &image_undo->xresolution, &image_undo->yresolution); image_undo->resolution_unit = gimp_image_get_unit (image); break; case GIMP_UNDO_IMAGE_GRID: g_assert (GIMP_IS_GRID (image_undo->grid)); break; case GIMP_UNDO_IMAGE_COLORMAP: image_undo->num_colors = gimp_image_get_colormap_size (image); image_undo->colormap = g_memdup (gimp_image_get_colormap (image), GIMP_IMAGE_COLORMAP_SIZE); break; case GIMP_UNDO_PARASITE_ATTACH: case GIMP_UNDO_PARASITE_REMOVE: g_assert (image_undo->parasite_name != NULL); image_undo->parasite = gimp_parasite_copy (gimp_image_parasite_find (image, image_undo->parasite_name)); break; default: g_assert_not_reached (); } }
static void file_open_profile_apply_rgb (GimpImage *image, GimpContext *context, GimpProgress *progress, GimpRunMode run_mode) { GimpColorConfig *config = image->gimp->config->color_management; GError *error = NULL; if (gimp_image_base_type (image) == GIMP_GRAY) return; if (config->mode == GIMP_COLOR_MANAGEMENT_OFF) return; if (! plug_in_icc_profile_apply_rgb (image, context, progress, run_mode, &error)) { if (error->domain == GIMP_PLUG_IN_ERROR && error->code == GIMP_PLUG_IN_NOT_FOUND) { gchar *msg = g_strdup_printf ("%s\n\n%s", error->message, _("Color management has been disabled. " "It can be enabled again in the " "Preferences dialog.")); g_object_set (config, "mode", GIMP_COLOR_MANAGEMENT_OFF, NULL); gimp_message_literal (image->gimp, G_OBJECT (progress), GIMP_MESSAGE_WARNING, msg); g_free (msg); } else { gimp_message_literal (image->gimp, G_OBJECT (progress), GIMP_MESSAGE_ERROR, error->message); } g_error_free (error); } }
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); }
void layers_actions_update (GimpActionGroup *group, gpointer data) { GimpImage *image = action_data_get_image (data); GimpLayer *layer = NULL; GimpLayerMask *mask = NULL; /* layer mask */ gboolean fs = FALSE; /* floating sel */ gboolean ac = FALSE; /* active channel */ gboolean sel = FALSE; gboolean alpha = FALSE; /* alpha channel present */ gboolean indexed = FALSE; /* is indexed */ gboolean lock_alpha = FALSE; gboolean text_layer = FALSE; GList *next = NULL; GList *prev = NULL; if (image) { fs = (gimp_image_floating_sel (image) != NULL); ac = (gimp_image_get_active_channel (image) != NULL); sel = ! gimp_channel_is_empty (gimp_image_get_mask (image)); indexed = (gimp_image_base_type (image) == GIMP_INDEXED); layer = gimp_image_get_active_layer (image); if (layer) { GList *list; mask = gimp_layer_get_mask (layer); lock_alpha = gimp_layer_get_lock_alpha (layer); alpha = gimp_drawable_has_alpha (GIMP_DRAWABLE (layer)); list = g_list_find (GIMP_LIST (image->layers)->list, layer); if (list) { prev = g_list_previous (list); next = g_list_next (list); } if (layer) text_layer = gimp_drawable_is_text_layer (GIMP_DRAWABLE (layer)); } } #define SET_VISIBLE(action,condition) \ gimp_action_group_set_action_visible (group, action, (condition) != 0) #define SET_SENSITIVE(action,condition) \ gimp_action_group_set_action_sensitive (group, action, (condition) != 0) #define SET_ACTIVE(action,condition) \ gimp_action_group_set_action_active (group, action, (condition) != 0) SET_VISIBLE ("layers-text-tool", text_layer && !ac); SET_SENSITIVE ("layers-edit-attributes", layer && !fs && !ac); SET_SENSITIVE ("layers-new", image); SET_SENSITIVE ("layers-new-last-values", image); SET_SENSITIVE ("layers-duplicate", layer && !fs && !ac); SET_SENSITIVE ("layers-delete", layer && !ac); SET_SENSITIVE ("layers-select-top", layer && !fs && !ac && prev); SET_SENSITIVE ("layers-select-bottom", layer && !fs && !ac && next); SET_SENSITIVE ("layers-select-previous", layer && !fs && !ac && prev); SET_SENSITIVE ("layers-select-next", layer && !fs && !ac && next); SET_SENSITIVE ("layers-raise", layer && !fs && !ac && prev); SET_SENSITIVE ("layers-raise-to-top", layer && !fs && !ac && prev); SET_SENSITIVE ("layers-lower", layer && !fs && !ac && next); SET_SENSITIVE ("layers-lower-to-bottom", layer && !fs && !ac && next); SET_SENSITIVE ("layers-anchor", layer && fs && !ac); SET_SENSITIVE ("layers-merge-down", layer && !fs && !ac && next); SET_SENSITIVE ("layers-merge-layers", layer && !fs && !ac); SET_SENSITIVE ("layers-flatten-image", layer && !fs && !ac); SET_VISIBLE ("layers-text-discard", text_layer && !ac); SET_VISIBLE ("layers-text-to-vectors", text_layer && !ac); SET_VISIBLE ("layers-text-along-vectors", text_layer && !ac); SET_VISIBLE ("layers-text-selection-replace", text_layer && !ac); SET_VISIBLE ("layers-text-selection-add", text_layer && !ac); SET_VISIBLE ("layers-text-selection-subtract", text_layer && !ac); SET_VISIBLE ("layers-text-selection-intersect", text_layer && !ac); SET_SENSITIVE ("layers-resize", layer && !ac); SET_SENSITIVE ("layers-resize-to-image", layer && !ac); SET_SENSITIVE ("layers-scale", layer && !ac); SET_SENSITIVE ("layers-crop", layer && sel); SET_SENSITIVE ("layers-alpha-add", layer && !fs && !alpha); SET_SENSITIVE ("layers-alpha-remove", layer && !fs && alpha); SET_SENSITIVE ("layers-lock-alpha", layer); SET_ACTIVE ("layers-lock-alpha", lock_alpha); SET_SENSITIVE ("layers-mask-add", layer && !fs && !ac && !mask); SET_SENSITIVE ("layers-mask-apply", layer && !fs && !ac && mask); SET_SENSITIVE ("layers-mask-delete", layer && !fs && !ac && mask); SET_SENSITIVE ("layers-mask-edit", layer && !fs && !ac && mask); SET_SENSITIVE ("layers-mask-show", layer && !fs && !ac && mask); SET_SENSITIVE ("layers-mask-disable", layer && !fs && !ac && mask); SET_ACTIVE ("layers-mask-edit", mask && gimp_layer_mask_get_edit (mask)); SET_ACTIVE ("layers-mask-show", mask && gimp_layer_mask_get_show (mask)); SET_ACTIVE ("layers-mask-disable", mask && !gimp_layer_mask_get_apply (mask)); SET_SENSITIVE ("layers-mask-selection-replace", layer && !fs && !ac && mask); SET_SENSITIVE ("layers-mask-selection-add", layer && !fs && !ac && mask); SET_SENSITIVE ("layers-mask-selection-subtract", layer && !fs && !ac && mask); SET_SENSITIVE ("layers-mask-selection-intersect", layer && !fs && !ac && mask); SET_SENSITIVE ("layers-alpha-selection-replace", layer && !fs && !ac); SET_SENSITIVE ("layers-alpha-selection-add", layer && !fs && !ac); SET_SENSITIVE ("layers-alpha-selection-subtract", layer && !fs && !ac); SET_SENSITIVE ("layers-alpha-selection-intersect", layer && !fs && !ac); #undef SET_VISIBLE #undef SET_SENSITIVE #undef SET_ACTIVE }
/** * gimp_layer_new_from_pixbuf: * @image_ID: The RGB image to which to add the layer. * @name: The layer name. * @pixbuf: A GdkPixbuf. * @opacity: The layer opacity. * @mode: The layer combination mode. * @progress_start: start of progress * @progress_end: end of progress * * Create a new layer from a %GdkPixbuf. * * This procedure creates a new layer from the given %GdkPixbuf. The * image has to be an RGB image and just like with gimp_layer_new() * you will still need to add the layer to it. * * If you pass @progress_end > @progress_start to this function, * @gimp_progress_update() will be called for. You have to call * @gimp_progress_init() beforehand. * * Returns: The newly created layer. * * Since: GIMP 2.4 */ gint32 gimp_layer_new_from_pixbuf (gint32 image_ID, const gchar *name, GdkPixbuf *pixbuf, gdouble opacity, GimpLayerModeEffects mode, gdouble progress_start, gdouble progress_end) { GimpDrawable *drawable; GimpPixelRgn rgn; const guchar *pixels; gpointer pr; gint32 layer; gint width; gint height; gint rowstride; gint bpp; gdouble range = progress_end - progress_start; guint count = 0; guint done = 0; g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), -1); if (gimp_image_base_type (image_ID) != GIMP_RGB) { g_warning ("gimp_layer_new_from_pixbuf() needs an RGB image"); return -1; } if (gdk_pixbuf_get_colorspace (pixbuf) != GDK_COLORSPACE_RGB) { g_warning ("gimp_layer_new_from_pixbuf() assumes that GdkPixbuf is RGB"); return -1; } width = gdk_pixbuf_get_width (pixbuf); height = gdk_pixbuf_get_height (pixbuf); bpp = gdk_pixbuf_get_n_channels (pixbuf); layer = gimp_layer_new (image_ID, name, width, height, bpp == 3 ? GIMP_RGB_IMAGE : GIMP_RGBA_IMAGE, opacity, mode); if (layer == -1) return -1; drawable = gimp_drawable_get (layer); gimp_pixel_rgn_init (&rgn, drawable, 0, 0, width, height, TRUE, FALSE); g_assert (bpp == rgn.bpp); rowstride = gdk_pixbuf_get_rowstride (pixbuf); pixels = gdk_pixbuf_get_pixels (pixbuf); for (pr = gimp_pixel_rgns_register (1, &rgn); pr != NULL; pr = gimp_pixel_rgns_process (pr)) { const guchar *src = pixels + rgn.y * rowstride + rgn.x * bpp; guchar *dest = rgn.data; gint y; for (y = 0; y < rgn.h; y++) { memcpy (dest, src, rgn.w * rgn.bpp); src += rowstride; dest += rgn.rowstride; } if (range > 0.0) { done += rgn.h * rgn.w; if (count++ % 32 == 0) gimp_progress_update (progress_start + (gdouble) done / (width * height) * range); } } if (range > 0.0) gimp_progress_update (progress_end); gimp_drawable_detach (drawable); return layer; }
GimpPDBStatusType SaveICNS (const gchar *file_name, gint32 image_ID) { // Horrible awful temporary hack ResourceHeader icnsHeader; ResourceHeader it32Header; ResourceHeader t8mkHeader; guchar *compData, *alphaData; FILE *outfile; guchar *pixels; gint dataSize; if (gimp_image_base_type (image_ID) != GIMP_RGB) { if (! gimp_image_convert_rgb (image_ID)) return GIMP_PDB_EXECUTION_ERROR; } gint *layers; gint nlayers; GimpPixelRgn region; layers = gimp_image_get_layers (image_ID, &nlayers); GimpDrawable *drawable = gimp_drawable_get (layers[0]); pixels = g_new (guchar, 128*128*4); gimp_pixel_rgn_init (®ion, drawable, 0, 0, 128, 128, TRUE, FALSE); gimp_pixel_rgn_get_rect (®ion, pixels, 0, 0, 128, 128); compData = icns_compress (128, 128, pixels, &dataSize); alphaData = icns_get_alpha (128, 128, pixels); it32Header.type = GUINT32_TO_BE ('it32'); it32Header.size = GUINT32_TO_BE (sizeof (ResourceHeader) + dataSize); t8mkHeader.type = GUINT32_TO_BE ('t8mk'); t8mkHeader.size = GUINT32_TO_BE (sizeof (ResourceHeader) + 128*128); icnsHeader.type = GUINT32_TO_BE ('icns'); icnsHeader.size = dataSize + 128*128 + 3 * sizeof (ResourceHeader); outfile = fopen (file_name, "wb"); if (outfile) { fwrite (&icnsHeader, 1, sizeof (ResourceHeader), outfile); fwrite (&it32Header, 1, sizeof (ResourceHeader), outfile); fwrite (compData, 1, dataSize, outfile); fwrite (&t8mkHeader, 1, sizeof (ResourceHeader), outfile); fwrite (alphaData, 1, 128*128, outfile); fclose (outfile); } else { g_warning ("SaveICNS: couldn't open output file"); } g_free (pixels); g_free (compData); g_free (alphaData); return GIMP_PDB_SUCCESS; }
static gboolean lcms_image_apply_profile (gint32 image, cmsHPROFILE src_profile, cmsHPROFILE dest_profile, const gchar *filename, GimpColorRenderingIntent intent, gboolean bpc) { gint32 saved_selection = -1; gimp_image_undo_group_start (image); if (! lcms_image_set_profile (image, dest_profile, filename, FALSE)) { gimp_image_undo_group_end (image); return FALSE; } { gchar *src = lcms_icc_profile_get_desc (src_profile); gchar *dest = lcms_icc_profile_get_desc (dest_profile); /* ICC color profile conversion */ gimp_progress_init_printf (_("Converting from '%s' to '%s'"), src, dest); g_printerr ("lcms: converting from '%s' to '%s'\n", src, dest); g_free (dest); g_free (src); } if (! gimp_selection_is_empty (image)) { saved_selection = gimp_selection_save (image); gimp_selection_none (image); } switch (gimp_image_base_type (image)) { case GIMP_RGB: lcms_image_transform_rgb (image, src_profile, dest_profile, intent, bpc); break; case GIMP_GRAY: g_warning ("colorspace conversion not implemented for " "grayscale images"); break; case GIMP_INDEXED: lcms_image_transform_indexed (image, src_profile, dest_profile, intent, bpc); break; } if (saved_selection != -1) { gimp_image_select_item (image, GIMP_CHANNEL_OP_REPLACE, saved_selection); gimp_image_remove_channel (image, saved_selection); } gimp_progress_update (1.0); gimp_image_undo_group_end (image); return TRUE; }
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 gboolean dialog_image_constraint_func (gint32 image_id, gpointer data) { return (gimp_image_base_type (image_id) == GIMP_RGB); }
static void gimp_component_editor_create_components (GimpComponentEditor *editor) { GimpImage *image = GIMP_IMAGE_EDITOR (editor)->image; gint n_components = 0; GimpChannelType components[MAX_CHANNELS]; GEnumClass *enum_class; gint i; switch (gimp_image_base_type (image)) { case GIMP_RGB: n_components = 3; components[0] = GIMP_RED_CHANNEL; components[1] = GIMP_GREEN_CHANNEL; components[2] = GIMP_BLUE_CHANNEL; break; case GIMP_GRAY: n_components = 1; components[0] = GIMP_GRAY_CHANNEL; break; case GIMP_INDEXED: n_components = 1; components[0] = GIMP_INDEXED_CHANNEL; break; } if (gimp_image_has_alpha (image)) components[n_components++] = GIMP_ALPHA_CHANNEL; enum_class = g_type_class_ref (GIMP_TYPE_CHANNEL_TYPE); for (i = 0; i < n_components; i++) { GimpViewRenderer *renderer; GtkTreeIter iter; GEnumValue *enum_value; const gchar *desc; gboolean visible; visible = gimp_image_get_component_visible (image, components[i]); renderer = gimp_view_renderer_new (GIMP_IMAGE_EDITOR (editor)->context, G_TYPE_FROM_INSTANCE (image), editor->view_size, 1, FALSE); gimp_view_renderer_set_viewable (renderer, GIMP_VIEWABLE (image)); gimp_view_renderer_remove_idle (renderer); GIMP_VIEW_RENDERER_IMAGE (renderer)->channel = components[i]; g_signal_connect (renderer, "update", G_CALLBACK (gimp_component_editor_renderer_update), editor); enum_value = g_enum_get_value (enum_class, components[i]); desc = gimp_enum_value_get_desc (enum_class, enum_value); gtk_list_store_append (GTK_LIST_STORE (editor->model), &iter); gtk_list_store_set (GTK_LIST_STORE (editor->model), &iter, COLUMN_CHANNEL, components[i], COLUMN_VISIBLE, visible, COLUMN_RENDERER, renderer, COLUMN_NAME, desc, -1); g_object_unref (renderer); if (gimp_image_get_component_active (image, components[i])) gtk_tree_selection_select_iter (editor->selection, &iter); } g_type_class_unref (enum_class); }
static void gimp_image_undo_pop (GimpUndo *undo, GimpUndoMode undo_mode, GimpUndoAccumulator *accum) { GimpImageUndo *image_undo = GIMP_IMAGE_UNDO (undo); GimpImage *image = undo->image; GimpImagePrivate *private = GIMP_IMAGE_GET_PRIVATE (image); GIMP_UNDO_CLASS (parent_class)->pop (undo, undo_mode, accum); switch (undo->undo_type) { case GIMP_UNDO_IMAGE_TYPE: { GimpImageBaseType base_type; base_type = image_undo->base_type; image_undo->base_type = gimp_image_base_type (image); g_object_set (image, "base-type", base_type, NULL); gimp_image_colormap_changed (image, -1); if (image_undo->base_type != gimp_image_base_type (image)) accum->mode_changed = TRUE; } break; case GIMP_UNDO_IMAGE_SIZE: { gint width; gint height; gint previous_origin_x; gint previous_origin_y; gint previous_width; gint previous_height; width = image_undo->width; height = image_undo->height; previous_origin_x = image_undo->previous_origin_x; previous_origin_y = image_undo->previous_origin_y; previous_width = image_undo->previous_width; previous_height = image_undo->previous_height; /* Transform to a redo */ image_undo->width = gimp_image_get_width (image); image_undo->height = gimp_image_get_height (image); image_undo->previous_origin_x = -previous_origin_x; image_undo->previous_origin_y = -previous_origin_y; image_undo->previous_width = width; image_undo->previous_height = height; g_object_set (image, "width", width, "height", height, NULL); gimp_drawable_invalidate_boundary (GIMP_DRAWABLE (gimp_image_get_mask (image))); if (gimp_image_get_width (image) != image_undo->width || gimp_image_get_height (image) != image_undo->height) { accum->size_changed = TRUE; accum->previous_origin_x = previous_origin_x; accum->previous_origin_y = previous_origin_y; accum->previous_width = previous_width; accum->previous_height = previous_height; } } break; case GIMP_UNDO_IMAGE_RESOLUTION: { gdouble xres; gdouble yres; gimp_image_get_resolution (image, &xres, &yres); if (ABS (image_undo->xresolution - xres) >= 1e-5 || ABS (image_undo->yresolution - yres) >= 1e-5) { private->xresolution = image_undo->xresolution; private->yresolution = image_undo->yresolution; image_undo->xresolution = xres; image_undo->yresolution = yres; accum->resolution_changed = TRUE; } }
void layers_actions_update (GimpActionGroup *group, gpointer data) { GimpImage *image = action_data_get_image (data); GimpLayer *layer = NULL; GimpLayerMask *mask = NULL; /* layer mask */ gboolean fs = FALSE; /* floating sel */ gboolean ac = FALSE; /* active channel */ gboolean sel = FALSE; gboolean alpha = FALSE; /* alpha channel present */ gboolean indexed = FALSE; /* is indexed */ gboolean lock_alpha = FALSE; gboolean can_lock_alpha = FALSE; gboolean text_layer = FALSE; gboolean writable = FALSE; gboolean children = FALSE; GList *next = NULL; GList *next_visible = NULL; GList *prev = NULL; if (image) { fs = (gimp_image_get_floating_selection (image) != NULL); ac = (gimp_image_get_active_channel (image) != NULL); sel = ! gimp_channel_is_empty (gimp_image_get_mask (image)); indexed = (gimp_image_base_type (image) == GIMP_INDEXED); layer = gimp_image_get_active_layer (image); if (layer) { GList *layer_list; GList *list; mask = gimp_layer_get_mask (layer); lock_alpha = gimp_layer_get_lock_alpha (layer); can_lock_alpha = gimp_layer_can_lock_alpha (layer); alpha = gimp_drawable_has_alpha (GIMP_DRAWABLE (layer)); writable = ! gimp_item_is_content_locked (GIMP_ITEM (layer)); if (gimp_viewable_get_children (GIMP_VIEWABLE (layer))) children = TRUE; layer_list = gimp_item_get_container_iter (GIMP_ITEM (layer)); list = g_list_find (layer_list, layer); if (list) { prev = g_list_previous (list); next = g_list_next (list); for (next_visible = next; next_visible; next_visible = g_list_next (next_visible)) { if (gimp_item_get_visible (next_visible->data)) { /* "next_visible" is actually "next_visible" and * "writable" and "not group" */ if (gimp_item_is_content_locked (next_visible->data) || gimp_viewable_get_children (next_visible->data)) next_visible = NULL; break; } } } text_layer = gimp_item_is_text_layer (GIMP_ITEM (layer)); } } #define SET_VISIBLE(action,condition) \ gimp_action_group_set_action_visible (group, action, (condition) != 0) #define SET_SENSITIVE(action,condition) \ gimp_action_group_set_action_sensitive (group, action, (condition) != 0) #define SET_ACTIVE(action,condition) \ gimp_action_group_set_action_active (group, action, (condition) != 0) #define SET_LABEL(action,label) \ gimp_action_group_set_action_label (group, action, label) SET_VISIBLE ("layers-text-tool", text_layer && !ac); SET_SENSITIVE ("layers-edit-attributes", layer && !fs && !ac); if (layer && gimp_layer_is_floating_sel (layer)) { SET_LABEL ("layers-new", C_("layers-action", "To _New Layer")); SET_LABEL ("layers-new-last-values", C_("layers-action", "To _New Layer")); } else { SET_LABEL ("layers-new", C_("layers-action", "_New Layer...")); SET_LABEL ("layers-new-last-values", C_("layers-action", "_New Layer")); } SET_SENSITIVE ("layers-new", image); SET_SENSITIVE ("layers-new-last-values", image); SET_SENSITIVE ("layers-new-from-visible", image); SET_SENSITIVE ("layers-new-group", image && !indexed); SET_SENSITIVE ("layers-duplicate", layer && !fs && !ac); SET_SENSITIVE ("layers-delete", layer && !ac); SET_SENSITIVE ("layers-select-top", layer && !fs && !ac && prev); SET_SENSITIVE ("layers-select-bottom", layer && !fs && !ac && next); SET_SENSITIVE ("layers-select-previous", layer && !fs && !ac && prev); SET_SENSITIVE ("layers-select-next", layer && !fs && !ac && next); SET_SENSITIVE ("layers-raise", layer && !fs && !ac && prev); SET_SENSITIVE ("layers-raise-to-top", layer && !fs && !ac && prev); SET_SENSITIVE ("layers-lower", layer && !fs && !ac && next); SET_SENSITIVE ("layers-lower-to-bottom", layer && !fs && !ac && next); SET_SENSITIVE ("layers-anchor", layer && fs && !ac); SET_SENSITIVE ("layers-merge-down", layer && !fs && !ac && next_visible); SET_VISIBLE ("layers-merge-group", children); SET_SENSITIVE ("layers-merge-group", layer && !fs && !ac && children); SET_SENSITIVE ("layers-merge-layers", layer && !fs && !ac); SET_SENSITIVE ("layers-flatten-image", layer && !fs && !ac); SET_VISIBLE ("layers-text-discard", text_layer && !ac); SET_VISIBLE ("layers-text-to-vectors", text_layer && !ac); SET_VISIBLE ("layers-text-along-vectors", text_layer && !ac); SET_SENSITIVE ("layers-resize", writable && !ac); SET_SENSITIVE ("layers-resize-to-image", writable && !ac); SET_SENSITIVE ("layers-scale", writable && !ac); SET_SENSITIVE ("layers-crop", writable && sel); SET_SENSITIVE ("layers-alpha-add", writable && !children && !fs && !alpha); SET_SENSITIVE ("layers-alpha-remove", writable && !children && !fs && alpha); SET_SENSITIVE ("layers-lock-alpha", can_lock_alpha); SET_ACTIVE ("layers-lock-alpha", lock_alpha); SET_SENSITIVE ("layers-mask-add", layer && !fs && !ac && !mask && !children); SET_SENSITIVE ("layers-mask-apply", writable && !fs && !ac && mask && !children); SET_SENSITIVE ("layers-mask-delete", layer && !fs && !ac && mask); SET_SENSITIVE ("layers-mask-edit", layer && !fs && !ac && mask); SET_SENSITIVE ("layers-mask-show", layer && !fs && !ac && mask); SET_SENSITIVE ("layers-mask-disable", layer && !fs && !ac && mask); SET_ACTIVE ("layers-mask-edit", mask && gimp_layer_mask_get_edit (mask)); SET_ACTIVE ("layers-mask-show", mask && gimp_layer_mask_get_show (mask)); SET_ACTIVE ("layers-mask-disable", mask && !gimp_layer_mask_get_apply (mask)); SET_SENSITIVE ("layers-mask-selection-replace", layer && !fs && !ac && mask); SET_SENSITIVE ("layers-mask-selection-add", layer && !fs && !ac && mask); SET_SENSITIVE ("layers-mask-selection-subtract", layer && !fs && !ac && mask); SET_SENSITIVE ("layers-mask-selection-intersect", layer && !fs && !ac && mask); SET_SENSITIVE ("layers-alpha-selection-replace", layer && !fs && !ac); SET_SENSITIVE ("layers-alpha-selection-add", layer && !fs && !ac); SET_SENSITIVE ("layers-alpha-selection-subtract", layer && !fs && !ac); SET_SENSITIVE ("layers-alpha-selection-intersect", layer && !fs && !ac); #undef SET_VISIBLE #undef SET_SENSITIVE #undef SET_ACTIVE #undef SET_LABEL }
/** * 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; }
void image_actions_update (GimpActionGroup *group, gpointer data) { GimpImage *image = action_data_get_image (data); gboolean fs = FALSE; gboolean aux = FALSE; gboolean lp = FALSE; gboolean sel = FALSE; if (image) { const gchar *action = NULL; switch (gimp_image_base_type (image)) { case GIMP_RGB: action = "image-convert-rgb"; break; case GIMP_GRAY: action = "image-convert-grayscale"; break; case GIMP_INDEXED: action = "image-convert-indexed"; break; } gimp_action_group_set_action_active (group, action, TRUE); fs = (gimp_image_floating_sel (image) != NULL); aux = (gimp_image_get_active_channel (image) != NULL); lp = ! gimp_image_is_empty (image); sel = ! gimp_channel_is_empty (gimp_image_get_mask (image)); } #define SET_SENSITIVE(action,condition) \ gimp_action_group_set_action_sensitive (group, action, (condition) != 0) SET_SENSITIVE ("image-convert-rgb", image); SET_SENSITIVE ("image-convert-grayscale", image); SET_SENSITIVE ("image-convert-indexed", image); SET_SENSITIVE ("image-flip-horizontal", image); SET_SENSITIVE ("image-flip-vertical", image); SET_SENSITIVE ("image-rotate-90", image); SET_SENSITIVE ("image-rotate-180", image); SET_SENSITIVE ("image-rotate-270", image); SET_SENSITIVE ("image-resize", image); SET_SENSITIVE ("image-resize-to-layers", image); SET_SENSITIVE ("image-resize-to-selection", image && sel); SET_SENSITIVE ("image-print-size", image); SET_SENSITIVE ("image-scale", image); SET_SENSITIVE ("image-crop", image && sel); SET_SENSITIVE ("image-duplicate", image); SET_SENSITIVE ("image-merge-layers", image && !fs && !aux && lp); SET_SENSITIVE ("image-flatten", image && !fs && !aux && lp); SET_SENSITIVE ("image-configure-grid", image); SET_SENSITIVE ("image-properties", image); #undef SET_SENSITIVE }
static void ico_dialog_update_icon_preview (GtkWidget *dialog, gint32 layer, gint bpp) { GtkWidget *preview = ico_dialog_get_layer_preview (dialog, layer); GdkPixbuf *pixbuf; gint w = gimp_drawable_width (layer); gint h = gimp_drawable_height (layer); if (! preview) return; if (bpp <= 8) { GimpDrawable *drawable; GimpDrawable *tmp; GimpPixelRgn src_pixel_rgn, dst_pixel_rgn; gint32 image; gint32 tmp_image; gint32 tmp_layer; guchar *buffer; guchar *cmap; gint num_colors; image = gimp_item_get_image (layer); tmp_image = gimp_image_new (w, h, gimp_image_base_type (image)); gimp_image_undo_disable (tmp_image); if (gimp_drawable_is_indexed (layer)) { cmap = gimp_image_get_colormap (image, &num_colors); gimp_image_set_colormap (tmp_image, cmap, num_colors); g_free (cmap); } tmp_layer = gimp_layer_new (tmp_image, "temporary", w, h, gimp_drawable_type (layer), 100, GIMP_NORMAL_MODE); gimp_image_insert_layer (tmp_image, tmp_layer, -1, 0); drawable = gimp_drawable_get (layer); tmp = gimp_drawable_get (tmp_layer); gimp_pixel_rgn_init (&src_pixel_rgn, drawable, 0, 0, w, h, FALSE, FALSE); gimp_pixel_rgn_init (&dst_pixel_rgn, tmp, 0, 0, w, h, TRUE, FALSE); buffer = g_malloc (w * h * 4); gimp_pixel_rgn_get_rect (&src_pixel_rgn, buffer, 0, 0, w, h); gimp_pixel_rgn_set_rect (&dst_pixel_rgn, buffer, 0, 0, w, h); gimp_drawable_detach (tmp); gimp_drawable_detach (drawable); if (gimp_drawable_is_indexed (layer)) gimp_image_convert_rgb (tmp_image); gimp_image_convert_indexed (tmp_image, GIMP_FS_DITHER, GIMP_MAKE_PALETTE, 1 <<bpp, TRUE, FALSE, "dummy"); cmap = gimp_image_get_colormap (tmp_image, &num_colors); if ( num_colors == (1 << bpp) && !ico_cmap_contains_black (cmap, num_colors)) { /* Windows icons with color maps need the color black. * We need to eliminate one more color to make room for black. */ if (gimp_drawable_is_indexed (layer)) { g_free (cmap); cmap = gimp_image_get_colormap (image, &num_colors); gimp_image_set_colormap (tmp_image, cmap, num_colors); } else if (gimp_drawable_is_gray (layer)) { gimp_image_convert_grayscale (tmp_image); } else { gimp_image_convert_rgb (tmp_image); } tmp = gimp_drawable_get (tmp_layer); gimp_pixel_rgn_init (&dst_pixel_rgn, tmp, 0, 0, w, h, TRUE, FALSE); gimp_pixel_rgn_set_rect (&dst_pixel_rgn, buffer, 0, 0, w, h); gimp_drawable_detach (tmp); if (!gimp_drawable_is_rgb (layer)) gimp_image_convert_rgb (tmp_image); gimp_image_convert_indexed (tmp_image, GIMP_FS_DITHER, GIMP_MAKE_PALETTE, (1<<bpp) - 1, TRUE, FALSE, "dummy"); } g_free (cmap); g_free (buffer); pixbuf = gimp_drawable_get_thumbnail (tmp_layer, MIN (w, 128), MIN (h, 128), GIMP_PIXBUF_SMALL_CHECKS); gimp_image_delete (tmp_image); } else if (bpp == 24) { GimpDrawable *drawable; GimpDrawable *tmp; GimpPixelRgn src_pixel_rgn, dst_pixel_rgn; gint32 image; gint32 tmp_image; gint32 tmp_layer; guchar *buffer; GimpParam *return_vals; gint n_return_vals; image = gimp_item_get_image (layer); tmp_image = gimp_image_new (w, h, gimp_image_base_type (image)); gimp_image_undo_disable (tmp_image); if (gimp_drawable_is_indexed (layer)) { guchar *cmap; gint num_colors; cmap = gimp_image_get_colormap (image, &num_colors); gimp_image_set_colormap (tmp_image, cmap, num_colors); g_free (cmap); } tmp_layer = gimp_layer_new (tmp_image, "temporary", w, h, gimp_drawable_type (layer), 100, GIMP_NORMAL_MODE); gimp_image_insert_layer (tmp_image, tmp_layer, -1, 0); drawable = gimp_drawable_get (layer); tmp = gimp_drawable_get (tmp_layer); gimp_pixel_rgn_init (&src_pixel_rgn, drawable, 0, 0, w, h, FALSE, FALSE); gimp_pixel_rgn_init (&dst_pixel_rgn, tmp, 0, 0, w, h, TRUE, FALSE); buffer = g_malloc (w * h * 4); gimp_pixel_rgn_get_rect (&src_pixel_rgn, buffer, 0, 0, w, h); gimp_pixel_rgn_set_rect (&dst_pixel_rgn, buffer, 0, 0, w, h); g_free (buffer); gimp_drawable_detach (tmp); gimp_drawable_detach (drawable); if (gimp_drawable_is_indexed (layer)) gimp_image_convert_rgb (tmp_image); return_vals = gimp_run_procedure ("plug-in-threshold-alpha", &n_return_vals, GIMP_PDB_INT32, GIMP_RUN_NONINTERACTIVE, GIMP_PDB_IMAGE, tmp_image, GIMP_PDB_DRAWABLE, tmp_layer, GIMP_PDB_INT32, ICO_ALPHA_THRESHOLD, GIMP_PDB_END); gimp_destroy_params (return_vals, n_return_vals); pixbuf = gimp_drawable_get_thumbnail (tmp_layer, MIN (w, 128), MIN (h, 128), GIMP_PIXBUF_SMALL_CHECKS); gimp_image_delete (tmp_image); } else { pixbuf = gimp_drawable_get_thumbnail (layer, MIN (w, 128), MIN (h, 128), GIMP_PIXBUF_SMALL_CHECKS); } gtk_image_set_from_pixbuf (GTK_IMAGE (preview), pixbuf); g_object_unref (pixbuf); }
static void ico_image_get_reduced_buf (guint32 layer, gint bpp, gint *num_colors, guchar **cmap_out, guchar **buf_out) { gint32 tmp_image; gint32 tmp_layer; gint w, h; guchar *buf; guchar *cmap = NULL; GeglBuffer *buffer = gimp_drawable_get_buffer (layer); const Babl *format; w = gegl_buffer_get_width (buffer); h = gegl_buffer_get_height (buffer); switch (gimp_drawable_type (layer)) { case GIMP_RGB_IMAGE: format = babl_format ("R'G'B' u8"); break; case GIMP_RGBA_IMAGE: format = babl_format ("R'G'B'A u8"); break; case GIMP_GRAY_IMAGE: format = babl_format ("Y' u8"); break; case GIMP_GRAYA_IMAGE: format = babl_format ("Y'A u8"); break; case GIMP_INDEXED_IMAGE: case GIMP_INDEXEDA_IMAGE: format = gegl_buffer_get_format (buffer); default: g_return_if_reached (); } *num_colors = 0; buf = g_new (guchar, w * h * 4); if (bpp <= 8 || bpp == 24 || babl_format_get_bytes_per_pixel (format) != 4) { gint32 image = gimp_item_get_image (layer); GeglBuffer *tmp; tmp_image = gimp_image_new (w, h, gimp_image_base_type (image)); gimp_image_undo_disable (tmp_image); if (gimp_drawable_is_indexed (layer)) { guchar *cmap; gint num_colors; cmap = gimp_image_get_colormap (image, &num_colors); gimp_image_set_colormap (tmp_image, cmap, num_colors); g_free (cmap); } tmp_layer = gimp_layer_new (tmp_image, "tmp", w, h, gimp_drawable_type (layer), 100, GIMP_NORMAL_MODE); gimp_image_insert_layer (tmp_image, tmp_layer, -1, 0); tmp = gimp_drawable_get_buffer (tmp_layer); gegl_buffer_get (buffer, GEGL_RECTANGLE (0, 0, w, h), 1.0, format, buf, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE); gegl_buffer_copy (buffer, NULL, GEGL_ABYSS_NONE, tmp, NULL); g_object_unref (tmp); if (! gimp_drawable_is_rgb (tmp_layer)) gimp_image_convert_rgb (tmp_image); if (bpp <= 8) { gimp_image_convert_indexed (tmp_image, GIMP_FS_DITHER, GIMP_MAKE_PALETTE, 1 << bpp, TRUE, FALSE, "dummy"); cmap = gimp_image_get_colormap (tmp_image, num_colors); if (*num_colors == (1 << bpp) && ! ico_cmap_contains_black (cmap, *num_colors)) { /* Windows icons with color maps need the color black. * We need to eliminate one more color to make room for black. */ if (gimp_drawable_is_indexed (layer)) { g_free (cmap); cmap = gimp_image_get_colormap (image, num_colors); gimp_image_set_colormap (tmp_image, cmap, *num_colors); } else if (gimp_drawable_is_gray (layer)) { gimp_image_convert_grayscale (tmp_image); } else { gimp_image_convert_rgb (tmp_image); } tmp = gimp_drawable_get_buffer (tmp_layer); gegl_buffer_set (tmp, GEGL_RECTANGLE (0, 0, w, h), 0, format, buf, GEGL_AUTO_ROWSTRIDE); g_object_unref (tmp); if (! gimp_drawable_is_rgb (layer)) gimp_image_convert_rgb (tmp_image); gimp_image_convert_indexed (tmp_image, GIMP_FS_DITHER, GIMP_MAKE_PALETTE, (1<<bpp) - 1, TRUE, FALSE, "dummy"); g_free (cmap); cmap = gimp_image_get_colormap (tmp_image, num_colors); } gimp_image_convert_rgb (tmp_image); } else if (bpp == 24) { GimpParam *return_vals; gint n_return_vals; return_vals = gimp_run_procedure ("plug-in-threshold-alpha", &n_return_vals, GIMP_PDB_INT32, GIMP_RUN_NONINTERACTIVE, GIMP_PDB_IMAGE, tmp_image, GIMP_PDB_DRAWABLE, tmp_layer, GIMP_PDB_INT32, ICO_ALPHA_THRESHOLD, GIMP_PDB_END); gimp_destroy_params (return_vals, n_return_vals); } gimp_layer_add_alpha (tmp_layer); tmp = gimp_drawable_get_buffer (tmp_layer); gegl_buffer_get (tmp, GEGL_RECTANGLE (0, 0, w, h), 1.0, NULL, buf, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE); g_object_unref (tmp); gimp_image_delete (tmp_image); } else { gegl_buffer_get (buffer, GEGL_RECTANGLE (0, 0, w, h), 1.0, format, buf, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE); } g_object_unref (buffer); *cmap_out = cmap; *buf_out = buf; }
/* 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 void run (const gchar *name, gint nparams, const GimpParam *param, gint *nreturn_vals, GimpParam **return_vals) { static GimpParam values[1]; GimpPDBStatusType status = GIMP_PDB_SUCCESS; GimpRunMode run_mode; /* Plug-in variables */ gboolean single_image; gboolean defaults_proc; /* Plug-In variables */ cairo_surface_t *pdf_file; cairo_t *cr; GimpExportCapabilities capabilities; guint32 i = 0; gint32 j = 0; gdouble x_res, y_res; gdouble x_scale, y_scale; gint32 image_id; gboolean exported; GimpImageBaseType type; gint32 temp; gint *layers; gint32 num_of_layers; GimpDrawable *layer; cairo_surface_t *layer_image; gdouble opacity; gint x, y; GimpRGB layer_color; gboolean single_color; gint32 mask_id = -1; GimpDrawable *mask = NULL; cairo_surface_t *mask_image = NULL; FILE *fp; INIT_I18N (); /* Setting mandatory output values */ *nreturn_vals = 1; *return_vals = values; values[0].type = GIMP_PDB_STATUS; values[0].data.d_status = status; /* Initializing all the settings */ multi_page.image_count = 0; if (! init_vals (name, nparams, param, &single_image, &defaults_proc, &run_mode)) { values[0].data.d_status = GIMP_PDB_CALLING_ERROR; return; } /* Starting the executions */ if (run_mode == GIMP_RUN_INTERACTIVE) { if (single_image) { if (! gui_single ()) { values[0].data.d_status = GIMP_PDB_CANCEL; return; } } else if (! gui_multi ()) { values[0].data.d_status = GIMP_PDB_CANCEL; return; } if (file_name == NULL) { values[0].data.d_status = GIMP_PDB_CALLING_ERROR; gimp_message (_("You must select a file to save!")); return; } } fp = g_fopen (file_name, "wb"); pdf_file = cairo_pdf_surface_create_for_stream (write_func, fp, 1, 1); if (cairo_surface_status (pdf_file) != CAIRO_STATUS_SUCCESS) { char *str = g_strdup_printf (_("An error occured while creating the PDF file:\n" "%s\n" "Make sure you entered a valid filename and that the selected location isn't read only!"), cairo_status_to_string (cairo_surface_status (pdf_file))); gimp_message (str); g_free (str); values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR; return; } cr = cairo_create (pdf_file); capabilities = GIMP_EXPORT_CAN_HANDLE_RGB | GIMP_EXPORT_CAN_HANDLE_ALPHA | GIMP_EXPORT_CAN_HANDLE_GRAY | GIMP_EXPORT_CAN_HANDLE_LAYERS | GIMP_EXPORT_CAN_HANDLE_INDEXED; if (optimize.apply_masks) capabilities |= GIMP_EXPORT_CAN_HANDLE_LAYER_MASKS; for (i = 0; i < multi_page.image_count; i++) { /* Save the state of the surface before any changes, so that settings * from one page won't affect all the others */ cairo_save (cr); image_id = multi_page.images[i]; /* We need the active layer in order to use gimp_image_export */ temp = gimp_image_get_active_drawable (image_id); if (temp == -1) exported = gimp_export_image (&image_id, &temp, NULL, capabilities) == GIMP_EXPORT_EXPORT; else exported = FALSE; type = gimp_image_base_type (image_id); gimp_image_get_resolution (image_id, &x_res, &y_res); x_scale = 72.0 / x_res; y_scale = 72.0 / y_res; cairo_pdf_surface_set_size (pdf_file, gimp_image_width (image_id) * x_scale, gimp_image_height (image_id) * y_scale); /* This way we set how many pixels are there in every inch. * It's very important for PangoCairo */ cairo_surface_set_fallback_resolution (pdf_file, x_res, y_res); /* PDF is usually 72 points per inch. If we have a different resolution, * we will need this to fit our drawings */ cairo_scale (cr, x_scale, y_scale); /* Now, we should loop over the layers of each image */ layers = gimp_image_get_layers (image_id, &num_of_layers); for (j = 0; j < num_of_layers; j++) { layer = gimp_drawable_get (layers [num_of_layers-j-1]); opacity = gimp_layer_get_opacity (layer->drawable_id)/100.0; /* Gimp doesn't display indexed layers with opacity below 50% * And if it's above 50%, it will be rounded to 100% */ if (type == GIMP_INDEXED) { if (opacity <= 0.5) opacity = 0.0; else opacity = 1.0; } if (gimp_item_get_visible (layer->drawable_id) && (! optimize.ignore_hidden || (optimize.ignore_hidden && opacity > 0.0))) { mask_id = gimp_layer_get_mask (layer->drawable_id); if (mask_id != -1) { mask = gimp_drawable_get (mask_id); mask_image = get_drawable_image (mask); } gimp_drawable_offsets (layer->drawable_id, &x, &y); /* For raster layers */ if (!gimp_item_is_text_layer (layer->drawable_id)) { layer_color = get_layer_color (layer, &single_color); cairo_rectangle (cr, x, y, layer->width, layer->height); if (optimize.vectorize && single_color) { cairo_set_source_rgba (cr, layer_color.r, layer_color.g, layer_color.b, layer_color.a * opacity); if (mask_id != -1) cairo_mask_surface (cr, mask_image, x, y); else cairo_fill (cr); } else { cairo_clip (cr); layer_image = get_drawable_image (layer); cairo_set_source_surface (cr, layer_image, x, y); cairo_push_group (cr); cairo_paint_with_alpha (cr, opacity); cairo_pop_group_to_source (cr); if (mask_id != -1) cairo_mask_surface (cr, mask_image, x, y); else cairo_paint (cr); cairo_reset_clip (cr); cairo_surface_destroy (layer_image); } } /* For text layers */ else { drawText (layer, opacity, cr, x_res, y_res); } } /* We are done with the layer - time to free some resources */ gimp_drawable_detach (layer); if (mask_id != -1) { gimp_drawable_detach (mask); cairo_surface_destroy (mask_image); } } /* We are done with this image - Show it! */ cairo_show_page (cr); cairo_restore (cr); if (exported) gimp_image_delete (image_id); } /* We are done with all the images - time to free the resources */ cairo_surface_destroy (pdf_file); cairo_destroy (cr); fclose (fp); /* Finally done, let's save the parameters */ gimp_set_data (DATA_OPTIMIZE, &optimize, sizeof (optimize)); if (!single_image) { g_strlcpy (multi_page.file_name, file_name, MAX_FILE_NAME_LENGTH); gimp_set_data (DATA_IMAGE_LIST, &multi_page, sizeof (multi_page)); } }
static gint32 do_optimizations (GimpRunMode run_mode, gboolean diff_only) { GimpPixelRgn pixel_rgn; static guchar *rawframe = NULL; guchar *srcptr; guchar *destptr; gint row, this_frame_num; guint32 frame_sizebytes; gint32 new_layer_id; DisposeType dispose; guchar *this_frame = NULL; guchar *last_frame = NULL; guchar *opti_frame = NULL; guchar *back_frame = NULL; gint this_delay; gint cumulated_delay = 0; gint last_true_frame = -1; gint buflen; gchar *oldlayer_name; gchar *newlayer_name; gboolean can_combine; gint32 bbox_top, bbox_bottom, bbox_left, bbox_right; gint32 rbox_top, rbox_bottom, rbox_left, rbox_right; switch (opmode) { case OPUNOPTIMIZE: gimp_progress_init (_("Unoptimizing animation")); break; case OPFOREGROUND: gimp_progress_init (_("Removing animation background")); break; case OPBACKGROUND: gimp_progress_init (_("Finding animation background")); break; case OPOPTIMIZE: default: gimp_progress_init (_("Optimizing animation")); break; } width = gimp_image_width (image_id); height = gimp_image_height (image_id); layers = gimp_image_get_layers (image_id, &total_frames); imagetype = gimp_image_base_type (image_id); pixelstep = (imagetype == GIMP_RGB) ? 4 : 2; /* gimp_tile_cache_ntiles(total_frames * (width / gimp_tile_width() + 1) );*/ drawabletype_alpha = (imagetype == GIMP_RGB) ? GIMP_RGBA_IMAGE : ((imagetype == GIMP_INDEXED) ? GIMP_INDEXEDA_IMAGE : GIMP_GRAYA_IMAGE); frame_sizebytes = width * height * pixelstep; this_frame = g_malloc (frame_sizebytes); last_frame = g_malloc (frame_sizebytes); opti_frame = g_malloc (frame_sizebytes); if (opmode == OPBACKGROUND || opmode == OPFOREGROUND) back_frame = g_malloc (frame_sizebytes); total_alpha (this_frame, width*height, pixelstep); total_alpha (last_frame, width*height, pixelstep); new_image_id = gimp_image_new(width, height, imagetype); gimp_image_undo_disable (new_image_id); if (imagetype == GIMP_INDEXED) { palette = gimp_image_get_colormap (image_id, &ncolours); gimp_image_set_colormap (new_image_id, palette, ncolours); } #if 1 if (opmode == OPBACKGROUND || opmode == OPFOREGROUND) { /* iterate through all rows of all frames, find statistical mode for each pixel position. */ gint i,j; guchar **these_rows; guchar **red; guchar **green; guchar **blue; guint **count; guint *num_colours; these_rows = g_new (guchar *, total_frames); red = g_new (guchar *, total_frames); green = g_new (guchar *, total_frames); blue = g_new (guchar *, total_frames); count = g_new (guint *, total_frames); num_colours = g_new (guint, width); for (this_frame_num=0; this_frame_num<total_frames; this_frame_num++) { these_rows[this_frame_num] = g_malloc(width * pixelstep); red[this_frame_num] = g_new (guchar, width); green[this_frame_num] = g_new (guchar, width); blue[this_frame_num] = g_new (guchar, width); count[this_frame_num] = g_new0(guint, width); } for (row = 0; row < height; row++) { memset(num_colours, 0, width * sizeof(guint)); for (this_frame_num=0; this_frame_num<total_frames; this_frame_num++) { drawable = gimp_drawable_get (layers[total_frames-(this_frame_num+1)]); dispose = get_frame_disposal (this_frame_num); compose_row(this_frame_num, dispose, row, these_rows[this_frame_num], width, drawable, FALSE ); gimp_drawable_detach(drawable); } for (this_frame_num=0; this_frame_num<total_frames; this_frame_num++) { for (i=0; i<width; i++) { if (these_rows[this_frame_num][i * pixelstep + pixelstep -1] >= 128) { for (j=0; j<num_colours[i]; j++) { switch (pixelstep) { case 4: if (these_rows[this_frame_num][i * 4 +0] == red[j][i] && these_rows[this_frame_num][i * 4 +1] == green[j][i] && these_rows[this_frame_num][i * 4 +2] == blue[j][i]) { (count[j][i])++; goto same; } break; case 2: if (these_rows[this_frame_num][i * 2 +0] == red[j][i]) { (count[j][i])++; goto same; } break; default: g_error ("Eeep!"); break; } } count[num_colours[i]][i] = 1; red[num_colours[i]][i] = these_rows[this_frame_num][i * pixelstep]; if (pixelstep == 4) { green[num_colours[i]][i] = these_rows[this_frame_num][i * 4 +1]; blue[num_colours[i]][i] = these_rows[this_frame_num][i * 4 +2]; } num_colours[i]++; } same: /* nop */; } } for (i=0; i<width; i++) { guint best_count = 0; guchar best_r = 255, best_g = 0, best_b = 255; for (j=0; j<num_colours[i]; j++) { if (count[j][i] > best_count) { best_count = count[j][i]; best_r = red[j][i]; best_g = green[j][i]; best_b = blue[j][i]; } } back_frame[width * pixelstep * row +i*pixelstep + 0] = best_r; if (pixelstep == 4) { back_frame[width * pixelstep * row +i*pixelstep + 1] = best_g; back_frame[width * pixelstep * row +i*pixelstep + 2] = best_b; } back_frame[width * pixelstep * row +i*pixelstep +pixelstep-1] = (best_count == 0) ? 0 : 255; if (best_count == 0) g_warning("yayyyy!"); } /* memcpy(&back_frame[width * pixelstep * row], these_rows[0], width * pixelstep);*/ } for (this_frame_num=0; this_frame_num<total_frames; this_frame_num++) { g_free (these_rows[this_frame_num]); g_free (red[this_frame_num]); g_free (green[this_frame_num]); g_free (blue[this_frame_num]); g_free (count[this_frame_num]); } g_free (these_rows); g_free (red); g_free (green); g_free (blue); g_free (count); g_free (num_colours); }
static void grid (gint32 image_ID, GimpDrawable *drawable, GimpPreview *preview) { GimpPixelRgn srcPR, destPR; gint bytes; gint x_offset, y_offset; guchar *dest, *buffer = NULL; gint x, y; gboolean alpha; gboolean blend; guchar hcolor[4]; guchar vcolor[4]; guchar icolor[4]; guchar *cmap; gint ncolors; gimp_rgba_get_uchar (&grid_cfg.hcolor, hcolor, hcolor + 1, hcolor + 2, hcolor + 3); gimp_rgba_get_uchar (&grid_cfg.vcolor, vcolor, vcolor + 1, vcolor + 2, vcolor + 3); gimp_rgba_get_uchar (&grid_cfg.icolor, icolor, icolor + 1, icolor + 2, icolor + 3); switch (gimp_image_base_type (image_ID)) { case GIMP_RGB: blend = TRUE; break; case GIMP_GRAY: hcolor[0] = gimp_rgb_luminance_uchar (&grid_cfg.hcolor); vcolor[0] = gimp_rgb_luminance_uchar (&grid_cfg.vcolor); icolor[0] = gimp_rgb_luminance_uchar (&grid_cfg.icolor); blend = TRUE; break; case GIMP_INDEXED: cmap = gimp_image_get_colormap (image_ID, &ncolors); hcolor[0] = best_cmap_match (cmap, ncolors, &grid_cfg.hcolor); vcolor[0] = best_cmap_match (cmap, ncolors, &grid_cfg.vcolor); icolor[0] = best_cmap_match (cmap, ncolors, &grid_cfg.icolor); g_free (cmap); blend = FALSE; break; default: g_assert_not_reached (); blend = FALSE; } bytes = drawable->bpp; alpha = gimp_drawable_has_alpha (drawable->drawable_id); if (preview) { gimp_preview_get_position (preview, &sx1, &sy1); gimp_preview_get_size (preview, &sx2, &sy2); buffer = g_new (guchar, bytes * sx2 * sy2); sx2 += sx1; sy2 += sy1; } else { gimp_drawable_mask_bounds (drawable->drawable_id, &sx1, &sy1, &sx2, &sy2); gimp_pixel_rgn_init (&destPR, drawable, 0, 0, sx2 - sx1, sy2 - sy1, TRUE, TRUE); } gimp_pixel_rgn_init (&srcPR, drawable, 0, 0, sx2 - sx1, sy2 - sy1, FALSE, FALSE); dest = g_new (guchar, (sx2 - sx1) * bytes); for (y = sy1; y < sy2; y++) { gimp_pixel_rgn_get_row (&srcPR, dest, sx1, y, (sx2 - sx1)); y_offset = y - grid_cfg.hoffset; while (y_offset < 0) y_offset += grid_cfg.hspace; if ((y_offset + (grid_cfg.hwidth / 2)) % grid_cfg.hspace < grid_cfg.hwidth) { for (x = sx1; x < sx2; x++) { pix_composite (&dest[(x-sx1) * bytes], hcolor, bytes, blend, alpha); } } for (x = sx1; x < sx2; x++) { x_offset = grid_cfg.vspace + x - grid_cfg.voffset; while (x_offset < 0) x_offset += grid_cfg.vspace; if ((x_offset + (grid_cfg.vwidth / 2)) % grid_cfg.vspace < grid_cfg.vwidth) { pix_composite (&dest[(x-sx1) * bytes], vcolor, bytes, blend, alpha); } if ((x_offset + (grid_cfg.iwidth / 2)) % grid_cfg.vspace < grid_cfg.iwidth && ((y_offset % grid_cfg.hspace >= grid_cfg.ispace && y_offset % grid_cfg.hspace < grid_cfg.ioffset) || (grid_cfg.hspace - (y_offset % grid_cfg.hspace) >= grid_cfg.ispace && grid_cfg.hspace - (y_offset % grid_cfg.hspace) < grid_cfg.ioffset))) { pix_composite (&dest[(x-sx1) * bytes], icolor, bytes, blend, alpha); } } if ((y_offset + (grid_cfg.iwidth / 2)) % grid_cfg.hspace < grid_cfg.iwidth) { for (x = sx1; x < sx2; x++) { x_offset = grid_cfg.vspace + x - grid_cfg.voffset; while (x_offset < 0) x_offset += grid_cfg.vspace; if ((x_offset % grid_cfg.vspace >= grid_cfg.ispace && x_offset % grid_cfg.vspace < grid_cfg.ioffset) || (grid_cfg.vspace - (x_offset % grid_cfg.vspace) >= grid_cfg.ispace && grid_cfg.vspace - (x_offset % grid_cfg.vspace) < grid_cfg.ioffset)) { pix_composite (&dest[(x-sx1) * bytes], icolor, bytes, blend, alpha); } } } if (preview) { memcpy (buffer + (y - sy1) * (sx2 - sx1) * bytes, dest, (sx2 - sx1) * bytes); } else { gimp_pixel_rgn_set_row (&destPR, dest, sx1, y, (sx2 - sx1)); if (y % 16 == 0) gimp_progress_update ((gdouble) y / (gdouble) (sy2 - sy1)); } } g_free (dest); if (preview) { gimp_preview_draw_buffer (preview, buffer, bytes * (sx2 - sx1)); g_free (buffer); } else { gimp_progress_update (1.0); gimp_drawable_flush (drawable); gimp_drawable_merge_shadow (drawable->drawable_id, TRUE); gimp_drawable_update (drawable->drawable_id, sx1, sy1, sx2 - sx1, sy2 - sy1); } }
static void gimp_display_shell_format_title (GimpDisplayShell *shell, gchar *title, gint title_len, const gchar *format) { Gimp *gimp; GimpImage *image; gint num, denom; gint i = 0; g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell)); image = shell->display->image; gimp = image->gimp; gimp_zoom_model_get_fraction (shell->zoom, &num, &denom); while (i < title_len && *format) { switch (*format) { case '%': format++; switch (*format) { case 0: /* format string ends within %-sequence, print literal '%' */ case '%': title[i++] = '%'; break; case 'f': /* pruned filename */ { const gchar *uri = gimp_image_get_uri (image); gchar *basename; basename = file_utils_uri_display_basename (uri); i += print (title, title_len, i, "%s", basename); g_free (basename); } break; case 'F': /* full filename */ { gchar *filename; const gchar *uri = gimp_image_get_uri (image); filename = file_utils_uri_display_name (uri); i += print (title, title_len, i, "%s", filename); g_free (filename); } break; case 'p': /* PDB id */ i += print (title, title_len, i, "%d", gimp_image_get_ID (image)); break; case 'i': /* instance */ i += print (title, title_len, i, "%d", shell->display->instance); break; case 't': /* type */ { const gchar *image_type_str = NULL; gboolean empty = gimp_image_is_empty (image); switch (gimp_image_base_type (image)) { case GIMP_RGB: image_type_str = empty ? _("RGB-empty") : _("RGB"); break; case GIMP_GRAY: image_type_str = empty ? _("grayscale-empty") : _("grayscale"); break; case GIMP_INDEXED: image_type_str = empty ? _("indexed-empty") : _("indexed"); break; default: g_assert_not_reached (); break; } i += print (title, title_len, i, "%s", image_type_str); } break; case 's': /* user source zoom factor */ i += print (title, title_len, i, "%d", denom); break; case 'd': /* user destination zoom factor */ i += print (title, title_len, i, "%d", num); break; case 'z': /* user zoom factor (percentage) */ { gdouble scale = gimp_zoom_model_get_factor (shell->zoom); i += print (title, title_len, i, scale >= 0.15 ? "%.0f" : "%.2f", 100.0 * scale); } break; case 'D': /* dirty flag */ if (format[1] == 0) { /* format string ends within %D-sequence, print literal '%D' */ i += print (title, title_len, i, "%%D"); break; } if (image->dirty) title[i++] = format[1]; format++; break; case 'C': /* clean flag */ if (format[1] == 0) { /* format string ends within %C-sequence, print literal '%C' */ i += print (title, title_len, i, "%%C"); break; } if (! image->dirty) title[i++] = format[1]; format++; break; case 'B': /* dirty flag (long) */ if (image->dirty) i += print (title, title_len, i, "%s", _("(modified)")); break; case 'A': /* clean flag (long) */ if (! image->dirty) i += print (title, title_len, i, "%s", _("(clean)")); break; case 'm': /* memory used by image */ { GimpObject *object = GIMP_OBJECT (image); gchar *str; str = gimp_memsize_to_string (gimp_object_get_memsize (object, NULL)); i += print (title, title_len, i, "%s", str); g_free (str); } break; case 'l': /* number of layers */ i += print (title, title_len, i, "%d", gimp_container_num_children (image->layers)); break; case 'L': /* number of layers (long) */ { gint num = gimp_container_num_children (image->layers); i += print (title, title_len, i, ngettext ("%d layer", "%d layers", num), num); } break; case 'n': /* active drawable name */ { GimpDrawable *drawable = gimp_image_get_active_drawable (image); if (drawable) i += print (title, title_len, i, "%s", gimp_object_get_name (GIMP_OBJECT (drawable))); else i += print (title, title_len, i, "%s", _("(none)")); } break; case 'P': /* active drawable PDB id */ { GimpDrawable *drawable = gimp_image_get_active_drawable (image); if (drawable) i += print (title, title_len, i, "%d", gimp_item_get_ID (GIMP_ITEM (drawable))); else i += print (title, title_len, i, "%s", _("(none)")); } break; case 'W': /* width in real-world units */ if (shell->unit != GIMP_UNIT_PIXEL) { gchar unit_format[8]; g_snprintf (unit_format, sizeof (unit_format), "%%.%df", _gimp_unit_get_digits (gimp, shell->unit) + 1); i += print (title, title_len, i, unit_format, (image->width * _gimp_unit_get_factor (gimp, shell->unit) / image->xresolution)); break; } /* else fallthru */ case 'w': /* width in pixels */ i += print (title, title_len, i, "%d", image->width); break; case 'H': /* height in real-world units */ if (shell->unit != GIMP_UNIT_PIXEL) { gchar unit_format[8]; g_snprintf (unit_format, sizeof (unit_format), "%%.%df", _gimp_unit_get_digits (gimp, shell->unit) + 1); i += print (title, title_len, i, unit_format, (image->height * _gimp_unit_get_factor (gimp, shell->unit) / image->yresolution)); break; } /* else fallthru */ case 'h': /* height in pixels */ i += print (title, title_len, i, "%d", image->height); break; case 'u': /* unit symbol */ i += print (title, title_len, i, "%s", _gimp_unit_get_symbol (gimp, shell->unit)); break; case 'U': /* unit abbreviation */ i += print (title, title_len, i, "%s", _gimp_unit_get_abbreviation (gimp, shell->unit)); break; /* Other cool things to be added: * %r = xresolution * %R = yresolution * %ø = image's fractal dimension * %þ = the answer to everything */ default: /* format string contains unknown %-sequence, print it literally */ i += print (title, title_len, i, "%%%c", *format); break; } break; default: title[i++] = *format; break; } format++; } title[MIN (i, title_len - 1)] = '\0'; }