1 /* GIMP - The GNU Image Manipulation Program
2 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <https://www.gnu.org/licenses/>.
16 */
17
18 #include "config.h"
19
20 #include <gegl.h>
21 #include <gtk/gtk.h>
22
23 #include "libgimpbase/gimpbase.h"
24 #include "libgimpcolor/gimpcolor.h"
25 #include "libgimpwidgets/gimpwidgets.h"
26
27 #include "actions-types.h"
28
29 #include "config/gimpdialogconfig.h"
30
31 #include "gegl/gimp-babl.h"
32
33 #include "core/core-enums.h"
34 #include "core/gimp.h"
35 #include "core/gimpcontext.h"
36 #include "core/gimpimage.h"
37 #include "core/gimpimage-color-profile.h"
38 #include "core/gimpimage-convert-indexed.h"
39 #include "core/gimpimage-convert-precision.h"
40 #include "core/gimpimage-convert-type.h"
41 #include "core/gimpimage-crop.h"
42 #include "core/gimpimage-duplicate.h"
43 #include "core/gimpimage-flip.h"
44 #include "core/gimpimage-merge.h"
45 #include "core/gimpimage-resize.h"
46 #include "core/gimpimage-rotate.h"
47 #include "core/gimpimage-scale.h"
48 #include "core/gimpimage-undo.h"
49 #include "core/gimpitem.h"
50 #include "core/gimppickable.h"
51 #include "core/gimppickable-auto-shrink.h"
52 #include "core/gimpprogress.h"
53
54 #include "widgets/gimpdialogfactory.h"
55 #include "widgets/gimpdock.h"
56 #include "widgets/gimphelp-ids.h"
57 #include "widgets/gimpwidgets-utils.h"
58
59 #include "display/gimpdisplay.h"
60 #include "display/gimpdisplayshell.h"
61
62 #include "dialogs/dialogs.h"
63 #include "dialogs/color-profile-dialog.h"
64 #include "dialogs/convert-indexed-dialog.h"
65 #include "dialogs/convert-precision-dialog.h"
66 #include "dialogs/grid-dialog.h"
67 #include "dialogs/image-merge-layers-dialog.h"
68 #include "dialogs/image-new-dialog.h"
69 #include "dialogs/image-properties-dialog.h"
70 #include "dialogs/image-scale-dialog.h"
71 #include "dialogs/print-size-dialog.h"
72 #include "dialogs/resize-dialog.h"
73
74 #include "actions.h"
75 #include "image-commands.h"
76
77 #include "gimp-intl.h"
78
79
80 /* local function prototypes */
81
82 static void image_convert_rgb_callback (GtkWidget *dialog,
83 GimpImage *image,
84 GimpColorProfile *new_profile,
85 GFile *new_file,
86 GimpColorRenderingIntent intent,
87 gboolean bpc,
88 gpointer user_data);
89
90 static void image_convert_gray_callback (GtkWidget *dialog,
91 GimpImage *image,
92 GimpColorProfile *new_profile,
93 GFile *new_file,
94 GimpColorRenderingIntent intent,
95 gboolean bpc,
96 gpointer user_data);
97
98 static void image_convert_indexed_callback (GtkWidget *dialog,
99 GimpImage *image,
100 GimpConvertPaletteType palette_type,
101 gint max_colors,
102 gboolean remove_duplicates,
103 GimpConvertDitherType dither_type,
104 gboolean dither_alpha,
105 gboolean dither_text_layers,
106 GimpPalette *custom_palette,
107 gpointer user_data);
108
109 static void image_convert_precision_callback (GtkWidget *dialog,
110 GimpImage *image,
111 GimpPrecision precision,
112 GeglDitherMethod layer_dither_method,
113 GeglDitherMethod text_layer_dither_method,
114 GeglDitherMethod mask_dither_method,
115 gpointer user_data);
116
117 static void image_profile_assign_callback (GtkWidget *dialog,
118 GimpImage *image,
119 GimpColorProfile *new_profile,
120 GFile *new_file,
121 GimpColorRenderingIntent intent,
122 gboolean bpc,
123 gpointer user_data);
124
125 static void image_profile_convert_callback (GtkWidget *dialog,
126 GimpImage *image,
127 GimpColorProfile *new_profile,
128 GFile *new_file,
129 GimpColorRenderingIntent intent,
130 gboolean bpc,
131 gpointer user_data);
132
133 static void image_resize_callback (GtkWidget *dialog,
134 GimpViewable *viewable,
135 GimpContext *context,
136 gint width,
137 gint height,
138 GimpUnit unit,
139 gint offset_x,
140 gint offset_y,
141 GimpFillType fill_type,
142 GimpItemSet layer_set,
143 gboolean resize_text_layers,
144 gpointer user_data);
145
146 static void image_print_size_callback (GtkWidget *dialog,
147 GimpImage *image,
148 gdouble xresolution,
149 gdouble yresolution,
150 GimpUnit resolution_unit,
151 gpointer user_data);
152
153 static void image_scale_callback (GtkWidget *dialog,
154 GimpViewable *viewable,
155 gint width,
156 gint height,
157 GimpUnit unit,
158 GimpInterpolationType interpolation,
159 gdouble xresolution,
160 gdouble yresolution,
161 GimpUnit resolution_unit,
162 gpointer user_data);
163
164 static void image_merge_layers_callback (GtkWidget *dialog,
165 GimpImage *image,
166 GimpContext *context,
167 GimpMergeType merge_type,
168 gboolean merge_active_group,
169 gboolean discard_invisible,
170 gpointer user_data);
171
172
173 /* private variables */
174
175 static GimpUnit image_resize_unit = GIMP_UNIT_PIXEL;
176 static GimpUnit image_scale_unit = GIMP_UNIT_PIXEL;
177 static GimpInterpolationType image_scale_interp = -1;
178 static GimpPalette *image_convert_indexed_custom_palette = NULL;
179
180
181 /* public functions */
182
183 void
image_new_cmd_callback(GimpAction * action,GVariant * value,gpointer data)184 image_new_cmd_callback (GimpAction *action,
185 GVariant *value,
186 gpointer data)
187 {
188 GtkWidget *widget;
189 GtkWidget *dialog;
190 return_if_no_widget (widget, data);
191
192 dialog = gimp_dialog_factory_dialog_new (gimp_dialog_factory_get_singleton (),
193 gtk_widget_get_screen (widget),
194 gimp_widget_get_monitor (widget),
195 NULL /*ui_manager*/,
196 "gimp-image-new-dialog", -1, FALSE);
197
198 if (dialog)
199 {
200 GimpImage *image = action_data_get_image (data);
201
202 image_new_dialog_set (dialog, image, NULL);
203
204 gtk_window_present (GTK_WINDOW (dialog));
205 }
206 }
207
208 void
image_duplicate_cmd_callback(GimpAction * action,GVariant * value,gpointer data)209 image_duplicate_cmd_callback (GimpAction *action,
210 GVariant *value,
211 gpointer data)
212 {
213 GimpDisplay *display;
214 GimpImage *image;
215 GimpDisplayShell *shell;
216 GimpImage *new_image;
217 return_if_no_display (display, data);
218
219 image = gimp_display_get_image (display);
220 shell = gimp_display_get_shell (display);
221
222 new_image = gimp_image_duplicate (image);
223
224 gimp_create_display (new_image->gimp, new_image, shell->unit,
225 gimp_zoom_model_get_factor (shell->zoom),
226 G_OBJECT (gtk_widget_get_screen (GTK_WIDGET (shell))),
227 gimp_widget_get_monitor (GTK_WIDGET (shell)));
228
229 g_object_unref (new_image);
230 }
231
232 void
image_convert_base_type_cmd_callback(GimpAction * action,GVariant * value,gpointer data)233 image_convert_base_type_cmd_callback (GimpAction *action,
234 GVariant *value,
235 gpointer data)
236 {
237 GimpImage *image;
238 GimpDisplay *display;
239 GtkWidget *widget;
240 GimpDialogConfig *config;
241 GtkWidget *dialog;
242 GimpImageBaseType base_type;
243 GError *error = NULL;
244 return_if_no_image (image, data);
245 return_if_no_display (display, data);
246 return_if_no_widget (widget, data);
247
248 base_type = (GimpImageBaseType) g_variant_get_int32 (value);
249
250 if (base_type == gimp_image_get_base_type (image))
251 return;
252
253 #define CONVERT_TYPE_DIALOG_KEY "gimp-convert-type-dialog"
254
255 dialog = dialogs_get_dialog (G_OBJECT (image), CONVERT_TYPE_DIALOG_KEY);
256
257 if (dialog)
258 {
259 gtk_widget_destroy (dialog);
260 dialog = NULL;
261 }
262
263 config = GIMP_DIALOG_CONFIG (image->gimp->config);
264
265 switch (base_type)
266 {
267 case GIMP_RGB:
268 case GIMP_GRAY:
269 if (gimp_image_get_color_profile (image))
270 {
271 ColorProfileDialogType dialog_type;
272 GimpColorProfileCallback callback;
273 GimpColorProfile *current_profile;
274 GimpColorProfile *default_profile;
275 const Babl *format;
276
277 current_profile =
278 gimp_color_managed_get_color_profile (GIMP_COLOR_MANAGED (image));
279
280 if (base_type == GIMP_RGB)
281 {
282 dialog_type = COLOR_PROFILE_DIALOG_CONVERT_TO_RGB;
283 callback = image_convert_rgb_callback;
284
285 format = gimp_babl_format (GIMP_RGB,
286 gimp_image_get_precision (image),
287 TRUE);
288 default_profile = gimp_babl_format_get_color_profile (format);
289 }
290 else
291 {
292 dialog_type = COLOR_PROFILE_DIALOG_CONVERT_TO_GRAY;
293 callback = image_convert_gray_callback;
294
295 format = gimp_babl_format (GIMP_GRAY,
296 gimp_image_get_precision (image),
297 TRUE);
298 default_profile = gimp_babl_format_get_color_profile (format);
299 }
300
301 dialog = color_profile_dialog_new (dialog_type,
302 image,
303 action_data_get_context (data),
304 widget,
305 current_profile,
306 default_profile,
307 0, 0,
308 callback,
309 display);
310 }
311 else if (! gimp_image_convert_type (image, base_type, NULL, NULL, &error))
312 {
313 gimp_message_literal (image->gimp,
314 G_OBJECT (widget), GIMP_MESSAGE_WARNING,
315 error->message);
316 g_clear_error (&error);
317 }
318 break;
319
320 case GIMP_INDEXED:
321 dialog = convert_indexed_dialog_new (image,
322 action_data_get_context (data),
323 widget,
324 config->image_convert_indexed_palette_type,
325 config->image_convert_indexed_max_colors,
326 config->image_convert_indexed_remove_duplicates,
327 config->image_convert_indexed_dither_type,
328 config->image_convert_indexed_dither_alpha,
329 config->image_convert_indexed_dither_text_layers,
330 image_convert_indexed_custom_palette,
331 image_convert_indexed_callback,
332 display);
333 break;
334 }
335
336 if (dialog)
337 {
338 dialogs_attach_dialog (G_OBJECT (image),
339 CONVERT_TYPE_DIALOG_KEY, dialog);
340 gtk_window_present (GTK_WINDOW (dialog));
341 }
342
343 /* always flush, also when only the indexed dialog was shown, so
344 * the menu items get updated back to the current image type
345 */
346 gimp_image_flush (image);
347 }
348
349 void
image_convert_precision_cmd_callback(GimpAction * action,GVariant * value,gpointer data)350 image_convert_precision_cmd_callback (GimpAction *action,
351 GVariant *value,
352 gpointer data)
353 {
354 GimpImage *image;
355 GimpDisplay *display;
356 GtkWidget *widget;
357 GimpDialogConfig *config;
358 GtkWidget *dialog;
359 GimpComponentType component_type;
360 return_if_no_image (image, data);
361 return_if_no_display (display, data);
362 return_if_no_widget (widget, data);
363
364 component_type = (GimpComponentType) g_variant_get_int32 (value);
365
366 if (component_type == gimp_image_get_component_type (image))
367 return;
368
369 #define CONVERT_PRECISION_DIALOG_KEY "gimp-convert-precision-dialog"
370
371 dialog = dialogs_get_dialog (G_OBJECT (image), CONVERT_PRECISION_DIALOG_KEY);
372
373 if (dialog)
374 {
375 gtk_widget_destroy (dialog);
376 dialog = NULL;
377 }
378
379 config = GIMP_DIALOG_CONFIG (image->gimp->config);
380
381 dialog = convert_precision_dialog_new (image,
382 action_data_get_context (data),
383 widget,
384 component_type,
385 config->image_convert_precision_layer_dither_method,
386 config->image_convert_precision_text_layer_dither_method,
387 config->image_convert_precision_channel_dither_method,
388 image_convert_precision_callback,
389 display);
390
391 dialogs_attach_dialog (G_OBJECT (image),
392 CONVERT_PRECISION_DIALOG_KEY, dialog);
393
394 gtk_window_present (GTK_WINDOW (dialog));
395
396 /* see comment above */
397 gimp_image_flush (image);
398 }
399
400 void
image_convert_gamma_cmd_callback(GimpAction * action,GVariant * value,gpointer data)401 image_convert_gamma_cmd_callback (GimpAction *action,
402 GVariant *value,
403 gpointer data)
404 {
405 GimpImage *image;
406 GimpDisplay *display;
407 gboolean linear;
408 GimpPrecision precision;
409 return_if_no_image (image, data);
410 return_if_no_display (display, data);
411
412 linear = (gboolean) g_variant_get_int32 (value);
413
414 if (linear == gimp_babl_format_get_linear (gimp_image_get_layer_format (image,
415 FALSE)))
416 return;
417
418 precision = gimp_babl_precision (gimp_image_get_component_type (image),
419 linear);
420
421 gimp_image_convert_precision (image, precision,
422 GEGL_DITHER_NONE,
423 GEGL_DITHER_NONE,
424 GEGL_DITHER_NONE,
425 GIMP_PROGRESS (display));
426 gimp_image_flush (image);
427 }
428
429 void
image_color_management_enabled_cmd_callback(GimpAction * action,GVariant * value,gpointer data)430 image_color_management_enabled_cmd_callback (GimpAction *action,
431 GVariant *value,
432 gpointer data)
433 {
434 GimpImage *image;
435 gboolean enabled;
436 return_if_no_image (image, data);
437
438 enabled = g_variant_get_boolean (value);
439
440 if (enabled != gimp_image_get_is_color_managed (image))
441 {
442 gimp_image_set_is_color_managed (image, enabled, TRUE);
443 gimp_image_flush (image);
444 }
445 }
446
447 void
image_color_profile_assign_cmd_callback(GimpAction * action,GVariant * value,gpointer data)448 image_color_profile_assign_cmd_callback (GimpAction *action,
449 GVariant *value,
450 gpointer data)
451 {
452 GimpImage *image;
453 GimpDisplay *display;
454 GtkWidget *widget;
455 GtkWidget *dialog;
456 return_if_no_image (image, data);
457 return_if_no_display (display, data);
458 return_if_no_widget (widget, data);
459
460 #define PROFILE_ASSIGN_DIALOG_KEY "gimp-profile-assign-dialog"
461
462 dialog = dialogs_get_dialog (G_OBJECT (image), PROFILE_ASSIGN_DIALOG_KEY);
463
464 if (! dialog)
465 {
466 GimpColorProfile *current_profile;
467 GimpColorProfile *default_profile;
468
469 current_profile = gimp_color_managed_get_color_profile (GIMP_COLOR_MANAGED (image));
470 default_profile = gimp_image_get_builtin_color_profile (image);
471
472 dialog = color_profile_dialog_new (COLOR_PROFILE_DIALOG_ASSIGN_PROFILE,
473 image,
474 action_data_get_context (data),
475 widget,
476 current_profile,
477 default_profile,
478 0, 0,
479 image_profile_assign_callback,
480 display);
481
482 dialogs_attach_dialog (G_OBJECT (image),
483 PROFILE_ASSIGN_DIALOG_KEY, dialog);
484 }
485
486 gtk_window_present (GTK_WINDOW (dialog));
487 }
488
489 void
image_color_profile_convert_cmd_callback(GimpAction * action,GVariant * value,gpointer data)490 image_color_profile_convert_cmd_callback (GimpAction *action,
491 GVariant *value,
492 gpointer data)
493 {
494 GimpImage *image;
495 GimpDisplay *display;
496 GtkWidget *widget;
497 GtkWidget *dialog;
498 return_if_no_image (image, data);
499 return_if_no_display (display, data);
500 return_if_no_widget (widget, data);
501
502 #define PROFILE_CONVERT_DIALOG_KEY "gimp-profile-convert-dialog"
503
504 dialog = dialogs_get_dialog (G_OBJECT (image), PROFILE_CONVERT_DIALOG_KEY);
505
506 if (! dialog)
507 {
508 GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config);
509 GimpColorProfile *current_profile;
510 GimpColorProfile *default_profile;
511
512 current_profile = gimp_color_managed_get_color_profile (GIMP_COLOR_MANAGED (image));
513 default_profile = gimp_image_get_builtin_color_profile (image);
514
515 dialog = color_profile_dialog_new (COLOR_PROFILE_DIALOG_CONVERT_TO_PROFILE,
516 image,
517 action_data_get_context (data),
518 widget,
519 current_profile,
520 default_profile,
521 config->image_convert_profile_intent,
522 config->image_convert_profile_bpc,
523 image_profile_convert_callback,
524 display);
525
526 dialogs_attach_dialog (G_OBJECT (image),
527 PROFILE_CONVERT_DIALOG_KEY, dialog);
528 }
529
530 gtk_window_present (GTK_WINDOW (dialog));
531 }
532
533 void
image_color_profile_discard_cmd_callback(GimpAction * action,GVariant * value,gpointer data)534 image_color_profile_discard_cmd_callback (GimpAction *action,
535 GVariant *value,
536 gpointer data)
537 {
538 GimpImage *image;
539 return_if_no_image (image, data);
540
541 gimp_image_set_color_profile (image, NULL, NULL);
542 gimp_image_flush (image);
543 }
544
545 static void
image_profile_save_dialog_response(GtkWidget * dialog,gint response_id,GimpImage * image)546 image_profile_save_dialog_response (GtkWidget *dialog,
547 gint response_id,
548 GimpImage *image)
549 {
550 if (response_id == GTK_RESPONSE_ACCEPT)
551 {
552 GimpColorProfile *profile;
553 GFile *file;
554 GError *error = NULL;
555
556 profile = gimp_color_managed_get_color_profile (GIMP_COLOR_MANAGED (image));
557 file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
558
559 if (! file)
560 return;
561
562 if (! gimp_color_profile_save_to_file (profile, file, &error))
563 {
564 gimp_message (image->gimp, NULL,
565 GIMP_MESSAGE_WARNING,
566 _("Saving color profile failed: %s"),
567 error->message);
568 g_clear_error (&error);
569 g_object_unref (file);
570 return;
571 }
572
573 g_object_unref (file);
574 }
575
576 gtk_widget_destroy (dialog);
577 }
578
579 void
image_color_profile_save_cmd_callback(GimpAction * action,GVariant * value,gpointer data)580 image_color_profile_save_cmd_callback (GimpAction *action,
581 GVariant *value,
582 gpointer data)
583 {
584 GimpImage *image;
585 GimpDisplay *display;
586 GtkWidget *widget;
587 GtkWidget *dialog;
588 return_if_no_image (image, data);
589 return_if_no_display (display, data);
590 return_if_no_widget (widget, data);
591
592 #define PROFILE_SAVE_DIALOG_KEY "gimp-profile-save-dialog"
593
594 dialog = dialogs_get_dialog (G_OBJECT (image), PROFILE_SAVE_DIALOG_KEY);
595
596 if (! dialog)
597 {
598 GtkWindow *toplevel;
599 GimpColorProfile *profile;
600 gchar *basename;
601
602 toplevel = GTK_WINDOW (gtk_widget_get_toplevel (widget));
603 profile = gimp_color_managed_get_color_profile (GIMP_COLOR_MANAGED (image));
604
605 dialog =
606 gimp_color_profile_chooser_dialog_new (_("Save Color Profile"),
607 toplevel,
608 GTK_FILE_CHOOSER_ACTION_SAVE);
609
610 gimp_color_profile_chooser_dialog_connect_path (dialog,
611 G_OBJECT (image->gimp->config),
612 "color-profile-path");
613
614 basename = g_strconcat (gimp_color_profile_get_label (profile),
615 ".icc", NULL);
616 gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), basename);
617 g_free (basename);
618
619 g_signal_connect (dialog, "response",
620 G_CALLBACK (image_profile_save_dialog_response),
621 image);
622
623 dialogs_attach_dialog (G_OBJECT (image), PROFILE_SAVE_DIALOG_KEY, dialog);
624 }
625
626 gtk_window_present (GTK_WINDOW (dialog));
627 }
628
629 void
image_resize_cmd_callback(GimpAction * action,GVariant * value,gpointer data)630 image_resize_cmd_callback (GimpAction *action,
631 GVariant *value,
632 gpointer data)
633 {
634 GimpImage *image;
635 GtkWidget *widget;
636 GimpDisplay *display;
637 GtkWidget *dialog;
638 return_if_no_image (image, data);
639 return_if_no_widget (widget, data);
640 return_if_no_display (display, data);
641
642 #define RESIZE_DIALOG_KEY "gimp-resize-dialog"
643
644 dialog = dialogs_get_dialog (G_OBJECT (image), RESIZE_DIALOG_KEY);
645
646 if (! dialog)
647 {
648 GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config);
649
650 if (image_resize_unit != GIMP_UNIT_PERCENT)
651 image_resize_unit = gimp_display_get_shell (display)->unit;
652
653 dialog = resize_dialog_new (GIMP_VIEWABLE (image),
654 action_data_get_context (data),
655 _("Set Image Canvas Size"),
656 "gimp-image-resize",
657 widget,
658 gimp_standard_help_func,
659 GIMP_HELP_IMAGE_RESIZE,
660 image_resize_unit,
661 config->image_resize_fill_type,
662 config->image_resize_layer_set,
663 config->image_resize_resize_text_layers,
664 image_resize_callback,
665 display);
666
667 dialogs_attach_dialog (G_OBJECT (image), RESIZE_DIALOG_KEY, dialog);
668 }
669
670 gtk_window_present (GTK_WINDOW (dialog));
671 }
672
673 void
image_resize_to_layers_cmd_callback(GimpAction * action,GVariant * value,gpointer data)674 image_resize_to_layers_cmd_callback (GimpAction *action,
675 GVariant *value,
676 gpointer data)
677 {
678 GimpDisplay *display;
679 GimpImage *image;
680 GimpProgress *progress;
681 return_if_no_display (display, data);
682
683 image = gimp_display_get_image (display);
684
685 progress = gimp_progress_start (GIMP_PROGRESS (display), FALSE,
686 _("Resizing"));
687
688 gimp_image_resize_to_layers (image,
689 action_data_get_context (data),
690 NULL, NULL, NULL, NULL, progress);
691
692 if (progress)
693 gimp_progress_end (progress);
694
695 gimp_image_flush (image);
696 }
697
698 void
image_resize_to_selection_cmd_callback(GimpAction * action,GVariant * value,gpointer data)699 image_resize_to_selection_cmd_callback (GimpAction *action,
700 GVariant *value,
701 gpointer data)
702 {
703 GimpDisplay *display;
704 GimpImage *image;
705 GimpProgress *progress;
706 return_if_no_display (display, data);
707
708 image = gimp_display_get_image (display);
709
710 progress = gimp_progress_start (GIMP_PROGRESS (display), FALSE,
711 _("Resizing"));
712
713 gimp_image_resize_to_selection (image,
714 action_data_get_context (data),
715 progress);
716
717 if (progress)
718 gimp_progress_end (progress);
719
720 gimp_image_flush (image);
721 }
722
723 void
image_print_size_cmd_callback(GimpAction * action,GVariant * value,gpointer data)724 image_print_size_cmd_callback (GimpAction *action,
725 GVariant *value,
726 gpointer data)
727 {
728 GimpDisplay *display;
729 GimpImage *image;
730 GtkWidget *widget;
731 GtkWidget *dialog;
732 return_if_no_display (display, data);
733 return_if_no_widget (widget, data);
734
735 image = gimp_display_get_image (display);
736
737 #define PRINT_SIZE_DIALOG_KEY "gimp-print-size-dialog"
738
739 dialog = dialogs_get_dialog (G_OBJECT (image), PRINT_SIZE_DIALOG_KEY);
740
741 if (! dialog)
742 {
743 dialog = print_size_dialog_new (image,
744 action_data_get_context (data),
745 _("Set Image Print Resolution"),
746 "gimp-image-print-size",
747 widget,
748 gimp_standard_help_func,
749 GIMP_HELP_IMAGE_PRINT_SIZE,
750 image_print_size_callback,
751 NULL);
752
753 dialogs_attach_dialog (G_OBJECT (image), PRINT_SIZE_DIALOG_KEY, dialog);
754 }
755
756 gtk_window_present (GTK_WINDOW (dialog));
757 }
758
759 void
image_scale_cmd_callback(GimpAction * action,GVariant * value,gpointer data)760 image_scale_cmd_callback (GimpAction *action,
761 GVariant *value,
762 gpointer data)
763 {
764 GimpDisplay *display;
765 GimpImage *image;
766 GtkWidget *widget;
767 GtkWidget *dialog;
768 return_if_no_display (display, data);
769 return_if_no_widget (widget, data);
770
771 image = gimp_display_get_image (display);
772
773 #define SCALE_DIALOG_KEY "gimp-scale-dialog"
774
775 dialog = dialogs_get_dialog (G_OBJECT (image), SCALE_DIALOG_KEY);
776
777 if (! dialog)
778 {
779 if (image_scale_unit != GIMP_UNIT_PERCENT)
780 image_scale_unit = gimp_display_get_shell (display)->unit;
781
782 if (image_scale_interp == -1)
783 image_scale_interp = display->gimp->config->interpolation_type;
784
785 dialog = image_scale_dialog_new (image,
786 action_data_get_context (data),
787 widget,
788 image_scale_unit,
789 image_scale_interp,
790 image_scale_callback,
791 display);
792
793 dialogs_attach_dialog (G_OBJECT (image), SCALE_DIALOG_KEY, dialog);
794 }
795
796 gtk_window_present (GTK_WINDOW (dialog));
797 }
798
799 void
image_flip_cmd_callback(GimpAction * action,GVariant * value,gpointer data)800 image_flip_cmd_callback (GimpAction *action,
801 GVariant *value,
802 gpointer data)
803 {
804 GimpDisplay *display;
805 GimpImage *image;
806 GimpProgress *progress;
807 GimpOrientationType orientation;
808 return_if_no_display (display, data);
809
810 orientation = (GimpOrientationType) g_variant_get_int32 (value);
811
812 image = gimp_display_get_image (display);
813
814 progress = gimp_progress_start (GIMP_PROGRESS (display), FALSE,
815 _("Flipping"));
816
817 gimp_image_flip (image, action_data_get_context (data),
818 orientation, progress);
819
820 if (progress)
821 gimp_progress_end (progress);
822
823 gimp_image_flush (image);
824 }
825
826 void
image_rotate_cmd_callback(GimpAction * action,GVariant * value,gpointer data)827 image_rotate_cmd_callback (GimpAction *action,
828 GVariant *value,
829 gpointer data)
830 {
831 GimpDisplay *display;
832 GimpImage *image;
833 GimpProgress *progress;
834 GimpRotationType rotation;
835 return_if_no_display (display, data);
836
837 rotation = (GimpRotationType) g_variant_get_int32 (value);
838
839 image = gimp_display_get_image (display);
840
841 progress = gimp_progress_start (GIMP_PROGRESS (display), FALSE,
842 _("Rotating"));
843
844 gimp_image_rotate (image, action_data_get_context (data),
845 rotation, progress);
846
847 if (progress)
848 gimp_progress_end (progress);
849
850 gimp_image_flush (image);
851 }
852
853 void
image_crop_to_selection_cmd_callback(GimpAction * action,GVariant * value,gpointer data)854 image_crop_to_selection_cmd_callback (GimpAction *action,
855 GVariant *value,
856 gpointer data)
857 {
858 GimpImage *image;
859 GtkWidget *widget;
860 gint x, y;
861 gint width, height;
862 return_if_no_image (image, data);
863 return_if_no_widget (widget, data);
864
865 if (! gimp_item_bounds (GIMP_ITEM (gimp_image_get_mask (image)),
866 &x, &y, &width, &height))
867 {
868 gimp_message_literal (image->gimp,
869 G_OBJECT (widget), GIMP_MESSAGE_WARNING,
870 _("Cannot crop because the current selection "
871 "is empty."));
872 return;
873 }
874
875 gimp_image_crop (image,
876 action_data_get_context (data), GIMP_FILL_TRANSPARENT,
877 x, y, width, height, TRUE);
878 gimp_image_flush (image);
879 }
880
881 void
image_crop_to_content_cmd_callback(GimpAction * action,GVariant * value,gpointer data)882 image_crop_to_content_cmd_callback (GimpAction *action,
883 GVariant *value,
884 gpointer data)
885 {
886 GimpImage *image;
887 GtkWidget *widget;
888 gint x, y;
889 gint width, height;
890 return_if_no_image (image, data);
891 return_if_no_widget (widget, data);
892
893 switch (gimp_pickable_auto_shrink (GIMP_PICKABLE (image),
894 0, 0,
895 gimp_image_get_width (image),
896 gimp_image_get_height (image),
897 &x, &y, &width, &height))
898 {
899 case GIMP_AUTO_SHRINK_SHRINK:
900 gimp_image_crop (image,
901 action_data_get_context (data), GIMP_FILL_TRANSPARENT,
902 x, y, width, height, TRUE);
903 gimp_image_flush (image);
904 break;
905
906 case GIMP_AUTO_SHRINK_EMPTY:
907 gimp_message_literal (image->gimp,
908 G_OBJECT (widget), GIMP_MESSAGE_INFO,
909 _("Cannot crop because the image has no content."));
910 break;
911
912 case GIMP_AUTO_SHRINK_UNSHRINKABLE:
913 gimp_message_literal (image->gimp,
914 G_OBJECT (widget), GIMP_MESSAGE_INFO,
915 _("Cannot crop because the image is already "
916 "cropped to its content."));
917 break;
918 }
919 }
920
921 void
image_merge_layers_cmd_callback(GimpAction * action,GVariant * value,gpointer data)922 image_merge_layers_cmd_callback (GimpAction *action,
923 GVariant *value,
924 gpointer data)
925 {
926 GtkWidget *dialog;
927 GimpImage *image;
928 GimpDisplay *display;
929 GtkWidget *widget;
930 return_if_no_image (image, data);
931 return_if_no_display (display, data);
932 return_if_no_widget (widget, data);
933
934 #define MERGE_LAYERS_DIALOG_KEY "gimp-merge-layers-dialog"
935
936 dialog = dialogs_get_dialog (G_OBJECT (image), MERGE_LAYERS_DIALOG_KEY);
937
938 if (! dialog)
939 {
940 GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config);
941
942 dialog = image_merge_layers_dialog_new (image,
943 action_data_get_context (data),
944 widget,
945 config->layer_merge_type,
946 config->layer_merge_active_group_only,
947 config->layer_merge_discard_invisible,
948 image_merge_layers_callback,
949 display);
950
951 dialogs_attach_dialog (G_OBJECT (image), MERGE_LAYERS_DIALOG_KEY, dialog);
952 }
953
954 gtk_window_present (GTK_WINDOW (dialog));
955 }
956
957 void
image_merge_layers_last_vals_cmd_callback(GimpAction * action,GVariant * value,gpointer data)958 image_merge_layers_last_vals_cmd_callback (GimpAction *action,
959 GVariant *value,
960 gpointer data)
961 {
962 GimpImage *image;
963 GimpDisplay *display;
964 GimpDialogConfig *config;
965 return_if_no_image (image, data);
966 return_if_no_display (display, data);
967
968 config = GIMP_DIALOG_CONFIG (image->gimp->config);
969
970 image_merge_layers_callback (NULL,
971 image,
972 action_data_get_context (data),
973 config->layer_merge_type,
974 config->layer_merge_active_group_only,
975 config->layer_merge_discard_invisible,
976 display);
977 }
978
979 void
image_flatten_image_cmd_callback(GimpAction * action,GVariant * value,gpointer data)980 image_flatten_image_cmd_callback (GimpAction *action,
981 GVariant *value,
982 gpointer data)
983 {
984 GimpImage *image;
985 GimpDisplay *display;
986 GtkWidget *widget;
987 GError *error = NULL;
988 return_if_no_image (image, data);
989 return_if_no_display (display, data);
990 return_if_no_widget (widget, data);
991
992 if (! gimp_image_flatten (image, action_data_get_context (data),
993 GIMP_PROGRESS (display), &error))
994 {
995 gimp_message_literal (image->gimp,
996 G_OBJECT (widget), GIMP_MESSAGE_WARNING,
997 error->message);
998 g_clear_error (&error);
999 return;
1000 }
1001
1002 gimp_image_flush (image);
1003 }
1004
1005 void
image_configure_grid_cmd_callback(GimpAction * action,GVariant * value,gpointer data)1006 image_configure_grid_cmd_callback (GimpAction *action,
1007 GVariant *value,
1008 gpointer data)
1009 {
1010 GimpDisplay *display;
1011 GimpImage *image;
1012 GtkWidget *dialog;
1013 return_if_no_display (display, data);
1014
1015 image = gimp_display_get_image (display);
1016
1017 #define GRID_DIALOG_KEY "gimp-grid-dialog"
1018
1019 dialog = dialogs_get_dialog (G_OBJECT (image), GRID_DIALOG_KEY);
1020
1021 if (! dialog)
1022 {
1023 GimpDisplayShell *shell = gimp_display_get_shell (display);
1024
1025 dialog = grid_dialog_new (image,
1026 action_data_get_context (data),
1027 gtk_widget_get_toplevel (GTK_WIDGET (shell)));
1028
1029 dialogs_attach_dialog (G_OBJECT (image), GRID_DIALOG_KEY, dialog);
1030 }
1031
1032 gtk_window_present (GTK_WINDOW (dialog));
1033 }
1034
1035 void
image_properties_cmd_callback(GimpAction * action,GVariant * value,gpointer data)1036 image_properties_cmd_callback (GimpAction *action,
1037 GVariant *value,
1038 gpointer data)
1039 {
1040 GimpDisplay *display;
1041 GimpImage *image;
1042 GtkWidget *dialog;
1043 return_if_no_display (display, data);
1044
1045 image = gimp_display_get_image (display);
1046
1047 #define PROPERTIES_DIALOG_KEY "gimp-image-properties-dialog"
1048
1049 dialog = dialogs_get_dialog (G_OBJECT (image), PROPERTIES_DIALOG_KEY);
1050
1051 if (! dialog)
1052 {
1053 GimpDisplayShell *shell = gimp_display_get_shell (display);
1054
1055 dialog = image_properties_dialog_new (image,
1056 action_data_get_context (data),
1057 gtk_widget_get_toplevel (GTK_WIDGET (shell)));
1058
1059 dialogs_attach_dialog (G_OBJECT (image), PROPERTIES_DIALOG_KEY, dialog);
1060 }
1061
1062 gtk_window_present (GTK_WINDOW (dialog));
1063 }
1064
1065
1066 /* private functions */
1067
1068 static void
image_convert_rgb_callback(GtkWidget * dialog,GimpImage * image,GimpColorProfile * new_profile,GFile * new_file,GimpColorRenderingIntent intent,gboolean bpc,gpointer user_data)1069 image_convert_rgb_callback (GtkWidget *dialog,
1070 GimpImage *image,
1071 GimpColorProfile *new_profile,
1072 GFile *new_file,
1073 GimpColorRenderingIntent intent,
1074 gboolean bpc,
1075 gpointer user_data)
1076 {
1077 GimpProgress *progress = user_data;
1078 GError *error = NULL;
1079
1080 progress = gimp_progress_start (progress, FALSE,
1081 _("Converting to RGB (%s)"),
1082 gimp_color_profile_get_label (new_profile));
1083
1084 if (! gimp_image_convert_type (image, GIMP_RGB, new_profile,
1085 progress, &error))
1086 {
1087 gimp_message (image->gimp, G_OBJECT (dialog),
1088 GIMP_MESSAGE_ERROR,
1089 "%s", error->message);
1090 g_clear_error (&error);
1091
1092 if (progress)
1093 gimp_progress_end (progress);
1094
1095 return;
1096 }
1097
1098 if (progress)
1099 gimp_progress_end (progress);
1100
1101 gimp_image_flush (image);
1102
1103 gtk_widget_destroy (dialog);
1104 }
1105
1106 static void
image_convert_gray_callback(GtkWidget * dialog,GimpImage * image,GimpColorProfile * new_profile,GFile * new_file,GimpColorRenderingIntent intent,gboolean bpc,gpointer user_data)1107 image_convert_gray_callback (GtkWidget *dialog,
1108 GimpImage *image,
1109 GimpColorProfile *new_profile,
1110 GFile *new_file,
1111 GimpColorRenderingIntent intent,
1112 gboolean bpc,
1113 gpointer user_data)
1114 {
1115 GimpProgress *progress = user_data;
1116 GError *error = NULL;
1117
1118 progress = gimp_progress_start (progress, FALSE,
1119 _("Converting to grayscale (%s)"),
1120 gimp_color_profile_get_label (new_profile));
1121
1122 if (! gimp_image_convert_type (image, GIMP_GRAY, new_profile,
1123 progress, &error))
1124 {
1125 gimp_message (image->gimp, G_OBJECT (dialog),
1126 GIMP_MESSAGE_ERROR,
1127 "%s", error->message);
1128 g_clear_error (&error);
1129
1130 if (progress)
1131 gimp_progress_end (progress);
1132
1133 return;
1134 }
1135
1136 if (progress)
1137 gimp_progress_end (progress);
1138
1139 gimp_image_flush (image);
1140
1141 gtk_widget_destroy (dialog);
1142 }
1143
1144 static void
image_convert_indexed_callback(GtkWidget * dialog,GimpImage * image,GimpConvertPaletteType palette_type,gint max_colors,gboolean remove_duplicates,GimpConvertDitherType dither_type,gboolean dither_alpha,gboolean dither_text_layers,GimpPalette * custom_palette,gpointer user_data)1145 image_convert_indexed_callback (GtkWidget *dialog,
1146 GimpImage *image,
1147 GimpConvertPaletteType palette_type,
1148 gint max_colors,
1149 gboolean remove_duplicates,
1150 GimpConvertDitherType dither_type,
1151 gboolean dither_alpha,
1152 gboolean dither_text_layers,
1153 GimpPalette *custom_palette,
1154 gpointer user_data)
1155 {
1156 GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config);
1157 GimpDisplay *display = user_data;
1158 GimpProgress *progress;
1159 GError *error = NULL;
1160
1161 g_object_set (config,
1162 "image-convert-indexed-palette-type", palette_type,
1163 "image-convert-indexed-max-colors", max_colors,
1164 "image-convert-indexed-remove-duplicates", remove_duplicates,
1165 "image-convert-indexed-dither-type", dither_type,
1166 "image-convert-indexed-dither-alpha", dither_alpha,
1167 "image-convert-indexed-dither-text-layers", dither_text_layers,
1168 NULL);
1169
1170 if (image_convert_indexed_custom_palette)
1171 g_object_remove_weak_pointer (G_OBJECT (image_convert_indexed_custom_palette),
1172 (gpointer) &image_convert_indexed_custom_palette);
1173
1174 image_convert_indexed_custom_palette = custom_palette;
1175
1176 if (image_convert_indexed_custom_palette)
1177 g_object_add_weak_pointer (G_OBJECT (image_convert_indexed_custom_palette),
1178 (gpointer) &image_convert_indexed_custom_palette);
1179
1180 progress = gimp_progress_start (GIMP_PROGRESS (display), FALSE,
1181 _("Converting to indexed colors"));
1182
1183 if (! gimp_image_convert_indexed (image,
1184 config->image_convert_indexed_palette_type,
1185 config->image_convert_indexed_max_colors,
1186 config->image_convert_indexed_remove_duplicates,
1187 config->image_convert_indexed_dither_type,
1188 config->image_convert_indexed_dither_alpha,
1189 config->image_convert_indexed_dither_text_layers,
1190 image_convert_indexed_custom_palette,
1191 progress,
1192 &error))
1193 {
1194 gimp_message_literal (image->gimp, G_OBJECT (display),
1195 GIMP_MESSAGE_WARNING, error->message);
1196 g_clear_error (&error);
1197
1198 if (progress)
1199 gimp_progress_end (progress);
1200
1201 return;
1202 }
1203
1204 if (progress)
1205 gimp_progress_end (progress);
1206
1207 gimp_image_flush (image);
1208
1209 gtk_widget_destroy (dialog);
1210 }
1211
1212 static void
image_convert_precision_callback(GtkWidget * dialog,GimpImage * image,GimpPrecision precision,GeglDitherMethod layer_dither_method,GeglDitherMethod text_layer_dither_method,GeglDitherMethod channel_dither_method,gpointer user_data)1213 image_convert_precision_callback (GtkWidget *dialog,
1214 GimpImage *image,
1215 GimpPrecision precision,
1216 GeglDitherMethod layer_dither_method,
1217 GeglDitherMethod text_layer_dither_method,
1218 GeglDitherMethod channel_dither_method,
1219 gpointer user_data)
1220 {
1221 GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config);
1222 GimpProgress *progress = user_data;
1223 const gchar *enum_desc;
1224 const Babl *old_format;
1225 const Babl *new_format;
1226 gint old_bits;
1227 gint new_bits;
1228
1229 g_object_set (config,
1230 "image-convert-precision-layer-dither-method",
1231 layer_dither_method,
1232 "image-convert-precision-text-layer-dither-method",
1233 text_layer_dither_method,
1234 "image-convert-precision-channel-dither-method",
1235 channel_dither_method,
1236 NULL);
1237
1238 /* we do the same dither method checks here *and* in the dialog,
1239 * because the dialog leaves the passed dither methods untouched if
1240 * dithering is disabled and passes the original values to the
1241 * callback, in order not to change the values saved in
1242 * GimpDialogConfig.
1243 */
1244
1245 /* random formats with the right precision */
1246 old_format = gimp_image_get_layer_format (image, FALSE);
1247 new_format = gimp_babl_format (GIMP_RGB, precision, FALSE);
1248
1249 old_bits = (babl_format_get_bytes_per_pixel (old_format) * 8 /
1250 babl_format_get_n_components (old_format));
1251 new_bits = (babl_format_get_bytes_per_pixel (new_format) * 8 /
1252 babl_format_get_n_components (new_format));
1253
1254 if (new_bits >= old_bits ||
1255 new_bits > CONVERT_PRECISION_DIALOG_MAX_DITHER_BITS)
1256 {
1257 /* don't dither if we are converting to a higher bit depth,
1258 * or to more than MAX_DITHER_BITS.
1259 */
1260 layer_dither_method = GEGL_DITHER_NONE;
1261 text_layer_dither_method = GEGL_DITHER_NONE;
1262 channel_dither_method = GEGL_DITHER_NONE;
1263 }
1264
1265 gimp_enum_get_value (GIMP_TYPE_PRECISION, precision,
1266 NULL, NULL, &enum_desc, NULL);
1267
1268 progress = gimp_progress_start (progress, FALSE,
1269 _("Converting image to %s"),
1270 enum_desc);
1271
1272 gimp_image_convert_precision (image,
1273 precision,
1274 layer_dither_method,
1275 text_layer_dither_method,
1276 channel_dither_method,
1277 progress);
1278
1279 if (progress)
1280 gimp_progress_end (progress);
1281
1282 gimp_image_flush (image);
1283
1284 gtk_widget_destroy (dialog);
1285 }
1286
1287 static void
image_profile_assign_callback(GtkWidget * dialog,GimpImage * image,GimpColorProfile * new_profile,GFile * new_file,GimpColorRenderingIntent intent,gboolean bpc,gpointer user_data)1288 image_profile_assign_callback (GtkWidget *dialog,
1289 GimpImage *image,
1290 GimpColorProfile *new_profile,
1291 GFile *new_file,
1292 GimpColorRenderingIntent intent,
1293 gboolean bpc,
1294 gpointer user_data)
1295 {
1296 GError *error = NULL;
1297
1298 gimp_image_undo_group_start (image,
1299 GIMP_UNDO_GROUP_PARASITE_ATTACH,
1300 _("Assign color profile"));
1301
1302 if (! gimp_image_set_color_profile (image, new_profile, &error))
1303 {
1304 gimp_message (image->gimp, G_OBJECT (dialog),
1305 GIMP_MESSAGE_ERROR,
1306 "%s", error->message);
1307 g_clear_error (&error);
1308
1309 gimp_image_undo_group_end (image);
1310 gimp_image_undo (image);
1311
1312 return;
1313 }
1314
1315 gimp_image_set_is_color_managed (image, TRUE, TRUE);
1316
1317 /* omg... */
1318 gimp_image_parasite_detach (image, "icc-profile-name", TRUE);
1319
1320 gimp_image_undo_group_end (image);
1321
1322 gimp_image_flush (image);
1323
1324 gtk_widget_destroy (dialog);
1325 }
1326
1327 static void
image_profile_convert_callback(GtkWidget * dialog,GimpImage * image,GimpColorProfile * new_profile,GFile * new_file,GimpColorRenderingIntent intent,gboolean bpc,gpointer user_data)1328 image_profile_convert_callback (GtkWidget *dialog,
1329 GimpImage *image,
1330 GimpColorProfile *new_profile,
1331 GFile *new_file,
1332 GimpColorRenderingIntent intent,
1333 gboolean bpc,
1334 gpointer user_data)
1335 {
1336 GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config);
1337 GimpProgress *progress = user_data;
1338 GError *error = NULL;
1339
1340 g_object_set (config,
1341 "image-convert-profile-intent", intent,
1342 "image-convert-profile-black-point-compensation", bpc,
1343 NULL);
1344
1345 progress = gimp_progress_start (progress, FALSE,
1346 _("Converting to '%s'"),
1347 gimp_color_profile_get_label (new_profile));
1348
1349 if (! gimp_image_convert_color_profile (image, new_profile,
1350 config->image_convert_profile_intent,
1351 config->image_convert_profile_bpc,
1352 progress, &error))
1353 {
1354 gimp_message (image->gimp, G_OBJECT (dialog),
1355 GIMP_MESSAGE_ERROR,
1356 "%s", error->message);
1357 g_clear_error (&error);
1358
1359 if (progress)
1360 gimp_progress_end (progress);
1361
1362 return;
1363 }
1364
1365 if (progress)
1366 gimp_progress_end (progress);
1367
1368 gimp_image_flush (image);
1369
1370 gtk_widget_destroy (dialog);
1371 }
1372
1373 static void
image_resize_callback(GtkWidget * dialog,GimpViewable * viewable,GimpContext * context,gint width,gint height,GimpUnit unit,gint offset_x,gint offset_y,GimpFillType fill_type,GimpItemSet layer_set,gboolean resize_text_layers,gpointer user_data)1374 image_resize_callback (GtkWidget *dialog,
1375 GimpViewable *viewable,
1376 GimpContext *context,
1377 gint width,
1378 gint height,
1379 GimpUnit unit,
1380 gint offset_x,
1381 gint offset_y,
1382 GimpFillType fill_type,
1383 GimpItemSet layer_set,
1384 gboolean resize_text_layers,
1385 gpointer user_data)
1386 {
1387 GimpDisplay *display = user_data;
1388
1389 image_resize_unit = unit;
1390
1391 if (width > 0 && height > 0)
1392 {
1393 GimpImage *image = GIMP_IMAGE (viewable);
1394 GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config);
1395 GimpProgress *progress;
1396
1397 g_object_set (config,
1398 "image-resize-fill-type", fill_type,
1399 "image-resize-layer-set", layer_set,
1400 "image-resize-resize-text-layers", resize_text_layers,
1401 NULL);
1402
1403 gtk_widget_destroy (dialog);
1404
1405 if (width == gimp_image_get_width (image) &&
1406 height == gimp_image_get_height (image))
1407 return;
1408
1409 progress = gimp_progress_start (GIMP_PROGRESS (display), FALSE,
1410 _("Resizing"));
1411
1412 gimp_image_resize_with_layers (image,
1413 context, fill_type,
1414 width, height, offset_x, offset_y,
1415 layer_set,
1416 resize_text_layers,
1417 progress);
1418
1419 if (progress)
1420 gimp_progress_end (progress);
1421
1422 gimp_image_flush (image);
1423 }
1424 else
1425 {
1426 g_warning ("Resize Error: "
1427 "Both width and height must be greater than zero.");
1428 }
1429 }
1430
1431 static void
image_print_size_callback(GtkWidget * dialog,GimpImage * image,gdouble xresolution,gdouble yresolution,GimpUnit resolution_unit,gpointer data)1432 image_print_size_callback (GtkWidget *dialog,
1433 GimpImage *image,
1434 gdouble xresolution,
1435 gdouble yresolution,
1436 GimpUnit resolution_unit,
1437 gpointer data)
1438 {
1439 gdouble xres;
1440 gdouble yres;
1441
1442 gtk_widget_destroy (dialog);
1443
1444 gimp_image_get_resolution (image, &xres, &yres);
1445
1446 if (xresolution == xres &&
1447 yresolution == yres &&
1448 resolution_unit == gimp_image_get_unit (image))
1449 return;
1450
1451 gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_IMAGE_SCALE,
1452 _("Change Print Size"));
1453
1454 gimp_image_set_resolution (image, xresolution, yresolution);
1455 gimp_image_set_unit (image, resolution_unit);
1456
1457 gimp_image_undo_group_end (image);
1458
1459 gimp_image_flush (image);
1460 }
1461
1462 static void
image_scale_callback(GtkWidget * dialog,GimpViewable * viewable,gint width,gint height,GimpUnit unit,GimpInterpolationType interpolation,gdouble xresolution,gdouble yresolution,GimpUnit resolution_unit,gpointer user_data)1463 image_scale_callback (GtkWidget *dialog,
1464 GimpViewable *viewable,
1465 gint width,
1466 gint height,
1467 GimpUnit unit,
1468 GimpInterpolationType interpolation,
1469 gdouble xresolution,
1470 gdouble yresolution,
1471 GimpUnit resolution_unit,
1472 gpointer user_data)
1473 {
1474 GimpProgress *progress = user_data;
1475 GimpImage *image = GIMP_IMAGE (viewable);
1476 gdouble xres;
1477 gdouble yres;
1478
1479 image_scale_unit = unit;
1480 image_scale_interp = interpolation;
1481
1482 gimp_image_get_resolution (image, &xres, &yres);
1483
1484 if (width > 0 && height > 0)
1485 {
1486 gtk_widget_destroy (dialog);
1487
1488 if (width == gimp_image_get_width (image) &&
1489 height == gimp_image_get_height (image) &&
1490 xresolution == xres &&
1491 yresolution == yres &&
1492 resolution_unit == gimp_image_get_unit (image))
1493 return;
1494
1495 gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_IMAGE_SCALE,
1496 _("Scale Image"));
1497
1498 gimp_image_set_resolution (image, xresolution, yresolution);
1499 gimp_image_set_unit (image, resolution_unit);
1500
1501 if (width != gimp_image_get_width (image) ||
1502 height != gimp_image_get_height (image))
1503 {
1504 progress = gimp_progress_start (progress, FALSE,
1505 _("Scaling"));
1506
1507 gimp_image_scale (image, width, height, interpolation, progress);
1508
1509 if (progress)
1510 gimp_progress_end (progress);
1511 }
1512
1513 gimp_image_undo_group_end (image);
1514
1515 gimp_image_flush (image);
1516 }
1517 else
1518 {
1519 g_warning ("Scale Error: "
1520 "Both width and height must be greater than zero.");
1521 }
1522 }
1523
1524 static void
image_merge_layers_callback(GtkWidget * dialog,GimpImage * image,GimpContext * context,GimpMergeType merge_type,gboolean merge_active_group,gboolean discard_invisible,gpointer user_data)1525 image_merge_layers_callback (GtkWidget *dialog,
1526 GimpImage *image,
1527 GimpContext *context,
1528 GimpMergeType merge_type,
1529 gboolean merge_active_group,
1530 gboolean discard_invisible,
1531 gpointer user_data)
1532 {
1533 GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config);
1534 GimpDisplay *display = user_data;
1535
1536 g_object_set (config,
1537 "layer-merge-type", merge_type,
1538 "layer-merge-active-group-only", merge_active_group,
1539 "layer-merge-discard-invisible", discard_invisible,
1540 NULL);
1541
1542 gimp_image_merge_visible_layers (image,
1543 context,
1544 config->layer_merge_type,
1545 config->layer_merge_active_group_only,
1546 config->layer_merge_discard_invisible,
1547 GIMP_PROGRESS (display));
1548
1549 gimp_image_flush (image);
1550
1551 gtk_widget_destroy (dialog);
1552 }
1553