diff --git a/src/bin/Makefile.am b/src/bin/Makefile.am index c0f3a43..008a8dd 100644 --- a/src/bin/Makefile.am +++ b/src/bin/Makefile.am @@ -22,7 +22,8 @@ ephoto_SOURCES = \ ephoto_slideshow.c \ ephoto_cropper.c \ ephoto_bcg.c \ - ephoto_hsv.c + ephoto_hsv.c \ + ephoto_filters.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 be89897..03a25b8 100644 --- a/src/bin/ephoto.h +++ b/src/bin/ephoto.h @@ -56,13 +56,9 @@ void ephoto_single_browser_entry_set(Evas_Object *obj, Ephoto_Entry *ent void ephoto_single_browser_path_pending_set(Evas_Object *obj, const char *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); void ephoto_single_browser_cancel_editing(Evas_Object *main, Evas_Object *image); -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. */ - Evas_Object *ephoto_slideshow_add(Ephoto *ephoto, Evas_Object *parent); void ephoto_slideshow_entry_set(Evas_Object *obj, Ephoto_Entry *entry); /* smart callbacks called: @@ -75,6 +71,14 @@ Evas_Object *ephoto_thumb_browser_add(Ephoto *ephoto, Evas_Object *parent); * "selected" - an item in the thumb browser is selected. The selected Ephoto_Entry is passed as event_info argument. */ +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); +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); +void ephoto_filter_old_photo(Evas_Object *main, Evas_Object *image); + enum _Ephoto_State { EPHOTO_STATE_THUMB, diff --git a/src/bin/ephoto_bcg.c b/src/bin/ephoto_bcg.c index 79ddb2c..75a97b0 100644 --- a/src/bin/ephoto_bcg.c +++ b/src/bin/ephoto_bcg.c @@ -298,7 +298,7 @@ void ephoto_bcg_add(Evas_Object *main, Evas_Object *parent, Evas_Object *image) 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_weight_set(ebcg->frame, 0.2, 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); @@ -343,7 +343,7 @@ void ephoto_bcg_add(Evas_Object *main, Evas_Object *parent, Evas_Object *image) 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"); + 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", _gamma_slider_changed, ebcg); diff --git a/src/bin/ephoto_filters.c b/src/bin/ephoto_filters.c new file mode 100644 index 0000000..8c0704c --- /dev/null +++ b/src/bin/ephoto_filters.c @@ -0,0 +1,230 @@ +#include "ephoto.h" + +void +ephoto_filter_blur(Evas_Object *main, Evas_Object *image) +{ + unsigned int *im_data, *im_data_new, *p1, *p2; + int rad = 3; + int x, y, w, h, mx, my, mw, mh, mt, xx, yy; + int a, r, g, b; + int *as, *rs, *gs, *bs; + + im_data = evas_object_image_data_get(elm_image_object_get(image), EINA_FALSE); + evas_object_image_size_get(elm_image_object_get(image), &w, &h); + + im_data_new = malloc(sizeof(unsigned int) * w * h); + as = malloc(sizeof(int) * w); + rs = malloc(sizeof(int) * w); + gs = malloc(sizeof(int) * w); + bs = malloc(sizeof(int) * w); + + for (y = 0; y < h; y++) + { + my = y - rad; + mh = (rad << 1) + 1; + if (my < 0) + { + mh += my; + my = 0; + } + if ((my + mh) > h) + { + mh = h - my; + } + p1 = im_data_new + (y * w); + memset(as, 0, w * sizeof(int)); + memset(rs, 0, w * sizeof(int)); + memset(gs, 0, w * sizeof(int)); + memset(bs, 0, w * sizeof(int)); + + for (yy = 0; yy < mh; yy++) + { + p2 = im_data + ((yy + my) * w); + for (x = 0; x < w; x++) + { + as[x] += (*p2 >> 24) & 0xff; + rs[x] += (*p2 >> 16) & 0xff; + gs[x] += (*p2 >> 8) & 0xff; + bs[x] += *p2 & 0xff; + p2++; + } + } + if (w > ((rad << 1) + 1)) + { + for (x = 0; x < w; x++) + { + a = 0; + r = 0; + g = 0; + b = 0; + mx = x - rad; + mw = (rad << 1) + 1; + if (mx < 0) + { + mw += mx; + mx = 0; + } + if ((mx + mw) > w) + { + mw = w - mx; + } + mt = mw * mh; + for (xx = mx; xx < (mw + mx); xx++) + { + a += as[xx]; + r += rs[xx]; + g += gs[xx]; + b += bs[xx]; + } + a = a / mt; + r = r / mt; + g = g / mt; + b = b / mt; + *p1 = (a << 24) | (r << 16) | (g << 8) | b; + p1 ++; + } + } + } + free(as); + free(rs); + free(gs); + free(bs); + + ephoto_single_browser_image_data_update(main, image, EINA_TRUE, im_data_new, w, h); +} + +void +ephoto_filter_sharpen(Evas_Object *main, Evas_Object *image) +{ + unsigned int *im_data, *im_data_new, *p1, *p2; + int a, r, g, b, x, y, w, h; + int mul, mul2, tot; + int rad = 3; + + im_data = evas_object_image_data_get(elm_image_object_get(image), EINA_FALSE); + evas_object_image_size_get(elm_image_object_get(image), &w, &h); + + im_data_new = malloc(sizeof(unsigned int) * w * h); + + mul = (rad * 4) + 1; + mul2 = rad; + tot = mul - (mul2 * 4); + for (y = 1; y < (h - 1); y ++) + { + p1 = im_data + 1 + (y * w); + p2 = im_data_new + 1 + (y * w); + for (x = 1; x < (w - 1); x++) + { + b = (int)((p1[0]) & 0xff) * 5; + g = (int)((p1[0] >> 8) & 0xff) * 5; + r = (int)((p1[0] >> 16) & 0xff) * 5; + a = (int)((p1[0] >> 24) & 0xff) * 5; + b -= (int)((p1[-1]) & 0xff); + g -= (int)((p1[-1] >> 8) & 0xff); + r -= (int)((p1[-1] >> 16) & 0xff); + a -= (int)((p1[-1] >> 24) & 0xff); + b -= (int)((p1[1]) & 0xff); + g -= (int)((p1[1] >> 8) & 0xff); + r -= (int)((p1[1] >> 16) & 0xff); + a -= (int)((p1[1] >> 24) & 0xff); + b -= (int)((p1[-w]) & 0xff); + g -= (int)((p1[-w] >> 8) & 0xff); + r -= (int)((p1[-w] >> 16) & 0xff); + a -= (int)((p1[-w] >> 24) & 0xff); + b -= (int)((p1[-w]) & 0xff); + g -= (int)((p1[-w] >> 8) & 0xff); + r -= (int)((p1[-w] >> 16) & 0xff); + a -= (int)((p1[-w] >> 24) & 0xff); + a = (a & ((~a) >> 16)); + a = ((a | ((a & 256) - ((a & 256) >> 8)))); + r = (r & ((~r) >> 16)); + r = ((r | ((r & 256) - ((r & 256) >> 8)))); + g = (g & ((~g) >> 16)); + g = ((g | ((g & 256) - ((g & 256) >> 8)))); + b = (b & ((~b) >> 16)); + b = ((b | ((b & 256) - ((b & 256) >> 8)))); + *p2 = (a << 24) | (r << 16) | (g << 8) | b; + p2++; + p1++; + } + } + ephoto_single_browser_image_data_update(main, image, EINA_TRUE, im_data_new, w, h); +} + +void +ephoto_filter_black_and_white(Evas_Object *main, Evas_Object *image) +{ + unsigned int *im_data, *im_data_new; + int gray, i, r, g, b, a, w, h; + + im_data = evas_object_image_data_get(elm_image_object_get(image), EINA_FALSE); + evas_object_image_size_get(elm_image_object_get(image), &w, &h); + + im_data_new = malloc(sizeof(unsigned int) * w * h); + + for (i = 0; i < (w * h); i++) + { + b = (int)((im_data[i]) & 0xff); + g = (int)((im_data[i] >> 8) & 0xff); + r = (int)((im_data[i] >> 16) & 0xff); + a = (int)((im_data[i] >> 24) & 0xff); + if (a > 0 && a < 255) + { + b = b * (255 / a); + g = g * (255 / a); + r = r * (255 / a); + } + gray = (int)((0.3 * r) + (0.59 * g) + (0.11 * b)); + if (a >= 0 && a < 255) + gray = (gray * a) / 255; + im_data_new[i] = (a << 24) | (gray << 16) | (gray << 8) | gray; + } + ephoto_single_browser_image_data_update(main, image, EINA_TRUE, im_data_new, w, h); +} + +void +ephoto_filter_old_photo(Evas_Object *main, Evas_Object *image) +{ + unsigned int *im_data, *im_data_new; + int i, r, rr, g, gg, b, bb, a, w, h; + + im_data = evas_object_image_data_get(elm_image_object_get(image), EINA_FALSE); + evas_object_image_size_get(elm_image_object_get(image), &w, &h); + im_data_new = malloc(sizeof(unsigned int) * w * h); + for (i = 0; i < (w * h); i++) + { + b = (int)((im_data[i]) & 0xff); + g = (int)((im_data[i] >> 8) & 0xff); + r = (int)((im_data[i] >> 16) & 0xff); + a = (int)((im_data[i] >> 24) & 0xff); + if (a > 0 && a < 255) + { + b = b * (255 / a); + g = g * (255 / a); + r = r * (255 / a); + } + rr = (int)((r* .393) + (g*.769) + (b*.189)); + if (rr < 0) + rr = 0; + if (rr > 255) + rr = 255; + gg = (int)((r* .349) + (g*.686) + (b*.168)); + if (gg < 0) + gg = 0; + if (gg > 255) + gg = 255; + bb = (int)((r* .272) + (g*.534) + (b*.131)); + if (bb < 0) + bb = 0; + if (bb > 255) + bb = 255; + if (a >= 0 && a < 255) + { + rr = (rr * a) / 255; + gg = (gg * a) / 255; + bb = (bb * a) / 255; + } + im_data_new[i] = (a << 24) | (rr << 16) | (gg << 8) | bb; + } + ephoto_single_browser_image_data_update(main, image, EINA_TRUE, im_data_new, w, h); +} diff --git a/src/bin/ephoto_hsv.c b/src/bin/ephoto_hsv.c index 8ac4722..b019e10 100644 --- a/src/bin/ephoto_hsv.c +++ b/src/bin/ephoto_hsv.c @@ -309,7 +309,7 @@ void ephoto_hsv_add(Evas_Object *main, Evas_Object *parent, Evas_Object *image) 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_weight_set(ehsv->frame, 0.2, 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); diff --git a/src/bin/ephoto_single_browser.c b/src/bin/ephoto_single_browser.c index e0a69aa..081eea0 100644 --- a/src/bin/ephoto_single_browser.c +++ b/src/bin/ephoto_single_browser.c @@ -1209,6 +1209,62 @@ _go_hsv(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) } } +static void +_go_blur(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_filter_blur(sb->main, v->image); + } +} + +static void +_go_sharpen(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_filter_sharpen(sb->main, v->image); + } +} + +static void +_go_black_and_white(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_filter_black_and_white(sb->main, v->image); + } +} + +static void +_go_old_photo(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_filter_old_photo(sb->main, v->image); + } +} + static void _slideshow(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { @@ -1394,14 +1450,22 @@ 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_separator_add(menu, NULL); 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_separator_add(menu, NULL); elm_menu_item_add(menu, NULL, "edit-cut", _("Crop"), _crop_image, sb); menu_it = elm_menu_item_add(menu, NULL, "document-properties", _("Enhance"), NULL, NULL); - elm_menu_item_add(menu, menu_it, NULL, _("Brightness/Contrast/Gamma"), _go_bcg, sb); - elm_menu_item_add(menu, menu_it, NULL, _("Hue/Saturation/Value"), _go_hsv, sb); + elm_menu_item_add(menu, menu_it, "insert-image", _("Blur"), _go_blur, sb); + elm_menu_item_add(menu, menu_it, "insert-image", _("Sharpen"), _go_sharpen, sb); + elm_menu_item_separator_add(menu, menu_it); + elm_menu_item_add(menu, menu_it, "insert-image", _("Brightness/Contrast/Gamma"), _go_bcg, sb); + elm_menu_item_add(menu, menu_it, "insert-image", _("Hue/Saturation/Value"), _go_hsv, sb); + menu_it = elm_menu_item_add(menu, NULL, "document-properties", _("Filters"), NULL, NULL); + elm_menu_item_add(menu, menu_it, "insert-image", _("Black and White"), _go_black_and_white, sb); + elm_menu_item_add(menu, menu_it, "insert-image", _("Old Photo"), _go_old_photo, 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);