modules/Makefile.am added a display filter which will simulate the vision
2002-12-16 Michael Natterer <mitch@gimp.org> * modules/Makefile.am * modules/cdisplay_colorblind.c: added a display filter which will simulate the vision of people with color-deficiency to address bug #101256. Didn't know any scientific name or any correct formula, so I just added the framework plus the approximation formula from the bug report. Will need some more work to become usable.
This commit is contained in:

committed by
Michael Natterer

parent
714b6fe881
commit
4e1051d6d1
@ -16,9 +16,11 @@ EXTRA_DIST = \
|
||||
|
||||
lib_LTLIBRARIES = \
|
||||
libcolorsel_triangle.la \
|
||||
libcolorsel_water.la \
|
||||
\
|
||||
libcdisplay_colorblind.la \
|
||||
libcdisplay_gamma.la \
|
||||
libcdisplay_highcontrast.la \
|
||||
libcolorsel_water.la
|
||||
libcdisplay_highcontrast.la
|
||||
|
||||
EXTRA_LTLIBRARIES =
|
||||
|
||||
@ -30,6 +32,10 @@ libcolorsel_water_la_SOURCES = colorsel_water.c
|
||||
libcolorsel_water_la_LDFLAGS = -avoid-version -module
|
||||
libcolorsel_water_la_LIBADD = $(GTK_LIBS)
|
||||
|
||||
libcdisplay_colorblind_la_SOURCES = cdisplay_colorblind.c
|
||||
libcdisplay_colorblind_la_LDFLAGS = -avoid-version -module
|
||||
libcdisplay_colorblind_la_LIBADD = $(GTK_LIBS)
|
||||
|
||||
libcdisplay_gamma_la_SOURCES = cdisplay_gamma.c
|
||||
libcdisplay_gamma_la_LDFLAGS = -avoid-version -module
|
||||
libcdisplay_gamma_la_LIBADD = $(GTK_LIBS)
|
||||
|
380
modules/cdisplay_colorblind.c
Normal file
380
modules/cdisplay_colorblind.c
Normal file
@ -0,0 +1,380 @@
|
||||
/* The GIMP -- an image manipulation program
|
||||
* Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* cdisplay_colorblind.c
|
||||
* Copyright (C) 2002 Michael Natterer <mitch@gimp.org>
|
||||
*
|
||||
* 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 Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "libgimpbase/gimpbase.h"
|
||||
#include "libgimpmodule/gimpmodule.h"
|
||||
#include "libgimpwidgets/gimpwidgets.h"
|
||||
|
||||
#include "libgimp/libgimp-intl.h"
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
COLORBLIND_DEFICIENCY_FOO,
|
||||
COLORBLIND_DEFICIENCY_BAR
|
||||
} ColorblindDeficiency;
|
||||
|
||||
|
||||
#define DEFAULT_DEFICIENCY COLORBLIND_DEFICIENCY_FOO
|
||||
|
||||
|
||||
#define CDISPLAY_TYPE_COLORBLIND (cdisplay_colorblind_type)
|
||||
#define CDISPLAY_COLORBLIND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CDISPLAY_TYPE_COLORBLIND, CdisplayColorblind))
|
||||
#define CDISPLAY_COLORBLIND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CDISPLAY_TYPE_COLORBLIND, CdisplayColorblindClass))
|
||||
#define CDISPLAY_IS_COLORBLIND(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CDISPLAY_TYPE_COLORBLIND))
|
||||
#define CDISPLAY_IS_COLORBLIND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CDISPLAY_TYPE_COLORBLIND))
|
||||
|
||||
|
||||
typedef struct _CdisplayColorblind CdisplayColorblind;
|
||||
typedef struct _CdisplayColorblindClass CdisplayColorblindClass;
|
||||
|
||||
struct _CdisplayColorblind
|
||||
{
|
||||
GimpColorDisplay parent_instance;
|
||||
|
||||
ColorblindDeficiency deficiency;
|
||||
|
||||
GtkWidget *hbox;
|
||||
GtkWidget *optionmenu;
|
||||
};
|
||||
|
||||
struct _CdisplayColorblindClass
|
||||
{
|
||||
GimpColorDisplayClass parent_instance;
|
||||
};
|
||||
|
||||
|
||||
static GType cdisplay_colorblind_get_type (GTypeModule *module);
|
||||
static void cdisplay_colorblind_class_init (CdisplayColorblindClass *klass);
|
||||
static void cdisplay_colorblind_init (CdisplayColorblind *colorblind);
|
||||
|
||||
static void cdisplay_colorblind_finalize (GObject *object);
|
||||
|
||||
static GimpColorDisplay * cdisplay_colorblind_clone (GimpColorDisplay *display);
|
||||
static void cdisplay_colorblind_convert (GimpColorDisplay *display,
|
||||
guchar *buf,
|
||||
gint w,
|
||||
gint h,
|
||||
gint bpp,
|
||||
gint bpl);
|
||||
static void cdisplay_colorblind_load_state (GimpColorDisplay *display,
|
||||
GimpParasite *state);
|
||||
static GimpParasite * cdisplay_colorblind_save_state (GimpColorDisplay *display);
|
||||
static GtkWidget * cdisplay_colorblind_configure (GimpColorDisplay *display);
|
||||
static void cdisplay_colorblind_configure_reset (GimpColorDisplay *display);
|
||||
|
||||
static void colorblind_deficiency_callback (GtkWidget *widget,
|
||||
CdisplayColorblind *colorblind);
|
||||
|
||||
|
||||
static const GimpModuleInfo cdisplay_colorblind_info =
|
||||
{
|
||||
N_("Colorblind display filter"),
|
||||
"Michael Natterer <mitch@gimp.org>",
|
||||
"v0.1",
|
||||
"(c) 2001, released under the GPL",
|
||||
"December 16, 2002"
|
||||
};
|
||||
|
||||
static GType cdisplay_colorblind_type = 0;
|
||||
static GimpColorDisplayClass *parent_class = NULL;
|
||||
|
||||
|
||||
G_MODULE_EXPORT const GimpModuleInfo *
|
||||
gimp_module_query (GTypeModule *module)
|
||||
{
|
||||
return &cdisplay_colorblind_info;
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT gboolean
|
||||
gimp_module_register (GTypeModule *module)
|
||||
{
|
||||
cdisplay_colorblind_get_type (module);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GType
|
||||
cdisplay_colorblind_get_type (GTypeModule *module)
|
||||
{
|
||||
if (! cdisplay_colorblind_type)
|
||||
{
|
||||
static const GTypeInfo select_info =
|
||||
{
|
||||
sizeof (CdisplayColorblindClass),
|
||||
(GBaseInitFunc) NULL,
|
||||
(GBaseFinalizeFunc) NULL,
|
||||
(GClassInitFunc) cdisplay_colorblind_class_init,
|
||||
NULL, /* class_finalize */
|
||||
NULL, /* class_data */
|
||||
sizeof (CdisplayColorblind),
|
||||
0, /* n_preallocs */
|
||||
(GInstanceInitFunc) cdisplay_colorblind_init,
|
||||
};
|
||||
|
||||
cdisplay_colorblind_type =
|
||||
g_type_module_register_type (module,
|
||||
GIMP_TYPE_COLOR_DISPLAY,
|
||||
"CdisplayColorblind",
|
||||
&select_info, 0);
|
||||
}
|
||||
|
||||
return cdisplay_colorblind_type;
|
||||
}
|
||||
|
||||
static void
|
||||
cdisplay_colorblind_class_init (CdisplayColorblindClass *klass)
|
||||
{
|
||||
GObjectClass *object_class;
|
||||
GimpColorDisplayClass *display_class;
|
||||
|
||||
object_class = G_OBJECT_CLASS (klass);
|
||||
display_class = GIMP_COLOR_DISPLAY_CLASS (klass);
|
||||
|
||||
parent_class = g_type_class_peek_parent (klass);
|
||||
|
||||
object_class->finalize = cdisplay_colorblind_finalize;
|
||||
|
||||
display_class->name = _("Colorblind");
|
||||
display_class->help_page = "modules/colorblind.html";
|
||||
display_class->clone = cdisplay_colorblind_clone;
|
||||
display_class->convert = cdisplay_colorblind_convert;
|
||||
display_class->load_state = cdisplay_colorblind_load_state;
|
||||
display_class->save_state = cdisplay_colorblind_save_state;
|
||||
display_class->configure = cdisplay_colorblind_configure;
|
||||
display_class->configure_reset = cdisplay_colorblind_configure_reset;
|
||||
}
|
||||
|
||||
static void
|
||||
cdisplay_colorblind_init (CdisplayColorblind *colorblind)
|
||||
{
|
||||
colorblind->deficiency = DEFAULT_DEFICIENCY;
|
||||
}
|
||||
|
||||
static void
|
||||
cdisplay_colorblind_finalize (GObject *object)
|
||||
{
|
||||
CdisplayColorblind *colorblind;
|
||||
|
||||
colorblind = CDISPLAY_COLORBLIND (object);
|
||||
|
||||
if (colorblind->hbox)
|
||||
gtk_widget_destroy (colorblind->hbox);
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
|
||||
static GimpColorDisplay *
|
||||
cdisplay_colorblind_clone (GimpColorDisplay *display)
|
||||
{
|
||||
CdisplayColorblind *colorblind;
|
||||
CdisplayColorblind *copy;
|
||||
|
||||
colorblind = CDISPLAY_COLORBLIND (display);
|
||||
|
||||
copy = CDISPLAY_COLORBLIND (gimp_color_display_new (G_TYPE_FROM_INSTANCE (colorblind)));
|
||||
|
||||
copy->deficiency = colorblind->deficiency;
|
||||
|
||||
return GIMP_COLOR_DISPLAY (copy);
|
||||
}
|
||||
|
||||
static void
|
||||
cdisplay_colorblind_convert (GimpColorDisplay *display,
|
||||
guchar *buf,
|
||||
gint width,
|
||||
gint height,
|
||||
gint bpp,
|
||||
gint bpl)
|
||||
{
|
||||
CdisplayColorblind *colorblind;
|
||||
gint i, j;
|
||||
guchar *b;
|
||||
guchar red, green, blue;
|
||||
|
||||
colorblind = CDISPLAY_COLORBLIND (display);
|
||||
|
||||
if (bpp != 3)
|
||||
return;
|
||||
|
||||
j = height;
|
||||
|
||||
while (j--)
|
||||
{
|
||||
i = width;
|
||||
b = buf;
|
||||
|
||||
switch (colorblind->deficiency)
|
||||
{
|
||||
case COLORBLIND_DEFICIENCY_FOO:
|
||||
while (i--)
|
||||
{
|
||||
red = b[0] >> 1;
|
||||
green = b[1] >> 1;
|
||||
|
||||
b[0] = red + green;
|
||||
b[1] = red + green;
|
||||
/* b[2] = b[2]; */
|
||||
|
||||
b += bpp;
|
||||
}
|
||||
break;
|
||||
|
||||
case COLORBLIND_DEFICIENCY_BAR:
|
||||
while (i--)
|
||||
{
|
||||
red = b[0];
|
||||
green = b[1];
|
||||
blue = b[2];
|
||||
|
||||
b[0] = green;
|
||||
b[1] = blue;
|
||||
b[2] = red;
|
||||
|
||||
b += bpp;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
buf += bpl;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cdisplay_colorblind_load_state (GimpColorDisplay *display,
|
||||
GimpParasite *state)
|
||||
{
|
||||
CdisplayColorblind *colorblind;
|
||||
gchar *str;
|
||||
|
||||
colorblind = CDISPLAY_COLORBLIND (display);
|
||||
|
||||
str = gimp_parasite_data (state);
|
||||
|
||||
if (str[gimp_parasite_data_size (state) - 1] == '\0')
|
||||
{
|
||||
gint deficiency;
|
||||
|
||||
if (sscanf (str, "%d", &deficiency) == 1)
|
||||
{
|
||||
if (deficiency >= COLORBLIND_DEFICIENCY_FOO &&
|
||||
deficiency <= COLORBLIND_DEFICIENCY_BAR)
|
||||
{
|
||||
colorblind->deficiency = deficiency;
|
||||
|
||||
gimp_color_display_changed (GIMP_COLOR_DISPLAY (colorblind));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static GimpParasite *
|
||||
cdisplay_colorblind_save_state (GimpColorDisplay *display)
|
||||
{
|
||||
CdisplayColorblind *colorblind;
|
||||
gchar buf[32];
|
||||
|
||||
colorblind = CDISPLAY_COLORBLIND (display);
|
||||
|
||||
g_snprintf (buf, sizeof (buf), "%d", colorblind->deficiency);
|
||||
|
||||
return gimp_parasite_new ("Display/Colorblind", GIMP_PARASITE_PERSISTENT,
|
||||
strlen (buf) + 1, buf);
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
cdisplay_colorblind_configure (GimpColorDisplay *display)
|
||||
{
|
||||
CdisplayColorblind *colorblind;
|
||||
GtkWidget *label;
|
||||
|
||||
colorblind = CDISPLAY_COLORBLIND (display);
|
||||
|
||||
if (colorblind->hbox)
|
||||
gtk_widget_destroy (colorblind->hbox);
|
||||
|
||||
colorblind->hbox = gtk_hbox_new (FALSE, 2);
|
||||
g_object_add_weak_pointer (G_OBJECT (colorblind->hbox),
|
||||
(gpointer) &colorblind->hbox);
|
||||
|
||||
label = gtk_label_new ( _("Color Deficiency Type:"));
|
||||
gtk_box_pack_start (GTK_BOX (colorblind->hbox), label, FALSE, FALSE, 0);
|
||||
gtk_widget_show (label);
|
||||
|
||||
colorblind->optionmenu =
|
||||
gimp_option_menu_new2 (FALSE,
|
||||
G_CALLBACK (colorblind_deficiency_callback),
|
||||
colorblind,
|
||||
GINT_TO_POINTER (colorblind->deficiency),
|
||||
|
||||
"FIXME: formula from bug #101256",
|
||||
GINT_TO_POINTER (COLORBLIND_DEFICIENCY_FOO),
|
||||
NULL,
|
||||
|
||||
"FIXME: random test formula",
|
||||
GINT_TO_POINTER (COLORBLIND_DEFICIENCY_BAR),
|
||||
NULL,
|
||||
|
||||
NULL);
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (colorblind->hbox), colorblind->optionmenu,
|
||||
FALSE, FALSE, 0);
|
||||
gtk_widget_show (colorblind->optionmenu);
|
||||
|
||||
return colorblind->hbox;
|
||||
}
|
||||
|
||||
static void
|
||||
cdisplay_colorblind_configure_reset (GimpColorDisplay *display)
|
||||
{
|
||||
CdisplayColorblind *colorblind;
|
||||
|
||||
colorblind = CDISPLAY_COLORBLIND (display);
|
||||
|
||||
if (colorblind->optionmenu)
|
||||
{
|
||||
gimp_option_menu_set_history (GTK_OPTION_MENU (colorblind->optionmenu),
|
||||
GINT_TO_POINTER (DEFAULT_DEFICIENCY));
|
||||
colorblind->deficiency = DEFAULT_DEFICIENCY;
|
||||
|
||||
gimp_color_display_changed (GIMP_COLOR_DISPLAY (colorblind));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
colorblind_deficiency_callback (GtkWidget *widget,
|
||||
CdisplayColorblind *colorblind)
|
||||
{
|
||||
gimp_menu_item_update (widget, &colorblind->deficiency);
|
||||
|
||||
gimp_color_display_changed (GIMP_COLOR_DISPLAY (colorblind));
|
||||
}
|
Reference in New Issue
Block a user