annotate src/similar.c @ 196:f6e307c7bad6

rename GQview -> Geeqie over the code
author nadvornik
date Sun, 23 Mar 2008 20:38:54 +0000
parents d907d608745f
children 9995c5fb202a
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
9
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
1 /*
196
f6e307c7bad6 rename GQview -> Geeqie over the code
nadvornik
parents: 9
diff changeset
2 * Geeqie
9
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
3 * (C) 2004 John Ellis
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
4 *
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
5 * Author: John Ellis
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
6 *
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
7 * This software is released under the GNU General Public License (GNU GPL).
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
8 * Please read the included file COPYING for more information.
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
9 * This software comes with no warranty of any kind, use at your own risk!
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
10 */
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
11
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
12
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
13 #include "gqview.h"
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
14 #include "similar.h"
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
15
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
16 /*
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
17 * These functions are intended to find images with similar color content. For
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
18 * example when an image was saved at different compression levels or dimensions
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
19 * (scaled down/up) the contents are similar, but these files do not match by file
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
20 * size, dimensions, or checksum.
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
21 *
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
22 * These functions create a 32 x 32 array for each color channel (red, green, blue).
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
23 * The array represents the average color of each corresponding part of the
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
24 * image. (imagine the image cut into 1024 rectangles, or a 32 x 32 grid.
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
25 * Each grid is then processed for the average color value, this is what
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
26 * is stored in the array)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
27 *
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
28 * To compare two images, generate a ImageSimilarityData for each image, then
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
29 * pass them to the compare function. The return value is the percent match
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
30 * of the two images. (for this, simple comparisons are used, basically the return
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
31 * is an average of the corresponding array differences)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
32 *
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
33 * for image_sim_compare(), the return is 0.0 to 1.0:
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
34 * 1.0 for exact matches (an image is compared to itself)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
35 * 0.0 for exact opposite images (compare an all black to an all white image)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
36 * generally only a match of > 0.85 are significant at all, and >.95 is useful to
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
37 * find images that have been re-saved to other formats, dimensions, or compression.
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
38 */
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
39
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
40
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
41 /*
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
42 * The experimental (alternate) algorithm is only for testing of new techniques to
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
43 * improve the result, and hopes to reduce false positives.
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
44 */
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
45
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
46 static gint alternate_enabled = FALSE;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
47
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
48 void image_sim_alternate_set(gint enable)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
49 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
50 alternate_enabled = enable;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
51 }
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
52
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
53 gint image_sim_alternate_enabled(void)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
54 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
55 return alternate_enabled;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
56 }
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
57
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
58 ImageSimilarityData *image_sim_new(void)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
59 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
60 ImageSimilarityData *sd = g_new0(ImageSimilarityData, 1);
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
61
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
62 return sd;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
63 }
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
64
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
65 void image_sim_free(ImageSimilarityData *sd)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
66 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
67 g_free(sd);
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
68 }
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
69
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
70 #if 0
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
71 static void image_sim_channel_expand(guint8 *pix, gint len)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
72 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
73 guint8 l, h;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
74 gint i;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
75 gdouble scale;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
76
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
77 /* set the start values */
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
78 l = h = pix[0];
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
79
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
80 /* find min/max */
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
81 for (i = 0; i < len; i++)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
82 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
83 if (pix[i] < l) l = pix[i];
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
84 if (pix[i] > h) h = pix[i];
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
85 }
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
86
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
87 /* calc scale from range */
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
88 if (l != h)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
89 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
90 scale = 255.0 / (gdouble)(h - l);
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
91 }
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
92 else
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
93 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
94 scale = 1.0;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
95 }
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
96
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
97 for (i = 0; i < len; i++)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
98 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
99 pix[i] = (guint8)((gdouble)pix[i] - l * scale);
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
100 }
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
101 }
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
102 #endif
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
103
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
104 static int image_sim_channel_eq_sort_cb(const void *a, const void *b)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
105 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
106 gint *pa = (void *)a;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
107 gint *pb = (void *)b;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
108 if (pa[1] < pb[1]) return -1;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
109 if (pa[1] > pb[1]) return 1;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
110 return 0;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
111 }
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
112
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
113 static void image_sim_channel_equal(guint8 *pix, gint len)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
114 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
115 gint *buf;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
116 gint i;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
117 gint p;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
118
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
119 buf = g_new0(gint, len * 2);
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
120
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
121 p = 0;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
122 for (i = 0; i < len; i++)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
123 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
124 buf[p] = i;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
125 p++;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
126 buf[p] = (gint)pix[i];
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
127 p++;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
128 }
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
129
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
130 qsort (buf, len, sizeof(gint) * 2, image_sim_channel_eq_sort_cb);
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
131
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
132 p = 0;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
133 for (i = 0; i < len; i++)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
134 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
135 gint n;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
136
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
137 n = buf[p];
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
138 p+= 2;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
139 pix[n] = (guint8)(255 * i / len);
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
140 }
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
141
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
142 g_free(buf);
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
143 }
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
144
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
145 static void image_sim_channel_norm(guint8 *pix, gint len)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
146 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
147 guint8 l, h;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
148 gint i;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
149 gdouble scale;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
150
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
151 l = h = pix[0];
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
152
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
153 for (i = 0; i < len; i++)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
154 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
155 if (pix[i] < l) l = pix[i];
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
156 if (pix[i] > h) h = pix[i];
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
157 }
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
158
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
159 scale = (h-l !=0) ? 255.0 / (gdouble)(h - l) : 1.0;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
160
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
161 for (i = 0; i < len; i++)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
162 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
163 pix[i] = (guint8)((gdouble)(pix[i] - l) * scale);
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
164 }
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
165 }
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
166
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
167 /*
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
168 * define these to enable various components of the experimental compare functions
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
169 *
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
170 * Convert the thumbprint to greyscale (ignore all color information when comparing)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
171 * #define ALTERNATE_USES_GREYSCALE 1
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
172 *
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
173 * Take into account the difference in change from one pixel to the next
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
174 * #define ALTERNATE_INCLUDE_COMPARE_CHANGE 1
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
175 */
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
176
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
177 void image_sim_alternate_processing(ImageSimilarityData *sd)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
178 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
179 #ifdef ALTERNATE_USES_GREYSCALE
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
180 gint i;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
181 #endif
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
182
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
183 if (!alternate_enabled) return;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
184
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
185 image_sim_channel_norm(sd->avg_r, sizeof(sd->avg_r));
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
186 image_sim_channel_norm(sd->avg_g, sizeof(sd->avg_g));
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
187 image_sim_channel_norm(sd->avg_b, sizeof(sd->avg_b));
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
188
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
189 image_sim_channel_equal(sd->avg_r, sizeof(sd->avg_r));
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
190 image_sim_channel_equal(sd->avg_g, sizeof(sd->avg_g));
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
191 image_sim_channel_equal(sd->avg_b, sizeof(sd->avg_b));
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
192
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
193 #ifdef ALTERNATE_USES_GREYSCALE
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
194 for (i = 0; i < sizeof(sd->avg_r); i++)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
195 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
196 guint8 n;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
197
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
198 n = (guint8)((gint)(sd->avg_r[i] + sd->avg_g[i] + sd->avg_b[i]) / 3);
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
199 sd->avg_r[i] = sd->avg_g[i] = sd->avg_b[i] = n;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
200 }
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
201 #endif
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
202 }
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
203
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
204 void image_sim_fill_data(ImageSimilarityData *sd, GdkPixbuf *pixbuf)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
205 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
206 gint w, h;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
207 gint rs;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
208 guchar *pix;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
209 gint has_alpha;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
210 gint p_step;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
211
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
212 guchar *p;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
213 gint i;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
214 gint j;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
215 gint x_inc, y_inc;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
216 gint xs, ys;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
217
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
218 gint x_small = FALSE; /* if less than 32 w or h, set TRUE */
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
219 gint y_small = FALSE;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
220
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
221 if (!sd || !pixbuf) return;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
222
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
223 w = gdk_pixbuf_get_width(pixbuf);
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
224 h = gdk_pixbuf_get_height(pixbuf);
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
225 rs = gdk_pixbuf_get_rowstride(pixbuf);
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
226 pix = gdk_pixbuf_get_pixels(pixbuf);
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
227 has_alpha = gdk_pixbuf_get_has_alpha(pixbuf);
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
228
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
229 p_step = has_alpha ? 4 : 3;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
230 x_inc = w / 32;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
231 y_inc = h / 32;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
232
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
233 if (x_inc < 1)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
234 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
235 x_inc = 1;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
236 x_small = TRUE;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
237 }
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
238 if (y_inc < 1)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
239 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
240 y_inc = 1;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
241 y_small = TRUE;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
242 }
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
243
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
244 j = 0;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
245
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
246 for (ys = 0; ys < 32; ys++)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
247 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
248 if (y_small) j = (gdouble)h / 32 * ys;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
249
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
250 i = 0;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
251
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
252 for (xs = 0; xs < 32; xs++)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
253 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
254 gint x, y;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
255 gint r, g, b;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
256 gint t;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
257
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
258 if (x_small) i = (gdouble)w / 32 * xs;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
259
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
260 r = g = b = 0;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
261
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
262 for (y = j; y < j + y_inc; y++)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
263 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
264 p = pix + (y * rs) + (i * p_step);
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
265 for (x = i; x < i + x_inc; x++)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
266 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
267 r += *p; p++;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
268 g += *p; p++;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
269 b += *p; p++;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
270 if (has_alpha) p++;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
271 }
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
272 }
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
273
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
274 t = x_inc * y_inc;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
275 r /= t;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
276 g /= t;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
277 b /= t;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
278
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
279 t = ys * 32 + xs;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
280 sd->avg_r[t] = r;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
281 sd->avg_g[t] = g;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
282 sd->avg_b[t] = b;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
283
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
284 i += x_inc;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
285 }
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
286
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
287 j += y_inc;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
288 }
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
289
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
290 sd->filled = TRUE;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
291 }
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
292
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
293 ImageSimilarityData *image_sim_new_from_pixbuf(GdkPixbuf *pixbuf)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
294 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
295 ImageSimilarityData *sd;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
296
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
297 sd = image_sim_new();
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
298 image_sim_fill_data(sd, pixbuf);
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
299
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
300 return sd;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
301 }
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
302
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
303 #ifdef ALTERNATE_INCLUDE_COMPARE_CHANGE
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
304 static gdouble alternate_image_sim_compare_fast(ImageSimilarityData *a, ImageSimilarityData *b, gdouble min)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
305 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
306 gint sim;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
307 gint i;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
308 gint j;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
309 gint ld;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
310
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
311 if (!a || !b || !a->filled || !b->filled) return 0.0;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
312
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
313
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
314 min = 1.0 - min;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
315 sim = 0.0;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
316 ld = 0;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
317
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
318 for (j = 0; j < 1024; j+= 32)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
319 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
320 for (i = j; i < j + 32; i++)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
321 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
322 gint cr, cg, cb;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
323 gint cd;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
324
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
325 cr = abs(a->avg_r[i] - b->avg_r[i]);
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
326 cg = abs(a->avg_g[i] - b->avg_g[i]);
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
327 cb = abs(a->avg_b[i] - b->avg_b[i]);
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
328
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
329 cd = cr + cg + cb;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
330 sim += cd + abs(cd - ld);
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
331 ld = cd / 3;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
332 }
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
333 /* check for abort, if so return 0.0 */
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
334 if ((gdouble)sim / (255.0 * 1024.0 * 4.0) > min) return 0.0;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
335 }
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
336
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
337 return (1.0 - ((gdouble)sim / (255.0 * 1024.0 * 4.0)) );
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
338 }
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
339 #endif
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
340
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
341 gdouble image_sim_compare(ImageSimilarityData *a, ImageSimilarityData *b)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
342 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
343 gint sim;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
344 gint i;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
345
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
346 if (!a || !b || !a->filled || !b->filled) return 0.0;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
347
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
348 sim = 0.0;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
349
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
350 for (i = 0; i < 1024; i++)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
351 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
352 sim += abs(a->avg_r[i] - b->avg_r[i]);
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
353 sim += abs(a->avg_g[i] - b->avg_g[i]);
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
354 sim += abs(a->avg_b[i] - b->avg_b[i]);
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
355 }
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
356
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
357 return 1.0 - ((gdouble)sim / (255.0 * 1024.0 * 3.0));
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
358 }
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
359
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
360 /* this uses a cutoff point so that it can abort early when it gets to
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
361 * a point that can simply no longer make the cut-off point.
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
362 */
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
363 gdouble image_sim_compare_fast(ImageSimilarityData *a, ImageSimilarityData *b, gdouble min)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
364 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
365 gint sim;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
366 gint i;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
367 gint j;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
368
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
369 #ifdef ALTERNATE_INCLUDE_COMPARE_CHANGE
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
370 if (alternate_enabled) return alternate_image_sim_compare_fast(a, b, min);
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
371 #endif
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
372
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
373 if (!a || !b || !a->filled || !b->filled) return 0.0;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
374
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
375 min = 1.0 - min;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
376 sim = 0.0;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
377
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
378 for (j = 0; j < 1024; j+= 32)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
379 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
380 for (i = j; i < j + 32; i++)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
381 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
382 sim += abs(a->avg_r[i] - b->avg_r[i]);
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
383 sim += abs(a->avg_g[i] - b->avg_g[i]);
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
384 sim += abs(a->avg_b[i] - b->avg_b[i]);
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
385 }
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
386 /* check for abort, if so return 0.0 */
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
387 if ((gdouble)sim / (255.0 * 1024.0 * 3.0) > min) return 0.0;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
388 }
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
389
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
390 return (1.0 - ((gdouble)sim / (255.0 * 1024.0 * 3.0)) );
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
391 }