okra pushed a commit to branch master.

http://git.enlightenment.org/apps/ephoto.git/commit/?id=5a5d2bb12e28fc4bd08db9f8058e1addf0d0723f

commit 5a5d2bb12e28fc4bd08db9f8058e1addf0d0723f
Author: Stephen okra Houston <smhousto...@gmail.com>
Date:   Mon Apr 4 15:50:56 2016 -0500

    Ephoto: Add tool for red eye removal
---
 src/bin/Makefile.am             |   1 +
 src/bin/ephoto.h                |   2 +
 src/bin/ephoto_red_eye.c        | 254 ++++++++++++++++++++++++++++++++++++++++
 src/bin/ephoto_single_browser.c |  21 ++++
 src/bin/ephoto_thumb_browser.c  |   4 +-
 5 files changed, 280 insertions(+), 2 deletions(-)

diff --git a/src/bin/Makefile.am b/src/bin/Makefile.am
index 802f96c..b369bed 100644
--- a/src/bin/Makefile.am
+++ b/src/bin/Makefile.am
@@ -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 \
diff --git a/src/bin/ephoto.h b/src/bin/ephoto.h
index 0375768..cf7170b 100644
--- a/src/bin/ephoto.h
+++ b/src/bin/ephoto.h
@@ -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);
diff --git a/src/bin/ephoto_red_eye.c b/src/bin/ephoto_red_eye.c
new file mode 100644
index 0000000..93dfbfb
--- /dev/null
+++ b/src/bin/ephoto_red_eye.c
@@ -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;
+}
diff --git a/src/bin/ephoto_single_browser.c b/src/bin/ephoto_single_browser.c
index 9cf5493..4c7a846 100644
--- a/src/bin/ephoto_single_browser.c
+++ b/src/bin/ephoto_single_browser.c
@@ -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);
@@ -1194,6 +1196,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);
 
diff --git a/src/bin/ephoto_thumb_browser.c b/src/bin/ephoto_thumb_browser.c
index 42ebf1a..b22efd9 100644
--- a/src/bin/ephoto_thumb_browser.c
+++ b/src/bin/ephoto_thumb_browser.c
@@ -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);

-- 


Reply via email to