1 #include "ephoto.h"
2 
3 typedef struct _Ephoto_HSV Ephoto_HSV;
4 struct _Ephoto_HSV
5 {
6    Evas_Object *main;
7    Evas_Object *parent;
8    Evas_Object *image;
9    Evas_Object *editor;
10    Evas_Object *hslider;
11    Evas_Object *sslider;
12    Evas_Object *vslider;
13    Eina_List *handlers;
14    double hue;
15    double saturation;
16    double value;
17    Evas_Coord w, h;
18    unsigned int *original_im_data;
19 };
20 
21 unsigned int *
_ephoto_hsv_adjust_hue(Ephoto_HSV * ehsv,double hue,unsigned int * image_data)22 _ephoto_hsv_adjust_hue(Ephoto_HSV *ehsv, double hue, unsigned int *image_data)
23 {
24    unsigned int *im_data, *im_data_new, *p1, *p2;
25    Evas_Coord x, y;
26    int a, r, g, b, bb, gg, rr;
27    float hh, s, v;
28 
29    im_data = malloc(sizeof(unsigned int) * ehsv->w * ehsv->h);
30    if (image_data)
31       memcpy(im_data, image_data, sizeof(unsigned int) * ehsv->w * ehsv->h);
32    else
33       memcpy(im_data, ehsv->original_im_data,
34 	  sizeof(unsigned int) * ehsv->w * ehsv->h);
35 
36    im_data_new = malloc(sizeof(unsigned int) * ehsv->w * ehsv->h);
37 
38    for (y = 0; y < ehsv->h; y++)
39      {
40 	p1 = im_data + (y * ehsv->w);
41 	p2 = im_data_new + (y * ehsv->w);
42 	for (x = 0; x < ehsv->w; x++)
43 	  {
44 	     b = (int) ((*p1) & 0xff);
45 	     g = (int) ((*p1 >> 8) & 0xff);
46 	     r = (int) ((*p1 >> 16) & 0xff);
47 	     a = (int) ((*p1 >> 24) & 0xff);
48 	     b = ephoto_mul_color_alpha(b, a);
49 	     g = ephoto_mul_color_alpha(g, a);
50 	     r = ephoto_mul_color_alpha(r, a);
51 	     evas_color_rgb_to_hsv(r, g, b, &hh, &s, &v);
52 	     hh += hue;
53 	     if (hh < 0)
54 		hh += 360;
55 	     if (hh > 360)
56 		hh -= 360;
57 	     evas_color_hsv_to_rgb(hh, s, v, &rr, &gg, &bb);
58 	     bb = ephoto_normalize_color(bb);
59 	     gg = ephoto_normalize_color(gg);
60 	     rr = ephoto_normalize_color(rr);
61 	     bb = ephoto_demul_color_alpha(bb, a);
62 	     gg = ephoto_demul_color_alpha(gg, a);
63 	     rr = ephoto_demul_color_alpha(rr, a);
64 	     *p2 = (a << 24) | (rr << 16) | (gg << 8) | bb;
65 	     p2++;
66 	     p1++;
67 	  }
68      }
69    ehsv->hue = hue;
70    ephoto_single_browser_image_data_update(ehsv->main, ehsv->image,
71        im_data_new, ehsv->w, ehsv->h);
72    free(im_data);
73    return im_data_new;
74 }
75 
76 unsigned int *
_ephoto_hsv_adjust_saturation(Ephoto_HSV * ehsv,double saturation,unsigned int * image_data)77 _ephoto_hsv_adjust_saturation(Ephoto_HSV *ehsv, double saturation,
78     unsigned int *image_data)
79 {
80    unsigned int *im_data, *im_data_new, *p1, *p2;
81    Evas_Coord x, y;
82    int a, r, g, b, bb, gg, rr;
83    float hh, s, v;
84 
85    im_data = malloc(sizeof(unsigned int) * ehsv->w * ehsv->h);
86    if (image_data)
87       memcpy(im_data, image_data, sizeof(unsigned int) * ehsv->w * ehsv->h);
88    else
89       memcpy(im_data, ehsv->original_im_data,
90 	  sizeof(unsigned int) * ehsv->w * ehsv->h);
91 
92    im_data_new = malloc(sizeof(unsigned int) * ehsv->w * ehsv->h);
93 
94    for (y = 0; y < ehsv->h; y++)
95      {
96 	p1 = im_data + (y * ehsv->w);
97 	p2 = im_data_new + (y * ehsv->w);
98 	for (x = 0; x < ehsv->w; x++)
99 	  {
100 	     b = (int) ((*p1) & 0xff);
101 	     g = (int) ((*p1 >> 8) & 0xff);
102 	     r = (int) ((*p1 >> 16) & 0xff);
103 	     a = (int) ((*p1 >> 24) & 0xff);
104 	     b = ephoto_mul_color_alpha(b, a);
105 	     g = ephoto_mul_color_alpha(g, a);
106 	     r = ephoto_mul_color_alpha(r, a);
107 	     evas_color_rgb_to_hsv(r, g, b, &hh, &s, &v);
108 	     s += s * ((float) saturation / 100);
109 	     if (s < 0)
110 		s = 0;
111 	     if (s > 1)
112 		s = 1;
113 	     evas_color_hsv_to_rgb(hh, s, v, &rr, &gg, &bb);
114 	     bb = ephoto_normalize_color(bb);
115 	     gg = ephoto_normalize_color(gg);
116 	     rr = ephoto_normalize_color(rr);
117 	     bb = ephoto_demul_color_alpha(bb, a);
118 	     gg = ephoto_demul_color_alpha(gg, a);
119 	     rr = ephoto_demul_color_alpha(rr, a);
120 	     *p2 = (a << 24) | (rr << 16) | (gg << 8) | bb;
121 	     p2++;
122 	     p1++;
123 	  }
124      }
125    ehsv->saturation = saturation;
126    ephoto_single_browser_image_data_update(ehsv->main, ehsv->image,
127        im_data_new, ehsv->w, ehsv->h);
128    free(im_data);
129    return im_data_new;
130 }
131 
132 unsigned int *
_ephoto_hsv_adjust_value(Ephoto_HSV * ehsv,double value,unsigned int * image_data)133 _ephoto_hsv_adjust_value(Ephoto_HSV *ehsv, double value,
134     unsigned int *image_data)
135 {
136    unsigned int *im_data, *im_data_new, *p1, *p2;
137    Evas_Coord x, y;
138    int a, r, g, b, bb, gg, rr;
139    float hh, s, v;
140 
141    im_data = malloc(sizeof(unsigned int) * ehsv->w * ehsv->h);
142    if (image_data)
143       memcpy(im_data, image_data, sizeof(unsigned int) * ehsv->w * ehsv->h);
144    else
145       memcpy(im_data, ehsv->original_im_data,
146 	  sizeof(unsigned int) * ehsv->w * ehsv->h);
147 
148    im_data_new = malloc(sizeof(unsigned int) * ehsv->w * ehsv->h);
149 
150    for (y = 0; y < ehsv->h; y++)
151      {
152 	p1 = im_data + (y * ehsv->w);
153 	p2 = im_data_new + (y * ehsv->w);
154 	for (x = 0; x < ehsv->w; x++)
155 	  {
156 	     b = (int) ((*p1) & 0xff);
157 	     g = (int) ((*p1 >> 8) & 0xff);
158 	     r = (int) ((*p1 >> 16) & 0xff);
159 	     a = (int) ((*p1 >> 24) & 0xff);
160 	     b = ephoto_mul_color_alpha(b, a);
161 	     g = ephoto_mul_color_alpha(g, a);
162 	     r = ephoto_mul_color_alpha(r, a);
163 	     evas_color_rgb_to_hsv(r, g, b, &hh, &s, &v);
164 	     v += (v * ((float) value / 100));
165 	     if (v < 0)
166 		v = 0;
167 	     if (v > 1)
168 		v = 1;
169 	     evas_color_hsv_to_rgb(hh, s, v, &rr, &gg, &bb);
170 	     bb = ephoto_normalize_color(bb);
171 	     gg = ephoto_normalize_color(gg);
172 	     rr = ephoto_normalize_color(rr);
173 	     bb = ephoto_demul_color_alpha(bb, a);
174 	     gg = ephoto_demul_color_alpha(gg, a);
175 	     rr = ephoto_demul_color_alpha(rr, a);
176 	     *p2 = (a << 24) | (rr << 16) | (gg << 8) | bb;
177 	     p2++;
178 	     p1++;
179 	  }
180      }
181    ehsv->value = value;
182    ephoto_single_browser_image_data_update(ehsv->main, ehsv->image,
183        im_data_new, ehsv->w, ehsv->h);
184    free(im_data);
185    return im_data_new;
186 }
187 
188 static void
_hue_slider_changed(void * data,Evas_Object * obj,void * event_info EINA_UNUSED)189 _hue_slider_changed(void *data, Evas_Object *obj, void *event_info EINA_UNUSED)
190 {
191    Ephoto_HSV *ehsv = data;
192    double hue;
193    unsigned int *image_data, *image_data_two;
194 
195    hue = elm_slider_value_get(obj);
196    image_data = _ephoto_hsv_adjust_hue(ehsv, hue, NULL);
197    image_data_two =
198        _ephoto_hsv_adjust_saturation(ehsv, ehsv->saturation, image_data);
199    _ephoto_hsv_adjust_value(ehsv, ehsv->value, image_data_two);
200 }
201 
202 static void
_saturation_slider_changed(void * data,Evas_Object * obj,void * event_info EINA_UNUSED)203 _saturation_slider_changed(void *data, Evas_Object *obj,
204     void *event_info EINA_UNUSED)
205 {
206    Ephoto_HSV *ehsv = data;
207    double saturation;
208    unsigned int *image_data, *image_data_two;
209 
210    saturation = elm_slider_value_get(obj);
211    image_data = _ephoto_hsv_adjust_saturation(ehsv, saturation, NULL);
212    image_data_two = _ephoto_hsv_adjust_hue(ehsv, ehsv->hue, image_data);
213    _ephoto_hsv_adjust_value(ehsv, ehsv->value, image_data_two);
214 }
215 
216 static void
_value_slider_changed(void * data,Evas_Object * obj,void * event_info EINA_UNUSED)217 _value_slider_changed(void *data, Evas_Object *obj,
218     void *event_info EINA_UNUSED)
219 {
220    Ephoto_HSV *ehsv = data;
221    double value;
222    unsigned int *image_data, *image_data_two;
223 
224    value = elm_slider_value_get(obj);
225    image_data = _ephoto_hsv_adjust_value(ehsv, value, NULL);
226    image_data_two = _ephoto_hsv_adjust_hue(ehsv, ehsv->hue, image_data);
227    _ephoto_hsv_adjust_saturation(ehsv, ehsv->saturation, image_data_two);
228 }
229 
230 static Eina_Bool
_hsv_reset(void * data,int type EINA_UNUSED,void * event_info EINA_UNUSED)231 _hsv_reset(void *data, int type EINA_UNUSED,
232     void *event_info EINA_UNUSED)
233 {
234    Ephoto_HSV *ehsv = data;
235 
236    elm_slider_value_set(ehsv->hslider, 0);
237    elm_slider_value_set(ehsv->sslider, 0);
238    elm_slider_value_set(ehsv->vslider, 0);
239    ehsv->hue = 0;
240    ehsv->saturation = 0;
241    ehsv->value = 0;
242    _hue_slider_changed(ehsv, ehsv->hslider, NULL);
243 
244    return ECORE_CALLBACK_PASS_ON;
245 }
246 
247 static Eina_Bool
_hsv_apply(void * data,int type EINA_UNUSED,void * event_info EINA_UNUSED)248 _hsv_apply(void *data, int type EINA_UNUSED,
249     void *event_info EINA_UNUSED)
250 {
251    Ephoto_HSV *ehsv = data;
252    unsigned int *image_data;
253    Evas_Coord w, h;
254 
255    if (elm_slider_value_get(ehsv->hslider) == 0 &&
256        elm_slider_value_get(ehsv->sslider) == 0 &&
257        elm_slider_value_get(ehsv->vslider) == 0)
258      {
259         ephoto_single_browser_cancel_editing(ehsv->main);
260      }
261    else
262      {
263         image_data =
264             evas_object_image_data_get(ehsv->image, EINA_FALSE);
265         evas_object_image_size_get(ehsv->image, &w, &h);
266         ephoto_single_browser_image_data_done(ehsv->main, image_data, w, h);
267      }
268    ephoto_editor_del(ehsv->editor, ehsv->parent);
269 
270    return ECORE_CALLBACK_PASS_ON;
271 }
272 
273 static Eina_Bool
_hsv_cancel(void * data,int type EINA_UNUSED,void * event_info EINA_UNUSED)274 _hsv_cancel(void *data, int type EINA_UNUSED,
275     void *event_info EINA_UNUSED)
276 {
277    Ephoto_HSV *ehsv = data;
278 
279    elm_slider_value_set(ehsv->hslider, 0);
280    elm_slider_value_set(ehsv->sslider, 0);
281    elm_slider_value_set(ehsv->vslider, 0);
282    ehsv->hue = 0;
283    ehsv->saturation = 0;
284    ehsv->value = 0;
285    _hue_slider_changed(ehsv, ehsv->hslider, NULL);
286    ephoto_single_browser_cancel_editing(ehsv->main);
287    ephoto_editor_del(ehsv->editor, ehsv->parent);
288 
289    return ECORE_CALLBACK_PASS_ON;
290 }
291 
292 static void
_editor_del(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)293 _editor_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
294     void *event_info EINA_UNUSED)
295 {
296    Ephoto_HSV *ehsv = data;
297    Ecore_Event_Handler *handler;
298 
299    EINA_LIST_FREE(ehsv->handlers, handler)
300      ecore_event_handler_del(handler);
301    free(ehsv->original_im_data);
302    free(ehsv);
303 }
304 
305 void
ephoto_hsv_add(Ephoto * ephoto,Evas_Object * main,Evas_Object * parent,Evas_Object * image)306 ephoto_hsv_add(Ephoto *ephoto, Evas_Object *main, Evas_Object *parent, Evas_Object *image)
307 {
308    Evas_Object *slider;
309    Ephoto_HSV *ehsv;
310    unsigned int *im_data;
311 
312    EINA_SAFETY_ON_NULL_GOTO(image, error);
313 
314    ehsv = calloc(1, sizeof(Ephoto_HSV));
315    EINA_SAFETY_ON_NULL_GOTO(ehsv, error);
316 
317    ehsv->hue = 0;
318    ehsv->saturation = 0;
319    ehsv->value = 0;
320    ehsv->main = main;
321    ehsv->parent = parent;
322    ehsv->image = image;
323    im_data =
324        evas_object_image_data_get(ehsv->image,
325        EINA_FALSE);
326    evas_object_image_size_get(ehsv->image, &ehsv->w,
327        &ehsv->h);
328    ehsv->original_im_data = malloc(sizeof(unsigned int) * ehsv->w * ehsv->h);
329    memcpy(ehsv->original_im_data, im_data,
330        sizeof(unsigned int) * ehsv->w * ehsv->h);
331 
332    ehsv->editor = ephoto_editor_add(ephoto, parent, _("Hue/Saturation/Value"),
333        "ehsv", ehsv);
334    evas_object_event_callback_add(ehsv->editor, EVAS_CALLBACK_DEL, _editor_del,
335        ehsv);
336 
337    slider = elm_slider_add(ehsv->editor);
338    elm_object_text_set(slider, _("Value"));
339    elm_slider_min_max_set(slider, -100, 100);
340    elm_slider_step_set(slider, 1.20);
341    elm_slider_value_set(slider, 0);
342    elm_slider_unit_format_set(slider, "%1.2f");
343    elm_slider_indicator_format_set(slider, "%1.2f");
344    EPHOTO_WEIGHT(slider, EVAS_HINT_EXPAND, EVAS_HINT_FILL);
345    EPHOTO_ALIGN(slider, EVAS_HINT_FILL, 0.5);
346    evas_object_smart_callback_add(slider, "delay,changed", _value_slider_changed,
347        ehsv);
348    elm_box_pack_start(ehsv->editor, slider);
349    evas_object_show(slider);
350    ehsv->vslider = slider;
351 
352    slider = elm_slider_add(ehsv->editor);
353    elm_object_text_set(slider, _("Saturation"));
354    elm_slider_min_max_set(slider, -100, 100);
355    elm_slider_step_set(slider, 1.20);
356    elm_slider_value_set(slider, 0);
357    elm_slider_unit_format_set(slider, "%1.2f");
358    elm_slider_indicator_format_set(slider, "%1.2f");
359    EPHOTO_WEIGHT(slider, EVAS_HINT_EXPAND, EVAS_HINT_FILL);
360    EPHOTO_ALIGN(slider, EVAS_HINT_FILL, 0.5);
361    evas_object_smart_callback_add(slider, "delay,changed",
362        _saturation_slider_changed, ehsv);
363    elm_box_pack_start(ehsv->editor, slider);
364    evas_object_show(slider);
365    ehsv->sslider = slider;
366 
367    slider = elm_slider_add(ehsv->editor);
368    elm_object_text_set(slider, _("Hue"));
369    elm_slider_min_max_set(slider, -180, 180);
370    elm_slider_step_set(slider, 1);
371    elm_slider_value_set(slider, 0);
372    elm_slider_unit_format_set(slider, "%1.0f");
373    elm_slider_indicator_format_set(slider, "%1.0f");
374    EPHOTO_WEIGHT(slider, EVAS_HINT_EXPAND, EVAS_HINT_FILL);
375    EPHOTO_ALIGN(slider, EVAS_HINT_FILL, 0.5);
376    evas_object_smart_callback_add(slider, "delay,changed",
377        _hue_slider_changed, ehsv);
378    elm_box_pack_start(ehsv->editor, slider);
379    evas_object_show(slider);
380    ehsv->hslider = slider;
381 
382    ehsv->handlers =
383        eina_list_append(ehsv->handlers,
384        ecore_event_handler_add(EPHOTO_EVENT_EDITOR_RESET,
385            _hsv_reset, ehsv));
386    ehsv->handlers =
387        eina_list_append(ehsv->handlers,
388        ecore_event_handler_add(EPHOTO_EVENT_EDITOR_APPLY,
389            _hsv_apply, ehsv));
390    ehsv->handlers =
391        eina_list_append(ehsv->handlers,
392        ecore_event_handler_add(EPHOTO_EVENT_EDITOR_CANCEL,
393            _hsv_cancel, ehsv));
394    return;
395 
396   error:
397    return;
398 }
399