From 54bd029e0df010e18b0f38bf2657560128906c89 Mon Sep 17 00:00:00 2001 From: Stephen Houston Date: Mon, 17 Aug 2015 13:10:33 -0500 Subject: [PATCH] Ephoto: Add in some simple editing features. More to come and some filters. --- src/bin/Makefile.am | 4 +- src/bin/ephoto.h | 7 +- src/bin/ephoto_bcg.c | 401 +++++++++++++++++++++++++++++++ src/bin/ephoto_cropper.c | 114 ++++++++- src/bin/ephoto_hsv.c | 411 +++++++++++++++++++++++++++++++ src/bin/ephoto_single_browser.c | 414 +++++++++++++------------------- 6 files changed, 1099 insertions(+), 252 deletions(-) create mode 100644 src/bin/ephoto_bcg.c create mode 100644 src/bin/ephoto_hsv.c diff --git a/src/bin/Makefile.am b/src/bin/Makefile.am index fbd6f27..c0f3a43 100644 --- a/src/bin/Makefile.am +++ b/src/bin/Makefile.am @@ -20,7 +20,9 @@ ephoto_SOURCES = \ ephoto_thumb_browser.c \ ephoto_single_browser.c \ ephoto_slideshow.c \ - ephoto_cropper.c + ephoto_cropper.c \ + ephoto_bcg.c \ + ephoto_hsv.c noinst_HEADERS = ephoto.h gettext.h EXTRA_DIST = ephoto.h gettext.h diff --git a/src/bin/ephoto.h b/src/bin/ephoto.h index 169ce3d..61e3a11 100644 --- a/src/bin/ephoto.h +++ b/src/bin/ephoto.h @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -53,7 +54,11 @@ void ephoto_config_window(Ephoto *em); Evas_Object *ephoto_single_browser_add(Ephoto *ephoto, Evas_Object *parent); void ephoto_single_browser_entry_set(Evas_Object *obj, Ephoto_Entry *entry); void ephoto_single_browser_path_pending_set(Evas_Object *obj, const char *path); -Evas_Object *ephoto_cropper_add(Evas_Object *parent, const char *file, const char *key); +void ephoto_single_browser_image_data_update(Evas_Object *main, Evas_Object *image, Eina_Bool finished, unsigned int *image_data, int w, int h); +void ephoto_single_browser_cancel_editing(Evas_Object *main); +Evas_Object *ephoto_cropper_add(Evas_Object *main, Evas_Object *toolbar, Evas_Object *parent, Evas_Object *image); +void ephoto_bcg_add(Evas_Object *main, Evas_Object *parent, Evas_Object *image); +void ephoto_hsv_add(Evas_Object *main, Evas_Object *parent, Evas_Object *image); /* smart callbacks called: * "back" - the user wants to go back to the previous screen. */ diff --git a/src/bin/ephoto_bcg.c b/src/bin/ephoto_bcg.c new file mode 100644 index 0000000..cea5f31 --- /dev/null +++ b/src/bin/ephoto_bcg.c @@ -0,0 +1,401 @@ +#include "ephoto.h" + +typedef struct _Ephoto_BCG Ephoto_BCG; +struct _Ephoto_BCG +{ + Evas_Object *main; + Evas_Object *parent; + Evas_Object *image; + Evas_Object *frame; + Evas_Object *bslider; + Evas_Object *cslider; + Evas_Object *gslider; + int contrast; + int brightness; + double gamma; + int w, h; + unsigned int *original_im_data; +}; + +unsigned int * +_ephoto_bcg_adjust_brightness(Ephoto_BCG *ebcg, int brightness, unsigned int *image_data) +{ + unsigned int *im_data, *im_data_new, *p1, *p2; + int x, y, w, h; + int a, r, g, b, nb, ng, nr; + + im_data = malloc(sizeof(unsigned int) * ebcg->w * ebcg->h); + if (image_data) + memcpy(im_data, image_data, sizeof(unsigned int) * ebcg->w * ebcg->h); + else + memcpy(im_data, ebcg->original_im_data, sizeof(unsigned int) * ebcg->w * ebcg->h); + + ebcg->brightness = brightness; + im_data_new = malloc(sizeof(unsigned int) * ebcg->w * ebcg->h); + + for (y = 0; y < ebcg->h; y++) + { + p1 = im_data + (y * ebcg->w); + p2 = im_data_new + (y * ebcg->w); + for (x = 0; x < ebcg->w; x++) + { + b = (int)((*p1) & 0xff); + g = (int)((*p1 >> 8) & 0xff); + r = (int)((*p1 >> 16) & 0xff); + a = (int)((*p1 >> 24) & 0xff); + if (a > 0 && a < 255) + { + b = b * (255 / a); + g = g * (255 / a); + r = r * (255 / a); + } + nb = (int)b+ebcg->brightness; + ng = (int)g+ebcg->brightness; + nr = (int)r+ebcg->brightness; + if (nb < 0) nb = 0; + if (nb > 255) nb = 255; + if (ng < 0) ng = 0; + if (ng > 255) ng = 255; + if (nr < 0) nr = 0; + if (nr > 255) nr = 255; + if (a > 0 && a < 255) + { + nb = (nb * a) / 255; + ng = (ng * a) / 255; + nr = (nr * a) / 255; + } + *p2 = (a << 24) | (nr << 16) | (ng << 8) | nb; + p2++; + p1++; + } + } + ephoto_single_browser_image_data_update(ebcg->main, ebcg->image, EINA_FALSE, im_data_new, ebcg->w, ebcg->h); + free(im_data); + return im_data_new; +} + +unsigned int * +_ephoto_bcg_adjust_contrast(Ephoto_BCG *ebcg, int contrast, unsigned int *image_data) +{ + unsigned int *im_data, *im_data_new, *p1, *p2; + int x, y, w, h, top, bottom; + int a, r, g, b, nb, ng, nr; + float factor; + + im_data = malloc(sizeof(unsigned int) * ebcg->w * ebcg->h); + if (image_data) + memcpy(im_data, image_data, sizeof(unsigned int) * ebcg->w * ebcg->h); + else + memcpy(im_data, ebcg->original_im_data, sizeof(unsigned int) * ebcg->w * ebcg->h); + + ebcg->contrast = contrast; + top = ((255+(contrast))*259); + bottom = ((259-(contrast))*255); + factor = (float)top / (float)bottom; + im_data_new = malloc(sizeof(unsigned int) * ebcg->w * ebcg->h); + + for (y = 0; y < ebcg->h; y++) + { + p1 = im_data + (y * ebcg->w); + p2 = im_data_new + (y * ebcg->w); + for (x = 0; x < ebcg->w; x++) + { + b = (int)((*p1) & 0xff); + g = (int)((*p1 >> 8) & 0xff); + r = (int)((*p1 >> 16) & 0xff); + a = (int)((*p1 >> 24) & 0xff); + if (a > 0 && a < 255) + { + b = b * (255 / a); + g = g * (255 / a); + r = r * (255 / a); + } + nb = (int)((factor * (b - 128)) + 128); + ng = (int)((factor * (g - 128)) + 128); + nr = (int)((factor * (r - 128)) + 128); + if (nb < 0) nb = 0; + if (nb > 255) nb = 255; + if (ng < 0) ng = 0; + if (ng > 255) ng = 255; + if (nr < 0) nr = 0; + if (nr > 255) nr = 255; + if (a > 0 && a < 255) + { + nb = (nb * a) / 255; + ng = (ng * a) / 255; + nr = (nr * a) / 255; + } + *p2 = (a << 24) | (nr << 16) | (ng << 8) | nb; + p2++; + p1++; + } + } + ephoto_single_browser_image_data_update(ebcg->main, ebcg->image, EINA_FALSE, im_data_new, ebcg->w, ebcg->h); + free(im_data); + return im_data_new; +} + +unsigned int * +_ephoto_bcg_adjust_gamma(Ephoto_BCG *ebcg, double gamma, unsigned int *image_data) +{ + unsigned int *im_data, *im_data_new, *p1, *p2; + int x, y, w, h; + int a, r, g, b, nb, ng, nr; + + im_data = malloc(sizeof(unsigned int) * ebcg->w * ebcg->h); + if (image_data) + memcpy(im_data, image_data, sizeof(unsigned int) * ebcg->w * ebcg->h); + else + memcpy(im_data, ebcg->original_im_data, sizeof(unsigned int) * ebcg->w * ebcg->h); + + ebcg->gamma = 1/gamma; + im_data_new = malloc(sizeof(unsigned int) * ebcg->w * ebcg->h); + + for (y = 0; y < ebcg->h; y++) + { + p1 = im_data + (y * ebcg->w); + p2 = im_data_new + (y * ebcg->w); + for (x = 0; x < ebcg->w; x++) + { + b = (int)((*p1) & 0xff); + g = (int)((*p1 >> 8) & 0xff); + r = (int)((*p1 >> 16) & 0xff); + a = (int)((*p1 >> 24) & 0xff); + if (a > 0 && a < 255) + { + b = b * (255 / a); + g = g * (255 / a); + r = r * (255 / a); + } + nb = (int)(pow(((double)b/255), ebcg->gamma) * 255); + ng = (int)(pow(((double)g/255), ebcg->gamma) * 255); + nr = (int)(pow(((double)r/255), ebcg->gamma) * 255); + if (nb < 0) nb = 0; + if (nb > 255) nb = 255; + if (ng < 0) ng = 0; + if (ng > 255) ng = 255; + if (nr < 0) nr = 0; + if (nr > 255) nr = 255; + if (a > 0 && a < 255) + { + nb = (nb * a) / 255; + ng = (ng * a) / 255; + nr = (nr * a) / 255; + } + *p2 = (a << 24) | (nr << 16) | (ng << 8) | nb; + p2++; + p1++; + } + } + ephoto_single_browser_image_data_update(ebcg->main, ebcg->image, EINA_FALSE, im_data_new, ebcg->w, ebcg->h); + free(im_data); + return im_data_new; +} + +static void +_brightness_slider_changed(void *data, Evas_Object *obj, void *event_info EINA_UNUSED) +{ + Ephoto_BCG *ebcg = data; + int brightness; + unsigned int *image_data, *image_data_two, *image_data_three; + + brightness = elm_slider_value_get(obj); + image_data = _ephoto_bcg_adjust_brightness(ebcg, brightness, NULL); + image_data_two = _ephoto_bcg_adjust_contrast(ebcg, ebcg->contrast, image_data); + image_data_three = _ephoto_bcg_adjust_gamma(ebcg, ebcg->gamma, image_data_two); +} + + +static void +_contrast_slider_changed(void *data, Evas_Object *obj, void *event_info EINA_UNUSED) +{ + Ephoto_BCG *ebcg = data; + int contrast; + unsigned int *image_data, *image_data_two, *image_data_three; + + contrast = elm_slider_value_get(obj); + image_data = _ephoto_bcg_adjust_contrast(ebcg, contrast, NULL); + image_data_two = _ephoto_bcg_adjust_brightness(ebcg, ebcg->brightness, image_data); + image_data_three = _ephoto_bcg_adjust_gamma(ebcg, ebcg->gamma, image_data_two); +} + +static void +_gamma_slider_changed(void *data, Evas_Object *obj, void *event_info EINA_UNUSED) +{ + Ephoto_BCG *ebcg = data; + double gamma; + unsigned int *image_data, *image_data_two, *image_data_three; + + gamma = elm_slider_value_get(obj); + image_data = _ephoto_bcg_adjust_gamma(ebcg, gamma, NULL); + image_data_two = _ephoto_bcg_adjust_brightness(ebcg, ebcg->brightness, image_data); + image_data_three = _ephoto_bcg_adjust_contrast(ebcg, ebcg->contrast, image_data_two); +} + +static void +_bcg_reset(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +{ + Ephoto_BCG *ebcg = data; + elm_slider_value_set(ebcg->bslider, 0); + elm_slider_value_set(ebcg->cslider, 0); + elm_slider_value_set(ebcg->gslider, 1); + ebcg->brightness = 0; + ebcg->contrast = 0; + ebcg->gamma = 1; + _brightness_slider_changed(ebcg, ebcg->bslider, NULL); +} + +static void +_bcg_apply(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +{ + Ephoto_BCG *ebcg = data; + unsigned int *image_data; + int w, h; + + image_data = evas_object_image_data_get(elm_image_object_get(ebcg->image), EINA_FALSE); + evas_object_image_size_get(elm_image_object_get(ebcg->image), &w, &h); + ephoto_single_browser_image_data_update(ebcg->main, ebcg->image, EINA_TRUE, image_data, w, h); + ephoto_single_browser_cancel_editing(ebcg->main); + evas_object_del(ebcg->frame); +} + +static void +_bcg_cancel(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +{ + Ephoto_BCG *ebcg = data; + ephoto_single_browser_cancel_editing(ebcg->main); + evas_object_del(ebcg->frame); +} + +static void +_frame_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +{ + Ephoto_BCG *ebcg = data; + free(ebcg->original_im_data); + free(ebcg); +} + +void ephoto_bcg_add(Evas_Object *main, Evas_Object *parent, Evas_Object *image) +{ + Evas_Object *win, *box, *slider, *ic, *button; + Ephoto_BCG *ebcg; + unsigned int *im_data; + + EINA_SAFETY_ON_NULL_GOTO(image, error); + + ebcg = calloc(1, sizeof(Ephoto_BCG)); + EINA_SAFETY_ON_NULL_GOTO(ebcg, error); + + ebcg->brightness = 0; + ebcg->contrast = 0; + ebcg->gamma = 1; + ebcg->main = main; + ebcg->parent = parent; + ebcg->image = image; + im_data = evas_object_image_data_get(elm_image_object_get(ebcg->image), EINA_FALSE); + evas_object_image_size_get(elm_image_object_get(ebcg->image), &ebcg->w, &ebcg->h); + ebcg->original_im_data = malloc(sizeof(unsigned int) * ebcg->w * ebcg->h); + memcpy(ebcg->original_im_data, im_data, sizeof(unsigned int) * ebcg->w * ebcg->h); + + ebcg->frame = elm_frame_add(parent); + elm_object_text_set(ebcg->frame, "Brightness/Contrast/Gamma"); + evas_object_size_hint_weight_set(ebcg->frame, 0.3, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(ebcg->frame, EVAS_HINT_FILL, EVAS_HINT_FILL); + elm_box_pack_end(parent, ebcg->frame); + evas_object_data_set(ebcg->frame, "ebcg", ebcg); + evas_object_event_callback_add(ebcg->frame, EVAS_CALLBACK_DEL, _frame_del, ebcg); + evas_object_show(ebcg->frame); + + box = elm_box_add(ebcg->frame); + elm_box_horizontal_set(box, EINA_FALSE); + evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(box, EVAS_HINT_FILL, EVAS_HINT_FILL); + elm_object_content_set(ebcg->frame, box); + evas_object_show(box); + + slider = elm_slider_add(box); + elm_object_text_set(slider, _("Brightness")); + elm_slider_min_max_set(slider, -100, 100); + elm_slider_step_set(slider, 1); + elm_slider_value_set(slider, 0); + 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", _brightness_slider_changed, ebcg); + elm_box_pack_end(box, slider); + evas_object_show(slider); + ebcg->bslider = slider; + + slider = elm_slider_add(box); + elm_object_text_set(slider, _("Contrast")); + elm_slider_min_max_set(slider, -100, 100); + elm_slider_step_set(slider, 1); + elm_slider_value_set(slider, 0); + 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", _contrast_slider_changed, ebcg); + elm_box_pack_end(box, slider); + evas_object_show(slider); + ebcg->cslider = slider; + + slider = elm_slider_add(box); + elm_object_text_set(slider, _("Gamma")); + elm_slider_min_max_set(slider, 0.1, 3); + elm_slider_step_set(slider, .1); + elm_slider_value_set(slider, 1); + elm_slider_unit_format_set(slider, "%1.1f"); + 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", _gamma_slider_changed, ebcg); + elm_box_pack_end(box, slider); + evas_object_show(slider); + ebcg->gslider = slider; + + ic = elm_icon_add(box); + elm_icon_order_lookup_set(ic, ELM_ICON_LOOKUP_FDO_THEME); + evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1); + elm_icon_standard_set(ic, "edit-undo"); + + button = elm_button_add(box); + elm_object_text_set(button, _("Reset")); + elm_object_part_content_set(button, "icon", ic); + evas_object_smart_callback_add(button, "clicked", _bcg_reset, ebcg); + evas_object_size_hint_weight_set(button, EVAS_HINT_FILL, EVAS_HINT_FILL); + evas_object_size_hint_align_set(button, EVAS_HINT_FILL, EVAS_HINT_FILL); + elm_box_pack_end(box, button); + evas_object_show(button); + + ic = elm_icon_add(box); + elm_icon_order_lookup_set(ic, ELM_ICON_LOOKUP_FDO_THEME); + evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1); + elm_icon_standard_set(ic, "document-save"); + + button = elm_button_add(box); + elm_object_text_set(button, _("Apply")); + elm_object_part_content_set(button, "icon", ic); + evas_object_smart_callback_add(button, "clicked", _bcg_apply, ebcg); + evas_object_size_hint_weight_set(button, EVAS_HINT_FILL, EVAS_HINT_FILL); + evas_object_size_hint_align_set(button, EVAS_HINT_FILL, EVAS_HINT_FILL); + elm_box_pack_end(box, button); + evas_object_show(button); + + ic = elm_icon_add(box); + elm_icon_order_lookup_set(ic, ELM_ICON_LOOKUP_FDO_THEME); + evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1); + elm_icon_standard_set(ic, "window-close"); + + button = elm_button_add(box); + elm_object_text_set(button, _("Cancel")); + elm_object_part_content_set(button, "icon", ic); + evas_object_smart_callback_add(button, "clicked", _bcg_cancel, ebcg); + evas_object_size_hint_weight_set(button, EVAS_HINT_FILL, EVAS_HINT_FILL); + evas_object_size_hint_align_set(button, EVAS_HINT_FILL, EVAS_HINT_FILL); + elm_box_pack_end(box, button); + evas_object_show(button); + + return; + + error: + return; +} diff --git a/src/bin/ephoto_cropper.c b/src/bin/ephoto_cropper.c index 4f12815..e9e48c6 100644 --- a/src/bin/ephoto_cropper.c +++ b/src/bin/ephoto_cropper.c @@ -3,6 +3,8 @@ typedef struct _Ephoto_Cropper Ephoto_Cropper; struct _Ephoto_Cropper { + Evas_Object *main; + Evas_Object *parent; Evas_Object *box; Evas_Object *image; Evas_Object *cropper; @@ -14,6 +16,70 @@ struct _Ephoto_Cropper int resizing; }; +static void _apply_crop(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED); +static void _cancel_crop(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED); + +static void +_apply_crop(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +{ + Ephoto_Cropper *ec = data; + Evas_Object *edje = elm_layout_edje_get(ec->layout); + + const char *path, *key, *type;; + int x, y, w, h, cx, cy, cw, ch, iw, ih; + int nx, ny, nw, nh, i, j, tmpx, tmpy, ind, index; + double scalex, scaley, scalew, scaleh; + unsigned int *idata, *idata_new; + + evas_object_geometry_get(ec->layout, &x, &y, &w, &h); + edje_object_part_geometry_get(edje, "ephoto.swallow.cropper", &cx, &cy, &cw, &ch); + evas_object_image_size_get(elm_image_object_get(ec->image), &iw, &ih); + + idata = evas_object_image_data_get(elm_image_object_get(ec->image), EINA_FALSE); + + scalex = (double)cx/(double)w; + scaley = (double)cy/(double)h; + scalew = (double)cw/(double)w; + scaleh = (double)ch/(double)h; + + nx = iw*scalex; + ny = ih*scaley; + nw = iw*scalew; + nh = ih*scaleh; + + index = 0; + idata_new = malloc(sizeof(unsigned int)*nw*nh); + + for (i = 0; i < nh; i++) + { + tmpy = (i+ny)*iw; + for (j = 0; j < nw; j++) + { + tmpx = j+nx; + ind = tmpy+tmpx; + idata_new[index] = idata[ind]; + index++; + } + } + elm_table_unpack(ec->parent, ec->box); + elm_layout_content_unset(ec->layout, "ephoto.swallow.image"); + elm_table_pack(ec->parent, ec->image, 0, 0, 1, 1); + ephoto_single_browser_image_data_update(ec->main, ec->image, EINA_TRUE, idata_new, nw, nh); + evas_object_del(ec->cropper); + evas_object_del(ec->layout); + evas_object_del(ec->box); +} + +static void +_cancel_crop(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +{ + Ephoto_Cropper *ec = data; + elm_table_unpack(ec->parent, ec->box); + elm_layout_content_unset(ec->layout, "ephoto.swallow.image"); + elm_table_pack(ec->parent, ec->image, 0, 0, 1, 1); + ephoto_single_browser_cancel_editing(ec->main); +} + static void _calculate_cropper_size(Ephoto_Cropper *ec) { @@ -352,23 +418,59 @@ _image_resize(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, voi } static void -_cropper_free(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +_cropper_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { Ephoto_Cropper *ec = data; free(ec); } Evas_Object * -ephoto_cropper_add(Evas_Object *parent, const char *file, const char *key) +ephoto_cropper_add(Evas_Object *main, Evas_Object *toolbar, Evas_Object *parent, Evas_Object *image) { Ephoto_Cropper *ec = calloc(1, sizeof(Ephoto_Cropper)); + Evas_Object *hbox, *ic, *button; + ec->resizing = 0; + ec->main = main; + ec->parent = parent; + ec->image = image; ec->box = elm_box_add(parent); evas_object_size_hint_weight_set(ec->box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(ec->box, EVAS_HINT_FILL, EVAS_HINT_FILL); + elm_table_pack(parent, ec->box, 0, 0, 1, 1); evas_object_show(ec->box); + hbox = elm_box_add(ec->box); + elm_box_homogeneous_set(hbox, EINA_TRUE); + elm_box_horizontal_set(hbox, EINA_TRUE); + evas_object_size_hint_weight_set(hbox, EVAS_HINT_EXPAND, 0.0); + evas_object_size_hint_align_set(hbox, EVAS_HINT_FILL, EVAS_HINT_FILL); + elm_box_pack_after(ec->main, hbox, toolbar); + evas_object_show(hbox); + + ic = elm_icon_add(hbox); + elm_icon_order_lookup_set(ic, ELM_ICON_LOOKUP_FDO_THEME); + evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1); + elm_icon_standard_set(ic, "document-save"); + button = elm_button_add(hbox); + elm_object_text_set(button, _("Apply")); + elm_object_part_content_set(button, "icon", ic); + evas_object_smart_callback_add(button, "clicked", _apply_crop, ec); + elm_box_pack_end(hbox, button); + evas_object_show(button); + + ic = elm_icon_add(hbox); + elm_icon_order_lookup_set(ic, ELM_ICON_LOOKUP_FDO_THEME); + evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1); + elm_icon_standard_set(ic, "window-close"); + button = elm_button_add(hbox); + elm_object_text_set(button, _("Cancel")); + elm_object_part_content_set(button, "icon", ic); + evas_object_smart_callback_add(button, "clicked", _cancel_crop, ec); + elm_box_pack_end(hbox, button); + evas_object_show(button); + ec->layout = elm_layout_add(ec->box); elm_layout_file_set(ec->layout, PACKAGE_DATA_DIR "/themes/crop.edj", "ephoto,image,cropper,base"); evas_object_size_hint_weight_set(ec->layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); @@ -376,12 +478,10 @@ ephoto_cropper_add(Evas_Object *parent, const char *file, const char *key) elm_box_pack_end(ec->box, ec->layout); evas_object_show(ec->layout); - ec->image = elm_image_add(ec->layout); - elm_image_file_set(ec->image, file, key); evas_object_size_hint_weight_set(ec->image, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(ec->image, EVAS_HINT_FILL, EVAS_HINT_FILL); elm_layout_content_set(ec->layout, "ephoto.swallow.image", ec->image); - evas_object_show(ec->image); + evas_object_show(ec->image); ec->cropper = edje_object_add(evas_object_evas_get(ec->layout)); edje_object_file_set(ec->cropper, PACKAGE_DATA_DIR "/themes/crop.edj", "ephoto,image,cropper"); @@ -398,10 +498,8 @@ ephoto_cropper_add(Evas_Object *parent, const char *file, const char *key) edje_object_signal_callback_add(ec->cropper, "mouse,down,1", "handle7", _cropper_resize_both, ec); edje_object_signal_callback_add(ec->cropper, "mouse,down,1", "handle8", _cropper_resize_horiz, ec); - evas_object_data_set(ec->box, "image", ec->image); - evas_object_data_set(ec->box, "layout", ec->layout); evas_object_event_callback_add(ec->layout, EVAS_CALLBACK_RESIZE, _image_resize, ec); - evas_object_event_callback_add(ec->box, EVAS_CALLBACK_FREE, _cropper_free, ec); + evas_object_event_callback_add(ec->box, EVAS_CALLBACK_DEL, _cropper_del, ec); return ec->box; } diff --git a/src/bin/ephoto_hsv.c b/src/bin/ephoto_hsv.c new file mode 100644 index 0000000..1333068 --- /dev/null +++ b/src/bin/ephoto_hsv.c @@ -0,0 +1,411 @@ +#include "ephoto.h" + +typedef struct _Ephoto_HSV Ephoto_HSV; +struct _Ephoto_HSV +{ + Evas_Object *main; + Evas_Object *parent; + Evas_Object *image; + Evas_Object *frame; + Evas_Object *hslider; + Evas_Object *sslider; + Evas_Object *vslider; + double hue; + double saturation; + double value; + int 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; + int x, y, w, h; + int a, r, g, b, nb, ng, nr; + 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); + if (a > 0 && a < 255) + { + b = b * (255 / a); + g = g * (255 / a); + r = r * (255 / 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, &nr, &ng, &nb); + if (nb < 0) nb = 0; + if (nb > 255) nb = 255; + if (ng < 0) ng = 0; + if (ng > 255) ng = 255; + if (nr < 0) nr = 0; + if (nr > 255) nr = 255; + if (a > 0 && a < 255) + { + nb = (nb * a) / 255; + ng = (ng * a) / 255; + nr = (nr * a) / 255; + } + *p2 = (a << 24) | (nr << 16) | (ng << 8) | nb; + p2++; + p1++; + } + } + ehsv->hue = hue; + ephoto_single_browser_image_data_update(ehsv->main, ehsv->image, EINA_FALSE, 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; + int x, y, w, h; + int a, r, g, b, nb, ng, nr; + 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); + if (a > 0 && a < 255) + { + b = b * (255 / a); + g = g * (255 / a); + r = r * (255 / 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, &nr, &ng, &nb); + if (nb < 0) nb = 0; + if (nb > 255) nb = 255; + if (ng < 0) ng = 0; + if (ng > 255) ng = 255; + if (nr < 0) nr = 0; + if (nr > 255) nr = 255; + if (a > 0 && a < 255) + { + nb = (nb * a) / 255; + ng = (ng * a) / 255; + nr = (nr * a) / 255; + } + *p2 = (a << 24) | (nr << 16) | (ng << 8) | nb; + p2++; + p1++; + } + } + ehsv->saturation = saturation; + ephoto_single_browser_image_data_update(ehsv->main, ehsv->image, EINA_FALSE, 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; + int x, y, w, h; + int a, r, g, b, nb, ng, nr; + 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); + if (a > 0 && a < 255) + { + b = b * (255 / a); + g = g * (255 / a); + r = r * (255 / 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, &nr, &ng, &nb); + if (nb < 0) nb = 0; + if (nb > 255) nb = 255; + if (ng < 0) ng = 0; + if (ng > 255) ng = 255; + if (nr < 0) nr = 0; + if (nr > 255) nr = 255; + if (a > 0 && a < 255) + { + nb = (nb * a) / 255; + ng = (ng * a) / 255; + nr = (nr * a) / 255; + } + *p2 = (a << 24) | (nr << 16) | (ng << 8) | nb; + p2++; + p1++; + } + } + ehsv->value = value; + ephoto_single_browser_image_data_update(ehsv->main, ehsv->image, EINA_FALSE, 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, *image_data_three; + + 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); + image_data_three = _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, *image_data_three; + + 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); + image_data_three = _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, *image_data_three; + + 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); + image_data_three = _ephoto_hsv_adjust_saturation(ehsv, ehsv->saturation, image_data_two); +} + +static void +_hsv_reset(void *data, Evas_Object *obj 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); +} + +static void +_hsv_apply(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +{ + Ephoto_HSV *ehsv = data; + unsigned int *image_data; + int w, h; + + image_data = evas_object_image_data_get(elm_image_object_get(ehsv->image), EINA_FALSE); + evas_object_image_size_get(elm_image_object_get(ehsv->image), &w, &h); + ephoto_single_browser_image_data_update(ehsv->main, ehsv->image, EINA_TRUE, image_data, w, h); + evas_object_del(ehsv->frame); +} + +static void +_hsv_cancel(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +{ + Ephoto_HSV *ehsv = data; + ephoto_single_browser_cancel_editing(ehsv->main); + evas_object_del(ehsv->frame); +} + +static void +_frame_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +{ + Ephoto_HSV *ehsv = data; + free(ehsv->original_im_data); + free(ehsv); +} + +void ephoto_hsv_add(Evas_Object *main, Evas_Object *parent, Evas_Object *image) +{ + Evas_Object *win, *box, *slider, *ic, *button; + 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(elm_image_object_get(ehsv->image), EINA_FALSE); + evas_object_image_size_get(elm_image_object_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->frame = elm_frame_add(parent); + elm_object_text_set(ehsv->frame, "Hue/Saturation/Value"); + evas_object_size_hint_weight_set(ehsv->frame, 0.3, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(ehsv->frame, EVAS_HINT_FILL, EVAS_HINT_FILL); + elm_box_pack_end(parent, ehsv->frame); + evas_object_data_set(ehsv->frame, "ehsv", ehsv); + evas_object_event_callback_add(ehsv->frame, EVAS_CALLBACK_DEL, _frame_del, ehsv); + evas_object_show(ehsv->frame); + + box = elm_box_add(ehsv->frame); + elm_box_horizontal_set(box, EINA_FALSE); + evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(box, EVAS_HINT_FILL, EVAS_HINT_FILL); + elm_object_content_set(ehsv->frame, box); + evas_object_show(box); + + slider = elm_slider_add(box); + 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"); + 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", _hue_slider_changed, ehsv); + elm_box_pack_end(box, slider); + evas_object_show(slider); + ehsv->hslider = slider; + + slider = elm_slider_add(box); + 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"); + 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", _saturation_slider_changed, ehsv); + elm_box_pack_end(box, slider); + evas_object_show(slider); + ehsv->sslider = slider; + + slider = elm_slider_add(box); + 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"); + 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", _value_slider_changed, ehsv); + elm_box_pack_end(box, slider); + evas_object_show(slider); + ehsv->vslider = slider; + + ic = elm_icon_add(box); + elm_icon_order_lookup_set(ic, ELM_ICON_LOOKUP_FDO_THEME); + evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1); + elm_icon_standard_set(ic, "edit-undo"); + + button = elm_button_add(box); + elm_object_text_set(button, _("Reset")); + elm_object_part_content_set(button, "icon", ic); + evas_object_smart_callback_add(button, "clicked", _hsv_reset, ehsv); + evas_object_size_hint_weight_set(button, EVAS_HINT_FILL, EVAS_HINT_FILL); + evas_object_size_hint_align_set(button, EVAS_HINT_FILL, EVAS_HINT_FILL); + elm_box_pack_end(box, button); + evas_object_show(button); + + ic = elm_icon_add(box); + elm_icon_order_lookup_set(ic, ELM_ICON_LOOKUP_FDO_THEME); + evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1); + elm_icon_standard_set(ic, "document-save"); + + button = elm_button_add(box); + elm_object_text_set(button, _("Apply")); + elm_object_part_content_set(button, "icon", ic); + evas_object_smart_callback_add(button, "clicked", _hsv_apply, ehsv); + evas_object_size_hint_weight_set(button, EVAS_HINT_FILL, EVAS_HINT_FILL); + evas_object_size_hint_align_set(button, EVAS_HINT_FILL, EVAS_HINT_FILL); + elm_box_pack_end(box, button); + evas_object_show(button); + + ic = elm_icon_add(box); + elm_icon_order_lookup_set(ic, ELM_ICON_LOOKUP_FDO_THEME); + evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1); + elm_icon_standard_set(ic, "window-close"); + + button = elm_button_add(box); + elm_object_text_set(button, _("Cancel")); + elm_object_part_content_set(button, "icon", ic); + evas_object_smart_callback_add(button, "clicked", _hsv_cancel, ehsv); + evas_object_size_hint_weight_set(button, EVAS_HINT_FILL, EVAS_HINT_FILL); + evas_object_size_hint_align_set(button, EVAS_HINT_FILL, EVAS_HINT_FILL); + elm_box_pack_end(box, button); + evas_object_show(button); + + return; + + error: + return; +} diff --git a/src/bin/ephoto_single_browser.c b/src/bin/ephoto_single_browser.c index 420f848..3afdaab 100644 --- a/src/bin/ephoto_single_browser.c +++ b/src/bin/ephoto_single_browser.c @@ -12,6 +12,7 @@ struct _Ephoto_Single_Browser Ephoto *ephoto; Evas_Object *main; Evas_Object *bar; + Evas_Object *mhbox; Evas_Object *table; Evas_Object *viewer; Evas_Object *infolabel; @@ -21,6 +22,7 @@ struct _Ephoto_Single_Browser Ephoto_Entry *entry; Ephoto_Orient orient; Eina_List *handlers; + Eina_Bool editing:1; Eina_Bool cropping:1; }; @@ -31,15 +33,12 @@ struct _Ephoto_Viewer Evas_Object *image; double zoom; Eina_Bool fit:1; - Eina_Bool cropping:1; Eina_Bool zoom_first:1; }; static void _zoom_set(Ephoto_Single_Browser *sb, double zoom); static void _zoom_in(Ephoto_Single_Browser *sb); static void _zoom_out(Ephoto_Single_Browser *sb); -static void _apply_crop(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED); -static void _cancel_crop(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED); static void _viewer_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) @@ -147,23 +146,17 @@ _viewer_add(Evas_Object *parent, const char *path) elm_object_content_set(v->scroller, v->table); evas_object_show(v->table); - v->cropping = sb->cropping; - if (v->cropping) - v->image = ephoto_cropper_add(v->table, path, group); - else - { - v->image = elm_image_add(v->table); - elm_image_preload_disabled_set(v->image, EINA_TRUE); - elm_image_file_set(v->image, path, group); - err = evas_object_image_load_error_get(elm_image_object_get(v->image)); - if (err != EVAS_LOAD_ERROR_NONE) goto load_error; - evas_object_image_size_get(elm_image_object_get(v->image), &w, &h); - elm_drop_target_add(v->image, ELM_SEL_FORMAT_IMAGE, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); - evas_object_size_hint_min_set(v->image, w, h); - evas_object_size_hint_max_set(v->image, w, h); - evas_object_event_callback_add(v->image, EVAS_CALLBACK_MOUSE_DOWN, _image_mouse_down_cb, v->image); - evas_object_event_callback_add(v->image, EVAS_CALLBACK_MOUSE_UP, _image_mouse_up_cb, v->image); - } + v->image = elm_image_add(v->table); + elm_image_preload_disabled_set(v->image, EINA_TRUE); + elm_image_file_set(v->image, path, group); + err = evas_object_image_load_error_get(elm_image_object_get(v->image)); + if (err != EVAS_LOAD_ERROR_NONE) goto load_error; + evas_object_image_size_get(elm_image_object_get(v->image), &w, &h); + elm_drop_target_add(v->image, ELM_SEL_FORMAT_IMAGE, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + evas_object_size_hint_min_set(v->image, w, h); + evas_object_size_hint_max_set(v->image, w, h); + evas_object_event_callback_add(v->image, EVAS_CALLBACK_MOUSE_DOWN, _image_mouse_down_cb, v->image); + evas_object_event_callback_add(v->image, EVAS_CALLBACK_MOUSE_UP, _image_mouse_up_cb, v->image); elm_table_pack(v->table, v->image, 0, 0, 1, 1); evas_object_show(v->image); @@ -185,10 +178,8 @@ _viewer_zoom_apply(Ephoto_Viewer *v, double zoom) Evas_Coord w, h; Evas_Object *image; - if (v->cropping) - image = evas_object_data_get(v->image, "image"); - else - image = v->image; + + image = v->image; evas_object_image_size_get(elm_image_object_get(image), &w, &h); w *= zoom; h *= zoom; @@ -203,10 +194,7 @@ _viewer_zoom_fit_apply(Ephoto_Viewer *v) Evas_Object *image; double zx, zy, zoom; - if (v->cropping) - image = evas_object_data_get(v->image, "image"); - else - image = v->image; + image = v->image; evas_object_geometry_get(v->scroller, NULL, NULL, &cw, &ch); evas_object_image_size_get(elm_image_object_get(image), &iw, &ih); @@ -230,10 +218,7 @@ _viewer_resized(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, v Evas_Coord cw, ch, iw, ih; Evas_Object *image; - if (v->cropping) - image = evas_object_data_get(v->image, "image"); - else - image = v->image; + image = v->image; evas_object_geometry_get(v->scroller, NULL, NULL, &cw, &ch); evas_object_image_size_get(elm_image_object_get(image), &iw, &ih); @@ -544,14 +529,14 @@ static void _ephoto_single_browser_recalc(Ephoto_Single_Browser *sb) { if (sb->viewer) - { + { evas_object_del(sb->viewer); sb->viewer = NULL; evas_object_del(sb->botbox); sb->botbox = NULL; evas_object_del(sb->infolabel); sb->infolabel = NULL; - } + } if (sb->nolabel) { evas_object_del(sb->nolabel); @@ -566,7 +551,7 @@ _ephoto_single_browser_recalc(Ephoto_Single_Browser *sb) sb->viewer = _viewer_add(sb->main, sb->entry->path); if (sb->viewer) { - char image_info[PATH_MAX]; + char image_info[PATH_MAX], *tmp; Evas_Coord w, h; Ephoto_Viewer *v = evas_object_data_get(sb->viewer, "viewer"); @@ -575,67 +560,30 @@ _ephoto_single_browser_recalc(Ephoto_Single_Browser *sb) evas_object_event_callback_add (sb->viewer, EVAS_CALLBACK_MOUSE_WHEEL, _mouse_wheel, sb); - if (sb->cropping) - { - Evas_Object *ic, *button; + evas_object_image_size_get(elm_image_object_get(v->image), &w, &h); + tmp = _ephoto_get_file_size(sb->entry->path); + snprintf(image_info, PATH_MAX, + "%s: %s %s: %dx%d %s: %s", + _("Type"), efreet_mime_type_get(sb->entry->path), _("Resolution"), w, h, + _("File Size"), tmp); + free(tmp); + sb->botbox = evas_object_rectangle_add(evas_object_evas_get(sb->table)); + evas_object_color_set(sb->botbox, 0, 0, 0, 0); + evas_object_size_hint_min_set(sb->botbox, 0, sb->ephoto->bottom_bar_size); + evas_object_size_hint_weight_set(sb->botbox, EVAS_HINT_EXPAND, 0.0); + evas_object_size_hint_fill_set(sb->botbox, EVAS_HINT_FILL, EVAS_HINT_FILL); + elm_table_pack(sb->table, sb->botbox, 0, 2, 4, 1); + evas_object_show(sb->botbox); - sb->botbox = elm_box_add(sb->table); - elm_box_homogeneous_set(sb->botbox, EINA_TRUE); - elm_box_horizontal_set(sb->botbox, EINA_TRUE); - evas_object_size_hint_weight_set(sb->botbox, EVAS_HINT_EXPAND, 0.0); - evas_object_size_hint_align_set(sb->botbox, EVAS_HINT_FILL, EVAS_HINT_FILL); - elm_table_pack(sb->table, sb->botbox, 0, 2, 4, 1); - evas_object_show(sb->botbox); + sb->infolabel = elm_label_add(sb->table); + elm_label_line_wrap_set(sb->infolabel, ELM_WRAP_NONE); + elm_object_text_set(sb->infolabel, image_info); + evas_object_size_hint_weight_set(sb->infolabel, EVAS_HINT_EXPAND, EVAS_HINT_FILL); + evas_object_size_hint_align_set(sb->infolabel, EVAS_HINT_FILL, EVAS_HINT_FILL); + elm_table_pack(sb->table, sb->infolabel, 0, 2, 4, 1); + evas_object_show(sb->infolabel); - ic = elm_icon_add(sb->botbox); - elm_icon_order_lookup_set(ic, ELM_ICON_LOOKUP_FDO_THEME); - evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1); - elm_icon_standard_set(ic, "document-save"); - button = elm_button_add(sb->botbox); - elm_object_text_set(button, _("Apply")); - elm_object_part_content_set(button, "icon", ic); - evas_object_smart_callback_add(button, "clicked", _apply_crop, sb); - elm_box_pack_end(sb->botbox, button); - evas_object_show(button); - - ic = elm_icon_add(sb->botbox); - elm_icon_order_lookup_set(ic, ELM_ICON_LOOKUP_FDO_THEME); - evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1); - elm_icon_standard_set(ic, "window-close"); - button = elm_button_add(sb->botbox); - elm_object_text_set(button, _("Cancel")); - elm_object_part_content_set(button, "icon", ic); - evas_object_smart_callback_add(button, "clicked", _cancel_crop, sb); - elm_box_pack_end(sb->botbox, button); - evas_object_show(button); - } - else - { - char *tmp = _ephoto_get_file_size(sb->entry->path); - evas_object_image_size_get(elm_image_object_get(v->image), &w, &h); - snprintf(image_info, PATH_MAX, - "%s: %s %s: %dx%d %s: %s", - _("Type"), efreet_mime_type_get(sb->entry->path), _("Resolution"), w, h, - _("File Size"), tmp); - free(tmp); - sb->botbox = evas_object_rectangle_add(evas_object_evas_get(sb->table)); - evas_object_color_set(sb->botbox, 0, 0, 0, 0); - evas_object_size_hint_min_set(sb->botbox, 0, sb->ephoto->bottom_bar_size); - evas_object_size_hint_weight_set(sb->botbox, EVAS_HINT_EXPAND, 0.0); - evas_object_size_hint_fill_set(sb->botbox, EVAS_HINT_FILL, EVAS_HINT_FILL); - elm_table_pack(sb->table, sb->botbox, 0, 2, 4, 1); - evas_object_show(sb->botbox); - - sb->infolabel = elm_label_add(sb->table); - elm_label_line_wrap_set(sb->infolabel, ELM_WRAP_NONE); - elm_object_text_set(sb->infolabel, image_info); - evas_object_size_hint_weight_set(sb->infolabel, EVAS_HINT_EXPAND, EVAS_HINT_FILL); - evas_object_size_hint_align_set(sb->infolabel, EVAS_HINT_FILL, EVAS_HINT_FILL); - elm_table_pack(sb->table, sb->infolabel, 0, 2, 4, 1); - evas_object_show(sb->infolabel); - - ephoto_title_set(sb->ephoto, bname); - } + ephoto_title_set(sb->ephoto, bname); } else { @@ -649,7 +597,6 @@ _ephoto_single_browser_recalc(Ephoto_Single_Browser *sb) ephoto_title_set(sb->ephoto, _("Bad Image")); } } - elm_object_focus_set(sb->main, EINA_TRUE); } @@ -788,7 +735,6 @@ _reset_yes(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSE Evas_Object *win = data; Ephoto_Single_Browser *sb = evas_object_data_get(win, "single_browser"); Ephoto_Viewer *v = evas_object_data_get(sb->viewer, "viewer"); - sb->cropping = EINA_FALSE; sb->orient = EPHOTO_ORIENT_0; ephoto_single_browser_entry_set(sb->main, sb->entry); evas_object_del(win); @@ -933,11 +879,6 @@ static void _save_image(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { Ephoto_Single_Browser *sb = data; - if (sb->cropping) - { - sb->cropping = EINA_FALSE; - ephoto_single_browser_entry_set(sb->main, sb->entry); - } Evas_Object *win, *box, *label, *hbox, *ic, *button; win = elm_win_inwin_add(sb->ephoto->win); @@ -1119,11 +1060,6 @@ static void _save_image_as(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { Ephoto_Single_Browser *sb = data; - if (sb->cropping) - { - sb->cropping = EINA_FALSE; - ephoto_single_browser_entry_set(sb->main, sb->entry); - } Evas_Object *win, *fsel; win = elm_win_inwin_add(sb->ephoto->win); @@ -1144,117 +1080,6 @@ _save_image_as(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_U evas_object_show(fsel); } -static void -_apply_crop(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) -{ - Ephoto_Single_Browser *sb = data; - Ephoto_Viewer *v = evas_object_data_get(sb->viewer, "viewer"); - Evas_Object *cropper = v->image; - Evas_Object *layout = evas_object_data_get(cropper, "layout"); - Evas_Object *image = evas_object_data_get(cropper, "image"); - Evas_Object *edje = elm_layout_edje_get(layout); - Evas_Object *crop; - - const char *path, *key, *type;; - char tmp_path[PATH_MAX], image_info[PATH_MAX], *tmp; - int x, y, w, h, cx, cy, cw, ch, iw, ih; - int nx, ny, nw, nh, i, j, tmpx, tmpy, ind, index; - double scalex, scaley, scalew, scaleh; - unsigned int *idata, *idata_new; - - elm_image_file_get(image, &path, &key); - crop = evas_object_image_add(evas_object_evas_get(sb->main)); - evas_object_image_file_set(crop, path, key); - - evas_object_geometry_get(layout, &x, &y, &w, &h); - edje_object_part_geometry_get(edje, "ephoto.swallow.cropper", &cx, &cy, &cw, &ch); - evas_object_image_size_get(crop, &iw, &ih); - - idata = evas_object_image_data_get(crop, EINA_FALSE); - - scalex = (double)cx/(double)w; - scaley = (double)cy/(double)h; - scalew = (double)cw/(double)w; - scaleh = (double)ch/(double)h; - - nx = iw*scalex; - ny = ih*scaley; - nw = iw*scalew; - nh = ih*scaleh; - - index = 0; - idata_new = malloc(sizeof(unsigned int)*nw*nh); - - for (i = 0; i < nh; i++) - { - tmpy = (i+ny)*iw; - for (j = 0; j < nw; j++) - { - tmpx = j+nx; - ind = tmpy+tmpx; - idata_new[index] = idata[ind]; - index++; - } - } - evas_object_image_size_set(crop, nw, nh); - evas_object_image_data_set(crop, idata_new); - evas_object_image_data_update_add(crop, 0, 0, nw, nh); - - type = strrchr(sb->entry->basename, '.'); - snprintf(tmp_path, PATH_MAX, "%s/.config/ephoto/tmp%s", getenv("HOME"), type); - if (ecore_file_exists(tmp_path)) - ecore_file_unlink(tmp_path); - evas_object_image_save(crop, tmp_path, NULL, NULL); - evas_object_del(crop); - - sb->cropping = EINA_FALSE; - evas_object_del(sb->viewer); - sb->viewer = _viewer_add(sb->main, tmp_path); - elm_table_pack(sb->table, sb->viewer, 0, 1, 4, 1); - evas_object_show(sb->viewer); - - evas_object_del(sb->botbox); - tmp = _ephoto_get_file_size(tmp_path); - snprintf(image_info, PATH_MAX, - "%s: %s %s: %dx%d %s: %s", - _("Type"), efreet_mime_type_get(tmp_path), _("Resolution"), nw, nh, - _("File Size"), tmp); - free(tmp); - sb->botbox = evas_object_rectangle_add(evas_object_evas_get(sb->table)); - evas_object_color_set(sb->botbox, 0, 0, 0, 0); - evas_object_size_hint_min_set(sb->botbox, 0, sb->ephoto->bottom_bar_size); - evas_object_size_hint_weight_set(sb->botbox, EVAS_HINT_EXPAND, 0.0); - evas_object_size_hint_fill_set(sb->botbox, EVAS_HINT_FILL, EVAS_HINT_FILL); - elm_table_pack(sb->table, sb->botbox, 0, 2, 4, 1); - evas_object_show(sb->botbox); - - sb->infolabel = elm_label_add(sb->table); - elm_label_line_wrap_set(sb->infolabel, ELM_WRAP_NONE); - elm_object_text_set(sb->infolabel, image_info); - evas_object_size_hint_weight_set(sb->infolabel, EVAS_HINT_EXPAND, EVAS_HINT_FILL); - evas_object_size_hint_align_set(sb->infolabel, EVAS_HINT_FILL, EVAS_HINT_FILL); - elm_table_pack(sb->table, sb->infolabel, 0, 2, 4, 1); - evas_object_show(sb->infolabel); - - _zoom_fit(sb); -} - -static void -_cancel_crop(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) -{ - Ephoto_Single_Browser *sb = data; - sb->cropping = EINA_FALSE; - ephoto_single_browser_entry_set(sb->main, sb->entry); -} - -static void -_crop_image(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) -{ - Ephoto_Single_Browser *sb = data; - sb->cropping = EINA_TRUE; - ephoto_single_browser_entry_set(sb->main, sb->entry); -} - static void _go_first(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { @@ -1311,6 +1136,50 @@ _go_flip_vert(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UN _flip_vert(sb); } +static void +_crop_image(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +{ + Ephoto_Single_Browser *sb = data; + if (sb->viewer) + { + sb->editing = EINA_TRUE; + sb->cropping = EINA_TRUE; + elm_object_disabled_set(sb->bar, EINA_TRUE); + evas_object_freeze_events_set(sb->bar, EINA_TRUE); + Ephoto_Viewer *v = evas_object_data_get(sb->viewer, "viewer"); + elm_table_unpack(v->table, v->image); + ephoto_cropper_add(sb->main, sb->bar, v->table, v->image); + } +} + +static void +_go_bcg(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +{ + Ephoto_Single_Browser *sb = data; + if (sb->viewer) + { + sb->editing = EINA_TRUE; + elm_object_disabled_set(sb->bar, EINA_TRUE); + evas_object_freeze_events_set(sb->bar, EINA_TRUE); + Ephoto_Viewer *v = evas_object_data_get(sb->viewer, "viewer"); + ephoto_bcg_add(sb->main, sb->mhbox, v->image); + } +} + +static void +_go_hsv(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +{ + Ephoto_Single_Browser *sb = data; + if (sb->viewer) + { + sb->editing = EINA_TRUE; + elm_object_disabled_set(sb->bar, EINA_TRUE); + evas_object_freeze_events_set(sb->bar, EINA_TRUE); + Ephoto_Viewer *v = evas_object_data_get(sb->viewer, "viewer"); + ephoto_hsv_add(sb->main, sb->mhbox, v->image); + } +} + static void _slideshow(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { @@ -1323,8 +1192,6 @@ static void _back(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { Ephoto_Single_Browser *sb = data; - if (sb->cropping) - _cancel_crop(sb, NULL, NULL); evas_object_smart_callback_call(sb->main, "back", sb->entry); } @@ -1361,37 +1228,28 @@ _key_down(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *e return; } - if (!strcmp(k, "Escape")) - { - if (sb->cropping) - _cancel_crop(sb, NULL, NULL); - else - evas_object_smart_callback_call(sb->main, "back", sb->entry); - } - else if (!strcmp(k, "Return")) - { - if (sb->cropping) - _apply_crop(sb, NULL, NULL); - } - else if (!strcmp(k, "Left")) + if (!strcmp(k, "Escape") && !sb->editing) + evas_object_smart_callback_call(sb->main, "back", sb->entry); +// else if (!strcmp(k, "Return")) + else if (!strcmp(k, "Left") && !sb->editing) _prev_entry(sb); - else if (!strcmp(k, "Right")) + else if (!strcmp(k, "Right") && !sb->editing) _next_entry(sb); - else if (!strcmp(k, "Home")) + else if (!strcmp(k, "Home") && !sb->editing) _first_entry(sb); - else if (!strcmp(k, "End")) + else if (!strcmp(k, "End") && !sb->editing) _last_entry(sb); - else if (!strcmp(k, "bracketleft")) + else if (!strcmp(k, "bracketleft") && !sb->editing) { if (!shift) _rotate_counterclock(sb); else _flip_horiz(sb); } - else if (!strcmp(k, "bracketright")) + else if (!strcmp(k, "bracketright") && !sb->editing) { if (!shift) _rotate_clock(sb); else _flip_vert(sb); } - else if (!strcmp(k, "F5")) + else if (!strcmp(k, "F5") && !sb->editing) { if (sb->entry) evas_object_smart_callback_call(sb->main, "slideshow", sb->entry); @@ -1476,6 +1334,7 @@ ephoto_single_browser_add(Ephoto *ephoto, Evas_Object *parent) EINA_SAFETY_ON_NULL_GOTO(sb, error); sb->ephoto = ephoto; + sb->editing = EINA_FALSE; sb->cropping = EINA_FALSE; sb->main = box; @@ -1506,12 +1365,13 @@ ephoto_single_browser_add(Ephoto *ephoto, Evas_Object *parent) elm_menu_item_add(menu, NULL, "edit-undo", _("Reset"), _reset_image, sb); elm_menu_item_add(menu, NULL, "document-save", _("Save"), _save_image, sb); elm_menu_item_add(menu, NULL, "document-save-as", _("Save As"), _save_image_as, sb); - elm_menu_item_add(menu, NULL, "edit-cut", _("Crop"), _crop_image, sb); elm_menu_item_add(menu, NULL, "object-rotate-left", _("Rotate Left"), _go_rotate_counterclock, sb); elm_menu_item_add(menu, NULL, "object-rotate-right", _("Rotate Right"), _go_rotate_clock, sb); elm_menu_item_add(menu, NULL, "object-flip-horizontal", _("Flip Horizontal"), _go_flip_horiz, sb); elm_menu_item_add(menu, NULL, "object-flip-vertical", _("Flip Vertical"), _go_flip_vert, sb); - + elm_menu_item_add(menu, NULL, "edit-cut", _("Crop"), _crop_image, sb); + elm_menu_item_add(menu, NULL, "document-properties", _("Brightness/Contrast/Gamma"), _go_bcg, sb); + elm_menu_item_add(menu, NULL, "document-properties", _("Hue/Saturation/Value"), _go_hsv, sb); /*FIXME: Use separators once they don't mess up homogeneous toolbar*/ //elm_toolbar_item_separator_set(elm_toolbar_item_append(sb->bar, NULL, NULL, NULL, NULL), EINA_TRUE); @@ -1535,10 +1395,17 @@ ephoto_single_browser_add(Ephoto *ephoto, Evas_Object *parent) elm_box_pack_end(sb->main, sb->bar); evas_object_show(sb->bar); - sb->table = elm_table_add(sb->main); + sb->mhbox = elm_box_add(sb->main); + elm_box_horizontal_set(sb->mhbox, EINA_TRUE); + evas_object_size_hint_weight_set(sb->mhbox, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(sb->mhbox, EVAS_HINT_FILL, EVAS_HINT_FILL); + elm_box_pack_end(sb->main, sb->mhbox); + evas_object_show(sb->mhbox); + + sb->table = elm_table_add(sb->mhbox); evas_object_size_hint_weight_set(sb->table, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(sb->table, EVAS_HINT_FILL, EVAS_HINT_FILL); - elm_box_pack_end(sb->main, sb->table); + elm_box_pack_end(sb->mhbox, sb->table); evas_object_show(sb->table); sb->handlers = eina_list_append @@ -1589,3 +1456,66 @@ ephoto_single_browser_path_pending_set(Evas_Object *obj, const char *path) DBG("Setting pending path '%s'", path); sb->pending_path = eina_stringshare_add(path); } + +void +ephoto_single_browser_image_data_update(Evas_Object *main, Evas_Object *image, Eina_Bool finished, unsigned int *image_data, int w, int h) +{ + Ephoto_Single_Browser *sb = evas_object_data_get(main, "single_browser"); + if (sb->editing) + { + char image_info[PATH_MAX]; + if (sb->cropping) + { + evas_object_image_size_set(elm_image_object_get(image), w, h); + sb->cropping = EINA_FALSE; + } + evas_object_image_data_set(elm_image_object_get(image), image_data); + evas_object_image_data_update_add(elm_image_object_get(image), 0, 0, w, h); + + if (finished) + { + evas_object_del(sb->botbox); + evas_object_del(sb->infolabel); + snprintf(image_info, PATH_MAX, + "%s: %s %s: %dx%d %s: %s", + _("Type"), _("Unsaved"), _("Resolution"), w, h, + _("File Size"), _("Unsaved")); + sb->botbox = evas_object_rectangle_add(evas_object_evas_get(sb->table)); + evas_object_color_set(sb->botbox, 0, 0, 0, 0); + evas_object_size_hint_min_set(sb->botbox, 0, sb->ephoto->bottom_bar_size); + evas_object_size_hint_weight_set(sb->botbox, EVAS_HINT_EXPAND, 0.0); + evas_object_size_hint_fill_set(sb->botbox, EVAS_HINT_FILL, EVAS_HINT_FILL); + elm_table_pack(sb->table, sb->botbox, 0, 2, 4, 1); + evas_object_show(sb->botbox); + + sb->infolabel = elm_label_add(sb->table); + elm_label_line_wrap_set(sb->infolabel, ELM_WRAP_NONE); + elm_object_text_set(sb->infolabel, image_info); + evas_object_size_hint_weight_set(sb->infolabel, EVAS_HINT_EXPAND, EVAS_HINT_FILL); + evas_object_size_hint_align_set(sb->infolabel, EVAS_HINT_FILL, EVAS_HINT_FILL); + elm_table_pack(sb->table, sb->infolabel, 0, 2, 4, 1); + evas_object_show(sb->infolabel); + + evas_object_freeze_events_set(sb->bar, EINA_FALSE); + elm_object_disabled_set(sb->bar, EINA_FALSE); + sb->editing = EINA_FALSE; + _zoom_fit(sb); + } + } +} + +void +ephoto_single_browser_cancel_editing(Evas_Object *main) +{ + Ephoto_Single_Browser *sb = evas_object_data_get(main, "single_browser"); + if (sb->editing) + { + evas_object_freeze_events_set(sb->bar, EINA_FALSE); + elm_object_disabled_set(sb->bar, EINA_FALSE); + sb->editing = EINA_FALSE; + if (sb->cropping) + sb->cropping = EINA_FALSE; + ephoto_single_browser_entry_set(sb->main, sb->entry); + } +} +