annotate src/similar.c @ 9:d907d608745f

Sync to GQview 1.5.9 release. ######## DO NOT BASE ENHANCEMENTS OR TRANSLATION UPDATES ON CODE IN THIS CVS! This CVS is never up to date with current development and is provided solely for reference purposes, please use the latest official release package when making any changes or translation updates. ########
author gqview
date Sat, 26 Feb 2005 00:13:35 +0000
parents
children f6e307c7bad6
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 /*
d907d608745f Sync to GQview 1.5.9 release.
gqview
parents:
diff changeset
2 * GQview
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 }