#include "ephoto.h" typedef struct _Ephoto_HSV Ephoto_HSV; struct _Ephoto_HSV { Evas_Object *main; Evas_Object *parent; Evas_Object *image; Evas_Object *editor; Evas_Object *hslider; Evas_Object *sslider; Evas_Object *vslider; Eina_List *handlers; double hue; double saturation; double value; Evas_Coord w, h; unsigned int *original_im_data; }; unsigned int * _ephoto_hsv_adjust_hue(Ephoto_HSV *ehsv, double hue, unsigned int *image_data) { unsigned int *im_data, *im_data_new, *p1, *p2; Evas_Coord x, y; int a, r, g, b, bb, gg, rr; float hh, s, v; im_data = malloc(sizeof(unsigned int) * ehsv->w * ehsv->h); if (image_data) memcpy(im_data, image_data, sizeof(unsigned int) * ehsv->w * ehsv->h); else memcpy(im_data, ehsv->original_im_data, sizeof(unsigned int) * ehsv->w * ehsv->h); im_data_new = malloc(sizeof(unsigned int) * ehsv->w * ehsv->h); for (y = 0; y < ehsv->h; y++) { p1 = im_data + (y * ehsv->w); p2 = im_data_new + (y * ehsv->w); for (x = 0; x < ehsv->w; x++) { b = (int) ((*p1) & 0xff); g = (int) ((*p1 >> 8) & 0xff); r = (int) ((*p1 >> 16) & 0xff); a = (int) ((*p1 >> 24) & 0xff); b = ephoto_mul_color_alpha(b, a); g = ephoto_mul_color_alpha(g, a); r = ephoto_mul_color_alpha(r, a); evas_color_rgb_to_hsv(r, g, b, &hh, &s, &v); hh += hue; if (hh < 0) hh += 360; if (hh > 360) hh -= 360; evas_color_hsv_to_rgb(hh, s, v, &rr, &gg, &bb); bb = ephoto_normalize_color(bb); gg = ephoto_normalize_color(gg); rr = ephoto_normalize_color(rr); bb = ephoto_demul_color_alpha(bb, a); gg = ephoto_demul_color_alpha(gg, a); rr = ephoto_demul_color_alpha(rr, a); *p2 = (a << 24) | (rr << 16) | (gg << 8) | bb; p2++; p1++; } } ehsv->hue = hue; ephoto_single_browser_image_data_update(ehsv->main, ehsv->image, im_data_new, ehsv->w, ehsv->h); free(im_data); return im_data_new; } unsigned int * _ephoto_hsv_adjust_saturation(Ephoto_HSV *ehsv, double saturation, unsigned int *image_data) { unsigned int *im_data, *im_data_new, *p1, *p2; Evas_Coord x, y; int a, r, g, b, bb, gg, rr; float hh, s, v; im_data = malloc(sizeof(unsigned int) * ehsv->w * ehsv->h); if (image_data) memcpy(im_data, image_data, sizeof(unsigned int) * ehsv->w * ehsv->h); else memcpy(im_data, ehsv->original_im_data, sizeof(unsigned int) * ehsv->w * ehsv->h); im_data_new = malloc(sizeof(unsigned int) * ehsv->w * ehsv->h); for (y = 0; y < ehsv->h; y++) { p1 = im_data + (y * ehsv->w); p2 = im_data_new + (y * ehsv->w); for (x = 0; x < ehsv->w; x++) { b = (int) ((*p1) & 0xff); g = (int) ((*p1 >> 8) & 0xff); r = (int) ((*p1 >> 16) & 0xff); a = (int) ((*p1 >> 24) & 0xff); b = ephoto_mul_color_alpha(b, a); g = ephoto_mul_color_alpha(g, a); r = ephoto_mul_color_alpha(r, a); evas_color_rgb_to_hsv(r, g, b, &hh, &s, &v); s += s * ((float) saturation / 100); if (s < 0) s = 0; if (s > 1) s = 1; evas_color_hsv_to_rgb(hh, s, v, &rr, &gg, &bb); bb = ephoto_normalize_color(bb); gg = ephoto_normalize_color(gg); rr = ephoto_normalize_color(rr); bb = ephoto_demul_color_alpha(bb, a); gg = ephoto_demul_color_alpha(gg, a); rr = ephoto_demul_color_alpha(rr, a); *p2 = (a << 24) | (rr << 16) | (gg << 8) | bb; p2++; p1++; } } ehsv->saturation = saturation; ephoto_single_browser_image_data_update(ehsv->main, ehsv->image, im_data_new, ehsv->w, ehsv->h); free(im_data); return im_data_new; } unsigned int * _ephoto_hsv_adjust_value(Ephoto_HSV *ehsv, double value, unsigned int *image_data) { unsigned int *im_data, *im_data_new, *p1, *p2; Evas_Coord x, y; int a, r, g, b, bb, gg, rr; float hh, s, v; im_data = malloc(sizeof(unsigned int) * ehsv->w * ehsv->h); if (image_data) memcpy(im_data, image_data, sizeof(unsigned int) * ehsv->w * ehsv->h); else memcpy(im_data, ehsv->original_im_data, sizeof(unsigned int) * ehsv->w * ehsv->h); im_data_new = malloc(sizeof(unsigned int) * ehsv->w * ehsv->h); for (y = 0; y < ehsv->h; y++) { p1 = im_data + (y * ehsv->w); p2 = im_data_new + (y * ehsv->w); for (x = 0; x < ehsv->w; x++) { b = (int) ((*p1) & 0xff); g = (int) ((*p1 >> 8) & 0xff); r = (int) ((*p1 >> 16) & 0xff); a = (int) ((*p1 >> 24) & 0xff); b = ephoto_mul_color_alpha(b, a); g = ephoto_mul_color_alpha(g, a); r = ephoto_mul_color_alpha(r, a); evas_color_rgb_to_hsv(r, g, b, &hh, &s, &v); v += (v * ((float) value / 100)); if (v < 0) v = 0; if (v > 1) v = 1; evas_color_hsv_to_rgb(hh, s, v, &rr, &gg, &bb); bb = ephoto_normalize_color(bb); gg = ephoto_normalize_color(gg); rr = ephoto_normalize_color(rr); bb = ephoto_demul_color_alpha(bb, a); gg = ephoto_demul_color_alpha(gg, a); rr = ephoto_demul_color_alpha(rr, a); *p2 = (a << 24) | (rr << 16) | (gg << 8) | bb; p2++; p1++; } } ehsv->value = value; ephoto_single_browser_image_data_update(ehsv->main, ehsv->image, im_data_new, ehsv->w, ehsv->h); free(im_data); return im_data_new; } static void _hue_slider_changed(void *data, Evas_Object *obj, void *event_info EINA_UNUSED) { Ephoto_HSV *ehsv = data; double hue; unsigned int *image_data, *image_data_two; hue = elm_slider_value_get(obj); image_data = _ephoto_hsv_adjust_hue(ehsv, hue, NULL); image_data_two = _ephoto_hsv_adjust_saturation(ehsv, ehsv->saturation, image_data); _ephoto_hsv_adjust_value(ehsv, ehsv->value, image_data_two); } static void _saturation_slider_changed(void *data, Evas_Object *obj, void *event_info EINA_UNUSED) { Ephoto_HSV *ehsv = data; double saturation; unsigned int *image_data, *image_data_two; saturation = elm_slider_value_get(obj); image_data = _ephoto_hsv_adjust_saturation(ehsv, saturation, NULL); image_data_two = _ephoto_hsv_adjust_hue(ehsv, ehsv->hue, image_data); _ephoto_hsv_adjust_value(ehsv, ehsv->value, image_data_two); } static void _value_slider_changed(void *data, Evas_Object *obj, void *event_info EINA_UNUSED) { Ephoto_HSV *ehsv = data; double value; unsigned int *image_data, *image_data_two; value = elm_slider_value_get(obj); image_data = _ephoto_hsv_adjust_value(ehsv, value, NULL); image_data_two = _ephoto_hsv_adjust_hue(ehsv, ehsv->hue, image_data); _ephoto_hsv_adjust_saturation(ehsv, ehsv->saturation, image_data_two); } static Eina_Bool _hsv_reset(void *data, int type EINA_UNUSED, void *event_info EINA_UNUSED) { Ephoto_HSV *ehsv = data; elm_slider_value_set(ehsv->hslider, 0); elm_slider_value_set(ehsv->sslider, 0); elm_slider_value_set(ehsv->vslider, 0); ehsv->hue = 0; ehsv->saturation = 0; ehsv->value = 0; _hue_slider_changed(ehsv, ehsv->hslider, NULL); return ECORE_CALLBACK_PASS_ON; } static Eina_Bool _hsv_apply(void *data, int type EINA_UNUSED, void *event_info EINA_UNUSED) { Ephoto_HSV *ehsv = data; unsigned int *image_data; Evas_Coord w, h; if (elm_slider_value_get(ehsv->hslider) == 0 && elm_slider_value_get(ehsv->sslider) == 0 && elm_slider_value_get(ehsv->vslider) == 0) { ephoto_single_browser_cancel_editing(ehsv->main); } else { image_data = evas_object_image_data_get(ehsv->image, EINA_FALSE); evas_object_image_size_get(ehsv->image, &w, &h); ephoto_single_browser_image_data_done(ehsv->main, image_data, w, h); } ephoto_editor_del(ehsv->editor, ehsv->parent); return ECORE_CALLBACK_PASS_ON; } static Eina_Bool _hsv_cancel(void *data, int type EINA_UNUSED, void *event_info EINA_UNUSED) { Ephoto_HSV *ehsv = data; elm_slider_value_set(ehsv->hslider, 0); elm_slider_value_set(ehsv->sslider, 0); elm_slider_value_set(ehsv->vslider, 0); ehsv->hue = 0; ehsv->saturation = 0; ehsv->value = 0; _hue_slider_changed(ehsv, ehsv->hslider, NULL); ephoto_single_browser_cancel_editing(ehsv->main); ephoto_editor_del(ehsv->editor, ehsv->parent); return ECORE_CALLBACK_PASS_ON; } static void _editor_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { Ephoto_HSV *ehsv = data; Ecore_Event_Handler *handler; EINA_LIST_FREE(ehsv->handlers, handler) ecore_event_handler_del(handler); free(ehsv->original_im_data); free(ehsv); } void ephoto_hsv_add(Ephoto *ephoto, Evas_Object *main, Evas_Object *parent, Evas_Object *image) { Evas_Object *slider; Ephoto_HSV *ehsv; unsigned int *im_data; EINA_SAFETY_ON_NULL_GOTO(image, error); ehsv = calloc(1, sizeof(Ephoto_HSV)); EINA_SAFETY_ON_NULL_GOTO(ehsv, error); ehsv->hue = 0; ehsv->saturation = 0; ehsv->value = 0; ehsv->main = main; ehsv->parent = parent; ehsv->image = image; im_data = evas_object_image_data_get(ehsv->image, EINA_FALSE); evas_object_image_size_get(ehsv->image, &ehsv->w, &ehsv->h); ehsv->original_im_data = malloc(sizeof(unsigned int) * ehsv->w * ehsv->h); memcpy(ehsv->original_im_data, im_data, sizeof(unsigned int) * ehsv->w * ehsv->h); ehsv->editor = ephoto_editor_add(ephoto, parent, _("Hue/Saturation/Value"), "ehsv", ehsv); evas_object_event_callback_add(ehsv->editor, EVAS_CALLBACK_DEL, _editor_del, ehsv); slider = elm_slider_add(ehsv->editor); elm_object_text_set(slider, _("Value")); elm_slider_min_max_set(slider, -100, 100); elm_slider_step_set(slider, 1.20); elm_slider_value_set(slider, 0); elm_slider_unit_format_set(slider, "%1.2f"); elm_slider_indicator_format_set(slider, "%1.2f"); EPHOTO_WEIGHT(slider, EVAS_HINT_EXPAND, EVAS_HINT_FILL); EPHOTO_ALIGN(slider, EVAS_HINT_FILL, 0.5); evas_object_smart_callback_add(slider, "delay,changed", _value_slider_changed, ehsv); elm_box_pack_start(ehsv->editor, slider); evas_object_show(slider); ehsv->vslider = slider; slider = elm_slider_add(ehsv->editor); elm_object_text_set(slider, _("Saturation")); elm_slider_min_max_set(slider, -100, 100); elm_slider_step_set(slider, 1.20); elm_slider_value_set(slider, 0); elm_slider_unit_format_set(slider, "%1.2f"); elm_slider_indicator_format_set(slider, "%1.2f"); EPHOTO_WEIGHT(slider, EVAS_HINT_EXPAND, EVAS_HINT_FILL); EPHOTO_ALIGN(slider, EVAS_HINT_FILL, 0.5); evas_object_smart_callback_add(slider, "delay,changed", _saturation_slider_changed, ehsv); elm_box_pack_start(ehsv->editor, slider); evas_object_show(slider); ehsv->sslider = slider; slider = elm_slider_add(ehsv->editor); elm_object_text_set(slider, _("Hue")); elm_slider_min_max_set(slider, -180, 180); elm_slider_step_set(slider, 1); elm_slider_value_set(slider, 0); elm_slider_unit_format_set(slider, "%1.0f"); elm_slider_indicator_format_set(slider, "%1.0f"); EPHOTO_WEIGHT(slider, EVAS_HINT_EXPAND, EVAS_HINT_FILL); EPHOTO_ALIGN(slider, EVAS_HINT_FILL, 0.5); evas_object_smart_callback_add(slider, "delay,changed", _hue_slider_changed, ehsv); elm_box_pack_start(ehsv->editor, slider); evas_object_show(slider); ehsv->hslider = slider; ehsv->handlers = eina_list_append(ehsv->handlers, ecore_event_handler_add(EPHOTO_EVENT_EDITOR_RESET, _hsv_reset, ehsv)); ehsv->handlers = eina_list_append(ehsv->handlers, ecore_event_handler_add(EPHOTO_EVENT_EDITOR_APPLY, _hsv_apply, ehsv)); ehsv->handlers = eina_list_append(ehsv->handlers, ecore_event_handler_add(EPHOTO_EVENT_EDITOR_CANCEL, _hsv_cancel, ehsv)); return; error: return; }