summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeif Middelschulte <leif.middelschulte@gmail.com>2013-02-19 04:38:00 +0100
committerLeif Middelschulte <leif.middelschulte@gmail.com>2013-02-19 04:38:00 +0100
commit6aa78757f4b2cf637b5d0cbcc4aea12d96c27e1f (patch)
treee3152f7f97560d2b5ce5b475f97ceeae53a3ba61
Initial (working) commit.
-rw-r--r--Embiance.h31
-rw-r--r--Makefile10
-rw-r--r--README7
-rw-r--r--embiance.c153
-rw-r--r--main.c68
5 files changed, 269 insertions, 0 deletions
diff --git a/Embiance.h b/Embiance.h
new file mode 100644
index 0000000..6bfd4eb
--- /dev/null
+++ b/Embiance.h
@@ -0,0 +1,31 @@
1#ifndef __EMBIANCE_H__
2#define __EMBIANCE_H__
3
4#include <leptonica/allheaders.h>
5#include <evas-1/Evas.h>
6
7#include <stdio.h>
8
9/**
10 * Extracts the @param ncolors most often used colors in a given image object @param obj.
11 * @param obj The Evas Image Object to get the ambient colors for
12 * @param ncolors The number used colors to extract
13 * @param sigbits Number of significant bits. Think of 'precision' here. (Automatically limited if necessary) Valid values: 1-6
14 * @param r pointer to an array of @param ncolors elements to hold the red values
15 * @param g pointer to an array of @param ncolors elements to hold the green values
16 * @param b pointer to an array of @param ncolors elements to hold the blue values
17 * @return returns the number of different colors that were extracted.
18 */
19unsigned int evas_object_image_frequent_colors_get_histo(Evas_Object *obj, unsigned int ncolors, unsigned int sigbits, l_int32 **rr, l_int32 **rg, l_int32 **rb);
20
21/**
22 * Extracts the @param ncolors most often used colors in a given image object @param obj.
23 * @param obj The Evas Image Object to get the ambient colors for
24 * @param ncolors The number used colors to extract
25 * @param r pointer to an array of @param ncolors elements to hold the red values
26 * @param g pointer to an array of @param ncolors elements to hold the green values
27 * @param b pointer to an array of @param ncolors elements to hold the blue values
28 * @return returns the number of different colors that were extracted.
29 */
30unsigned int evas_object_image_frequent_colors_get_median_cut(Evas_Object *obj, unsigned int ncolors, l_int32 **r, l_int32 **g, l_int32 **b);
31#endif
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..b13382e
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,10 @@
1all: main
2
3clean:
4 rm -f libembiance.so main
5
6libembiance.so: embiance.c
7 $(CC) `pkg-config --cflags --libs evas` -llept -fPIC -shared $? -o $@
8
9main: main.c libembiance.so
10 $(CC) `pkg-config --cflags --libs elementary` -L. -lembiance $< -o $@
diff --git a/README b/README
new file mode 100644
index 0000000..5f67837
--- /dev/null
+++ b/README
@@ -0,0 +1,7 @@
1Embiance is intended to provide ambient colors given an evas_object_image.
2
3So far two methods to retrieve colors are provided:
4 - Median Cut
5 - Histogram
6
7The main.c file implements an example usage for it.
diff --git a/embiance.c b/embiance.c
new file mode 100644
index 0000000..286b373
--- /dev/null
+++ b/embiance.c
@@ -0,0 +1,153 @@
1#include "Embiance.h"
2
3#define WARN(f, __VAR_ARGS__) fprintf(stderr, "WARN:" f "\n", __VAR_ARGS__)
4
5static unsigned int _rotl(const unsigned int value, int shift) {
6 if ((shift &= sizeof(value)*8 - 1) == 0)
7 return value;
8 return (value << shift) | (value >> (sizeof(value)*8 - shift));
9}
10
11static unsigned int ARGBtoRGBA(unsigned int argb)
12{
13 return _rotl(argb, 8);
14}
15
16static void _argb_to_rgba(void *imgData, size_t n)
17{
18 unsigned int i = 0;
19 /* convert ARGB to RGBA */
20 for (i = 0; i < n; i++)
21 {
22 ((unsigned int*)imgData)[i] = ARGBtoRGBA(((unsigned int*)imgData)[i]);
23 }
24}
25
26unsigned int evas_object_image_frequent_colors_get_median_cut(Evas_Object *obj, unsigned int ncolors, l_int32 **r, l_int32 **g, l_int32 **b)
27{
28 PIX *pixs = NULL, *cut = NULL;
29 PIXCMAP *cmap_cut = NULL;
30 unsigned int ncolors_found = 0;
31 Eina_Rectangle size;
32 void *imgData;
33 l_int32 *rr, *gg, *bb;
34
35 evas_object_image_size_get(obj, &size.w, &size.h);
36
37 pixs = pixCreateHeader(size.w, size.h, 32);
38 imgData = malloc(size.w * size.h * sizeof(l_int32));
39 memcpy(imgData, evas_object_image_data_get(obj, EINA_FALSE), (size.w * size.h * sizeof(l_int32)));
40 _argb_to_rgba(imgData, (size.w * size.h));
41 pixSetData(pixs, imgData);
42
43 cut = pixMedianCutQuantGeneral(pixs, 0, 0, ncolors, 0, 0, 1);
44
45 cmap_cut = pixGetColormap(cut);
46 ncolors_found = pixcmapGetCount(cmap_cut);
47
48 pixcmapToArrays(cmap_cut, r, g, b);
49
50 rr = calloc(ncolors_found, sizeof(l_int32));
51 gg = calloc(ncolors_found, sizeof(l_int32));
52 bb = calloc(ncolors_found, sizeof(l_int32));
53
54 memcpy(rr, *r, (ncolors_found * sizeof(l_int32)));
55 memcpy(gg, *g, (ncolors_found * sizeof(l_int32)));
56 memcpy(bb, *b, (ncolors_found * sizeof(l_int32)));
57
58 *r = rr;
59 *g = gg;
60 *b = bb;
61
62 pixDestroy(&cut);
63 pixDestroy(&pixs);
64
65 return ncolors_found;
66}
67
68unsigned int evas_object_image_frequent_colors_get_histo(Evas_Object *obj, unsigned int ncolors, unsigned int sigbits, l_int32 **rr, l_int32 **rg, l_int32 **rb)
69{
70 PIX *pixs = NULL;
71 Eina_Rectangle size;
72 void *imgData;
73 unsigned int i, j;
74 NUMA *na = NULL;
75 l_int32 hvals[ncolors + 1];
76 const unsigned int nchannel = 3;
77 unsigned int word_width;
78 l_int32 *r, *g, *b;
79 l_int32 hval;
80 unsigned int hr = 0, hg = 0, hb = 0;
81 unsigned int segment, shifted_index_val;
82
83 if (sigbits > 6)
84 sigbits = 6;
85 else if (sigbits < 1)
86 sigbits = 1;
87 word_width = (sigbits * nchannel);
88
89 evas_object_image_size_get(obj, &size.w, &size.h);
90
91 pixs = pixCreateHeader(size.w, size.h, 32);
92 imgData = malloc(size.w * size.h * sizeof(l_int32));
93 memcpy(imgData, evas_object_image_data_get(obj, EINA_FALSE), (size.w * size.h * sizeof(l_int32)));
94 _argb_to_rgba(imgData, (size.w * size.h));
95 pixSetData(pixs, imgData);
96
97 r = calloc((ncolors + 1), sizeof(l_int32));
98 g = calloc((ncolors + 1), sizeof(l_int32));
99 b = calloc((ncolors + 1), sizeof(l_int32));
100
101#define BIT(v, i) ((v >> ((word_width - 1) - i)) & 0x1)
102
103 na = pixOctcubeHistogram(pixs, sigbits, NULL);
104 memset(hvals, 0, ((ncolors + 1) * sizeof(l_int32)));
105 for (i = 0; i < numaGetCount(na); i++)
106 {
107 numaGetIValue(na, i, &hval);
108 if (hval == 0)
109 continue;
110 if (hval > hvals[ncolors - 1])
111 {
112 hr = hg = hb = 0;
113 for (segment = 0, shifted_index_val = i; segment < sigbits; segment++, (shifted_index_val <<= nchannel))
114 {
115 hr = (hr << 1) | BIT(shifted_index_val, 0);
116 hg = (hg << 1) | BIT(shifted_index_val, 1);
117 hb = (hb << 1) | BIT(shifted_index_val, 2);
118 }
119
120 hr = (hr << (8 - sigbits));
121 hg = (hg << (8 - sigbits));
122 hb = (hb << (8 - sigbits));
123
124 for (j = 0; j < ncolors; j++)
125 {
126 if (hval > hvals[j])
127 {
128 if (hvals[j] != 0)
129 {
130 memmove(&r[j + 1], &r[j], ((ncolors - j) * sizeof(l_int32)));
131 memmove(&g[j + 1], &g[j], ((ncolors - j) * sizeof(l_int32)));
132 memmove(&b[j + 1], &b[j], ((ncolors - j) * sizeof(l_int32)));
133 memmove(&hvals[j + 1], &hvals[j], ((ncolors - j) * sizeof(l_int32)));
134 }
135 r[j] = hr;
136 g[j] = hg;
137 b[j] = hb;
138 hvals[j] = hval;
139 break;
140 }
141 }
142 }
143 }
144
145 *rr = r;
146 *rg = g;
147 *rb = b;
148
149 numaDestroy(&na);
150 pixDestroy(&pixs);
151
152 return ncolors;
153}
diff --git a/main.c b/main.c
new file mode 100644
index 0000000..d0382f7
--- /dev/null
+++ b/main.c
@@ -0,0 +1,68 @@
1#include <elementary-1/Elementary.h>
2#include "Embiance.h"
3
4#define WIDTH 640
5#define HEIGHT 480
6
7int main(int argc, char **argv)
8{
9 Evas *evas;
10 Evas_Object *win, *bg, *image, *txt;
11 l_int32 *r, *g, *b;
12 unsigned int ncolors_found;
13
14 if (argc != 2)
15 {
16 printf("%s some_image_file\n", argv[0]);
17 return EXIT_FAILURE;
18 }
19 elm_init(argc, argv);
20
21 elm_policy_set(ELM_POLICY_QUIT_LAST_WINDOW_CLOSED, EINA_TRUE);
22
23 win = elm_win_add(NULL, "embiance", ELM_WIN_BASIC);
24 elm_win_title_set(win, "Embiance test");
25 elm_win_autodel_set(win, EINA_TRUE);
26 evas_object_resize(win, WIDTH, HEIGHT);
27 evas_object_show(win);
28
29 bg = elm_bg_add(win);
30 evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
31 evas_object_size_hint_align_set(bg, EVAS_HINT_FILL, EVAS_HINT_FILL);
32 elm_win_resize_object_add(win, bg);
33 evas_object_show(bg);
34
35 evas = evas_object_evas_get(win);
36
37 image = evas_object_image_filled_add(evas);
38 evas_object_show(image);
39 evas_object_image_file_set(image, argv[1], NULL);
40 evas_object_size_hint_aspect_set(image, EVAS_ASPECT_CONTROL_BOTH, 1, 1);
41 evas_object_resize(image, (WIDTH - 150), HEIGHT);
42 evas_object_move(image, 150, 0);
43
44 /*ncolors_found = evas_object_image_frequent_colors_get_histo(image, 3, &r, &g, &b);*/
45 ncolors_found = evas_object_image_frequent_colors_get_median_cut(image, 3, &r, &g, &b);
46
47 elm_bg_color_set(bg, r[0], g[0], b[0]);
48
49 txt = evas_object_text_add(evas);
50 evas_object_text_font_set(txt, "DejaVu Sans", 24);
51 evas_object_color_set(txt, r[1], g[1], b[1], 255);
52 evas_object_text_text_set(txt, "Color 2...");
53 evas_object_show(txt);
54
55 txt = evas_object_text_add(evas);
56 evas_object_text_font_set(txt, "DejaVu Sans", 18);
57 evas_object_color_set(txt, r[2], g[2], b[2], 255);
58 evas_object_text_text_set(txt, "Color 3...");
59 evas_object_move(txt, 0, 100);
60 evas_object_show(txt);
61
62 elm_run();
63 elm_shutdown();
64
65 free(r), free(g), free(b);
66
67 return 0;
68}