summaryrefslogtreecommitdiff
path: root/wimmel.c
diff options
context:
space:
mode:
Diffstat (limited to 'wimmel.c')
-rw-r--r--wimmel.c158
1 files changed, 158 insertions, 0 deletions
diff --git a/wimmel.c b/wimmel.c
new file mode 100644
index 0000000..712dacb
--- /dev/null
+++ b/wimmel.c
@@ -0,0 +1,158 @@
+#include <stdlib.h>
+#include <glib.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+
+#include "util.h"
+
+static void
+find_image_in_wimmel(GdkPixbuf *wimmel, GdkPixbuf *match, GdkPixbuf *output)
+{
+ int wimmel_width, wimmel_height;
+ int width, height;
+ int i, j, k, n;
+ int difference, barrier;
+
+ wimmel_width = gdk_pixbuf_get_width(wimmel);
+ wimmel_height = gdk_pixbuf_get_height(wimmel);
+ width = gdk_pixbuf_get_width(match);
+ height = gdk_pixbuf_get_height(match);
+
+ barrier = width * height / 2;
+
+ for (j = 0; j < wimmel_height - height; ++j) {
+ for (i = 0; i < wimmel_width - width; ++i) {
+
+ difference = 0;
+ for (n = 0; n < height; ++n) {
+ for (k = 0; k < width; ++k) {
+ color_t color = get_pixel(wimmel, POINT(i + k, j + n));
+ color_t color_orig = get_pixel(match, POINT(k, n));
+
+#if 1
+ if (abs(color.r - color_orig.r) > 50 ||
+ abs(color.g - color_orig.g) > 50 ||
+ abs(color.b - color_orig.b) > 50) {
+ difference++;
+ if (difference > barrier)
+ break;
+ }
+#else
+ difference +=
+ abs(color.r - color_orig.r) +
+ abs(color.g - color_orig.g) +
+ abs(color.b - color_orig.b);
+ if (difference > barrier * 300)
+ break;
+#endif
+ }
+ }
+
+#if 0
+ if (difference < barrier * 300) {
+#else
+ if (difference < barrier) {
+#endif
+ g_print("kleeblatt @ %d, %d; difference: %d\n", i, j, difference);
+ color_t color = COLOR(255, 0, 0, 0);
+ for (k = i; k < i+width; k++) {
+ put_pixel(output, POINT(k, j), color);
+ put_pixel(output, POINT(k, j+height), color);
+ }
+ for (n = j; n < j+height; n++) {
+ put_pixel(output, POINT(i, n), color);
+ put_pixel(output, POINT(i+width, n), color);
+ }
+ }
+ }
+ }
+}
+struct find_params {
+ GdkPixbuf *wimmel;
+ GdkPixbuf *match;
+ GdkPixbuf *output;
+};
+
+static gpointer
+find_thread(gpointer data)
+{
+ struct find_params *params = data;
+
+ find_image_in_wimmel(params->wimmel, params->match, params->output);
+ g_object_unref(params->wimmel);
+ g_object_unref(params->match);
+ g_object_unref(params->output);
+
+ free(params);
+
+ return NULL;
+}
+
+int
+main(int argc, char *argv[])
+{
+ char *file;
+ GdkPixbuf *wimmel, *output;
+ GdkPixbuf *match_tmp, *match;
+ int i, j;
+ int x1, y1, mwidth, mheight, width, height;
+#define N 4
+#define K 4
+ GThread *thread[N][K];
+
+ g_type_init();
+
+ if (argc < 5)
+ exit(EXIT_FAILURE);
+
+ file = argv[1];
+ x1 = atoi(argv[2]);
+ y1 = atoi(argv[3]);
+ mwidth = atoi(argv[4]);
+ mheight = atoi(argv[5]);
+
+ wimmel = gdk_pixbuf_new_from_file(file, NULL);
+ if (!wimmel)
+ exit(EXIT_FAILURE);
+
+ output = gdk_pixbuf_copy(wimmel);
+
+ match_tmp = gdk_pixbuf_new_subpixbuf(wimmel, x1, y1, mwidth, mheight);
+ match = gdk_pixbuf_copy(match_tmp);
+ g_object_unref(match_tmp);
+
+ width = gdk_pixbuf_get_width(wimmel);
+ height = gdk_pixbuf_get_height(wimmel);
+
+ int step_x = width / N, step_y = height / K;
+ int x, y;
+ for (i = 0, x = 0; i < N; ++i, x += step_x) {
+ for (j = 0, y = 0; j < K; ++j, y += step_y) {
+ struct find_params *params = malloc(sizeof (struct find_params));;
+ if (!params)
+ exit(EXIT_FAILURE);
+
+ int w = step_x + mwidth;
+ int h = step_y + mheight;
+
+ if (x + w > width)
+ w = width - x;
+ if (y + h > height)
+ h = height - y;
+
+ params->wimmel = gdk_pixbuf_new_subpixbuf(wimmel, x, y, w, h);
+ params->output = gdk_pixbuf_new_subpixbuf(output, x, y, w, h);
+ params->match = g_object_ref(match);
+
+ thread[i][j] = g_thread_create(find_thread, params, TRUE, NULL);
+ }
+ }
+
+ for (i = 0; i < N; ++i)
+ for (j = 0; j < K; ++j)
+ g_thread_join(thread[i][j]);
+
+ gdk_pixbuf_save(output, "output.png", "png", NULL, NULL);
+ g_object_unref(wimmel);
+ g_object_unref(output);
+ g_object_unref(match);
+}