parent
48a0084337
commit
5a5d2bb12e
5 changed files with 280 additions and 2 deletions
@ -0,0 +1,254 @@ |
||||
#include "ephoto.h" |
||||
|
||||
typedef struct _Ephoto_Reye Ephoto_Reye; |
||||
struct _Ephoto_Reye |
||||
{ |
||||
Evas_Object *main; |
||||
Evas_Object *parent; |
||||
Evas_Object *image; |
||||
Evas_Object *editor; |
||||
Evas_Object *rslider; |
||||
Eina_List *handlers; |
||||
int rad; |
||||
int w, h; |
||||
unsigned int *original_im_data; |
||||
unsigned int *edited_im_data; |
||||
}; |
||||
|
||||
static int |
||||
_normalize_color(int color) |
||||
{ |
||||
if (color < 0) |
||||
return 0; |
||||
else if (color > 255) |
||||
return 255; |
||||
else |
||||
return color; |
||||
} |
||||
|
||||
static int |
||||
_mul_color_alpha(int color, int alpha) |
||||
{ |
||||
if (alpha > 0 && alpha < 255) |
||||
return color * (255 / alpha); |
||||
else |
||||
return color; |
||||
} |
||||
|
||||
static int |
||||
_demul_color_alpha(int color, int alpha) |
||||
{ |
||||
if (alpha > 0 && alpha < 255) |
||||
return (color * alpha) / 255; |
||||
else |
||||
return color; |
||||
} |
||||
|
||||
static void |
||||
_reye_clicked(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, |
||||
void *event_data EINA_UNUSED) |
||||
{ |
||||
Ephoto_Reye *er = data; |
||||
unsigned int *im_data, *im_data_new, *p1, *p2; |
||||
int x, y, imx, imy, xpos, ypos, xadj, yadj; |
||||
int a, r, g, b; |
||||
|
||||
evas_pointer_canvas_xy_get(evas_object_evas_get(er->image), &xpos, &ypos); |
||||
evas_object_geometry_get(er->image, &imx, &imy, 0, 0); |
||||
|
||||
xadj = (xpos-imx)-(er->rad/2); |
||||
yadj = (ypos-imy)-(er->rad/2); |
||||
|
||||
if (xadj < 0) xadj = 0; |
||||
if (yadj < 0) yadj = 0; |
||||
|
||||
im_data = malloc(sizeof(unsigned int) * er->w * er->h); |
||||
if (er->edited_im_data) |
||||
memcpy(im_data, er->edited_im_data, |
||||
sizeof(unsigned int) * er->w * er->h); |
||||
else |
||||
memcpy(im_data, er->original_im_data, |
||||
sizeof(unsigned int) * er->w * er->h); |
||||
|
||||
im_data_new = malloc(sizeof(unsigned int) * er->w * er->h); |
||||
|
||||
for (y = 0; y < er->h; y++) |
||||
{ |
||||
p1 = im_data + (y * er->w); |
||||
p2 = im_data_new + (y * er->w); |
||||
for (x = 0; x < er->w; x++) |
||||
{ |
||||
b = (int) ((*p1) & 0xff); |
||||
g = (int) ((*p1 >> 8) & 0xff); |
||||
r = (int) ((*p1 >> 16) & 0xff); |
||||
a = (int) ((*p1 >> 24) & 0xff); |
||||
b = _mul_color_alpha(b, a); |
||||
g = _mul_color_alpha(g, a); |
||||
r = _mul_color_alpha(r, a); |
||||
if (y >= yadj && y <= yadj+er->rad) |
||||
{ |
||||
if (x >= xadj && x <= xadj+er->rad) |
||||
r = (int) ((g+b)/2); |
||||
} |
||||
b = _normalize_color(b); |
||||
g = _normalize_color(g); |
||||
r = _normalize_color(r); |
||||
b = _demul_color_alpha(b, a); |
||||
g = _demul_color_alpha(g, a); |
||||
r = _demul_color_alpha(r, a); |
||||
*p2 = (a << 24) | (r << 16) | (g << 8) | b; |
||||
p2++; |
||||
p1++; |
||||
} |
||||
} |
||||
er->edited_im_data = im_data_new; |
||||
ephoto_single_browser_image_data_update(er->main, er->image, EINA_FALSE, |
||||
im_data_new, er->w, er->h); |
||||
free(im_data); |
||||
} |
||||
|
||||
static void |
||||
_radius_slider_changed(void *data, Evas_Object *obj, void *event_info EINA_UNUSED) |
||||
{ |
||||
Ephoto_Reye *er = data; |
||||
|
||||
er->rad = elm_slider_value_get(obj); |
||||
} |
||||
|
||||
static Eina_Bool |
||||
_reye_reset(void *data, int type EINA_UNUSED, |
||||
void *event_info EINA_UNUSED) |
||||
{ |
||||
Ephoto_Reye *er = data; |
||||
|
||||
elm_slider_value_set(er->rslider, 15); |
||||
er->rad = 15; |
||||
|
||||
ephoto_single_browser_image_data_update(er->main, er->image, EINA_FALSE, |
||||
er->original_im_data, er->w, er->h); |
||||
|
||||
return ECORE_CALLBACK_PASS_ON; |
||||
} |
||||
|
||||
static Eina_Bool |
||||
_reye_apply(void *data, int type EINA_UNUSED, |
||||
void *event_info EINA_UNUSED) |
||||
{ |
||||
Ephoto_Reye *er = data; |
||||
unsigned int *image_data; |
||||
int w, h; |
||||
|
||||
image_data = |
||||
evas_object_image_data_get(elm_image_object_get(er->image), |
||||
EINA_FALSE); |
||||
evas_object_image_size_get(elm_image_object_get(er->image), &w, &h); |
||||
ephoto_single_browser_image_data_update(er->main, er->image, EINA_TRUE, |
||||
image_data, w, h); |
||||
ephoto_editor_del(er->editor); |
||||
|
||||
return ECORE_CALLBACK_PASS_ON; |
||||
} |
||||
|
||||
static Eina_Bool |
||||
_reye_cancel(void *data, int type EINA_UNUSED, |
||||
void *event_info EINA_UNUSED) |
||||
{ |
||||
Ephoto_Reye *er = data; |
||||
|
||||
elm_slider_value_set(er->rslider, 15); |
||||
er->rad = 15; |
||||
|
||||
ephoto_single_browser_image_data_update(er->main, er->image, EINA_FALSE, |
||||
er->original_im_data, er->w, er->h); |
||||
ephoto_single_browser_cancel_editing(er->main, er->image); |
||||
ephoto_editor_del(er->editor); |
||||
|
||||
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_Reye *er = data; |
||||
Ecore_Event_Handler *handler; |
||||
|
||||
evas_object_event_callback_del(er->image, EVAS_CALLBACK_MOUSE_UP, _reye_clicked); |
||||
EINA_LIST_FREE(er->handlers, handler) |
||||
ecore_event_handler_del(handler); |
||||
free(er->original_im_data); |
||||
free(er); |
||||
} |
||||
|
||||
void |
||||
ephoto_red_eye_add(Evas_Object *main, Evas_Object *parent, Evas_Object *image) |
||||
{ |
||||
Evas_Object *slider, *label; |
||||
Ephoto_Reye *er; |
||||
unsigned int *im_data; |
||||
|
||||
EINA_SAFETY_ON_NULL_GOTO(image, error); |
||||
|
||||
er = calloc(1, sizeof(Ephoto_Reye)); |
||||
EINA_SAFETY_ON_NULL_GOTO(er, error); |
||||
|
||||
er->rad = 15; |
||||
er->main = main; |
||||
er->parent = parent; |
||||
er->image = image; |
||||
im_data = |
||||
evas_object_image_data_get(elm_image_object_get(er->image), |
||||
EINA_FALSE); |
||||
evas_object_image_size_get(elm_image_object_get(er->image), &er->w, |
||||
&er->h); |
||||
er->original_im_data = malloc(sizeof(unsigned int) * er->w * er->h); |
||||
memcpy(er->original_im_data, im_data, |
||||
sizeof(unsigned int) * er->w * er->h); |
||||
|
||||
evas_object_event_callback_add(er->image, EVAS_CALLBACK_MOUSE_UP, |
||||
_reye_clicked, er); |
||||
|
||||
er->editor = ephoto_editor_add(parent, _("Red Eye Removal"), |
||||
"ereye", er); |
||||
evas_object_event_callback_add(er->editor, EVAS_CALLBACK_DEL, _editor_del, |
||||
er); |
||||
|
||||
slider = elm_slider_add(er->editor); |
||||
elm_object_text_set(slider, _("Radius")); |
||||
elm_slider_min_max_set(slider, 5, 50); |
||||
elm_slider_step_set(slider, 1); |
||||
elm_slider_value_set(slider, 15); |
||||
elm_slider_unit_format_set(slider, "%1.0f"); |
||||
evas_object_size_hint_weight_set(slider, EVAS_HINT_EXPAND, EVAS_HINT_FILL); |
||||
evas_object_size_hint_align_set(slider, EVAS_HINT_FILL, 0.5); |
||||
evas_object_smart_callback_add(slider, "delay,changed", |
||||
_radius_slider_changed, er); |
||||
elm_box_pack_start(er->editor, slider); |
||||
evas_object_show(slider); |
||||
er->rslider = slider; |
||||
|
||||
label = elm_label_add(er->editor); |
||||
elm_object_text_set(label, _("<b>Click on an eye</b>")); |
||||
evas_object_size_hint_weight_set(label, EVAS_HINT_EXPAND, EVAS_HINT_FILL); |
||||
evas_object_size_hint_align_set(label, EVAS_HINT_FILL, 0.5); |
||||
elm_box_pack_start(er->editor, label); |
||||
evas_object_show(label); |
||||
|
||||
er->handlers = |
||||
eina_list_append(er->handlers, |
||||
ecore_event_handler_add(EPHOTO_EVENT_EDITOR_RESET, |
||||
_reye_reset, er)); |
||||
er->handlers = |
||||
eina_list_append(er->handlers, |
||||
ecore_event_handler_add(EPHOTO_EVENT_EDITOR_APPLY, |
||||
_reye_apply, er)); |
||||
er->handlers = |
||||
eina_list_append(er->handlers, |
||||
ecore_event_handler_add(EPHOTO_EVENT_EDITOR_CANCEL, |
||||
_reye_cancel, er)); |
||||
|
||||
return; |
||||
|
||||
error: |
||||
return; |
||||
} |
Loading…
Reference in new issue