annotate src/similar.c @ 646:91dfc98f3ca1

Reading of Iptc.Application2.Keywords should now be fixed. Use uft8_validate_or_convert() on exif's text data to be safe.
author zas_
date Mon, 12 May 2008 23:26:00 +0000
parents f9bf33be53ff
children d27b4184ceb8
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
475
48c8e49b571c updated copyright in source files
nadvornik
parents: 442
diff changeset
4 * Copyright (C) 2008 The Geeqie Team
9
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
5 *
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
6 * Author: John Ellis
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
7 *
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
8 * This software is released under the GNU General Public License (GNU GPL).
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
9 * Please read the included file COPYING for more information.
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
10 * 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
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
281
9995c5fb202a gqview.h -> main.h
zas_
parents: 196
diff changeset
14 #include "main.h"
9
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
15 #include "similar.h"
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 /*
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
18 * These functions are intended to find images with similar color content. For
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
19 * example when an image was saved at different compression levels or dimensions
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
20 * (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
21 * size, dimensions, or checksum.
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
22 *
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
23 * 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
24 * The array represents the average color of each corresponding part of the
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
25 * 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
26 * 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
27 * is stored in the array)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
28 *
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
29 * To compare two images, generate a ImageSimilarityData for each image, then
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
30 * 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
31 * 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
32 * is an average of the corresponding array differences)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
33 *
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
34 * for image_sim_compare(), the return is 0.0 to 1.0:
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
35 * 1.0 for exact matches (an image is compared to itself)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
36 * 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
37 * 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
38 * 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
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 /*
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
43 * The experimental (alternate) algorithm is only for testing of new techniques to
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
44 * improve the result, and hopes to reduce false positives.
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
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
47 static gint alternate_enabled = FALSE;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
48
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
49 void image_sim_alternate_set(gint enable)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
50 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
51 alternate_enabled = enable;
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
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
54 gint image_sim_alternate_enabled(void)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
55 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
56 return alternate_enabled;
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
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
59 ImageSimilarityData *image_sim_new(void)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
60 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
61 ImageSimilarityData *sd = g_new0(ImageSimilarityData, 1);
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
62
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
63 return sd;
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
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
66 void image_sim_free(ImageSimilarityData *sd)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
67 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
68 g_free(sd);
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
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
71 #if 0
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
72 static void image_sim_channel_expand(guint8 *pix, gint len)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
73 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
74 guint8 l, h;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
75 gint i;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
76 gdouble scale;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
77
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
78 /* set the start values */
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
79 l = h = pix[0];
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
80
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
81 /* find min/max */
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
82 for (i = 0; i < len; i++)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
83 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
84 if (pix[i] < l) l = pix[i];
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
85 if (pix[i] > h) h = pix[i];
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
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
88 /* calc scale from range */
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
89 if (l != h)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
90 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
91 scale = 255.0 / (gdouble)(h - l);
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
92 }
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
93 else
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
94 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
95 scale = 1.0;
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
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
98 for (i = 0; i < len; i++)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
99 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
100 pix[i] = (guint8)((gdouble)pix[i] - l * scale);
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 }
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
103 #endif
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
104
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
105 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
106 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
107 gint *pa = (void *)a;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
108 gint *pb = (void *)b;
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 if (pa[1] > pb[1]) return 1;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
111 return 0;
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
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
114 static void image_sim_channel_equal(guint8 *pix, gint len)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
115 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
116 gint *buf;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
117 gint i;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
118 gint p;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
119
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
120 buf = g_new0(gint, len * 2);
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
121
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
122 p = 0;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
123 for (i = 0; i < len; i++)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
124 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
125 buf[p] = i;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
126 p++;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
127 buf[p] = (gint)pix[i];
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
128 p++;
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
512
f9bf33be53ff Remove whitespace between function name and first parenthesis for the sake of consistency.
zas_
parents: 475
diff changeset
131 qsort(buf, len, sizeof(gint) * 2, image_sim_channel_eq_sort_cb);
9
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
132
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
133 p = 0;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
134 for (i = 0; i < len; i++)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
135 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
136 gint n;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
137
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
138 n = buf[p];
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
139 p+= 2;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
140 pix[n] = (guint8)(255 * i / len);
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
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
143 g_free(buf);
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
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
146 static void image_sim_channel_norm(guint8 *pix, gint len)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
147 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
148 guint8 l, h;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
149 gint i;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
150 gdouble scale;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
151
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
152 l = h = pix[0];
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
153
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
154 for (i = 0; i < len; i++)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
155 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
156 if (pix[i] < l) l = pix[i];
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
157 if (pix[i] > h) h = pix[i];
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
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
160 scale = (h-l !=0) ? 255.0 / (gdouble)(h - l) : 1.0;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
161
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
162 for (i = 0; i < len; i++)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
163 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
164 pix[i] = (guint8)((gdouble)(pix[i] - l) * scale);
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 /*
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
169 * define these to enable various components of the experimental compare functions
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
170 *
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
171 * Convert the thumbprint to greyscale (ignore all color information when comparing)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
172 * #define ALTERNATE_USES_GREYSCALE 1
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
173 *
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
174 * 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
175 * #define ALTERNATE_INCLUDE_COMPARE_CHANGE 1
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
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
178 void image_sim_alternate_processing(ImageSimilarityData *sd)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
179 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
180 #ifdef ALTERNATE_USES_GREYSCALE
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
181 gint i;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
182 #endif
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
183
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
184 if (!alternate_enabled) return;
442
4b2d7f9af171 Big whitespaces cleanup:
zas_
parents: 281
diff changeset
185
9
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
186 image_sim_channel_norm(sd->avg_r, sizeof(sd->avg_r));
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
187 image_sim_channel_norm(sd->avg_g, sizeof(sd->avg_g));
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
188 image_sim_channel_norm(sd->avg_b, sizeof(sd->avg_b));
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
189
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
190 image_sim_channel_equal(sd->avg_r, sizeof(sd->avg_r));
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
191 image_sim_channel_equal(sd->avg_g, sizeof(sd->avg_g));
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
192 image_sim_channel_equal(sd->avg_b, sizeof(sd->avg_b));
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
193
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
194 #ifdef ALTERNATE_USES_GREYSCALE
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
195 for (i = 0; i < sizeof(sd->avg_r); i++)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
196 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
197 guint8 n;
442
4b2d7f9af171 Big whitespaces cleanup:
zas_
parents: 281
diff changeset
198
9
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
199 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
200 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
201 }
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
202 #endif
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
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
205 void image_sim_fill_data(ImageSimilarityData *sd, GdkPixbuf *pixbuf)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
206 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
207 gint w, h;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
208 gint rs;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
209 guchar *pix;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
210 gint has_alpha;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
211 gint p_step;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
212
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
213 guchar *p;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
214 gint i;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
215 gint j;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
216 gint x_inc, y_inc;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
217 gint xs, ys;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
218
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
219 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
220 gint y_small = FALSE;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
221
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
222 if (!sd || !pixbuf) return;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
223
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
224 w = gdk_pixbuf_get_width(pixbuf);
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
225 h = gdk_pixbuf_get_height(pixbuf);
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
226 rs = gdk_pixbuf_get_rowstride(pixbuf);
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
227 pix = gdk_pixbuf_get_pixels(pixbuf);
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
228 has_alpha = gdk_pixbuf_get_has_alpha(pixbuf);
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
229
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
230 p_step = has_alpha ? 4 : 3;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
231 x_inc = w / 32;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
232 y_inc = h / 32;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
233
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
234 if (x_inc < 1)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
235 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
236 x_inc = 1;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
237 x_small = TRUE;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
238 }
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
239 if (y_inc < 1)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
240 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
241 y_inc = 1;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
242 y_small = TRUE;
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
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
245 j = 0;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
246
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
247 for (ys = 0; ys < 32; ys++)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
248 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
249 if (y_small) j = (gdouble)h / 32 * ys;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
250
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
251 i = 0;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
252
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
253 for (xs = 0; xs < 32; xs++)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
254 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
255 gint x, y;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
256 gint r, g, b;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
257 gint t;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
258
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
259 if (x_small) i = (gdouble)w / 32 * xs;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
260
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
261 r = g = b = 0;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
262
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
263 for (y = j; y < j + y_inc; y++)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
264 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
265 p = pix + (y * rs) + (i * p_step);
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
266 for (x = i; x < i + x_inc; x++)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
267 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
268 r += *p; p++;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
269 g += *p; p++;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
270 b += *p; p++;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
271 if (has_alpha) p++;
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
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
275 t = x_inc * y_inc;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
276 r /= t;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
277 g /= t;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
278 b /= t;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
279
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
280 t = ys * 32 + xs;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
281 sd->avg_r[t] = r;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
282 sd->avg_g[t] = g;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
283 sd->avg_b[t] = b;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
284
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
285 i += x_inc;
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
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
288 j += y_inc;
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
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
291 sd->filled = TRUE;
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
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
294 ImageSimilarityData *image_sim_new_from_pixbuf(GdkPixbuf *pixbuf)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
295 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
296 ImageSimilarityData *sd;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
297
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
298 sd = image_sim_new();
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
299 image_sim_fill_data(sd, pixbuf);
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
300
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
301 return sd;
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
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
304 #ifdef ALTERNATE_INCLUDE_COMPARE_CHANGE
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
305 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
306 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
307 gint sim;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
308 gint i;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
309 gint j;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
310 gint ld;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
311
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
312 if (!a || !b || !a->filled || !b->filled) return 0.0;
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
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
315 min = 1.0 - min;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
316 sim = 0.0;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
317 ld = 0;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
318
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
319 for (j = 0; j < 1024; j+= 32)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
320 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
321 for (i = j; i < j + 32; i++)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
322 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
323 gint cr, cg, cb;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
324 gint cd;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
325
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
326 cr = abs(a->avg_r[i] - b->avg_r[i]);
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
327 cg = abs(a->avg_g[i] - b->avg_g[i]);
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
328 cb = abs(a->avg_b[i] - b->avg_b[i]);
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
329
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
330 cd = cr + cg + cb;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
331 sim += cd + abs(cd - ld);
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
332 ld = cd / 3;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
333 }
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
334 /* check for abort, if so return 0.0 */
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
335 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
336 }
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
337
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
338 return (1.0 - ((gdouble)sim / (255.0 * 1024.0 * 4.0)) );
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
339 }
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
340 #endif
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
341
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
342 gdouble image_sim_compare(ImageSimilarityData *a, ImageSimilarityData *b)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
343 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
344 gint sim;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
345 gint i;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
346
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
347 if (!a || !b || !a->filled || !b->filled) return 0.0;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
348
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
349 sim = 0.0;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
350
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
351 for (i = 0; i < 1024; i++)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
352 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
353 sim += abs(a->avg_r[i] - b->avg_r[i]);
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
354 sim += abs(a->avg_g[i] - b->avg_g[i]);
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
355 sim += abs(a->avg_b[i] - b->avg_b[i]);
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
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
358 return 1.0 - ((gdouble)sim / (255.0 * 1024.0 * 3.0));
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
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
361 /* 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
362 * a point that can simply no longer make the cut-off point.
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
363 */
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
364 gdouble image_sim_compare_fast(ImageSimilarityData *a, ImageSimilarityData *b, gdouble min)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
365 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
366 gint sim;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
367 gint i;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
368 gint j;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
369
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
370 #ifdef ALTERNATE_INCLUDE_COMPARE_CHANGE
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
371 if (alternate_enabled) return alternate_image_sim_compare_fast(a, b, min);
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
372 #endif
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
373
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
374 if (!a || !b || !a->filled || !b->filled) return 0.0;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
375
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
376 min = 1.0 - min;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
377 sim = 0.0;
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
378
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
379 for (j = 0; j < 1024; j+= 32)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
380 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
381 for (i = j; i < j + 32; i++)
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
382 {
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
383 sim += abs(a->avg_r[i] - b->avg_r[i]);
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
384 sim += abs(a->avg_g[i] - b->avg_g[i]);
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
385 sim += abs(a->avg_b[i] - b->avg_b[i]);
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
386 }
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
387 /* check for abort, if so return 0.0 */
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
388 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
389 }
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
390
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
391 return (1.0 - ((gdouble)sim / (255.0 * 1024.0 * 3.0)) );
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
392 }