static GimpTempBuf * gimp_buffer_get_new_preview (GimpViewable *viewable, GimpContext *context, gint width, gint height) { GimpBuffer *buffer = GIMP_BUFFER (viewable); const Babl *format = gimp_buffer_get_format (buffer); GimpTempBuf *preview; if (babl_format_is_palette (format)) format = gimp_babl_format (GIMP_RGB, GIMP_PRECISION_U8_GAMMA, babl_format_has_alpha (format)); else format = gimp_babl_format (gimp_babl_format_get_base_type (format), gimp_babl_precision (GIMP_COMPONENT_TYPE_U8, gimp_babl_format_get_linear (format)), babl_format_has_alpha (format)); preview = gimp_temp_buf_new (width, height, format); gegl_buffer_get (buffer->buffer, GEGL_RECTANGLE (0, 0, width, height), MIN ((gdouble) width / (gdouble) gimp_buffer_get_width (buffer), (gdouble) height / (gdouble) gimp_buffer_get_height (buffer)), format, gimp_temp_buf_get_data (preview), GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE); return preview; }
const Babl * gimp_drawable_get_preview_format (GimpDrawable *drawable) { gboolean alpha; gboolean linear; g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL); alpha = gimp_drawable_has_alpha (drawable); linear = gimp_drawable_get_linear (drawable); switch (gimp_drawable_get_base_type (drawable)) { case GIMP_GRAY: return gimp_babl_format (GIMP_GRAY, gimp_babl_precision (GIMP_COMPONENT_TYPE_U8, linear), alpha); case GIMP_RGB: return gimp_babl_format (GIMP_RGB, gimp_babl_precision (GIMP_COMPONENT_TYPE_U8, linear), alpha); case GIMP_INDEXED: if (alpha) return babl_format ("R'G'B'A u8"); else return babl_format ("R'G'B' u8"); } g_return_val_if_reached (NULL); }
GimpTempBuf * gimp_image_get_new_preview (GimpViewable *viewable, GimpContext *context, gint width, gint height) { GimpImage *image = GIMP_IMAGE (viewable); const Babl *format; gboolean linear; GimpTempBuf *buf; gdouble scale_x; gdouble scale_y; scale_x = (gdouble) width / (gdouble) gimp_image_get_width (image); scale_y = (gdouble) height / (gdouble) gimp_image_get_height (image); format = gimp_projectable_get_format (GIMP_PROJECTABLE (image)); linear = gimp_babl_format_get_linear (format); format = gimp_babl_format (gimp_babl_format_get_base_type (format), gimp_babl_precision (GIMP_COMPONENT_TYPE_U8, linear), babl_format_has_alpha (format)); buf = gimp_temp_buf_new (width, height, format); gegl_buffer_get (gimp_pickable_get_buffer (GIMP_PICKABLE (image)), GEGL_RECTANGLE (0, 0, width, height), MIN (scale_x, scale_y), gimp_temp_buf_get_format (buf), gimp_temp_buf_get_data (buf), GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_CLAMP); return buf; }
const Babl * gimp_babl_compat_u8_mask_format (const Babl *format) { g_return_val_if_fail (format != NULL, NULL); return gimp_babl_format (gimp_babl_format_get_base_type (format), GIMP_PRECISION_U8_LINEAR, FALSE, NULL); }
const Babl * gimp_babl_compat_u8_format (const Babl *format) { g_return_val_if_fail (format != NULL, NULL); /* indexed images only exist in u8, return the same format */ if (babl_format_is_palette (format)) return format; return gimp_babl_format (gimp_babl_format_get_base_type (format), GIMP_PRECISION_U8, babl_format_has_alpha (format)); }
/** * gimp_projection_estimate_memsize: * @type: the projectable's base type * @precision: the projectable's precision * @width: projection width * @height: projection height * * Calculates a rough estimate of the memory that is required for the * projection of an image with the given @width and @height. * * Return value: a rough estimate of the memory requirements. **/ gint64 gimp_projection_estimate_memsize (GimpImageBaseType type, GimpPrecision precision, gint width, gint height) { const Babl *format; gint64 bytes; if (type == GIMP_INDEXED) type = GIMP_RGB; format = gimp_babl_format (type, precision, TRUE); bytes = babl_format_get_bytes_per_pixel (format); /* The pyramid levels constitute a geometric sum with a ratio of 1/4. */ return bytes * (gint64) width * (gint64) height * 1.33; }
static const Babl * choose_format (GeglBuffer *buffer, GimpSelectCriterion select_criterion, gint *n_components, gboolean *has_alpha) { const Babl *format = gegl_buffer_get_format (buffer); *has_alpha = babl_format_has_alpha (format); switch (select_criterion) { case GIMP_SELECT_CRITERION_COMPOSITE: if (babl_format_is_palette (format)) format = babl_format ("R'G'B'A float"); else format = gimp_babl_format (gimp_babl_format_get_base_type (format), GIMP_PRECISION_FLOAT_GAMMA, *has_alpha); break; case GIMP_SELECT_CRITERION_R: case GIMP_SELECT_CRITERION_G: case GIMP_SELECT_CRITERION_B: case GIMP_SELECT_CRITERION_A: format = babl_format ("R'G'B'A float"); break; case GIMP_SELECT_CRITERION_H: case GIMP_SELECT_CRITERION_S: case GIMP_SELECT_CRITERION_V: format = babl_format ("HSVA float"); break; default: g_return_val_if_reached (NULL); break; } *n_components = babl_format_get_n_components (format); return format; }
static void gimp_color_frame_update (GimpColorFrame *frame) { const gchar *names[GIMP_COLOR_FRAME_ROWS] = { NULL, }; gchar **values = NULL; gboolean has_alpha; gint i; has_alpha = babl_format_has_alpha (frame->sample_format); if (frame->sample_valid) { gimp_color_area_set_color (GIMP_COLOR_AREA (frame->color_area), &frame->color); } switch (frame->frame_mode) { case GIMP_COLOR_FRAME_MODE_PIXEL: { GimpImageBaseType base_type; base_type = gimp_babl_format_get_base_type (frame->sample_format); if (frame->sample_valid) { const Babl *print_format = NULL; guchar print_pixel[32]; switch (gimp_babl_format_get_precision (frame->sample_format)) { case GIMP_PRECISION_U8_GAMMA: if (babl_format_is_palette (frame->sample_format)) { print_format = gimp_babl_format (GIMP_RGB, GIMP_PRECISION_U8_GAMMA, has_alpha); break; } /* else fall thru */ case GIMP_PRECISION_U8_LINEAR: case GIMP_PRECISION_U16_LINEAR: case GIMP_PRECISION_U16_GAMMA: case GIMP_PRECISION_U32_LINEAR: case GIMP_PRECISION_U32_GAMMA: case GIMP_PRECISION_FLOAT_LINEAR: case GIMP_PRECISION_FLOAT_GAMMA: case GIMP_PRECISION_DOUBLE_LINEAR: case GIMP_PRECISION_DOUBLE_GAMMA: print_format = frame->sample_format; break; case GIMP_PRECISION_HALF_GAMMA: print_format = gimp_babl_format (base_type, GIMP_PRECISION_FLOAT_GAMMA, has_alpha); break; case GIMP_PRECISION_HALF_LINEAR: print_format = gimp_babl_format (base_type, GIMP_PRECISION_FLOAT_LINEAR, has_alpha); break; } if (frame->sample_average) { /* FIXME: this is broken: can't use the averaged sRGB GimpRGB * value for displaying pixel values when color management * is enabled */ gimp_rgba_get_pixel (&frame->color, print_format, print_pixel); } else { babl_process (babl_fish (frame->sample_format, print_format), frame->pixel, print_pixel, 1); } values = gimp_babl_print_pixel (print_format, print_pixel); } if (base_type == GIMP_GRAY) { names[0] = _("Value:"); if (has_alpha) names[1] = _("Alpha:"); } else { names[0] = _("Red:"); names[1] = _("Green:"); names[2] = _("Blue:"); if (has_alpha) names[3] = _("Alpha:"); if (babl_format_is_palette (frame->sample_format)) { names[4] = _("Index:"); if (frame->sample_valid) { gchar **v = g_new0 (gchar *, 6); gchar **tmp = values; memcpy (v, values, 4 * sizeof (gchar *)); values = v; g_free (tmp); if (! frame->sample_average) values[4] = g_strdup_printf ("%d", frame->pixel[0]); } } } }
GtkWidget * color_profile_dialog_new (ColorProfileDialogType dialog_type, GimpImage *image, GimpContext *context, GtkWidget *parent, GimpProgress *progress) { ProfileDialog *dialog; GtkWidget *frame; GtkWidget *vbox; GtkWidget *expander; GtkWidget *label; GimpColorProfile *src_profile; g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL); g_return_val_if_fail (GTK_IS_WIDGET (parent), NULL); g_return_val_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress), NULL); dialog = g_slice_new0 (ProfileDialog); dialog->dialog_type = dialog_type; dialog->image = image; dialog->progress = progress; dialog->config = image->gimp->config->color_management; if (saved_intent == -1) { dialog->intent = GIMP_COLOR_RENDERING_INTENT_RELATIVE_COLORIMETRIC; dialog->bpc = TRUE; } else { dialog->intent = saved_intent; dialog->bpc = saved_bpc; } switch (dialog_type) { const Babl *format; case COLOR_PROFILE_DIALOG_ASSIGN_PROFILE: dialog->dialog = gimp_viewable_dialog_new (GIMP_VIEWABLE (image), context, _("Assign ICC Color Profile"), "gimp-image-color-profile-assign", NULL, _("Assign a color profile to the image"), parent, gimp_standard_help_func, GIMP_HELP_IMAGE_COLOR_PROFILE_ASSIGN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, _("_Assign"), GTK_RESPONSE_OK, NULL); dialog->builtin_profile = gimp_image_get_builtin_color_profile (dialog->image); break; case COLOR_PROFILE_DIALOG_CONVERT_TO_PROFILE: dialog->dialog = gimp_viewable_dialog_new (GIMP_VIEWABLE (image), context, _("Convert to ICC Color Profile"), "gimp-image-color-profile-convert", NULL, _("Convert the image to a color profile"), parent, gimp_standard_help_func, GIMP_HELP_IMAGE_COLOR_PROFILE_CONVERT, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_CONVERT, GTK_RESPONSE_OK, NULL); dialog->builtin_profile = gimp_image_get_builtin_color_profile (dialog->image); break; case COLOR_PROFILE_DIALOG_CONVERT_TO_RGB: dialog->dialog = gimp_viewable_dialog_new (GIMP_VIEWABLE (image), context, _("RGB Conversion"), "gimp-image-convert-rgb", GIMP_STOCK_CONVERT_RGB, _("Convert Image to RGB"), parent, gimp_standard_help_func, GIMP_HELP_IMAGE_CONVERT_RGB, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_CONVERT, GTK_RESPONSE_OK, NULL); format = gimp_babl_format (GIMP_RGB, gimp_image_get_precision (dialog->image), TRUE); dialog->builtin_profile = gimp_babl_format_get_color_profile (format); break; case COLOR_PROFILE_DIALOG_CONVERT_TO_GRAY: dialog->dialog = gimp_viewable_dialog_new (GIMP_VIEWABLE (image), context, _("Grayscale Conversion"), "gimp-image-convert-gray", GIMP_STOCK_CONVERT_GRAYSCALE, _("Convert Image to Grayscale"), parent, gimp_standard_help_func, GIMP_HELP_IMAGE_CONVERT_GRAYSCALE, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_CONVERT, GTK_RESPONSE_OK, NULL); format = gimp_babl_format (GIMP_GRAY, gimp_image_get_precision (dialog->image), TRUE); dialog->builtin_profile = gimp_babl_format_get_color_profile (format); break; } gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog->dialog), GTK_RESPONSE_OK, GTK_RESPONSE_CANCEL, -1); gtk_window_set_resizable (GTK_WINDOW (dialog->dialog), FALSE); g_object_weak_ref (G_OBJECT (dialog->dialog), (GWeakNotify) color_profile_dialog_free, dialog); g_signal_connect (dialog->dialog, "response", G_CALLBACK (color_profile_dialog_response), dialog); dialog->main_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12); gtk_container_set_border_width (GTK_CONTAINER (dialog->main_vbox), 12); gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog->dialog))), dialog->main_vbox, TRUE, TRUE, 0); gtk_widget_show (dialog->main_vbox); frame = gimp_frame_new (_("Current Color Profile")); gtk_box_pack_start (GTK_BOX (dialog->main_vbox), frame, FALSE, FALSE, 0); gtk_widget_show (frame); src_profile = gimp_color_managed_get_color_profile (GIMP_COLOR_MANAGED (image)); label = gimp_color_profile_label_new (src_profile); gtk_container_add (GTK_CONTAINER (frame), label); gtk_widget_show (label); frame = gimp_frame_new (dialog_type == COLOR_PROFILE_DIALOG_ASSIGN_PROFILE ? _("Assign") : _("Convert to")); gtk_box_pack_start (GTK_BOX (dialog->main_vbox), frame, FALSE, FALSE, 0); gtk_widget_show (frame); vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6); gtk_container_add (GTK_CONTAINER (frame), vbox); gtk_widget_show (vbox); dialog->combo = color_profile_combo_box_new (dialog); gtk_box_pack_start (GTK_BOX (vbox), dialog->combo, FALSE, FALSE, 0); gtk_widget_show (dialog->combo); expander = gtk_expander_new_with_mnemonic (_("Profile _details")); gtk_box_pack_start (GTK_BOX (vbox), expander, FALSE, FALSE, 0); gtk_widget_show (expander); dialog->dest_view = gimp_color_profile_view_new (); gtk_container_add (GTK_CONTAINER (expander), dialog->dest_view); gtk_widget_show (dialog->dest_view); g_signal_connect (dialog->combo, "changed", G_CALLBACK (color_profile_dest_changed), dialog); color_profile_dest_changed (dialog->combo, dialog); if (dialog_type == COLOR_PROFILE_DIALOG_CONVERT_TO_PROFILE) { GtkWidget *vbox; GtkWidget *hbox; GtkWidget *combo; GtkWidget *toggle; vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6); gtk_box_pack_start (GTK_BOX (dialog->main_vbox), vbox, FALSE, FALSE, 0); gtk_widget_show (vbox); hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); gtk_widget_show (hbox); label = gtk_label_new_with_mnemonic (_("_Rendering Intent:")); gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); gtk_widget_show (label); combo = gimp_enum_combo_box_new (GIMP_TYPE_COLOR_RENDERING_INTENT); gtk_box_pack_start (GTK_BOX (hbox), combo, TRUE, TRUE, 0); gtk_widget_show (combo); gimp_int_combo_box_connect (GIMP_INT_COMBO_BOX (combo), dialog->intent, G_CALLBACK (gimp_int_combo_box_get_active), &dialog->intent); gtk_label_set_mnemonic_widget (GTK_LABEL (label), combo); toggle = gtk_check_button_new_with_mnemonic (_("_Black Point Compensation")); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), dialog->bpc); gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0); gtk_widget_show (toggle); g_signal_connect (toggle, "toggled", G_CALLBACK (gimp_toggle_button_update), &dialog->bpc); } return dialog->dialog; }
GtkWidget * convert_precision_dialog_new (GimpImage *image, GimpContext *context, GtkWidget *parent, GimpPrecision precision, GimpProgress *progress) { ConvertDialog *dialog; GtkWidget *button; GtkWidget *main_vbox; GtkWidget *vbox; GtkWidget *hbox; GtkWidget *label; GtkWidget *frame; GtkWidget *combo; GtkSizeGroup *size_group; const gchar *enum_desc; gchar *blurb; GType dither_type; const Babl *format; gint bits; g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL); g_return_val_if_fail (GTK_IS_WIDGET (parent), NULL); g_return_val_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress), NULL); dialog = g_slice_new0 (ConvertDialog); /* a random format with precision */ format = gimp_babl_format (GIMP_RGB, precision, FALSE); bits = (babl_format_get_bytes_per_pixel (format) * 8 / babl_format_get_n_components (format)); dialog->image = image; dialog->progress = progress; dialog->precision = precision; dialog->bits = bits; /* gegl:color-reduction only does 16 bits */ if (bits <= 16) { dialog->layer_dither_type = saved_layer_dither_type; dialog->text_layer_dither_type = saved_text_layer_dither_type; dialog->mask_dither_type = saved_mask_dither_type; } gimp_enum_get_value (GIMP_TYPE_PRECISION, precision, NULL, NULL, &enum_desc, NULL); blurb = g_strdup_printf (_("Convert Image to %s"), enum_desc); dialog->dialog = gimp_viewable_dialog_new (GIMP_VIEWABLE (image), context, _("Precision Conversion"), "gimp-image-convert-precision", GIMP_STOCK_CONVERT_PRECISION, blurb, parent, gimp_standard_help_func, GIMP_HELP_IMAGE_CONVERT_PRECISION, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, NULL); g_free (blurb); button = gtk_dialog_add_button (GTK_DIALOG (dialog->dialog), _("C_onvert"), GTK_RESPONSE_OK); gtk_button_set_image (GTK_BUTTON (button), gtk_image_new_from_icon_name (GIMP_STOCK_CONVERT_PRECISION, GTK_ICON_SIZE_BUTTON)); gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog->dialog), GTK_RESPONSE_OK, GTK_RESPONSE_CANCEL, -1); gtk_window_set_resizable (GTK_WINDOW (dialog->dialog), FALSE); g_object_weak_ref (G_OBJECT (dialog->dialog), (GWeakNotify) convert_precision_dialog_free, dialog); g_signal_connect (dialog->dialog, "response", G_CALLBACK (convert_precision_dialog_response), dialog); main_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12); gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12); gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog->dialog))), main_vbox, TRUE, TRUE, 0); gtk_widget_show (main_vbox); /* dithering */ dither_type = gimp_gegl_get_op_enum_type ("gegl:color-reduction", "dither-strategy"); frame = gimp_frame_new (_("Dithering")); gtk_box_pack_start (GTK_BOX (main_vbox), frame, FALSE, FALSE, 0); gtk_widget_show (frame); vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6); gtk_container_add (GTK_CONTAINER (frame), vbox); gtk_widget_show (vbox); /* gegl:color-reduction only does 16 bits */ gtk_widget_set_sensitive (vbox, bits <= 16); size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); /* layers */ hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); gtk_widget_show (hbox); label = gtk_label_new_with_mnemonic (_("_Layers:")); gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); gtk_size_group_add_widget (size_group, label); gtk_widget_show (label); combo = gimp_enum_combo_box_new (dither_type); gtk_label_set_mnemonic_widget (GTK_LABEL (label), combo); gtk_box_pack_start (GTK_BOX (hbox), combo, TRUE, TRUE, 0); gtk_widget_show (combo); gimp_int_combo_box_connect (GIMP_INT_COMBO_BOX (combo), dialog->layer_dither_type, G_CALLBACK (gimp_int_combo_box_get_active), &dialog->layer_dither_type); /* text layers */ hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); gtk_widget_show (hbox); label = gtk_label_new_with_mnemonic (_("_Text Layers:")); gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); gtk_size_group_add_widget (size_group, label); gtk_widget_show (label); combo = gimp_enum_combo_box_new (dither_type); gtk_label_set_mnemonic_widget (GTK_LABEL (label), combo); gtk_box_pack_start (GTK_BOX (hbox), combo, TRUE, TRUE, 0); gtk_widget_show (combo); gimp_int_combo_box_connect (GIMP_INT_COMBO_BOX (combo), dialog->text_layer_dither_type, G_CALLBACK (gimp_int_combo_box_get_active), &dialog->text_layer_dither_type); gimp_help_set_help_data (combo, _("Dithering text layers will make them uneditable"), NULL); /* channels */ hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); gtk_widget_show (hbox); label = gtk_label_new_with_mnemonic (_("_Channels and Masks:")); gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); gtk_size_group_add_widget (size_group, label); gtk_widget_show (label); combo = gimp_enum_combo_box_new (dither_type); gtk_label_set_mnemonic_widget (GTK_LABEL (label), combo); gtk_box_pack_start (GTK_BOX (hbox), combo, TRUE, TRUE, 0); gtk_widget_show (combo); gimp_int_combo_box_connect (GIMP_INT_COMBO_BOX (combo), dialog->mask_dither_type, G_CALLBACK (gimp_int_combo_box_get_active), &dialog->mask_dither_type); g_object_unref (size_group); return dialog->dialog; }
/** * file_open_thumbnail: * @gimp: * @context: * @progress: * @file: an image file * @size: requested size of the thumbnail * @mime_type: return location for image MIME type * @image_width: return location for image width * @image_height: return location for image height * @format: return location for image format (set to NULL if unknown) * @num_layers: return location for number of layers * (set to -1 if the number of layers is not known) * @error: * * Attempts to load a thumbnail by using a registered thumbnail loader. * * Return value: the thumbnail image */ GimpImage * file_open_thumbnail (Gimp *gimp, GimpContext *context, GimpProgress *progress, GFile *file, gint size, const gchar **mime_type, gint *image_width, gint *image_height, const Babl **format, gint *num_layers, GError **error) { GimpPlugInProcedure *file_proc; GimpProcedure *procedure; g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL); g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL); g_return_val_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress), NULL); g_return_val_if_fail (G_IS_FILE (file), NULL); g_return_val_if_fail (mime_type != NULL, NULL); g_return_val_if_fail (image_width != NULL, NULL); g_return_val_if_fail (image_height != NULL, NULL); g_return_val_if_fail (format != NULL, NULL); g_return_val_if_fail (num_layers != NULL, NULL); g_return_val_if_fail (error == NULL || *error == NULL, NULL); *image_width = 0; *image_height = 0; *format = NULL; *num_layers = -1; file_proc = file_procedure_find (gimp->plug_in_manager->load_procs, file, NULL); if (! file_proc || ! file_proc->thumb_loader) return NULL; procedure = gimp_pdb_lookup_procedure (gimp->pdb, file_proc->thumb_loader); if (procedure && procedure->num_args >= 2 && procedure->num_values >= 1) { GimpPDBStatusType status; GimpValueArray *return_vals; GimpImage *image = NULL; gchar *path = NULL; if (! file_proc->handles_uri) path = g_file_get_path (file); if (! path) path = g_file_get_uri (file); return_vals = gimp_pdb_execute_procedure_by_name (gimp->pdb, context, progress, error, gimp_object_get_name (procedure), G_TYPE_STRING, path, GIMP_TYPE_INT32, size, G_TYPE_NONE); g_free (path); status = g_value_get_enum (gimp_value_array_index (return_vals, 0)); if (status == GIMP_PDB_SUCCESS && GIMP_VALUE_HOLDS_IMAGE_ID (gimp_value_array_index (return_vals, 1))) { image = gimp_value_get_image (gimp_value_array_index (return_vals, 1), gimp); if (gimp_value_array_length (return_vals) >= 3 && G_VALUE_HOLDS_INT (gimp_value_array_index (return_vals, 2)) && G_VALUE_HOLDS_INT (gimp_value_array_index (return_vals, 3))) { *image_width = MAX (0, g_value_get_int (gimp_value_array_index (return_vals, 2))); *image_height = MAX (0, g_value_get_int (gimp_value_array_index (return_vals, 3))); if (gimp_value_array_length (return_vals) >= 5 && G_VALUE_HOLDS_INT (gimp_value_array_index (return_vals, 4))) { gint value = g_value_get_int (gimp_value_array_index (return_vals, 4)); switch (value) { case GIMP_RGB_IMAGE: *format = gimp_babl_format (GIMP_RGB, GIMP_PRECISION_U8_GAMMA, FALSE); break; case GIMP_RGBA_IMAGE: *format = gimp_babl_format (GIMP_RGB, GIMP_PRECISION_U8_GAMMA, TRUE); break; case GIMP_GRAY_IMAGE: *format = gimp_babl_format (GIMP_GRAY, GIMP_PRECISION_U8_GAMMA, FALSE); break; case GIMP_GRAYA_IMAGE: *format = gimp_babl_format (GIMP_GRAY, GIMP_PRECISION_U8_GAMMA, TRUE); break; case GIMP_INDEXED_IMAGE: case GIMP_INDEXEDA_IMAGE: { const Babl *rgb; const Babl *rgba; babl_new_palette ("-gimp-indexed-format-dummy", &rgb, &rgba); if (value == GIMP_INDEXED_IMAGE) *format = rgb; else *format = rgba; } break; default: break; } } if (gimp_value_array_length (return_vals) >= 6 && G_VALUE_HOLDS_INT (gimp_value_array_index (return_vals, 5))) { *num_layers = MAX (0, g_value_get_int (gimp_value_array_index (return_vals, 5))); } } if (image) { file_open_sanitize_image (image, FALSE); *mime_type = file_proc->mime_type; #ifdef GIMP_UNSTABLE g_printerr ("opened thumbnail at %d x %d\n", gimp_image_get_width (image), gimp_image_get_height (image)); #endif } } gimp_value_array_unref (return_vals); return image; } return NULL; }
void gimp_gegl_convolve (GeglBuffer *src_buffer, const GeglRectangle *src_rect, GeglBuffer *dest_buffer, const GeglRectangle *dest_rect, const gfloat *kernel, gint kernel_size, gdouble divisor, GimpConvolutionType mode, gboolean alpha_weighting) { GeglBufferIterator *iter; GeglRectangle *src_roi; GeglRectangle *dest_roi; const Babl *src_format; const Babl *dest_format; gint src_components; gint dest_components; src_format = gegl_buffer_get_format (src_buffer); if (babl_format_is_palette (src_format)) src_format = gimp_babl_format (GIMP_RGB, GIMP_PRECISION_FLOAT_LINEAR, babl_format_has_alpha (src_format)); else src_format = gimp_babl_format (gimp_babl_format_get_base_type (src_format), GIMP_PRECISION_FLOAT_LINEAR, babl_format_has_alpha (src_format)); dest_format = gegl_buffer_get_format (dest_buffer); if (babl_format_is_palette (dest_format)) dest_format = gimp_babl_format (GIMP_RGB, GIMP_PRECISION_FLOAT_LINEAR, babl_format_has_alpha (dest_format)); else dest_format = gimp_babl_format (gimp_babl_format_get_base_type (dest_format), GIMP_PRECISION_FLOAT_LINEAR, babl_format_has_alpha (dest_format)); src_components = babl_format_get_n_components (src_format); dest_components = babl_format_get_n_components (dest_format); iter = gegl_buffer_iterator_new (src_buffer, src_rect, 0, src_format, GEGL_BUFFER_READ, GEGL_ABYSS_NONE); src_roi = &iter->roi[0]; gegl_buffer_iterator_add (iter, dest_buffer, dest_rect, 0, dest_format, GEGL_BUFFER_WRITE, GEGL_ABYSS_NONE); dest_roi = &iter->roi[1]; while (gegl_buffer_iterator_next (iter)) { /* Convolve the src image using the convolution kernel, writing * to dest Convolve is not tile-enabled--use accordingly */ const gfloat *src = iter->data[0]; gfloat *dest = iter->data[1]; const gint components = src_components; const gint a_component = components - 1; const gint rowstride = src_components * src_roi->width; const gint margin = kernel_size / 2; const gint x1 = src_roi->x; const gint y1 = src_roi->y; const gint x2 = src_roi->x + src_roi->width - 1; const gint y2 = src_roi->y + src_roi->height - 1; gint x, y; gfloat offset; /* If the mode is NEGATIVE_CONVOL, the offset should be 128 */ if (mode == GIMP_NEGATIVE_CONVOL) { offset = 0.5; mode = GIMP_NORMAL_CONVOL; } else { offset = 0.0; } for (y = 0; y < dest_roi->height; y++) { gfloat *d = dest; if (alpha_weighting) { for (x = 0; x < dest_roi->width; x++) { const gfloat *m = kernel; gdouble total[4] = { 0.0, 0.0, 0.0, 0.0 }; gdouble weighted_divisor = 0.0; gint i, j, b; for (j = y - margin; j <= y + margin; j++) { for (i = x - margin; i <= x + margin; i++, m++) { gint xx = CLAMP (i, x1, x2); gint yy = CLAMP (j, y1, y2); const gfloat *s = src + yy * rowstride + xx * components; const gfloat a = s[a_component]; if (a) { gdouble mult_alpha = *m * a; weighted_divisor += mult_alpha; for (b = 0; b < a_component; b++) total[b] += mult_alpha * s[b]; total[a_component] += mult_alpha; } } } if (weighted_divisor == 0.0) weighted_divisor = divisor; for (b = 0; b < a_component; b++) total[b] /= weighted_divisor; total[a_component] /= divisor; for (b = 0; b < components; b++) { total[b] += offset; if (mode != GIMP_NORMAL_CONVOL && total[b] < 0.0) total[b] = - total[b]; *d++ = CLAMP (total[b], 0.0, 1.0); } } } else { for (x = 0; x < dest_roi->width; x++) { const gfloat *m = kernel; gdouble total[4] = { 0.0, 0.0, 0.0, 0.0 }; gint i, j, b; for (j = y - margin; j <= y + margin; j++) { for (i = x - margin; i <= x + margin; i++, m++) { gint xx = CLAMP (i, x1, x2); gint yy = CLAMP (j, y1, y2); const gfloat *s = src + yy * rowstride + xx * components; for (b = 0; b < components; b++) total[b] += *m * s[b]; } } for (b = 0; b < components; b++) { total[b] = total[b] / divisor + offset; if (mode != GIMP_NORMAL_CONVOL && total[b] < 0.0) total[b] = - total[b]; total[b] = CLAMP (total[b], 0.0, 1.0); } } } dest += dest_roi->width * dest_components; } } }
void gimp_histogram_calculate (GimpHistogram *histogram, GeglBuffer *buffer, const GeglRectangle *buffer_rect, GeglBuffer *mask, const GeglRectangle *mask_rect) { GeglBufferIterator *iter; const Babl *format; gint n_components; g_return_if_fail (histogram != NULL); g_return_if_fail (GEGL_IS_BUFFER (buffer)); g_return_if_fail (buffer_rect != NULL); format = gegl_buffer_get_format (buffer); if (babl_format_is_palette (format)) format = gimp_babl_format (GIMP_RGB, GIMP_PRECISION_U8, babl_format_has_alpha (format)); else format = gimp_babl_format (gimp_babl_format_get_base_type (format), GIMP_PRECISION_U8, babl_format_has_alpha (format)); n_components = babl_format_get_n_components (format); gimp_histogram_alloc_values (histogram, n_components); iter = gegl_buffer_iterator_new (buffer, buffer_rect, 0, format, GEGL_BUFFER_READ, GEGL_ABYSS_NONE); if (mask) gegl_buffer_iterator_add (iter, mask, mask_rect, 0, babl_format ("Y float"), GEGL_BUFFER_READ, GEGL_ABYSS_NONE); #define VALUE(c,i) (histogram->values[(c) * 256 + (i)]) while (gegl_buffer_iterator_next (iter)) { const guchar *data = iter->data[0]; gint max; if (mask) { const gfloat *mask_data = iter->data[1]; switch (n_components) { case 1: while (iter->length) { const gdouble masked = *mask_data; VALUE (0, data[0]) += masked; data += n_components; mask_data += 1; } break; case 2: while (iter->length--) { const gdouble masked = *mask_data; const gdouble weight = data[1] / 255.0; VALUE (0, data[0]) += weight * masked; VALUE (1, data[1]) += masked; data += n_components; mask_data += 1; } break; case 3: /* calculate separate value values */ while (iter->length--) { const gdouble masked = *mask_data; VALUE (1, data[0]) += masked; VALUE (2, data[1]) += masked; VALUE (3, data[2]) += masked; max = MAX (data[0], data[1]); max = MAX (data[2], max); VALUE (0, max) += masked; data += n_components; mask_data += 1; } break; case 4: /* calculate separate value values */ while (iter->length--) { const gdouble masked = *mask_data; const gdouble weight = data[3] / 255.0; VALUE (1, data[0]) += weight * masked; VALUE (2, data[1]) += weight * masked; VALUE (3, data[2]) += weight * masked; VALUE (4, data[3]) += masked; max = MAX (data[0], data[1]); max = MAX (data[2], max); VALUE (0, max) += weight * masked; data += n_components; mask_data += 1; } break; } } else /* no mask */ { switch (n_components) { case 1: while (iter->length--) { VALUE (0, data[0]) += 1.0; data += n_components; } break; case 2: while (iter->length--) { const gdouble weight = data[1] / 255; VALUE (0, data[0]) += weight; VALUE (1, data[1]) += 1.0; data += n_components; } break; case 3: /* calculate separate value values */ while (iter->length--) { VALUE (1, data[0]) += 1.0; VALUE (2, data[1]) += 1.0; VALUE (3, data[2]) += 1.0; max = MAX (data[0], data[1]); max = MAX (data[2], max); VALUE (0, max) += 1.0; data += n_components; } break; case 4: /* calculate separate value values */ while (iter->length--) { const gdouble weight = data[3] / 255; VALUE (1, data[0]) += weight; VALUE (2, data[1]) += weight; VALUE (3, data[2]) += weight; VALUE (4, data[3]) += 1.0; max = MAX (data[0], data[1]); max = MAX (data[2], max); VALUE (0, max) += weight; data += n_components; } break; } } } #undef VALUE }