forked from enlightenment/ephoto
Ephoto: Add tool for red eye removal
This commit is contained in:
parent
48a0084337
commit
5a5d2bb12e
|
@ -30,6 +30,7 @@ ephoto_SOURCES = \
|
|||
ephoto_hsv.c \
|
||||
ephoto_ipc.c \
|
||||
ephoto_main.c \
|
||||
ephoto_red_eye.c \
|
||||
ephoto_thumb.c \
|
||||
ephoto_thumb_browser.c \
|
||||
ephoto_single_browser.c \
|
||||
|
|
|
@ -127,6 +127,8 @@ void ephoto_hsv_add(Evas_Object *main, Evas_Object *parent,
|
|||
Evas_Object *image);
|
||||
void ephoto_color_add(Evas_Object *main, Evas_Object *parent,
|
||||
Evas_Object *image);
|
||||
void ephoto_red_eye_add(Evas_Object *main, Evas_Object *parent,
|
||||
Evas_Object *image);
|
||||
void ephoto_filter_blur(Evas_Object *main, Evas_Object *image);
|
||||
void ephoto_filter_sharpen(Evas_Object *main, Evas_Object *image);
|
||||
void ephoto_filter_black_and_white(Evas_Object *main, Evas_Object *image);
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -148,6 +148,8 @@ _scroller_mouse_up_cb(void *data, Evas *e EINA_UNUSED,
|
|||
Ephoto_Single_Browser *sb = data;
|
||||
Evas_Event_Mouse_Up *ev = event_info;
|
||||
|
||||
if (sb->editing)
|
||||
return;
|
||||
if (ev->button == 3)
|
||||
{
|
||||
_edit_menu(sb);
|
||||
|
@ -1193,6 +1195,23 @@ _go_color(void *data, Evas_Object *obj EINA_UNUSED,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_go_reye(void *data, Evas_Object *obj EINA_UNUSED,
|
||||
void *event_info EINA_UNUSED)
|
||||
{
|
||||
Ephoto_Single_Browser *sb = data;
|
||||
|
||||
if (sb->viewer)
|
||||
{
|
||||
sb->editing = EINA_TRUE;
|
||||
if (sb->botbox)
|
||||
evas_object_hide(sb->botbox);
|
||||
Ephoto_Viewer *v = evas_object_data_get(sb->viewer, "viewer");
|
||||
|
||||
ephoto_red_eye_add(sb->main, sb->mhbox, v->image);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_go_auto_eq(void *data, Evas_Object *obj EINA_UNUSED,
|
||||
void *event_info EINA_UNUSED)
|
||||
|
@ -1377,6 +1396,8 @@ _add_edit_menu_items(Ephoto_Single_Browser *sb, Evas_Object *menu)
|
|||
_("Brightness/Contrast/Gamma"), _go_bcg, sb);
|
||||
elm_menu_item_add(menu, menu_itt, "insert-image", _("Hue/Saturation/Value"),
|
||||
_go_hsv, sb);
|
||||
elm_menu_item_add(menu, menu_itt, "insert-image", _("Red Eye Removal"),
|
||||
_go_reye, sb);
|
||||
elm_menu_item_add(menu, menu_itt, "insert-image", _("Color Levels"),
|
||||
_go_color, sb);
|
||||
|
||||
|
|
|
@ -2808,7 +2808,7 @@ ephoto_thumb_browser_add(Ephoto *ephoto, Evas_Object *parent)
|
|||
{
|
||||
elm_object_part_content_set(but, "icon", ic);
|
||||
elm_object_tooltip_text_set(but, _("Zoom In"));
|
||||
elm_object_tooltip_orient_set(but, ELM_TOOLTIP_ORIENT_CENTER);
|
||||
elm_object_tooltip_orient_set(but, ELM_TOOLTIP_ORIENT_TOP);
|
||||
}
|
||||
evas_object_smart_callback_add(but, "clicked", _zoom_in, tb);
|
||||
elm_box_pack_end(hbox, but);
|
||||
|
@ -2826,7 +2826,7 @@ ephoto_thumb_browser_add(Ephoto *ephoto, Evas_Object *parent)
|
|||
{
|
||||
elm_object_part_content_set(but, "icon", ic);
|
||||
elm_object_tooltip_text_set(but, _("Zoom Out"));
|
||||
elm_object_tooltip_orient_set(but, ELM_TOOLTIP_ORIENT_CENTER);
|
||||
elm_object_tooltip_orient_set(but, ELM_TOOLTIP_ORIENT_TOP);
|
||||
}
|
||||
evas_object_smart_callback_add(but, "clicked", _zoom_out, tb);
|
||||
elm_box_pack_end(hbox, but);
|
||||
|
|
Loading…
Reference in New Issue