From 27093f569743eff0722da30bd464a991e2e68ffb Mon Sep 17 00:00:00 2001 From: Benjamin Franzke Date: Wed, 18 Apr 2012 16:13:11 +0200 Subject: Add a simple GTK3 based OpenCV gauß-filter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Makefile | 6 +- gauss_cv.c | 242 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ gauss_cv.ui | 114 ++++++++++++++++++++++++++++ 3 files changed, 361 insertions(+), 1 deletion(-) create mode 100644 gauss_cv.c create mode 100644 gauss_cv.ui diff --git a/Makefile b/Makefile index afdc528..d80fd4c 100644 --- a/Makefile +++ b/Makefile @@ -19,7 +19,10 @@ capture_LIBS=$(shell pkg-config --libs gtk+-3.0 opencv glib-2.0) unvignette_CFLAGS=$(shell pkg-config --cflags cairo) unvignette_LIBS=$(shell pkg-config --libs cairo) -lm -PROGS = wimmel wimmel_gl roi capture unvignette +gauss_cv_CFLAGS=$(shell pkg-config --cflags gtk+-3.0 gmodule-2.0 opencv) +gauss_cv_LIBS=$(shell pkg-config --libs gtk+-3.0 gmodule-2.0 opencv) + +PROGS = wimmel wimmel_gl roi capture unvignette gauss_cv OBJS = $(PROGS:=.o) util.o all: $(PROGS) @@ -29,6 +32,7 @@ wimmel_gl: wimmel_gl.o util.o roi: roi.o capture: capture.o unvignette: unvignette.o +gauss_cv: gauss_cv.o .PHONY: clean all diff --git a/gauss_cv.c b/gauss_cv.c new file mode 100644 index 0000000..da832ae --- /dev/null +++ b/gauss_cv.c @@ -0,0 +1,242 @@ +#include +#include +#include +#include + +struct cvg { + GtkWidget *drawing_area1; + GtkWidget *drawing_area2; + GtkButton *gauss_btn; + GtkButton *open_btn; + IplImage *image; + IplImage *output; + cairo_surface_t *input_surface; + cairo_surface_t *output_surface; +}; + +static cairo_surface_t * +cairo_surface_create_from_ipl_image(IplImage *image) +{ + cairo_surface_t *surface; + guchar *row1, *row2, *p1, *p2; + int x, y; + + surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, + image->width, image->height); + row1 = (guchar *) image->imageData; + row2 = cairo_image_surface_get_data(surface); + for (y = 0; y < image->height; ++y) { + p1 = row1; + p2 = row2; + for (x = 0; x < image->width; ++x) { + memcpy(p2, p1, 3); + + p1 += image->nChannels; + p2 += 4; + } + row1 += image->widthStep; + row2 += cairo_image_surface_get_stride(surface); + } + + return surface; +} + +static inline double +min3(double x1, double x2, double x3) +{ + return MIN(MIN(x1, x2), x3); +} + +static void +scale_centered(cairo_t *cr, double w, double h, double sw, double sh) +{ + double scale = min3(sw / w, sh / h, 1.0); + + cairo_translate(cr, (sw - scale * w) / 2.0, (sh - scale * h) / 2.0); + cairo_scale(cr, scale, scale); +} + +gboolean +draw(GtkWidget *widget, cairo_t *cr, gpointer userdata) +{ + struct cvg *cvg = userdata; + cairo_surface_t *surface; + + if (widget == cvg->drawing_area1) + surface = cvg->input_surface; + else + surface = cvg->output_surface; + + if (surface) { + scale_centered(cr, + cairo_image_surface_get_width(surface), + cairo_image_surface_get_height(surface), + gtk_widget_get_allocated_width(widget), + gtk_widget_get_allocated_height(widget)); + cairo_set_source_surface(cr, surface, 0, 0); + } else { + cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 0.0); + } + cairo_paint(cr); + + return FALSE; +} + +static void +destroy_images(struct cvg *cvg) +{ + if (cvg->image) + cvReleaseImage(&cvg->image); + if (cvg->output) + cvReleaseImage(&cvg->output); + + if (cvg->input_surface) + cairo_surface_destroy(cvg->input_surface); + cvg->input_surface = NULL; + if (cvg->output_surface) + cairo_surface_destroy(cvg->output_surface); + cvg->output_surface = NULL; +} + +gboolean +key_event(GtkWidget *widget, GdkEventKey *event, gpointer userdata) +{ + struct cvg *cvg = userdata; + + switch (event->type) { + case GDK_KEY_RELEASE: + switch (event->keyval) { + case GDK_KEY_g: + g_signal_emit_by_name(cvg->gauss_btn, "released", NULL); + g_signal_emit_by_name(cvg->gauss_btn, "clicked", NULL); + break; + case GDK_KEY_o: + g_signal_emit_by_name(cvg->open_btn, "released", NULL); + g_signal_emit_by_name(cvg->open_btn, "clicked", NULL); + break; + } + return FALSE; + case GDK_KEY_PRESS: + switch (event->keyval) { + case GDK_KEY_g: + g_signal_emit_by_name(cvg->gauss_btn, "pressed", NULL); + break; + case GDK_KEY_o: + g_signal_emit_by_name(cvg->open_btn, "pressed", NULL); + break; + case GDK_KEY_d: + destroy_images(cvg); + gtk_widget_queue_draw(cvg->drawing_area1); + gtk_widget_queue_draw(cvg->drawing_area2); + break; + case GDK_KEY_q: + gtk_main_quit(); + break; + } + return FALSE; + default: + return TRUE; + } +} + +static void +open_file(struct cvg *cvg, const gchar *file) +{ + if (cvg->image) + cvReleaseImage(&cvg->image); + if (cvg->input_surface) + cairo_surface_destroy(cvg->input_surface); + + cvg->image = cvLoadImage(file, CV_LOAD_IMAGE_COLOR); + if (!cvg->image) + return; + cvg->input_surface = cairo_surface_create_from_ipl_image(cvg->image); +} + +void +file_set(GtkFileChooserButton *widget, gpointer userdata) +{ + struct cvg *cvg = userdata; + gchar *filename; + + filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(widget)); + open_file(cvg, filename); + g_free(filename); + + gtk_widget_queue_draw(cvg->drawing_area1); +} + +void +on_gauss_button_click(GtkButton *button, gpointer userdata) +{ + struct cvg *cvg = userdata; + + if (!cvg->image) + return; + + if (cvg->output) + cvReleaseImage(&cvg->output); + + cvg->output = cvCreateImage(cvGetSize(cvg->image), IPL_DEPTH_8U, 3); + cvSmooth(cvg->image, cvg->output, CV_GAUSSIAN, 9, 9, 0, 0); + + if (cvg->output_surface) + cairo_surface_destroy(cvg->output_surface); + cvg->output_surface = cairo_surface_create_from_ipl_image(cvg->output); + + gtk_widget_queue_draw(cvg->drawing_area2); +} + +void +destroy(GtkWidget *widget, gpointer userdata) +{ + gtk_main_quit(); +} + +static void +find_button(GtkWidget *widget, gpointer data) +{ + GtkButton **p = data; + + if (GTK_IS_BUTTON(widget)) + *p = GTK_BUTTON(widget); +} + +int +main(int argc, char *argv[]) +{ + struct cvg cvg; + GtkBuilder *builder; + GObject *file_chooser; + + memset(&cvg, 0, sizeof cvg); + gtk_init(&argc, &argv); + + if (argc >= 2) + open_file(&cvg, argv[argc-1]); + builder = gtk_builder_new(); + gtk_builder_add_from_file(builder, "gauss_cv.ui", NULL); + gtk_builder_connect_signals(builder, &cvg); + + cvg.drawing_area1 = GTK_WIDGET(gtk_builder_get_object(builder, + "drawingarea1")); + cvg.drawing_area2 = GTK_WIDGET(gtk_builder_get_object(builder, + "drawingarea2")); + cvg.gauss_btn = GTK_BUTTON(gtk_builder_get_object(builder, "gauss")); + file_chooser = gtk_builder_get_object(builder, "file-chooser"); + gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(file_chooser), + g_get_current_dir()); + /* There is no way to retreive the GtkButton from GtkFileChooserButton, + * Try to find a GtkButton in the inherited GtkContainer. + */ + gtk_container_forall(GTK_CONTAINER(file_chooser), + find_button, &cvg.open_btn); + + gtk_widget_show_all(GTK_WIDGET(gtk_builder_get_object(builder, "win"))); + g_object_unref(builder); + gtk_main(); + + destroy_images(&cvg); + + return 0; +} diff --git a/gauss_cv.ui b/gauss_cv.ui new file mode 100644 index 0000000..302711d --- /dev/null +++ b/gauss_cv.ui @@ -0,0 +1,114 @@ + + + + + + image/tiff + image/png + image/jpeg + image/gif + + + + False + 600 + 400 + + + + + + True + False + True + True + + + True + False + 1 + 1 + 1 + 1 + True + True + + + + 0 + 0 + 1 + 1 + + + + + True + False + 1 + 1 + 1 + 1 + True + True + + + + 1 + 0 + 1 + 1 + + + + + True + False + filefilter1 + Bild auswählen + + + + 0 + 1 + 1 + 1 + + + + + Gauss-Filter + False + True + True + True + True + False + + + + 1 + 1 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + -- cgit