#include #include #include "image.h" #include "fft.h" complex_image_t * complex_image_new (int width, int height) { complex_image_t *image = g_new0 (complex_image_t, 1); image->width = width; image->height = height; image->red = g_new0 (complex_t, width * height); image->green = g_new0 (complex_t, width * height); image->blue = g_new0 (complex_t, width * height); return image; } complex_image_t * complex_image_copy (complex_image_t *image) { complex_image_t *copy = complex_image_new (image->width, image->height); int width = image->width; int height = image->height; copy->red = g_memdup (image->red, width * height * sizeof (complex_t)); copy->green = g_memdup (image->green, width * height * sizeof (complex_t)); copy->blue = g_memdup (image->blue, width * height * sizeof (complex_t)); return copy; } void complex_image_subtract (complex_image_t *image, complex_image_t *other) { int i, j; int h = image->height; int w = image->width; for (i = 0; i < h; ++i) { for (j = 0; j < w; ++j) { int idx = i * w + j; image->red[idx] = complex_sub (image->red[idx], other->red[idx]); image->green[idx] = complex_sub (image->green[idx], other->green[idx]); image->blue[idx] = complex_sub (image->blue[idx], other->blue[idx]); } } } void complex_image_mul (complex_image_t *image, double m) { int i, j; int h = image->height; int w = image->width; for (i = 0; i < h; ++i) { for (j = 0; j < w; ++j) { int idx = i * w + j; image->red[idx] = complex_smul (image->red[idx], m); image->green[idx] = complex_smul (image->green[idx], m); image->blue[idx] = complex_smul (image->blue[idx], m); } } } complex_image_t * complex_image_from_pixbuf (GdkPixbuf *pixbuf) { complex_image_t *result; uint8_t *pdata; int w, h, s; int i, j; gboolean has_alpha; int n_channels; w = gdk_pixbuf_get_width (pixbuf); h = gdk_pixbuf_get_height (pixbuf); s = gdk_pixbuf_get_rowstride (pixbuf); pdata = gdk_pixbuf_get_pixels (pixbuf); has_alpha = gdk_pixbuf_get_has_alpha (pixbuf); n_channels = 3 + has_alpha; printf ("has alpha: %d\n", has_alpha); result = complex_image_new (w, h); for (i = 0; i < h; ++i) { for (j = 0; j < w; ++j) { uint8_t *p = &pdata[i * s + j * n_channels]; int idx = i * w + j; result->red[idx].re = p[0] / 255.0; result->green[idx].re = p[1] / 255.0; result->blue[idx].re = p[2] / 255.0; } } return result; } typedef uint8_t (* converter_t) (complex_t c); static uint8_t convert_mag (complex_t d) { double m = complex_mag (d); m = log (m + 1) / 12.0; if (m > 1.0) { printf ("%f\n", m); m = 1.0; } if (m < 0) { printf ("%f\n", m); m = 0; } return (uint8_t) (m * 255.0 + 0.5); } static uint8_t convert_re (complex_t c) { if (c.re > 1.0) c.re = 1.0; if (c.re < 0) c.re = 0; return c.re * 255.0 + 0.5; } GdkPixbuf * pixbuf_from_complex_image (complex_image_t *image, convert_type_t convert) { int w = image->width; int h = image->height; GdkPixbuf *pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, w, h); uint8_t *p_bits = (uint8_t *)gdk_pixbuf_get_pixels (pixbuf); int s = gdk_pixbuf_get_rowstride (pixbuf); converter_t converter; int i, j; switch (convert) { case CONVERT_MAG: converter = convert_mag; break; case CONVERT_RE: converter = convert_re; break; default: g_assert_not_reached(); } for (i = 0; i < h; ++i) { for (j = 0; j < w; ++j) { uint8_t *p = &(p_bits[i * s + j * 4]); int idx = i * w + j; p[0] = converter (image->red[idx]); p[1] = converter (image->green[idx]); p[2] = converter (image->blue[idx]); p[3] = 0xff; // convert (image->alpha[idx]); } } return pixbuf; } static gboolean on_expose (GtkWidget *widget, GdkEventExpose *expose, gpointer data) { GdkPixbuf *pixbuf = data; int i, j; int pwidth = gdk_pixbuf_get_width (pixbuf); int pheight = gdk_pixbuf_get_height (pixbuf); int dwidth, dheight; gdk_drawable_get_size (widget->window, &dwidth, &dheight); for (i = 0; i < dheight; i += pheight) { for (j = 0; j < dwidth; j += pwidth) { gdk_draw_pixbuf (widget->window, NULL, pixbuf, 0, 0, j, i, pwidth, pheight, GDK_RGB_DITHER_NONE, 0, 0); } } return TRUE; } void complex_image_show (const char *title, complex_image_t *image, convert_type_t convert) { GtkWidget *window, *da; GdkPixbuf *pixbuf; int argc; char **argv; char *arg0 = g_strdup (title); argc = 1; argv = (char **)&arg0; gtk_init (&argc, &argv); window = gtk_window_new (GTK_WINDOW_TOPLEVEL); da = gtk_drawing_area_new (); gtk_container_add (GTK_CONTAINER (window), da); gtk_window_set_default_size (GTK_WINDOW (window), image->width * 2, image->height * 2); pixbuf = pixbuf_from_complex_image (image, convert); g_signal_connect (da, "expose_event", G_CALLBACK (on_expose), pixbuf); g_signal_connect (window, "delete_event", G_CALLBACK (gtk_main_quit), NULL); gtk_widget_show_all (window); gtk_main (); } void complex_image_fft (complex_image_t *image) { fft_shift_2d (image->red, image->width); fft_shift_2d (image->green, image->width); fft_shift_2d (image->blue, image->width); } void complex_image_ifft (complex_image_t *image) { ifft_shift_2d (image->red, image->width); ifft_shift_2d (image->green, image->width); ifft_shift_2d (image->blue, image->width); }