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