1 /**
2  * Copyright (C) 2012 hejian <hejian.he@gmail.com>
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 <http://www.gnu.org/licenses/>.
16  */
17 
18 #include <libgimp/gimp.h>
19 #include <libgimp/gimpui.h>
20 
21 #include "beautify-effect.h"
22 
23 #define PLUG_IN_PROC   "plug-in-beautify"
24 #define PLUG_IN_BINARY "beautify"
25 #define PLUG_IN_ROLE   "gimp-beautify"
26 
27 #define PREVIEW_SIZE  480
28 #define THUMBNAIL_SIZE  80
29 
30 typedef struct
31 {
32   gint brightness;
33   gint contrast;
34   gdouble saturation;
35   gdouble definition;
36   gdouble hue;
37   gdouble cyan_red;
38   gdouble magenta_green;
39   gdouble yellow_blue;
40 
41   BeautifyEffectType effect;
42   gdouble opacity;
43 } BeautifyValues;
44 
45 static const BeautifyEffectType basic_effects[] =
46 {
47   BEAUTIFY_EFFECT_SOFT_LIGHT,
48   BEAUTIFY_EFFECT_WARM,
49   BEAUTIFY_EFFECT_SHARPEN,
50   BEAUTIFY_EFFECT_SOFT,
51   BEAUTIFY_EFFECT_STRONG_CONTRAST,
52   BEAUTIFY_EFFECT_SMART_COLOR,
53   BEAUTIFY_EFFECT_BLACK_AND_WHITE,
54   BEAUTIFY_EFFECT_INVERT,
55 };
56 
57 static const BeautifyEffectType lomo_effects[] =
58 {
59   BEAUTIFY_EFFECT_CLASSIC_LOMO,
60   BEAUTIFY_EFFECT_RETRO_LOMO,
61   BEAUTIFY_EFFECT_GOTHIC_STYLE,
62   BEAUTIFY_EFFECT_FILM,
63   BEAUTIFY_EFFECT_HDR,
64   BEAUTIFY_EFFECT_CLASSIC_HDR,
65   BEAUTIFY_EFFECT_YELLOWING_DARK_CORNERS,
66   BEAUTIFY_EFFECT_IMPRESSION,
67   BEAUTIFY_EFFECT_DEEP_BLUE_TEAR_RAIN,
68   BEAUTIFY_EFFECT_PURPLE_SENSATION,
69   BEAUTIFY_EFFECT_BRONZE,
70   BEAUTIFY_EFFECT_RECALL,
71 };
72 
73 static const BeautifyEffectType studio_effects[] =
74 {
75   BEAUTIFY_EFFECT_ELEGANT,
76   BEAUTIFY_EFFECT_LITTLE_FRESH,
77   BEAUTIFY_EFFECT_CLASSIC_STUDIO,
78   BEAUTIFY_EFFECT_RETRO,
79   BEAUTIFY_EFFECT_PINK_LADY,
80   BEAUTIFY_EFFECT_ABAO_COLOR,
81   BEAUTIFY_EFFECT_ICE_SPIRIT,
82   BEAUTIFY_EFFECT_JAPANESE_STYLE,
83   BEAUTIFY_EFFECT_NEW_JAPANESE_STYLE,
84   BEAUTIFY_EFFECT_MILK,
85   BEAUTIFY_EFFECT_OLD_PHOTOS,
86   BEAUTIFY_EFFECT_WARM_YELLOW,
87   BEAUTIFY_EFFECT_BLUES,
88   BEAUTIFY_EFFECT_COLD_BLUE,
89   BEAUTIFY_EFFECT_COLD_GREEN,
90   BEAUTIFY_EFFECT_PURPLE_FANTASY,
91   BEAUTIFY_EFFECT_COLD_PURPLE,
92 };
93 
94 static const BeautifyEffectType fashion_effects[] =
95 {
96   BEAUTIFY_EFFECT_BRIGHT_RED,
97   BEAUTIFY_EFFECT_CHRISTMAS_EVE,
98   BEAUTIFY_EFFECT_NIGHT_VIEW,
99   BEAUTIFY_EFFECT_ASTRAL,
100   BEAUTIFY_EFFECT_COLORFUL_GLOW,
101   BEAUTIFY_EFFECT_PICK_LIGHT,
102   BEAUTIFY_EFFECT_GLASS_DROPS,
103 };
104 
105 static const BeautifyEffectType art_effects[] =
106 {
107   BEAUTIFY_EFFECT_SKETCH,
108   BEAUTIFY_EFFECT_LIFE_SKETCH,
109   BEAUTIFY_EFFECT_CLASSIC_SKETCH,
110   BEAUTIFY_EFFECT_COLOR_PENCIL,
111   BEAUTIFY_EFFECT_TV_LINES,
112   BEAUTIFY_EFFECT_RELIEF,
113 };
114 
115 static const BeautifyEffectType gradient_effects[] =
116 {
117   BEAUTIFY_EFFECT_BEAM_GRADIENT,
118   BEAUTIFY_EFFECT_SUNSET_GRADIENT,
119   BEAUTIFY_EFFECT_RAINBOW_GRADIENT,
120   BEAUTIFY_EFFECT_PINK_PURPLE_GRADIENG,
121   BEAUTIFY_EFFECT_PINK_BLUE_GRADIENT,
122 };
123 
124 static void     query    (void);
125 static void     run      (const gchar      *name,
126                           gint              nparams,
127                           const GimpParam  *param,
128                           gint             *nreturn_vals,
129                           GimpParam       **return_vals);
130 
131 static void     beautify        (GimpDrawable *drawable);
132 static void     beautify_effect (GimpDrawable *drawable);
133 
134 static gboolean beautify_dialog (gint32        image_ID,
135                                  GimpDrawable *drawable);
136 
137 static void     create_base_page (GtkNotebook *notebook);
138 static void     create_color_page (GtkNotebook *notebook);
139 
140 static void     brightness_update    (GtkRange *range, gpointer data);
141 static void     contrast_update      (GtkRange *range, gpointer data);
142 static void     saturation_update    (GtkRange *range, gpointer data);
143 static void     definition_update    (GtkRange *range, gpointer data);
144 static void     hue_update           (GtkRange *range, gpointer data);
145 static void     cyan_red_update      (GtkRange *range, gpointer data);
146 static void     magenta_green_update (GtkRange *range, gpointer data);
147 static void     yellow_blue_update   (GtkRange *range, gpointer data);
148 
149 static void     adjustment();
150 
151 static void     reset_pressed (GtkButton *button, gpointer user_date);
152 
153 static void     preview_update (GtkWidget *preview);
154 
155 static GtkWidget* effect_option_new ();
156 static void       effect_opacity_update (GtkRange *range, gpointer data);
157 
158 static void create_effect_pages (GtkNotebook *notebook);
159 static void create_effect_page  (GtkNotebook *notebook, gchar *str);
160 static void effects_switch_page (GtkNotebook *notebook, GtkWidget *page, guint page_num, gpointer user_data);
161 
162 static GtkWidget* effect_icon_new (BeautifyEffectType effect);
163 
164 static gboolean select_effect (GtkWidget *widget, GdkEvent *event, gpointer user_data);
165 
166 static void reset_adjustment ();
167 
168 static void apply_effect ();
169 static void cancel_effect ();
170 
171 const GimpPlugInInfo PLUG_IN_INFO =
172 {
173   NULL,  /* init_proc  */
174   NULL,  /* quit_proc  */
175   query, /* query_proc */
176   run,   /* run_proc   */
177 };
178 
179 static BeautifyValues bvals =
180 {
181   0,  /* brightness */
182   0,  /* contrast   */
183   0,  /* saturation */
184   0,  /* definition */
185   0,  /* hue */
186   0,  /* cyan_red */
187   0,  /* magenta_green */
188   0,  /* yellow_blue */
189 
190   BEAUTIFY_EFFECT_NONE, /* effect */
191   100,  /* opacity */
192 };
193 
194 static gint32     image_ID         = 0;
195 static gint       width;
196 static gint       height;
197 
198 static GtkWidget *brightness = NULL;
199 static GtkWidget *contrast = NULL;
200 static GtkWidget *saturation = NULL;
201 static GtkWidget *definition = NULL;
202 static GtkWidget *hue = NULL;
203 static GtkWidget *cyan_red = NULL;
204 static GtkWidget *magenta_green = NULL;
205 static GtkWidget *yellow_blue = NULL;
206 
207 static GtkWidget *preview          = NULL;
208 static gint32     preview_image    = 0;
209 static gint32     saved_image      = 0;
210 
211 static GtkWidget *effect_option    = NULL;
212 static GtkWidget *effect_opacity   = NULL;
213 
214 static BeautifyEffectType current_effect = BEAUTIFY_EFFECT_NONE;
215 gint32 preview_effect_layer = 0;
216 
217 /* compatable with gtk2 */
218 #if GTK_MAJOR_VERSION < 3
219 GtkWidget *
gtk_box_new(GtkOrientation orientation,gint spacing)220 gtk_box_new (GtkOrientation  orientation,
221              gint            spacing)
222 {
223   if (orientation == GTK_ORIENTATION_HORIZONTAL)
224     return gtk_hbox_new (FALSE, spacing);
225   else
226     return gtk_vbox_new (FALSE, spacing);
227 }
228 #endif
229 
MAIN()230 MAIN ()
231 
232 static void
233 query (void)
234 {
235   static const GimpParamDef args[] =
236   {
237     { GIMP_PDB_INT32,    "run-mode",   "The run mode { RUN-INTERACTIVE (0), RUN-NONINTERACTIVE (1) }" },
238     { GIMP_PDB_IMAGE,    "image",      "Input image" },
239     { GIMP_PDB_DRAWABLE, "drawable",   "Input drawable" },
240     { GIMP_PDB_INT32,    "effect",     "The effect to apply { SOFT_LIGHT (1), WARM (2), SHARPEN (3), SOFT (4), REMOVE_FOG (5), STRONG_CONTRAST (6), SMART_COLOR (7), FULL_COLOR (8), BLACK_AND_WHITE (9), INVERT (10), NOISE (11), CLASSIC_LOMO (12), RETRO_LOMO (13), GOTHIC_STYLE (14), FILM (15), HDR (16), CLASSIC_HDR (17), REVERSE_COLOR (18) TIME_TUNNEL (19), AFTER_THE_YOUTH (20), AXIS_LENS (21), YELLOWING_DARK_CORNERS (22), OLD_DAYS (23), NOSTALGIA (24), IMPRESSION (25), DEEP_BLUE_TEAR_RAIN (26), PURPLE_SENSATION (27), BRONZE (28), COOL_COLORS (29), RECALL (30), RETRO_BLACK_AND_WHITE (31), COLORFUL_LOMO (32), ELEGANT (33), LITTLE_FRESH (34), CLASSIC_STUDIO (35), RETRO (36), PINK_LADY (37), ABAO_COLOR (38), ICE_SPIRIT (39), MATTE_FINISH_STYLE (40), JAPANESE_STYLE (41), NEW_JAPANESE_STYLE (42), MILK (43), FLEETING_TIME (44), CLOUD (45), OLD_PHOTOS (46), WARM_YELLOW (47), BLUES (48), COLD_BLUE (49), COLD_GREEN (50), PURPLE_FANTASY (51), COLD_PURPLE (52), BRIGHT_RED (53), CHRISTMAS_EVE (54), SNOW (55), NIGHT_VIEW (56), ASTRAL (57), COLORFUL_GLOW (58), BACKLIGHT (59), PICK_LIGHT (60), COLORFUL (61), HEART_SHAPED_HALO (62), BUBBLES_GRADIENT (63), GLASS_DROPS (64), NEW_YEAR_ATMOSPHERE (65), SKETCH (66), LIFE_SKETCH (67), CLASSIC_SKETCH (68), COLOR_PENCIL (69), TV_LINES (70), BLACK_AND_WHITE_NEWSPAPER (71), RELIEF (72), BEAUTIFY_EFFECT_PAINTING (73), BEAM_GRADIENT (74), SUNSET_GRADIENT (75), COOL_GRADIENT (76), BLUE_YELLOW_GRADIENT (77), RAINBOW_GRADIENT (78), FOUR_COLOR_GRADIENT (79), PINK_PURPLE_GRADIENG (80), PINK_BLUE_GRADIENT (81) }" },
241     { GIMP_PDB_FLOAT,    "opacity",   "The effect opacity (0 <= opacity <= 100)" }
242   };
243 
244   gimp_install_procedure (PLUG_IN_PROC,
245                           "Quickly and easily beautify the photo.",
246                           "Quickly and easily beautify the photo. Goto https://github.com/hejiann/beautify/wiki get more help.",
247                           "Hejian <hejian.he@gmail.com>",
248                           "Hejian <hejian.he@gmail.com>",
249                           "2012",
250                           "_Beautify...",
251                           "RGB*, GRAY*",
252                           GIMP_PLUGIN,
253                           G_N_ELEMENTS (args), 0,
254                           args, NULL);
255 
256   gimp_plugin_menu_register (PLUG_IN_PROC, "<Image>/Filters/Beautify");
257 }
258 
259 static void
run(const gchar * name,gint nparams,const GimpParam * param,gint * nreturn_vals,GimpParam ** return_vals)260 run (const gchar      *name,
261      gint              nparams,
262      const GimpParam  *param,
263      gint             *nreturn_vals,
264      GimpParam       **return_vals)
265 {
266   static GimpParam   values[2];
267   GimpDrawable      *drawable;
268   GimpRunMode        run_mode;
269   GimpPDBStatusType  status = GIMP_PDB_SUCCESS;
270 
271   run_mode = param[0].data.d_int32;
272 
273   *nreturn_vals = 1;
274   *return_vals  = values;
275 
276   values[0].type          = GIMP_PDB_STATUS;
277   values[0].data.d_status = status;
278 
279   image_ID = param[1].data.d_image;
280   drawable = gimp_drawable_get (param[2].data.d_drawable);
281 
282   width = gimp_image_width (image_ID);
283   height = gimp_image_height (image_ID);
284 
285   switch (run_mode)
286   {
287     case GIMP_RUN_INTERACTIVE:
288       if (! beautify_dialog (image_ID, drawable))
289         return;
290       break;
291 
292     case GIMP_RUN_NONINTERACTIVE:
293       /*  Make sure all the arguments are there!  */
294       if (nparams != 5)
295         status = GIMP_PDB_CALLING_ERROR;
296 
297       if (status == GIMP_PDB_SUCCESS)
298       {
299         bvals.effect = param[3].data.d_int32;
300         bvals.opacity = param[4].data.d_float;
301       }
302       break;
303 
304     case GIMP_RUN_WITH_LAST_VALS:
305       /*  Possibly retrieve data  */
306       gimp_get_data (PLUG_IN_PROC, &bvals);
307       break;
308 
309     default:
310       break;
311   }
312 
313   if ((status == GIMP_PDB_SUCCESS) &&
314       (gimp_drawable_is_rgb(drawable->drawable_id) ||
315        gimp_drawable_is_gray(drawable->drawable_id)))
316     {
317       /* Run! */
318       gimp_image_undo_group_start (image_ID);
319       if (run_mode == GIMP_RUN_INTERACTIVE)
320         beautify (drawable);
321       else
322         beautify_effect (drawable);
323       gimp_image_undo_group_end (image_ID);
324 
325       /* If run mode is interactive, flush displays */
326       if (run_mode != GIMP_RUN_NONINTERACTIVE)
327         gimp_displays_flush ();
328 
329       /* Store data */
330       if (run_mode == GIMP_RUN_INTERACTIVE)
331         gimp_set_data (PLUG_IN_PROC, &bvals, sizeof (BeautifyValues));
332 
333     }
334 
335   gimp_drawable_detach (drawable);
336 }
337 
338 static void
beautify(GimpDrawable * drawable)339 beautify (GimpDrawable *drawable)
340 {
341   apply_effect ();
342   gint32 source = gimp_image_get_active_layer (preview_image);
343   gimp_edit_copy (source);
344   gint32 floating_sel = gimp_edit_paste (drawable->drawable_id, FALSE);
345   gimp_floating_sel_anchor (floating_sel);
346 }
347 
348 static void
beautify_effect(GimpDrawable * drawable)349 beautify_effect (GimpDrawable *drawable)
350 {
351   run_effect (image_ID, bvals.effect);
352 
353   gint32 layer = gimp_image_get_active_layer (image_ID);
354   gimp_layer_set_opacity (layer, bvals.opacity);
355 
356   gimp_image_merge_down (image_ID, layer, GIMP_CLIP_TO_IMAGE);
357 }
358 
359 static gboolean
beautify_dialog(gint32 image_ID,GimpDrawable * drawable)360 beautify_dialog (gint32        image_ID,
361                  GimpDrawable *drawable)
362 {
363   GtkWidget *dialog;
364   GtkWidget *main_hbox;
365   GtkWidget *left_vbox;
366   GtkWidget *middle_vbox;
367   GtkWidget *right_vbox;
368 
369   gimp_ui_init (PLUG_IN_BINARY, FALSE);
370 
371   dialog = gimp_dialog_new ("Beautify", PLUG_IN_ROLE,
372                             NULL, 0,
373                             gimp_standard_help_func, PLUG_IN_PROC,
374 
375                             GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
376                             GTK_STOCK_OK,     GTK_RESPONSE_OK,
377 
378                             NULL);
379 
380   gimp_window_set_transient (GTK_WINDOW (dialog));
381 
382   gtk_widget_show (dialog);
383 
384   main_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
385   gtk_container_set_border_width (GTK_CONTAINER (main_hbox), 12);
386   gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
387                       main_hbox, TRUE, TRUE, 0);
388   gtk_widget_show (main_hbox);
389 
390   left_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
391   gtk_container_set_border_width (GTK_CONTAINER (left_vbox), 12);
392   gtk_box_pack_start (GTK_BOX (main_hbox), left_vbox, TRUE, TRUE, 0);
393   gtk_widget_show (left_vbox);
394 
395   middle_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
396   gtk_container_set_border_width (GTK_CONTAINER (middle_vbox), 12);
397   gtk_box_pack_start (GTK_BOX (main_hbox), middle_vbox, TRUE, TRUE, 0);
398   gtk_widget_show (middle_vbox);
399 
400   right_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
401   gtk_container_set_border_width (GTK_CONTAINER (right_vbox), 12);
402   gtk_box_pack_start (GTK_BOX (main_hbox), right_vbox, TRUE, TRUE, 0);
403   gtk_widget_show (right_vbox);
404 
405   /* adjustment */
406   GtkWidget *notebook = gtk_notebook_new ();
407   gtk_box_pack_start (GTK_BOX (left_vbox), notebook, FALSE, FALSE, 0);
408   gtk_widget_show (notebook);
409 
410   create_base_page (GTK_NOTEBOOK (notebook));
411   create_color_page (GTK_NOTEBOOK (notebook));
412 
413   /* buttons */
414   GtkWidget *buttons = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
415   gtk_box_pack_start (GTK_BOX (middle_vbox), buttons, FALSE, FALSE, 0);
416   gtk_widget_show (buttons);
417 
418   GtkWidget *reset = gtk_button_new_with_label ("Reset");
419   gtk_box_pack_start (GTK_BOX (buttons), reset, FALSE, FALSE, 0);
420   gtk_widget_show (reset);
421   g_signal_connect (reset, "pressed", G_CALLBACK (reset_pressed), NULL);
422 
423   /* preview */
424   preview_image = gimp_image_duplicate (image_ID);
425 
426   preview = gtk_image_new();
427   preview_update (preview);
428 
429   gtk_box_pack_start (GTK_BOX (middle_vbox), preview, FALSE, FALSE, 0);
430   gtk_widget_show (preview);
431 
432   /* effect option */
433   effect_option = effect_option_new ();
434   gtk_box_pack_start (GTK_BOX (middle_vbox), effect_option, FALSE, FALSE, 0);
435 
436   /* effects */
437   notebook = gtk_notebook_new ();
438   gtk_box_pack_start (GTK_BOX (right_vbox), notebook, FALSE, FALSE, 0);
439   gtk_widget_show (notebook);
440 
441   create_effect_pages (GTK_NOTEBOOK (notebook));
442 
443   gboolean run = (gimp_dialog_run (GIMP_DIALOG (dialog)) == GTK_RESPONSE_OK);
444 
445   gtk_widget_destroy (dialog);
446 
447   return run;
448 }
449 
450 static void
create_base_page(GtkNotebook * notebook)451 create_base_page (GtkNotebook *notebook) {
452   GtkWidget *label;
453   GtkWidget *hscale;
454 
455   GtkWidget *pagelabel = gtk_label_new ("Basic");
456 
457   GtkWidget *thispage = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
458   gtk_container_set_border_width (GTK_CONTAINER (thispage), 12);
459   gtk_widget_show (thispage);
460 
461   /* brightness */
462   label = gtk_label_new ("Brightness");
463   gtk_box_pack_start (GTK_BOX (thispage), label, FALSE, FALSE, 0);
464   gtk_widget_show (label);
465 
466   brightness = gtk_hscale_new_with_range (-127, 127, 1);
467   gtk_range_set_value (GTK_RANGE (brightness), bvals.brightness);
468   gtk_scale_set_value_pos (GTK_SCALE (brightness), GTK_POS_BOTTOM);
469   gtk_box_pack_start (GTK_BOX (thispage), brightness, FALSE, FALSE, 0);
470   gtk_widget_show (brightness);
471 
472   g_signal_connect (brightness, "value-changed",
473                    G_CALLBACK (brightness_update),
474                    NULL);
475 
476   /* contrast */
477   label = gtk_label_new ("Contrast");
478   gtk_box_pack_start (GTK_BOX (thispage), label, FALSE, FALSE, 0);
479   gtk_widget_show (label);
480 
481   contrast = gtk_hscale_new_with_range (-50, 50, 1);
482   gtk_range_set_value (GTK_RANGE (contrast), bvals.contrast);
483   gtk_scale_set_value_pos (GTK_SCALE (contrast), GTK_POS_BOTTOM);
484   gtk_box_pack_start (GTK_BOX (thispage), contrast, FALSE, FALSE, 0);
485   gtk_widget_show (contrast);
486 
487   g_signal_connect (contrast, "value-changed",
488                    G_CALLBACK (contrast_update),
489                    NULL);
490 
491   /* saturation */
492   label = gtk_label_new ("Saturation");
493   gtk_box_pack_start (GTK_BOX (thispage), label, FALSE, FALSE, 0);
494   gtk_widget_show (label);
495 
496   saturation = gtk_hscale_new_with_range (-50, 50, 1);
497   gtk_range_set_value (GTK_RANGE (saturation), bvals.saturation);
498   gtk_scale_set_value_pos (GTK_SCALE (saturation), GTK_POS_BOTTOM);
499   gtk_box_pack_start (GTK_BOX (thispage), saturation, FALSE, FALSE, 0);
500   gtk_widget_show (saturation);
501 
502   g_signal_connect (saturation, "value-changed",
503                    G_CALLBACK (saturation_update),
504                    NULL);
505 
506   /* definition */
507   label = gtk_label_new ("Definition");
508   gtk_box_pack_start (GTK_BOX (thispage), label, FALSE, FALSE, 0);
509   gtk_widget_show (label);
510 
511   definition = gtk_hscale_new_with_range (-50, 50, 1);
512   gtk_range_set_value (GTK_RANGE (definition), bvals.definition);
513   gtk_scale_set_value_pos (GTK_SCALE (definition), GTK_POS_BOTTOM);
514   gtk_box_pack_start (GTK_BOX (thispage), definition, FALSE, FALSE, 0);
515   gtk_widget_show (definition);
516 
517   g_signal_connect (definition, "value-changed",
518                    G_CALLBACK (definition_update),
519                    NULL);
520 
521   gtk_notebook_append_page_menu (notebook, thispage, pagelabel, NULL);
522 }
523 
524 static void
brightness_update(GtkRange * range,gpointer data)525 brightness_update (GtkRange *range, gpointer data) {
526   bvals.brightness = gtk_range_get_value (range);
527   adjustment ();
528   preview_update (preview);
529 }
530 
531 static void
contrast_update(GtkRange * range,gpointer data)532 contrast_update (GtkRange *range, gpointer data) {
533   bvals.contrast = gtk_range_get_value (range);
534   adjustment ();
535   preview_update (preview);
536 }
537 
538 static void
saturation_update(GtkRange * range,gpointer data)539 saturation_update (GtkRange *range, gpointer data) {
540   bvals.saturation = gtk_range_get_value (range);
541   adjustment ();
542   preview_update (preview);
543 }
544 
545 static void
definition_update(GtkRange * range,gpointer data)546 definition_update (GtkRange *range, gpointer data) {
547   bvals.definition = gtk_range_get_value (range);
548   adjustment ();
549   preview_update (preview);
550 }
551 
552 static void
create_color_page(GtkNotebook * notebook)553 create_color_page (GtkNotebook *notebook) {
554   GtkWidget *label;
555   GtkWidget *hscale;
556 
557   GtkWidget *pagelabel = gtk_label_new ("Color");
558 
559   GtkWidget *thispage = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
560   gtk_container_set_border_width (GTK_CONTAINER (thispage), 12);
561   gtk_widget_show (thispage);
562 
563   /* hue */
564   label = gtk_label_new ("Hue");
565   gtk_box_pack_start (GTK_BOX (thispage), label, FALSE, FALSE, 0);
566   gtk_widget_show (label);
567 
568   hue = gtk_hscale_new_with_range (-180, 180, 1);
569   gtk_range_set_value (GTK_RANGE (hue), bvals.hue);
570   gtk_scale_set_value_pos (GTK_SCALE (hue), GTK_POS_BOTTOM);
571   gtk_box_pack_start (GTK_BOX (thispage), hue, FALSE, FALSE, 0);
572   gtk_widget_show (hue);
573 
574   g_signal_connect (hue, "value-changed",
575                    G_CALLBACK (hue_update),
576                    NULL);
577 
578   GtkWidget *table = gtk_table_new (3, 3, FALSE);
579   gtk_table_set_col_spacings (GTK_TABLE (table), 6);
580   gtk_table_set_row_spacings (GTK_TABLE (table), 6);
581   gtk_box_pack_start (GTK_BOX (thispage), table, FALSE, FALSE, 0);
582   gtk_widget_show (table);
583 
584   /* cyan_red */
585   GtkWidget *event_box;
586   GdkColor color;
587 
588   event_box = gtk_event_box_new ();
589   color.red = 0x0; color.green = 0xFFFF; color.blue = 0xFFFF;
590   gtk_widget_modify_bg (event_box, 0, &color);
591 
592   label = gtk_label_new ("C");
593   gtk_container_add (GTK_CONTAINER (event_box), label);
594   gtk_widget_show (label);
595   gtk_table_attach_defaults (GTK_TABLE (table), event_box, 0, 1, 0, 1);
596   gtk_widget_show (event_box);
597 
598   cyan_red = gtk_hscale_new_with_range (-50, 50, 1);
599   gtk_range_set_value (GTK_RANGE (cyan_red), bvals.cyan_red);
600   gtk_scale_set_value_pos (GTK_SCALE (cyan_red), GTK_POS_BOTTOM);
601   gtk_table_attach_defaults (GTK_TABLE (table), cyan_red, 1, 2, 0, 1);
602   gtk_widget_show (cyan_red);
603 
604   gtk_widget_set_size_request (cyan_red, 100, -1);
605 
606   g_signal_connect (cyan_red, "value-changed",
607                    G_CALLBACK (cyan_red_update),
608                    NULL);
609 
610   event_box = gtk_event_box_new ();
611   color.red = 0xFFFF; color.green = 0x0; color.blue = 0x0;
612   gtk_widget_modify_bg (event_box, 0, &color);
613 
614   label = gtk_label_new ("R");
615   gtk_container_add (GTK_CONTAINER (event_box), label);
616   gtk_widget_show (label);
617   gtk_table_attach_defaults (GTK_TABLE (table), event_box, 2, 3, 0, 1);
618   gtk_widget_show (event_box);
619 
620   /* magenta_green */
621   event_box = gtk_event_box_new ();
622   color.red = 0xFFFF; color.green = 0x0; color.blue = 0xFFFF;
623   gtk_widget_modify_bg (event_box, 0, &color);
624 
625   label = gtk_label_new ("M");
626   gtk_container_add (GTK_CONTAINER (event_box), label);
627   gtk_widget_show (label);
628   gtk_table_attach_defaults (GTK_TABLE (table), event_box, 0, 1, 1, 2);
629   gtk_widget_show (event_box);
630 
631   magenta_green = gtk_hscale_new_with_range (-50, 50, 1);
632   gtk_range_set_value (GTK_RANGE (magenta_green), bvals.magenta_green);
633   gtk_scale_set_value_pos (GTK_SCALE (magenta_green), GTK_POS_BOTTOM);
634   gtk_table_attach_defaults (GTK_TABLE (table), magenta_green, 1, 2, 1, 2);
635   gtk_widget_show (magenta_green);
636 
637   g_signal_connect (magenta_green, "value-changed",
638                    G_CALLBACK (magenta_green_update),
639                    NULL);
640 
641   event_box = gtk_event_box_new ();
642   color.red = 0x0; color.green = 0xFFFF; color.blue = 0x0;
643   gtk_widget_modify_bg (event_box, 0, &color);
644 
645   label = gtk_label_new ("G");
646   gtk_container_add (GTK_CONTAINER (event_box), label);
647   gtk_widget_show (label);
648   gtk_table_attach_defaults (GTK_TABLE (table), event_box, 2, 3, 1, 2);
649   gtk_widget_show (event_box);
650 
651   /* yellow_blue */
652   event_box = gtk_event_box_new ();
653   color.red = 0xFFFF; color.green = 0xFFFF; color.blue = 0x0;
654   gtk_widget_modify_bg (event_box, 0, &color);
655 
656   label = gtk_label_new ("Y");
657   gtk_container_add (GTK_CONTAINER (event_box), label);
658   gtk_widget_show (label);
659   gtk_table_attach_defaults (GTK_TABLE (table), event_box, 0, 1, 2, 3);
660   gtk_widget_show (event_box);
661 
662   yellow_blue = gtk_hscale_new_with_range (-50, 50, 1);
663   gtk_range_set_value (GTK_RANGE (yellow_blue), bvals.yellow_blue);
664   gtk_scale_set_value_pos (GTK_SCALE (yellow_blue), GTK_POS_BOTTOM);
665   gtk_table_attach_defaults (GTK_TABLE (table), yellow_blue, 1, 2, 2, 3);
666   gtk_widget_show (yellow_blue);
667 
668   g_signal_connect (yellow_blue, "value-changed",
669                    G_CALLBACK (yellow_blue_update),
670                    NULL);
671 
672   event_box = gtk_event_box_new ();
673   color.red = 0x0; color.green = 0x0; color.blue = 0xFFFF;
674   gtk_widget_modify_bg (event_box, 0, &color);
675 
676   label = gtk_label_new ("B");
677   gtk_container_add (GTK_CONTAINER (event_box), label);
678   gtk_widget_show (label);
679   gtk_table_attach_defaults (GTK_TABLE (table), event_box, 2, 3, 2, 3);
680   gtk_widget_show (event_box);
681 
682   gtk_notebook_append_page_menu (notebook, thispage, pagelabel, NULL);
683 }
684 
685 static void
hue_update(GtkRange * range,gpointer data)686 hue_update (GtkRange *range, gpointer data) {
687   bvals.hue = gtk_range_get_value (range);
688   adjustment ();
689   preview_update (preview);
690 }
691 
692 static void
cyan_red_update(GtkRange * range,gpointer data)693 cyan_red_update (GtkRange *range, gpointer data) {
694   bvals.cyan_red = gtk_range_get_value (range);
695   adjustment ();
696   preview_update (preview);
697 }
698 
699 static void
magenta_green_update(GtkRange * range,gpointer data)700 magenta_green_update (GtkRange *range, gpointer data) {
701   bvals.magenta_green = gtk_range_get_value (range);
702   adjustment ();
703   preview_update (preview);
704 }
705 
706 static void
yellow_blue_update(GtkRange * range,gpointer data)707 yellow_blue_update (GtkRange *range, gpointer data) {
708   bvals.yellow_blue = gtk_range_get_value (range);
709   adjustment ();
710   preview_update (preview);
711 }
712 
713 static void
adjustment()714 adjustment () {
715   if (bvals.brightness == 0 && bvals.contrast == 0 && bvals.saturation == 0 && bvals.definition == 0 && bvals.hue == 0 && bvals.cyan_red == 0 && bvals.magenta_green == 0 && bvals.yellow_blue == 0)
716     return;
717 
718   apply_effect ();
719 
720   if (!saved_image)
721     saved_image = gimp_image_duplicate (preview_image);
722 
723   preview_image = gimp_image_duplicate (saved_image);
724   gint32 layer = gimp_image_get_active_layer (preview_image);
725 
726   if (bvals.brightness != 0 || bvals.contrast != 0)
727   {
728     gint low_input = 0;
729     gint high_input = 255;
730     gint low_output = 0;
731     gint high_output = 255;
732 
733     if (bvals.brightness > 0)
734       high_input -= bvals.brightness;
735     if (bvals.brightness < 0)
736       high_output += bvals.brightness;
737 
738     gint value = 62 * (bvals.contrast / 50);
739     if (value > 0) {
740       low_input += value;
741       high_input -= value;
742     }
743     if (value < 0) {
744       low_output -= value;
745       high_output += value;
746     }
747 
748     gimp_levels (layer, GIMP_HISTOGRAM_VALUE,
749                  low_input, high_input,
750                  1,
751                  low_output, high_output);
752   }
753 
754   if (bvals.saturation != 0 || bvals.hue)
755     gimp_hue_saturation (layer, GIMP_ALL_HUES, bvals.hue, 0, bvals.saturation);
756 
757   if (bvals.definition > 0)
758   {
759     gint       nreturn_vals;
760     GimpParam *return_vals;
761     gint32     percent = 78 * (bvals.definition / 50);
762     return_vals = gimp_run_procedure ("plug-in-sharpen",
763                                       &nreturn_vals,
764                                       GIMP_PDB_INT32, GIMP_RUN_NONINTERACTIVE,
765                                       GIMP_PDB_IMAGE, image_ID,
766                                       GIMP_PDB_DRAWABLE, layer,
767                                       GIMP_PDB_INT32, percent,
768                                       GIMP_PDB_END);
769     gimp_destroy_params (return_vals, nreturn_vals);
770   }
771   else if (bvals.definition < 0)
772   {
773     // TODO
774   }
775 
776   if (bvals.cyan_red != 0 || bvals.magenta_green != 0 || bvals.yellow_blue != 0)
777   {
778     gimp_color_balance (layer, GIMP_SHADOWS, TRUE,
779                         bvals.cyan_red, bvals.magenta_green, bvals.yellow_blue);
780     gimp_color_balance (layer, GIMP_MIDTONES, TRUE,
781                         bvals.cyan_red, bvals.magenta_green, bvals.yellow_blue);
782     gimp_color_balance (layer, GIMP_HIGHLIGHTS, TRUE,
783                         bvals.cyan_red, bvals.magenta_green, bvals.yellow_blue);
784   }
785 }
786 
787 static void
reset_pressed(GtkButton * button,gpointer user_date)788 reset_pressed (GtkButton *button, gpointer user_date)
789 {
790   reset_adjustment ();
791   cancel_effect ();
792 
793   gimp_image_delete (preview_image);
794   preview_image = gimp_image_duplicate (image_ID);
795   preview_update (preview);
796 }
797 
798 static void
preview_update(GtkWidget * preview)799 preview_update (GtkWidget *preview)
800 {
801   gint preview_size = PREVIEW_SIZE;
802   gint max_size = height;
803   if (height < width)
804     max_size = width;
805   if (preview_size > max_size)
806     preview_size = max_size;
807   GdkPixbuf *pixbuf = gimp_image_get_thumbnail (preview_image, preview_size, preview_size, GIMP_PIXBUF_SMALL_CHECKS);
808   gtk_image_set_from_pixbuf (GTK_IMAGE(preview), pixbuf);
809 }
810 
811 static GtkWidget*
effect_option_new()812 effect_option_new () {
813   GtkWidget *box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
814 
815   GtkWidget *label = gtk_label_new ("Effect Opacity:");
816   gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 0);
817   gtk_widget_show (label);
818 
819   effect_opacity = gtk_hscale_new_with_range (0, 100, 1);
820   gtk_range_set_value (GTK_RANGE (effect_opacity), 100);
821   gtk_scale_set_value_pos (GTK_SCALE (effect_opacity), GTK_POS_RIGHT);
822   gtk_box_pack_start (GTK_BOX (box), effect_opacity, TRUE, TRUE, 0);
823   gtk_widget_show (effect_opacity);
824 
825   g_signal_connect (effect_opacity, "value-changed",
826                    G_CALLBACK (effect_opacity_update),
827                    NULL);
828 
829   return box;
830 }
831 
832 static void
effect_opacity_update(GtkRange * range,gpointer data)833 effect_opacity_update (GtkRange *range, gpointer data) {
834   if (current_effect == BEAUTIFY_EFFECT_NONE) {
835     return;
836   }
837 
838   gdouble opacity = gtk_range_get_value (range);
839   gint32 layer = gimp_image_get_active_layer (preview_image);
840   gimp_layer_set_opacity (layer, opacity);
841 
842   preview_update (preview);
843 }
844 
845 static void
create_effect_pages(GtkNotebook * notebook)846 create_effect_pages (GtkNotebook *notebook) {
847   create_effect_page (notebook, "Basic");
848   create_effect_page (notebook, "LOMO");
849   create_effect_page (notebook, "Studio");
850   create_effect_page (notebook, "Fashion");
851   create_effect_page (notebook, "Art");
852   create_effect_page (notebook, "Gradient");
853 
854   g_signal_connect (notebook, "switch-page", G_CALLBACK (effects_switch_page), NULL);
855 
856   GtkWidget *page = gtk_notebook_get_nth_page (notebook, 0);
857   effects_switch_page(notebook, page, 0, NULL);
858 }
859 
860 static void
create_effect_page(GtkNotebook * notebook,gchar * str)861 create_effect_page (GtkNotebook *notebook, gchar *str) {
862   GtkWidget *pagelabel = gtk_label_new (str);
863 
864   GtkWidget *thispage = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
865   gtk_container_set_border_width (GTK_CONTAINER (thispage), 12);
866   gtk_widget_show (thispage);
867 
868   gtk_notebook_append_page_menu (notebook, thispage, pagelabel, NULL);
869 }
870 
871 static void
effects_switch_page(GtkNotebook * notebook,GtkWidget * page,guint page_num,gpointer user_data)872 effects_switch_page (GtkNotebook *notebook, GtkWidget *page, guint page_num, gpointer user_data)
873 {
874   static time_t effects_timestamp [] = {0, 0, 0, 0, 0, 0};
875 
876   if (effects_timestamp[page_num] > 0)
877     return;
878 
879   // fix gtk2
880   page = gtk_notebook_get_nth_page (notebook, page_num);
881 
882   const BeautifyEffectType* effects;
883   guint n_effects;
884 
885   switch (page_num)
886   {
887     case 0:
888     {
889       effects = basic_effects;
890       n_effects = G_N_ELEMENTS (basic_effects);
891       break;
892     }
893     case 1:
894     {
895       effects = lomo_effects;
896       n_effects = G_N_ELEMENTS (lomo_effects);
897       break;
898     }
899     case 2:
900     {
901       effects = studio_effects;
902       n_effects = G_N_ELEMENTS (studio_effects);
903       break;
904     }
905     case 3:
906     {
907       effects = fashion_effects;
908       n_effects = G_N_ELEMENTS (fashion_effects);
909       break;
910     }
911     case 4:
912     {
913       effects = art_effects;
914       n_effects = G_N_ELEMENTS (art_effects);
915       break;
916     }
917     case 5:
918     {
919       effects = gradient_effects;
920       n_effects = G_N_ELEMENTS (gradient_effects);
921       break;
922     }
923   }
924 
925   gtk_container_set_border_width (GTK_CONTAINER (page), 0);
926   gtk_widget_set_size_request (page, -1, 480);
927 
928   /* scrolled window */
929   GtkWidget *scrolled_window = gtk_scrolled_window_new (NULL, NULL);
930   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
931   gtk_box_pack_start (GTK_BOX (page), scrolled_window, TRUE, TRUE, 0);
932   gtk_widget_show (scrolled_window);
933 
934   /* table */
935   gint rows = 5;
936   gint cols = 3;
937   GtkWidget *table = gtk_table_new (rows, cols, FALSE);
938   gtk_table_set_col_spacings (GTK_TABLE (table), 6);
939   gtk_table_set_row_spacings (GTK_TABLE (table), 6);
940   gtk_container_set_border_width (GTK_CONTAINER (table), 10);
941   gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_window), table);
942   gtk_widget_show (table);
943 
944   gint row = 1;
945   gint col = 1;
946 
947   gint i;
948   for (i = 0; i < n_effects; i++)
949   {
950     GtkWidget *icon = effect_icon_new (effects[i]);
951     gtk_table_attach_defaults (GTK_TABLE (table), icon, col - 1, col, row - 1, row);
952     gtk_widget_show (icon);
953 
954     col++;
955     if (col > cols)
956     {
957       row++;
958       col = 1;
959     }
960   }
961 
962   effects_timestamp[page_num] = time (NULL);
963 }
964 
965 static GtkWidget *
effect_icon_new(BeautifyEffectType effect)966 effect_icon_new (BeautifyEffectType effect)
967 {
968   gchar *title;
969 
970   switch (effect) {
971     case BEAUTIFY_EFFECT_SOFT_LIGHT:
972       title = "Soft Light";
973       break;
974     case BEAUTIFY_EFFECT_WARM:
975       title = "Warm";
976       break;
977     case BEAUTIFY_EFFECT_SHARPEN:
978       title = "Sharpen";
979       break;
980     case BEAUTIFY_EFFECT_SOFT:
981       title = "Soft";
982       break;
983     case BEAUTIFY_EFFECT_STRONG_CONTRAST:
984       title = "Strong\nContrast";
985       break;
986     case BEAUTIFY_EFFECT_SMART_COLOR:
987       title = "Smart Color";
988       break;
989     case BEAUTIFY_EFFECT_BLACK_AND_WHITE:
990       title = "Black\nand White";
991       break;
992     case BEAUTIFY_EFFECT_INVERT:
993       title = "Invert";
994       break;
995     case BEAUTIFY_EFFECT_CLASSIC_LOMO:
996       title = "Classic LOMO";
997       break;
998     case BEAUTIFY_EFFECT_RETRO_LOMO:
999       title = "Retro LOMO";
1000       break;
1001     case BEAUTIFY_EFFECT_GOTHIC_STYLE:
1002       title = "Gothic Style";
1003       break;
1004     case BEAUTIFY_EFFECT_FILM:
1005       title = "Film";
1006       break;
1007     case BEAUTIFY_EFFECT_HDR:
1008       title = "HDR";
1009       break;
1010     case BEAUTIFY_EFFECT_CLASSIC_HDR:
1011       title = "Classic HDR";
1012       break;
1013     case BEAUTIFY_EFFECT_YELLOWING_DARK_CORNERS:
1014       title = "Yellow Dark\nCorner";
1015       break;
1016     case BEAUTIFY_EFFECT_IMPRESSION:
1017       title = "Impression";
1018       break;
1019     case BEAUTIFY_EFFECT_DEEP_BLUE_TEAR_RAIN:
1020       title = "Deep Blue\nTear Rain";
1021       break;
1022     case BEAUTIFY_EFFECT_PURPLE_SENSATION:
1023       title = "Purple\nSensation";
1024       break;
1025     case BEAUTIFY_EFFECT_BRONZE:
1026       title = "Bronze";
1027       break;
1028     case BEAUTIFY_EFFECT_RECALL:
1029       title = "Recall";
1030       break;
1031     case BEAUTIFY_EFFECT_ELEGANT:
1032       title = "Elegant";
1033       break;
1034     case BEAUTIFY_EFFECT_LITTLE_FRESH:
1035       title = "Little Fresh";
1036       break;
1037     case BEAUTIFY_EFFECT_CLASSIC_STUDIO:
1038       title = "Classic Studio";
1039       break;
1040     case BEAUTIFY_EFFECT_RETRO:
1041       title = "Retro";
1042       break;
1043     case BEAUTIFY_EFFECT_PINK_LADY:
1044       title = "Pink Lady";
1045       break;
1046     case BEAUTIFY_EFFECT_ABAO_COLOR:
1047       title = "ABao Color";
1048       break;
1049     case BEAUTIFY_EFFECT_ICE_SPIRIT:
1050       title = "Ice Spirit";
1051       break;
1052     case BEAUTIFY_EFFECT_JAPANESE_STYLE:
1053       title = "Japanese";
1054       break;
1055     case BEAUTIFY_EFFECT_NEW_JAPANESE_STYLE:
1056       title = "New\nJapanese";
1057       break;
1058     case BEAUTIFY_EFFECT_MILK:
1059       title = "Milk";
1060       break;
1061     case BEAUTIFY_EFFECT_OLD_PHOTOS:
1062       title = "Old Photos";
1063       break;
1064     case BEAUTIFY_EFFECT_WARM_YELLOW:
1065       title = "Warm Yellow";
1066       break;
1067     case BEAUTIFY_EFFECT_BLUES:
1068       title = "Blues";
1069       break;
1070     case BEAUTIFY_EFFECT_COLD_BLUE:
1071       title = "Cold Blue";
1072       break;
1073     case BEAUTIFY_EFFECT_COLD_GREEN:
1074       title = "Cold Green";
1075       break;
1076     case BEAUTIFY_EFFECT_PURPLE_FANTASY:
1077       title = "Purple\nFantasy";
1078       break;
1079     case BEAUTIFY_EFFECT_COLD_PURPLE:
1080       title = "Cold Purple";
1081       break;
1082     case BEAUTIFY_EFFECT_BRIGHT_RED:
1083       title = "Bright Red";
1084       break;
1085     case BEAUTIFY_EFFECT_CHRISTMAS_EVE:
1086       title = "Christmas Eve";
1087       break;
1088     case BEAUTIFY_EFFECT_NIGHT_VIEW:
1089       title = "Night View";
1090       break;
1091     case BEAUTIFY_EFFECT_ASTRAL:
1092       title = "Astral";
1093       break;
1094     case BEAUTIFY_EFFECT_COLORFUL_GLOW:
1095       title = "Colorful Glow";
1096       break;
1097     case BEAUTIFY_EFFECT_PICK_LIGHT:
1098       title = "Pick Light";
1099       break;
1100     case BEAUTIFY_EFFECT_GLASS_DROPS:
1101       title = "Glass Drops";
1102       break;
1103     case BEAUTIFY_EFFECT_SKETCH:
1104       title = "Sketch";
1105       break;
1106     case BEAUTIFY_EFFECT_LIFE_SKETCH:
1107       title = "Life Sketch";
1108       break;
1109     case BEAUTIFY_EFFECT_CLASSIC_SKETCH:
1110       title = "Classic Sketch";
1111       break;
1112     case BEAUTIFY_EFFECT_COLOR_PENCIL:
1113       title = "Color Pencil";
1114       break;
1115     case BEAUTIFY_EFFECT_TV_LINES:
1116       title = "TV Lines";
1117       break;
1118     case BEAUTIFY_EFFECT_RELIEF:
1119       title = "Relief";
1120       break;
1121     case BEAUTIFY_EFFECT_BEAM_GRADIENT:
1122       title = "Beam\nGradient";
1123       break;
1124     case BEAUTIFY_EFFECT_SUNSET_GRADIENT:
1125       title = "Sunset\nGradient";
1126       break;
1127     case BEAUTIFY_EFFECT_RAINBOW_GRADIENT:
1128       title = "Rainbow\nGradient";
1129       break;
1130     case BEAUTIFY_EFFECT_PINK_PURPLE_GRADIENG:
1131       title = "Pink Purple\nGradient";
1132       break;
1133     case BEAUTIFY_EFFECT_PINK_BLUE_GRADIENT:
1134       title = "Pink Blue\nGradient";
1135       break;
1136   }
1137 
1138   gint32 image = gimp_image_duplicate (preview_image);
1139 
1140   /*if (width > THUMBNAIL_SIZE && height > THUMBNAIL_SIZE) {
1141     if (width > height)
1142     {
1143       gimp_image_scale (image, THUMBNAIL_SIZE * width / height, THUMBNAIL_SIZE);
1144     }
1145     else
1146     {
1147       gimp_image_scale (image, THUMBNAIL_SIZE, THUMBNAIL_SIZE * height / width);
1148     }
1149   }*/
1150 
1151   run_effect (image, effect);
1152 
1153   GtkWidget *box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
1154 
1155   GdkPixbuf *pixbuf = gimp_image_get_thumbnail (image, THUMBNAIL_SIZE, THUMBNAIL_SIZE, GIMP_PIXBUF_SMALL_CHECKS);
1156   GtkWidget *icon = gtk_image_new_from_pixbuf (pixbuf);
1157   GtkWidget *event_box = gtk_event_box_new ();
1158   gtk_container_add (GTK_CONTAINER (event_box), icon);
1159   gtk_widget_show (icon);
1160   gtk_box_pack_start (GTK_BOX (box), event_box, FALSE, FALSE, 0);
1161   gtk_widget_show (event_box);
1162 
1163   GtkWidget *label = gtk_label_new (title);
1164   /* gtk_label_set_line_wrap will let textalign to left instead of center :(
1165   gtk_widget_set_size_request (label, THUMBNAIL_SIZE, -1);
1166   gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);*/
1167   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_CENTER);
1168   gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 0);
1169   gtk_widget_show (label);
1170 
1171   g_signal_connect (event_box, "button_press_event", G_CALLBACK (select_effect), (gpointer) effect);
1172 
1173   gimp_image_delete (image);
1174 
1175   return box;
1176 }
1177 
1178 static gboolean
select_effect(GtkWidget * widget,GdkEvent * event,gpointer user_data)1179 select_effect (GtkWidget *widget, GdkEvent *event, gpointer user_data)
1180 {
1181   reset_adjustment ();
1182   apply_effect();
1183 
1184   BeautifyEffectType effect = (BeautifyEffectType) user_data;
1185   run_effect (preview_image, effect);
1186   current_effect = effect;
1187   preview_update (preview);
1188 
1189   /* effect option */
1190   gtk_range_set_value (GTK_RANGE (effect_opacity), 100);
1191   gtk_widget_show (effect_option);
1192 
1193   return TRUE;
1194 }
1195 
1196 static void
reset_adjustment()1197 reset_adjustment ()
1198 {
1199   if (bvals.brightness != 0) {
1200     bvals.brightness = 0;
1201     gtk_range_set_value (GTK_RANGE (brightness), 0);
1202   }
1203   if (bvals.contrast != 0) {
1204     bvals.contrast = 0;
1205     gtk_range_set_value (GTK_RANGE (contrast), 0);
1206   }
1207   if (bvals.saturation != 0) {
1208     bvals.saturation = 0;
1209     gtk_range_set_value (GTK_RANGE (saturation), 0);
1210   }
1211   if (bvals.definition != 0) {
1212     bvals.definition = 0;
1213     gtk_range_set_value (GTK_RANGE (definition), 0);
1214   }
1215   if (bvals.hue != 0) {
1216     bvals.hue = 0;
1217     gtk_range_set_value (GTK_RANGE (hue), 0);
1218   }
1219   if (bvals.cyan_red != 0) {
1220     bvals.cyan_red = 0;
1221     gtk_range_set_value (GTK_RANGE (cyan_red), 0);
1222   }
1223   if (bvals.magenta_green != 0) {
1224     bvals.magenta_green = 0;
1225     gtk_range_set_value (GTK_RANGE (magenta_green), 0);
1226   }
1227   if (bvals.yellow_blue != 0) {
1228     bvals.yellow_blue = 0;
1229     gtk_range_set_value (GTK_RANGE (yellow_blue), 0);
1230   }
1231 }
1232 
1233 static void
apply_effect()1234 apply_effect ()
1235 {
1236   if (current_effect == BEAUTIFY_EFFECT_NONE) {
1237     return;
1238   }
1239 
1240   gint32 current_layer = gimp_image_get_active_layer (preview_image);
1241   gimp_image_merge_down (preview_image, current_layer, GIMP_CLIP_TO_IMAGE);
1242 
1243   current_effect = BEAUTIFY_EFFECT_NONE;
1244 
1245   gtk_widget_hide (effect_option);
1246 
1247   if (saved_image) {
1248     gimp_image_delete (saved_image);
1249     saved_image = 0;
1250   }
1251 }
1252 
1253 static void
cancel_effect()1254 cancel_effect ()
1255 {
1256   if (current_effect == BEAUTIFY_EFFECT_NONE) {
1257     return;
1258   }
1259 
1260   gint32 current_layer = gimp_image_get_active_layer (preview_image);
1261   gimp_drawable_delete (current_layer);
1262 
1263   current_effect = BEAUTIFY_EFFECT_NONE;
1264 
1265   gtk_widget_hide (effect_option);
1266 
1267   if (saved_image) {
1268     gimp_image_delete (saved_image);
1269     saved_image = 0;
1270   }
1271 }
1272 
1273