[gthumb/ext] [file tools] added the equalize command



commit 8268f7ae92dd34c2b9b3c49e0327ed406d038670
Author: Paolo Bacchilega <paobac src gnome org>
Date:   Fri Sep 11 13:38:58 2009 +0200

    [file tools] added the equalize command

 extensions/file_tools/Makefile.am                |    2 +
 extensions/file_tools/gth-file-tool-desaturate.c |    6 +-
 extensions/file_tools/gth-file-tool-enhance.c    |    8 +-
 extensions/file_tools/gth-file-tool-equalize.c   |  226 ++++++++++++++++++++++
 extensions/file_tools/gth-file-tool-equalize.h   |   52 +++++
 extensions/file_tools/main.c                     |    2 +
 gthumb/gth-pixbuf-task.c                         |   21 +-
 gthumb/gth-pixbuf-task.h                         |   47 +++---
 8 files changed, 326 insertions(+), 38 deletions(-)
---
diff --git a/extensions/file_tools/Makefile.am b/extensions/file_tools/Makefile.am
index 8cd7dee..276897b 100644
--- a/extensions/file_tools/Makefile.am
+++ b/extensions/file_tools/Makefile.am
@@ -10,6 +10,8 @@ libfile_tools_la_SOURCES = 		\
 	gth-file-tool-desaturate.h	\
 	gth-file-tool-enhance.c		\
 	gth-file-tool-enhance.h		\
+	gth-file-tool-equalize.c	\
+	gth-file-tool-equalize.h	\
 	gth-file-tool-redo.c		\
 	gth-file-tool-redo.h		\
 	gth-file-tool-save.c		\
diff --git a/extensions/file_tools/gth-file-tool-desaturate.c b/extensions/file_tools/gth-file-tool-desaturate.c
index d80857b..f7df83b 100644
--- a/extensions/file_tools/gth-file-tool-desaturate.c
+++ b/extensions/file_tools/gth-file-tool-desaturate.c
@@ -64,9 +64,11 @@ desaturate_step (GthPixbufTask *pixop)
 
 
 static void
-desaturate_release (GthPixbufTask *pixop)
+desaturate_release (GthPixbufTask *pixop,
+		    GError        *error)
 {
-	gth_image_viewer_page_set_pixbuf (GTH_IMAGE_VIEWER_PAGE (pixop->data), pixop->dest);
+	if (error == NULL)
+		gth_image_viewer_page_set_pixbuf (GTH_IMAGE_VIEWER_PAGE (pixop->data), pixop->dest);
 }
 
 
diff --git a/extensions/file_tools/gth-file-tool-enhance.c b/extensions/file_tools/gth-file-tool-enhance.c
index 3147af3..5d4e599 100644
--- a/extensions/file_tools/gth-file-tool-enhance.c
+++ b/extensions/file_tools/gth-file-tool-enhance.c
@@ -200,11 +200,13 @@ adjust_levels_step (GthPixbufTask *pixop)
 
 
 static void
