void gimp_image_convert_precision (GimpImage *image, GimpPrecision precision, gint layer_dither_type, gint text_layer_dither_type, gint mask_dither_type, GimpProgress *progress) { GimpColorProfile *old_profile; GimpColorProfile *new_profile = NULL; const Babl *old_format; const Babl *new_format; GList *all_drawables; GList *list; const gchar *undo_desc = NULL; GimpProgress *sub_progress = NULL; gint nth_drawable, n_drawables; g_return_if_fail (GIMP_IS_IMAGE (image)); g_return_if_fail (precision != gimp_image_get_precision (image)); g_return_if_fail (precision == GIMP_PRECISION_U8_GAMMA || gimp_image_get_base_type (image) != GIMP_INDEXED); g_return_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress)); all_drawables = g_list_concat (gimp_image_get_layer_list (image), gimp_image_get_channel_list (image)); n_drawables = g_list_length (all_drawables) + 1 /* + selection */; if (progress) sub_progress = gimp_sub_progress_new (progress); switch (precision) { case GIMP_PRECISION_U8_LINEAR: undo_desc = C_("undo-type", "Convert Image to 8 bit linear integer"); break; case GIMP_PRECISION_U8_GAMMA: undo_desc = C_("undo-type", "Convert Image to 8 bit gamma integer"); break; case GIMP_PRECISION_U16_LINEAR: undo_desc = C_("undo-type", "Convert Image to 16 bit linear integer"); break; case GIMP_PRECISION_U16_GAMMA: undo_desc = C_("undo-type", "Convert Image to 16 bit gamma integer"); break; case GIMP_PRECISION_U32_LINEAR: undo_desc = C_("undo-type", "Convert Image to 32 bit linear integer"); break; case GIMP_PRECISION_U32_GAMMA: undo_desc = C_("undo-type", "Convert Image to 32 bit gamma integer"); break; case GIMP_PRECISION_HALF_LINEAR: undo_desc = C_("undo-type", "Convert Image to 16 bit linear floating point"); break; case GIMP_PRECISION_HALF_GAMMA: undo_desc = C_("undo-type", "Convert Image to 16 bit gamma floating point"); break; case GIMP_PRECISION_FLOAT_LINEAR: undo_desc = C_("undo-type", "Convert Image to 32 bit linear floating point"); break; case GIMP_PRECISION_FLOAT_GAMMA: undo_desc = C_("undo-type", "Convert Image to 32 bit gamma floating point"); break; case GIMP_PRECISION_DOUBLE_LINEAR: undo_desc = C_("undo-type", "Convert Image to 64 bit linear floating point"); break; case GIMP_PRECISION_DOUBLE_GAMMA: undo_desc = C_("undo-type", "Convert Image to 64 bit gamma floating point"); break; } if (progress) gimp_progress_start (progress, FALSE, "%s", undo_desc); g_object_freeze_notify (G_OBJECT (image)); gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_IMAGE_CONVERT, undo_desc); /* Push the image precision to the stack */ gimp_image_undo_push_image_precision (image, NULL); old_profile = gimp_image_get_color_profile (image); old_format = gimp_image_get_layer_format (image, FALSE); /* Set the new precision */ g_object_set (image, "precision", precision, NULL); new_format = gimp_image_get_layer_format (image, FALSE); if (old_profile && gimp_babl_format_get_linear (old_format) != gimp_babl_format_get_linear (new_format)) { GimpColorProfile *new_profile; /* when converting between linear and gamma, we create a new * profile using the original profile's chromacities and * whitepoint, but a linear/sRGB-gamma TRC. */ if (gimp_babl_format_get_linear (new_format)) { new_profile = gimp_color_profile_new_linear_from_color_profile (old_profile); } else { new_profile = gimp_color_profile_new_srgb_trc_from_color_profile (old_profile); } /* if a new profile cannot be be generated, convert to the * builtin profile, which is better than leaving the user with * broken colors */ if (! new_profile) { new_profile = gimp_image_get_builtin_color_profile (image); g_object_ref (new_profile); } } for (list = all_drawables, nth_drawable = 0; list; list = g_list_next (list), nth_drawable++) { GimpDrawable *drawable = list->data; gint dither_type; if (gimp_item_is_text_layer (GIMP_ITEM (drawable))) dither_type = text_layer_dither_type; else dither_type = layer_dither_type; if (sub_progress) gimp_sub_progress_set_step (GIMP_SUB_PROGRESS (sub_progress), nth_drawable, n_drawables); gimp_drawable_convert_type (drawable, image, gimp_drawable_get_base_type (drawable), precision, new_profile, dither_type, mask_dither_type, TRUE, sub_progress); } g_list_free (all_drawables); if (old_profile) { gimp_image_set_color_profile (image, new_profile, NULL); g_object_unref (new_profile); } /* convert the selection mask */ { GimpChannel *mask = gimp_image_get_mask (image); GeglBuffer *buffer; if (sub_progress) gimp_sub_progress_set_step (GIMP_SUB_PROGRESS (sub_progress), nth_drawable, n_drawables); gimp_image_undo_push_mask_precision (image, NULL, mask); buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0, gimp_image_get_width (image), gimp_image_get_height (image)), gimp_image_get_mask_format (image)); gegl_buffer_copy (gimp_drawable_get_buffer (GIMP_DRAWABLE (mask)), NULL, GEGL_ABYSS_NONE, buffer, NULL); gimp_drawable_set_buffer (GIMP_DRAWABLE (mask), FALSE, NULL, buffer); g_object_unref (buffer); nth_drawable++; } if (sub_progress) gimp_progress_set_value (sub_progress, 1.0); gimp_image_undo_group_end (image); gimp_image_precision_changed (image); g_object_thaw_notify (G_OBJECT (image)); if (sub_progress) g_object_unref (sub_progress); if (progress) gimp_progress_end (progress); }
static void gimp_thumb_box_create_thumbnails (GimpThumbBox *box, gboolean force) { Gimp *gimp = box->imagefile->gimp; GimpProgress *progress = GIMP_PROGRESS (box); GimpFileDialog *dialog = NULL; GtkWidget *toplevel; GSList *list; gint n_uris; gint i; if (gimp->config->thumbnail_size == GIMP_THUMBNAIL_SIZE_NONE) return; toplevel = gtk_widget_get_toplevel (GTK_WIDGET (box)); if (GIMP_IS_FILE_DIALOG (toplevel)) dialog = GIMP_FILE_DIALOG (toplevel); gimp_set_busy (gimp); if (dialog) gimp_file_dialog_set_sensitive (dialog, FALSE); else gtk_widget_set_sensitive (toplevel, FALSE); if (box->uris) { gtk_widget_hide (box->info); gtk_widget_show (box->progress); } n_uris = g_slist_length (box->uris); if (n_uris > 1) { gchar *str; gimp_progress_start (GIMP_PROGRESS (box), "", TRUE); progress = gimp_sub_progress_new (GIMP_PROGRESS (box)); gimp_sub_progress_set_step (GIMP_SUB_PROGRESS (progress), 0, n_uris); for (list = box->uris->next, i = 1; list; list = g_slist_next (list), i++) { str = g_strdup_printf (_("Thumbnail %d of %d"), i, n_uris); gtk_progress_bar_set_text (GTK_PROGRESS_BAR (box->progress), str); g_free (str); gimp_progress_set_value (progress, 0.0); while (gtk_events_pending ()) gtk_main_iteration (); gimp_thumb_box_create_thumbnail (box, list->data, gimp->config->thumbnail_size, force, progress); if (dialog && dialog->canceled) goto canceled; gimp_sub_progress_set_step (GIMP_SUB_PROGRESS (progress), i, n_uris); } str = g_strdup_printf (_("Thumbnail %d of %d"), n_uris, n_uris); gtk_progress_bar_set_text (GTK_PROGRESS_BAR (box->progress), str); g_free (str); gimp_progress_set_value (progress, 0.0); while (gtk_events_pending ()) gtk_main_iteration (); } if (box->uris) { gimp_thumb_box_create_thumbnail (box, box->uris->data, gimp->config->thumbnail_size, force, progress); gimp_progress_set_value (progress, 1.0); } canceled: if (n_uris > 1) { g_object_unref (progress); gimp_progress_end (GIMP_PROGRESS (box)); gtk_progress_bar_set_text (GTK_PROGRESS_BAR (box->progress), ""); } if (box->uris) { gtk_widget_hide (box->progress); gtk_widget_show (box->info); } if (dialog) gimp_file_dialog_set_sensitive (dialog, TRUE); else gtk_widget_set_sensitive (toplevel, TRUE); gimp_unset_busy (gimp); }
void gimp_image_scale (GimpImage *image, gint new_width, gint new_height, GimpInterpolationType interpolation_type, GimpProgress *progress) { GimpProgress *sub_progress; GList *all_layers; GList *all_channels; GList *all_vectors; GList *list; gint old_width; gint old_height; gint offset_x; gint offset_y; gdouble img_scale_w = 1.0; gdouble img_scale_h = 1.0; gint progress_steps; gint progress_current = 0; g_return_if_fail (GIMP_IS_IMAGE (image)); g_return_if_fail (new_width > 0 && new_height > 0); g_return_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress)); gimp_set_busy (image->gimp); sub_progress = gimp_sub_progress_new (progress); all_layers = gimp_image_get_layer_list (image); all_channels = gimp_image_get_channel_list (image); all_vectors = gimp_image_get_vectors_list (image); progress_steps = (g_list_length (all_layers) + g_list_length (all_channels) + g_list_length (all_vectors) + 1 /* selection */); g_object_freeze_notify (G_OBJECT (image)); gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_IMAGE_SCALE, C_("undo-type", "Scale Image")); old_width = gimp_image_get_width (image); old_height = gimp_image_get_height (image); img_scale_w = (gdouble) new_width / (gdouble) old_width; img_scale_h = (gdouble) new_height / (gdouble) old_height; offset_x = (old_width - new_width) / 2; offset_y = (old_height - new_height) / 2; /* Push the image size to the stack */ gimp_image_undo_push_image_size (image, NULL, offset_x, offset_y, new_width, new_height); /* Set the new width and height early, so below image item setters * (esp. guides and sample points) don't choke about moving stuff * out of the image */ g_object_set (image, "width", new_width, "height", new_height, NULL); /* Scale all channels */ for (list = all_channels; list; list = g_list_next (list)) { GimpItem *item = list->data; gimp_sub_progress_set_step (GIMP_SUB_PROGRESS (sub_progress), progress_current++, progress_steps); gimp_item_scale (item, new_width, new_height, 0, 0, interpolation_type, sub_progress); } /* Scale all vectors */ for (list = all_vectors; list; list = g_list_next (list)) { GimpItem *item = list->data; gimp_sub_progress_set_step (GIMP_SUB_PROGRESS (sub_progress), progress_current++, progress_steps); gimp_item_scale (item, new_width, new_height, 0, 0, interpolation_type, sub_progress); } /* Don't forget the selection mask! */ gimp_sub_progress_set_step (GIMP_SUB_PROGRESS (sub_progress), progress_current++, progress_steps); gimp_item_scale (GIMP_ITEM (gimp_image_get_mask (image)), new_width, new_height, 0, 0, interpolation_type, sub_progress); /* Scale all layers */ for (list = all_layers; list; list = g_list_next (list)) { GimpItem *item = list->data; gimp_sub_progress_set_step (GIMP_SUB_PROGRESS (sub_progress), progress_current++, progress_steps); /* group layers are updated automatically */ if (gimp_viewable_get_children (GIMP_VIEWABLE (item))) { gimp_group_layer_suspend_resize (GIMP_GROUP_LAYER (item), FALSE); continue; } if (! gimp_item_scale_by_factors (item, img_scale_w, img_scale_h, interpolation_type, sub_progress)) { /* Since 0 < img_scale_w, img_scale_h, failure due to one or more * vanishing scaled layer dimensions. Implicit delete implemented * here. Upstream warning implemented in resize_check_layer_scaling(), * which offers the user the chance to bail out. */ gimp_image_remove_layer (image, GIMP_LAYER (item), TRUE, NULL); } } for (list = all_layers; list; list = g_list_next (list)) if (gimp_viewable_get_children (list->data)) gimp_group_layer_resume_resize (list->data, FALSE); /* Scale all Guides */ for (list = gimp_image_get_guides (image); list; list = g_list_next (list)) { GimpGuide *guide = list->data; gint position = gimp_guide_get_position (guide); switch (gimp_guide_get_orientation (guide)) { case GIMP_ORIENTATION_HORIZONTAL: gimp_image_move_guide (image, guide, (position * new_height) / old_height, TRUE); break; case GIMP_ORIENTATION_VERTICAL: gimp_image_move_guide (image, guide, (position * new_width) / old_width, TRUE); break; default: break; } } /* Scale all sample points */ for (list = gimp_image_get_sample_points (image); list; list = g_list_next (list)) { GimpSamplePoint *sample_point = list->data; gimp_image_move_sample_point (image, sample_point, sample_point->x * new_width / old_width, sample_point->y * new_height / old_height, TRUE); } gimp_image_undo_group_end (image); g_list_free (all_layers); g_list_free (all_channels); g_list_free (all_vectors); g_object_unref (sub_progress); gimp_image_size_changed_detailed (image, -offset_x, -offset_y, old_width, old_height); g_object_thaw_notify (G_OBJECT (image)); gimp_unset_busy (image->gimp); }
static void gimp_image_convert_profile_layers (GimpImage *image, GimpColorProfile *src_profile, GimpColorProfile *dest_profile, GimpColorRenderingIntent intent, gboolean bpc, GimpProgress *progress) { GList *layers; GList *list; gint n_drawables = 0; gint nth_drawable = 0; layers = gimp_image_get_layer_list (image); for (list = layers; list; list = g_list_next (list)) { if (! gimp_viewable_get_children (list->data)) n_drawables++; } for (list = layers; list; list = g_list_next (list)) { GimpDrawable *drawable = list->data; GimpProgress *sub_progress = NULL; if (gimp_viewable_get_children (GIMP_VIEWABLE (drawable))) continue; if (progress) { sub_progress = gimp_sub_progress_new (progress); gimp_sub_progress_set_step (GIMP_SUB_PROGRESS (sub_progress), nth_drawable, n_drawables); } nth_drawable++; gimp_drawable_push_undo (drawable, NULL, NULL, 0, 0, gimp_item_get_width (GIMP_ITEM (drawable)), gimp_item_get_height (GIMP_ITEM (drawable))); gimp_gegl_convert_color_profile (gimp_drawable_get_buffer (drawable), NULL, src_profile, gimp_drawable_get_buffer (drawable), NULL, dest_profile, intent, bpc, sub_progress); gimp_drawable_update (drawable, 0, 0, gimp_item_get_width (GIMP_ITEM (drawable)), gimp_item_get_height (GIMP_ITEM (drawable))); if (sub_progress) g_object_unref (sub_progress); } g_list_free (layers); }
static void gimp_warp_tool_animate (GimpWarpTool *wt) { GimpTool *tool = GIMP_TOOL (wt); GimpWarpOptions *options = GIMP_WARP_TOOL_GET_OPTIONS (wt); GimpImage *orig_image; GimpImage *image; GimpLayer *layer; GimpLayer *first_layer; GeglNode *scale_node; GimpProgress *progress; GtkWidget *widget; gint i; if (! gimp_warp_tool_get_undo_desc (tool, tool->display)) { gimp_tool_message_literal (tool, tool->display, _("Please add some warp strokes first.")); return; } /* get rid of the image map so we can use wt->graph */ if (wt->image_map) { gimp_image_map_abort (wt->image_map); g_object_unref (wt->image_map); wt->image_map = NULL; } gimp_progress_start (GIMP_PROGRESS (tool), FALSE, _("Rendering Frame %d"), 1); orig_image = gimp_item_get_image (GIMP_ITEM (tool->drawable)); image = gimp_create_image (orig_image->gimp, gimp_item_get_width (GIMP_ITEM (tool->drawable)), gimp_item_get_height (GIMP_ITEM (tool->drawable)), gimp_drawable_get_base_type (tool->drawable), gimp_drawable_get_precision (tool->drawable), TRUE); /* the first frame is always the unwarped image */ layer = GIMP_LAYER (gimp_item_convert (GIMP_ITEM (tool->drawable), image, GIMP_TYPE_LAYER)); gimp_object_take_name (GIMP_OBJECT (layer), g_strdup_printf (_("Frame %d"), 1)); gimp_item_set_offset (GIMP_ITEM (layer), 0, 0); gimp_item_set_visible (GIMP_ITEM (layer), TRUE, FALSE); gimp_layer_set_mode (layer, GIMP_NORMAL_MODE, FALSE); gimp_layer_set_opacity (layer, GIMP_OPACITY_OPAQUE, FALSE); gimp_image_add_layer (image, layer, NULL, 0, FALSE); first_layer = layer; scale_node = gegl_node_new_child (NULL, "operation", "gimp:scalar-multiply", "n-components", 2, NULL); gimp_warp_tool_add_op (wt, scale_node); progress = gimp_sub_progress_new (GIMP_PROGRESS (tool)); for (i = 1; i < options->n_animation_frames; i++) { gimp_progress_set_text (GIMP_PROGRESS (tool), _("Rendering Frame %d"), i + 1); gimp_sub_progress_set_step (GIMP_SUB_PROGRESS (progress), i, options->n_animation_frames); layer = GIMP_LAYER (gimp_item_duplicate (GIMP_ITEM (first_layer), GIMP_TYPE_LAYER)); gimp_object_take_name (GIMP_OBJECT (layer), g_strdup_printf (_("Frame %d"), i + 1)); gegl_node_set (scale_node, "factor", (gdouble) i / (gdouble) (options->n_animation_frames - 1), NULL); gimp_gegl_apply_operation (gimp_drawable_get_buffer (GIMP_DRAWABLE (first_layer)), progress, _("Frame"), wt->graph, gimp_drawable_get_buffer (GIMP_DRAWABLE (layer)), NULL); gimp_image_add_layer (image, layer, NULL, 0, FALSE); } g_object_unref (progress); gimp_warp_tool_remove_op (wt, scale_node); gimp_progress_end (GIMP_PROGRESS (tool)); /* recreate the image map */ gimp_warp_tool_create_image_map (wt, tool->drawable); gimp_image_map_apply (wt->image_map, NULL); widget = GTK_WIDGET (gimp_display_get_shell (tool->display)); gimp_create_display (orig_image->gimp, image, GIMP_UNIT_PIXEL, 1.0, G_OBJECT (gtk_widget_get_screen (widget)), gimp_widget_get_monitor (widget)); g_object_unref (image); }