-adjust_levels_release (GthPixbufTask *pixop)
+adjust_levels_release (GthPixbufTask *pixop,
+		       GError        *error)
 {
 	EnhanceData *data = pixop->data;
 
-	gth_image_viewer_page_set_pixbuf (GTH_IMAGE_VIEWER_PAGE (data->viewer_page), pixop->dest);
+	if (error == NULL)
+		gth_image_viewer_page_set_pixbuf (GTH_IMAGE_VIEWER_PAGE (data->viewer_page), pixop->dest);
 
 	gth_histogram_free (data->hist);
 	g_free (data->levels);
@@ -237,7 +239,7 @@ gth_file_tool_enhance_activate (GthFileTool *base)
 	dest_pixbuf = gdk_pixbuf_copy (src_pixbuf);
 	data = g_new0 (EnhanceData, 1);
 	data->viewer_page = g_object_ref (viewer_page);
-	task = gth_pixbuf_task_new (_("Enhancing image colors"),
+	task = gth_pixbuf_task_new (_("White balance correction"),
 				    src_pixbuf,
 				    dest_pixbuf,
 				    adjust_levels_init,
diff --git a/extensions/file_tools/gth-file-tool-equalize.c b/extensions/file_tools/gth-file-tool-equalize.c
new file mode 100644
index 0000000..091b761
--- /dev/null
+++ b/extensions/file_tools/gth-file-tool-equalize.c
@@ -0,0 +1,226 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Copyright (C) 2009 Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include <math.h>
+#include <gthumb.h>
+#include <extensions/image_viewer/gth-image-viewer-page.h>
+#include "gth-file-tool-equalize.h"
+
+
+typedef struct {
+	GtkWidget     *viewer_page;
+	GthHistogram  *histogram;
+	int          **part;
+} EqualizeData;
+
+
+static void
+equalize_histogram_setup (GthHistogram  *hist,
+			  int          **part)
+{
+	int  i, k, j;
+	int  pixels_per_value;
+	int  desired;
+	int  sum, dif;
+
+	pixels_per_value = gth_histogram_get_count (hist, 0, 255) / 256.0;
+
+	for (k = 0; k < gth_histogram_get_nchannels (hist); k++) {
+		/* First and last points in partition */
+		part[k][0]   = 0;
+		part[k][256] = 256;
+
+		/* Find intermediate points */
+		j   = 0;
+		sum = (gth_histogram_get_value (hist, k + 1, 0) +
+		       gth_histogram_get_value (hist, k + 1, 1));
+
+		for (i = 1; i < 256; i++) {
+			desired = i * pixels_per_value;
+
+			while (sum <= desired) {
+				j++;
+				sum += gth_histogram_get_value (hist, k + 1, j + 1);
+			}
+
+			/* Nearest sum */
+			dif = sum - gth_histogram_get_value (hist, k + 1, j);
+
+			if ((sum - desired) > (dif / 2.0))
+				part[k][i] = j;
+			else
+				part[k][i] = j + 1;
+		}
+	}
+}
+
+
+static void
+equalize_init (GthPixbufTask *pixop)
+{
+	EqualizeData *data = pixop->data;
+	int           i;
+
+	data->histogram = gth_histogram_new ();
+	gth_histogram_calculate (data->histogram, pixop->src);
+
+	data->part = g_new0 (int *, MAX_N_CHANNELS + 1);
+	for (i = 0; i < MAX_N_CHANNELS + 1; i++)
+		data->part[i] = g_new0 (int, 257);
+	equalize_histogram_setup (data->histogram, data->part);
+}
+
+
+static guchar
+equalize_func (guchar   u_value,
+	       int    **part,
+	       int      channel)
+{
+	guchar i = 0;
+	while (part[channel][i + 1] <= u_value)
+		i++;
+	return i;
+}
+
+
+static void
+equalize_step (GthPixbufTask *pixop)
+{
+	EqualizeData *data = pixop->data;
+
+	pixop->dest_pixel[RED_PIX]   = equalize_func (pixop->src_pixel[RED_PIX], data->part, 0);
+	pixop->dest_pixel[GREEN_PIX] = equalize_func (pixop->src_pixel[GREEN_PIX], data->part, 1);
+	pixop->dest_pixel[BLUE_PIX]  = equalize_func (pixop->src_pixel[BLUE_PIX], data->part, 2);
+	if (pixop->has_alpha)
+		pixop->dest_pixel[ALPHA_PIX] = equalize_func (pixop->src_pixel[ALPHA_PIX], data->part, 3);
+}
+
+
+static void
+equalize_release (GthPixbufTask *pixop,
+		  GError        *error)
+{
+	EqualizeData *data = pixop->data;
+	int           i;
+
+	if (error == NULL)
+		gth_image_viewer_page_set_pixbuf (GTH_IMAGE_VIEWER_PAGE (data->viewer_page), pixop->dest);
+
+	for (i = 0; i < MAX_N_CHANNELS + 1; i++)
+		g_free (data->part[i]);
+	g_free (data->part);
+	gth_histogram_free (data->histogram);
+	g_object_unref (data->viewer_page);
+	g_free (data);
+}
+
+
+static void
+gth_file_tool_equalize_activate (GthFileTool *base)
+{
+	GtkWidget   *window;
+	GtkWidget   *viewer_page;
+	GtkWidget   *viewer;
+	GdkPixbuf   *src_pixbuf;
+	GdkPixbuf   *dest_pixbuf;
+	EqualizeData *data;
+	GthTask     *task;
+
+	window = gth_file_tool_get_window (base);
+	viewer_page = gth_browser_get_viewer_page (GTH_BROWSER (window));
+	if (! GTH_IS_IMAGE_VIEWER_PAGE (viewer_page))
+		return;
+
+	viewer = gth_image_viewer_page_get_image_viewer (GTH_IMAGE_VIEWER_PAGE (viewer_page));
+	src_pixbuf = gth_image_viewer_get_current_pixbuf (GTH_IMAGE_VIEWER (viewer));
+	if (src_pixbuf == NULL)
+		return;
+
+	dest_pixbuf = gdk_pixbuf_copy (src_pixbuf);
+	data = g_new0 (EqualizeData, 1);
+	data->viewer_page = g_object_ref (viewer_page);
+	task = gth_pixbuf_task_new (_("Enhancing image contrast"),
+				    src_pixbuf,
+				    dest_pixbuf,
+				    equalize_init,
+				    equalize_step,
+				    equalize_release,
+				    data);
+	gth_browser_exec_task (GTH_BROWSER (window), task, FALSE);
+
+	g_object_unref (task);
+	g_object_unref (dest_pixbuf);
+}
+
+
+static void
+gth_file_tool_equalize_update_sensitivity (GthFileTool *base)
+{
+	GtkWidget *window;
+	GtkWidget *viewer_page;
+
+	window = gth_file_tool_get_window (base);
+	viewer_page = gth_browser_get_viewer_page (GTH_BROWSER (window));
+	if (! GTH_IS_IMAGE_VIEWER_PAGE (viewer_page))
+		gtk_widget_set_sensitive (GTK_WIDGET (base), FALSE);
+	else
+		gtk_widget_set_sensitive (GTK_WIDGET (base), TRUE);
+}
+
+
+static void
+gth_file_tool_equalize_instance_init (GthFileToolEqualize *self)
+{
+	gth_file_tool_construct (GTH_FILE_TOOL (self), GTK_STOCK_EDIT /* FIXME GTH_STOCK_EQUALIZE */, _("Equalize"), NULL);
+	gtk_widget_set_tooltip_text (GTK_WIDGET (self), _("Automatic contrast enhancement"));
+}
+
+
+static void
+gth_file_tool_equalize_class_init (GthFileToolClass *klass)
+{
+	klass->update_sensitivity = gth_file_tool_equalize_update_sensitivity;
+	klass->activate = gth_file_tool_equalize_activate;
+}
+
+
+GType
+gth_file_tool_equalize_get_type (void) {
+	static GType type_id = 0;
+	if (type_id == 0) {
+		static const GTypeInfo g_define_type_info = {
+			sizeof (GthFileToolEqualizeClass),
+			(GBaseInitFunc) NULL,
+			(GBaseFinalizeFunc) NULL,
+			(GClassInitFunc) gth_file_tool_equalize_class_init,
+			(GClassFinalizeFunc) NULL,
+			NULL,
+			sizeof (GthFileToolEqualize),
+			0,
+			(GInstanceInitFunc) gth_file_tool_equalize_instance_init,
+			NULL
+		};
+		type_id = g_type_register_static (GTH_TYPE_FILE_TOOL, "GthFileToolEqualize", &g_define_type_info, 0);
+	}
+	return type_id;
+}
diff --git a/extensions/file_tools/gth-file-tool-equalize.h b/extensions/file_tools/gth-file-tool-equalize.h
new file mode 100644
index 0000000..9d06651
--- /dev/null
+++ b/extensions/file_tools/gth-file-tool-equalize.h
@@ -0,0 +1,52 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Copyright (C) 2009 Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef GTH_FILE_TOOL_EQUALIZE_H
+#define GTH_FILE_TOOL_EQUALIZE_H
+
+#include <gthumb.h>
+
+G_BEGIN_DECLS
+
+#define GTH_TYPE_FILE_TOOL_EQUALIZE (gth_file_tool_equalize_get_type ())
+#define GTH_FILE_TOOL_EQUALIZE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTH_TYPE_FILE_TOOL_EQUALIZE, GthFileToolEqualize))
+#define GTH_FILE_TOOL_EQUALIZE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTH_TYPE_FILE_TOOL_EQUALIZE, GthFileToolEqualizeClass))
+#define GTH_IS_FILE_TOOL_EQUALIZE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTH_TYPE_FILE_TOOL_EQUALIZE))
+#define GTH_IS_FILE_TOOL_EQUALIZE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTH_TYPE_FILE_TOOL_EQUALIZE))
+#define GTH_FILE_TOOL_EQUALIZE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTH_TYPE_FILE_TOOL_EQUALIZE, GthFileToolEqualizeClass))
+
+typedef struct _GthFileToolEqualize GthFileToolEqualize;
+typedef struct _GthFileToolEqualizeClass GthFileToolEqualizeClass;
+
+struct _GthFileToolEqualize {
+	GthFileTool parent_instance;
+};
+
+struct _GthFileToolEqualizeClass {
+	GthFileToolClass parent_class;
+};
+
+GType  gth_file_tool_equalize_get_type  (void);
+
+G_END_DECLS
+
+#endif /* GTH_FILE_TOOL_EQUALIZE_H */
diff --git a/extensions/file_tools/main.c b/extensions/file_tools/main.c
index 65819f6..8a34fde 100644
--- a/extensions/file_tools/main.c
+++ b/extensions/file_tools/main.c
@@ -27,6 +27,7 @@
 #include "gth-file-tool-crop.h"
 #include "gth-file-tool-desaturate.h"
 #include "gth-file-tool-enhance.h"
+#include "gth-file-tool-equalize.h"
 #include "gth-file-tool-redo.h"
 #include "gth-file-tool-save.h"
 #include "gth-file-tool-undo.h"
@@ -41,6 +42,7 @@ gthumb_extension_activate (void)
 	gth_main_register_type ("file-tools", GTH_TYPE_FILE_TOOL_CROP);
 	gth_main_register_type ("file-tools", GTH_TYPE_FILE_TOOL_DESATURATE);
 	gth_main_register_type ("file-tools", GTH_TYPE_FILE_TOOL_ENHANCE);
+	gth_main_register_type ("file-tools", GTH_TYPE_FILE_TOOL_EQUALIZE);
 }
 
 
diff --git a/gthumb/gth-pixbuf-task.c b/gthumb/gth-pixbuf-task.c
index 79fedf9..5bc537b 100644
--- a/gthumb/gth-pixbuf-task.c
+++ b/gthumb/gth-pixbuf-task.c
@@ -82,11 +82,12 @@ one_step (gpointer data)
 	{
 		GError *error = NULL;
 
+		if (pixbuf_task->interrupt)
+			error = g_error_new_literal (GTH_TASK_ERROR, GTH_TASK_ERROR_CANCELLED, "");
+
 		if (pixbuf_task->release_func != NULL)
-			(*pixbuf_task->release_func) (pixbuf_task);
+			(*pixbuf_task->release_func) (pixbuf_task, error);
 
-		if (pixbuf_task->interrupt)
-			error = g_error_new_literal (GTH_TASK_ERROR, GTH_TASK_ERROR_CANCELLED, NULL);
 		gth_task_completed (GTH_TASK (pixbuf_task), error);
 
 		return FALSE;
@@ -253,13 +254,13 @@ gth_pixbuf_task_get_type (void)
 
 
 GthTask *
-gth_pixbuf_task_new (const char   *description,
-		     GdkPixbuf    *src,
-		     GdkPixbuf    *dest,
-		     PixbufOpFunc  init_func,
-		     PixbufOpFunc  step_func,
-		     PixbufOpFunc  release_func,
-		     gpointer      data)
+gth_pixbuf_task_new (const char     *description,
+		     GdkPixbuf      *src,
+		     GdkPixbuf      *dest,
+		     PixbufOpFunc    init_func,
+		     PixbufOpFunc    step_func,
+		     PixbufDoneFunc  release_func,
+		     gpointer        data)
 {
 	GthPixbufTask *pixbuf_task;
 
diff --git a/gthumb/gth-pixbuf-task.h b/gthumb/gth-pixbuf-task.h
index 8070599..e3b0d83 100644
--- a/gthumb/gth-pixbuf-task.h
+++ b/gthumb/gth-pixbuf-task.h
@@ -39,7 +39,8 @@ G_BEGIN_DECLS
 typedef struct _GthPixbufTask        GthPixbufTask;
 typedef struct _GthPixbufTaskClass   GthPixbufTaskClass;
 
-typedef void (*PixbufOpFunc) (GthPixbufTask *pixbuf_task);
+typedef void (*PixbufOpFunc)   (GthPixbufTask *pixbuf_task);
+typedef void (*PixbufDoneFunc) (GthPixbufTask *pixbuf_task, GError *error);
 
 enum {
 	RED_PIX   = 0,
@@ -51,32 +52,32 @@ enum {
 struct _GthPixbufTask {
 	GthTask __parent;
 
-	GdkPixbuf    *src;
-	GdkPixbuf    *dest;
-	gpointer      data;
+	GdkPixbuf      *src;
+	GdkPixbuf      *dest;
+	gpointer        data;
 
-	PixbufOpFunc  init_func;
-	PixbufOpFunc  step_func;
-	PixbufOpFunc  release_func;
-	PixbufOpFunc  free_data_func;
+	PixbufOpFunc    init_func;
+	PixbufOpFunc    step_func;
+	PixbufDoneFunc  release_func;
+	PixbufOpFunc    free_data_func;
 
-	gboolean      single_step;
+	gboolean        single_step;
 
-	gboolean      has_alpha;
-	int           bytes_per_pixel;
-	int           width, height;
-	int           rowstride;
-	guchar       *src_line, *src_pixel;
-	guchar       *dest_line, *dest_pixel;
+	gboolean        has_alpha;
+	int             bytes_per_pixel;
+	int             width, height;
+	int             rowstride;
+	guchar         *src_line, *src_pixel;
+	guchar         *dest_line, *dest_pixel;
 
-	gboolean      ltr, first_step, last_step;
-	guint         timeout_id;
-	int           line;
-	int           line_step;
-	int           column;
-	gboolean      interrupt;
+	gboolean        ltr, first_step, last_step;
+	guint           timeout_id;
+	int             line;
+	int             line_step;
+	int             column;
+	gboolean        interrupt;
 
-	const char   *description;
+	const char     *description;
 };
 
 struct _GthPixbufTaskClass {
@@ -89,7 +90,7 @@ GthTask *     gth_pixbuf_task_new             (const char     *description,
 					       GdkPixbuf      *dest,
 					       PixbufOpFunc    init_func,
 					       PixbufOpFunc    step_func,
-					       PixbufOpFunc    release_func,
+					       PixbufDoneFunc  release_func,
 					       gpointer        data);
 void          gth_pixbuf_task_set_single_step (GthPixbufTask  *pixbuf_task,
 					       gboolean        single_step);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]