home *** CD-ROM | disk | FTP | other *** search
- /* The GIMP -- an image manipulation program
- * Copyright (C) 1995 Spencer Kimball and Peter Mattis
- *
- * 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 <gtk/gtk.h>
-
- #include "apptypes.h"
-
- #include "appenv.h"
- #include "cursorutil.h"
- #include "drawable.h"
- #include "gdisplay.h"
- #include "gimphistogram.h"
- #include "gimpui.h"
- #include "curves.h"
- #include "gimplut.h"
-
- #include "libgimp/gimpenv.h"
- #include "libgimp/gimpmath.h"
-
- #include "libgimp/gimpintl.h"
-
- #define GRAPH 0x1
- #define XRANGE_TOP 0x2
- #define XRANGE_BOTTOM 0x4
- #define YRANGE 0x8
- #define DRAW 0x10
- #define ALL 0xFF
-
- /* NB: take care when changing these values: make sure the curve[] array in
- * curves.h is large enough.
- */
- #define GRAPH_WIDTH 256
- #define GRAPH_HEIGHT 256
- #define XRANGE_WIDTH 256
- #define XRANGE_HEIGHT 16
- #define YRANGE_WIDTH 16
- #define YRANGE_HEIGHT 256
- #define RADIUS 3
- #define MIN_DISTANCE 8
-
- #define RANGE_MASK GDK_EXPOSURE_MASK | \
- GDK_ENTER_NOTIFY_MASK
-
- #define GRAPH_MASK GDK_EXPOSURE_MASK | \
- GDK_POINTER_MOTION_MASK | \
- GDK_POINTER_MOTION_HINT_MASK | \
- GDK_ENTER_NOTIFY_MASK | \
- GDK_BUTTON_PRESS_MASK | \
- GDK_BUTTON_RELEASE_MASK | \
- GDK_BUTTON1_MOTION_MASK
-
- /* the curves structures */
-
- typedef struct _Curves Curves;
-
- struct _Curves
- {
- gint x, y; /* coords for last mouse click */
- };
-
- typedef gdouble CRMatrix[4][4];
-
- /* the curves tool options */
- static ToolOptions * curves_options = NULL;
-
- /* the curves dialog */
- static CurvesDialog * curves_dialog = NULL;
-
- /* the curves file dialog */
- static GtkWidget *file_dlg = NULL;
- static gboolean load_save;
-
- static GtkWidget *channel_items[5];
-
- static CRMatrix CR_basis =
- {
- { -0.5, 1.5, -1.5, 0.5 },
- { 1.0, -2.5, 2.0, -0.5 },
- { -0.5, 0.0, 0.5, 0.0 },
- { 0.0, 1.0, 0.0, 0.0 },
- };
-
-
- /* curves action functions */
-
- static void curves_button_press (Tool *, GdkEventButton *, gpointer);
- static void curves_button_release (Tool *, GdkEventButton *, gpointer);
- static void curves_motion (Tool *, GdkEventMotion *, gpointer);
- static void curves_control (Tool *, ToolAction, gpointer);
-
- static CurvesDialog * curves_dialog_new (void);
-
- static void curves_update (CurvesDialog *, int);
- static void curves_plot_curve (CurvesDialog *, int, int, int, int);
- static void curves_preview (CurvesDialog *);
-
- static void curves_channel_callback (GtkWidget *, gpointer);
-
- static void curves_smooth_callback (GtkWidget *, gpointer);
- static void curves_free_callback (GtkWidget *, gpointer);
-
- static void curves_channel_reset (int);
- static void curves_reset_callback (GtkWidget *, gpointer);
- static void curves_ok_callback (GtkWidget *, gpointer);
- static void curves_cancel_callback (GtkWidget *, gpointer);
- static void curves_load_callback (GtkWidget *, gpointer);
- static void curves_save_callback (GtkWidget *, gpointer);
- static void curves_preview_update (GtkWidget *, gpointer);
- static gint curves_xrange_events (GtkWidget *, GdkEvent *, CurvesDialog *);
- static gint curves_yrange_events (GtkWidget *, GdkEvent *, CurvesDialog *);
- static gint curves_graph_events (GtkWidget *, GdkEvent *, CurvesDialog *);
- static void curves_CR_compose (CRMatrix, CRMatrix, CRMatrix);
-
- static void file_dialog_create (GtkWidget *);
- static void file_dialog_ok_callback (GtkWidget *, gpointer);
- static void file_dialog_cancel_callback (GtkWidget *, gpointer);
-
- static gboolean curves_read_from_file (FILE *f);
- static void curves_write_to_file (FILE *f);
-
-
- /* curves machinery */
-
- gfloat
- curves_lut_func (CurvesDialog *cd,
- gint nchannels,
- gint channel,
- gfloat value)
- {
- gfloat f;
- gint index;
- gdouble inten;
- gint j;
-
- if (nchannels == 1)
- j = 0;
- else
- j = channel + 1;
-
- inten = value;
-
- /* For color images this runs through the loop with j = channel +1
- the first time and j = 0 the second time */
- /* For bw images this runs through the loop with j = 0 the first and
- only time */
- for (; j >= 0; j -= (channel + 1))
- {
- /* don't apply the overall curve to the alpha channel */
- if (j == 0 && (nchannels == 2 || nchannels == 4)
- && channel == nchannels -1)
- return inten;
-
- if (inten < 0.0)
- inten = cd->curve[j][0]/255.0;
- else if (inten >= 1.0)
- inten = cd->curve[j][255]/255.0;
- else /* interpolate the curve */
- {
- index = floor(inten * 255.0);
- f = inten*255.0 - index;
- inten = ((1.0 - f) * cd->curve[j][index ] +
- ( f) * cd->curve[j][index + 1] ) / 255.0;
- }
- }
- return inten;
- }
-
- static void
- curves_colour_update (Tool *tool,
- GDisplay *gdisp,
- GimpDrawable *drawable,
- gint x,
- gint y)
- {
- guchar *color;
- gint offx;
- gint offy;
- gint maxval;
- gboolean has_alpha;
- gboolean is_indexed;
- GimpImageType sample_type;
-
- if(!tool || tool->state != ACTIVE)
- return;
-
- drawable_offsets (drawable, &offx, &offy);
-
- x -= offx;
- y -= offy;
-
- if (!(color = image_map_get_color_at(curves_dialog->image_map, x, y)))
- return;
-
- sample_type = gimp_drawable_type (drawable);
- is_indexed = gimp_drawable_is_indexed (drawable);
- has_alpha = GIMP_IMAGE_TYPE_HAS_ALPHA (sample_type);
-
- curves_dialog->col_value[GIMP_HISTOGRAM_RED] = color[RED_PIX];
- curves_dialog->col_value[GIMP_HISTOGRAM_GREEN] = color[GREEN_PIX];
- curves_dialog->col_value[GIMP_HISTOGRAM_BLUE] = color[BLUE_PIX];
-
- if (has_alpha)
- {
- curves_dialog->col_value [GIMP_HISTOGRAM_ALPHA] = color[3];
- }
-
- if (is_indexed)
- curves_dialog->col_value [GIMP_HISTOGRAM_ALPHA] = color[4];
-
- maxval = MAX (color[RED_PIX], color[GREEN_PIX]);
- curves_dialog->col_value[GIMP_HISTOGRAM_VALUE] = MAX (maxval, color[BLUE_PIX]);
-
- g_free (color);
- }
-
- static void
- curves_add_point (GimpDrawable *drawable,
- gint x,
- gint y,
- gint cchan)
- {
- /* Add point onto the curve */
- gint closest_point = 0;
- gint distance;
- gint curvex;
- gint i;
-
- switch (curves_dialog->curve_type[cchan])
- {
- case SMOOTH:
- curvex = curves_dialog->col_value[cchan];
- distance = G_MAXINT;
- for (i = 0; i < 17; i++)
- {
- if (curves_dialog->points[cchan][i][0] != -1)
- if (abs (curvex - curves_dialog->points[cchan][i][0]) < distance)
- {
- distance = abs (curvex - curves_dialog->points[cchan][i][0]);
- closest_point = i;
- }
- }
-
- if (distance > MIN_DISTANCE)
- closest_point = (curvex + 8) / 16;
-
- curves_dialog->points[cchan][closest_point][0] = curvex;
- curves_dialog->points[cchan][closest_point][1] = curves_dialog->curve[cchan][curvex];
- break;
-
- case GFREE:
- curves_dialog->curve[cchan][x] = 255 - y;
- break;
- }
- }
-
- /* curves action functions */
-
- static void
- curves_button_press (Tool *tool,
- GdkEventButton *bevent,
- gpointer gdisp_ptr)
- {
- gint x, y;
- GDisplay *gdisp;
- GimpDrawable *drawable;
-
- gdisp = gdisp_ptr;
- drawable = gimage_active_drawable (gdisp->gimage);
-
- tool->gdisp_ptr = gdisp;
-
- if (drawable != tool->drawable)
- {
- active_tool->preserve = TRUE;
- image_map_abort (curves_dialog->image_map);
- active_tool->preserve = FALSE;
-
- tool->drawable = drawable;
-
- curves_dialog->drawable = drawable;
- curves_dialog->color = drawable_color (drawable);
- curves_dialog->image_map = image_map_create (gdisp, drawable);
- }
-
- tool->state = ACTIVE;
-
- gdisplay_untransform_coords (gdisp, bevent->x, bevent->y, &x, &y,
- FALSE, FALSE);
- curves_colour_update (tool, gdisp, drawable, x, y);
- curves_update (curves_dialog, GRAPH | DRAW);
- }
-
- static void
- curves_button_release (Tool *tool,
- GdkEventButton *bevent,
- gpointer gdisp_ptr)
- {
- gint x, y;
- GimpDrawable *drawable;
- GDisplay *gdisp;
-
- gdisp = (GDisplay *) gdisp_ptr;
-
- if(!curves_dialog ||
- !gdisp ||
- !(drawable = gimage_active_drawable (gdisp->gimage)))
- return;
-
- gdisplay_untransform_coords (gdisp, bevent->x, bevent->y, &x, &y, FALSE, FALSE);
- curves_colour_update (tool, gdisp, drawable, x, y);
-
- if (bevent->state & GDK_SHIFT_MASK)
- {
- curves_add_point (drawable, x, y, curves_dialog->channel);
- curves_calculate_curve (curves_dialog);
- }
- else if (bevent->state & GDK_CONTROL_MASK)
- {
- curves_add_point (drawable, x, y, GIMP_HISTOGRAM_VALUE);
- curves_add_point (drawable, x, y, GIMP_HISTOGRAM_RED);
- curves_add_point (drawable, x, y, GIMP_HISTOGRAM_GREEN);
- curves_add_point (drawable, x, y, GIMP_HISTOGRAM_BLUE);
- curves_add_point (drawable, x, y, GIMP_HISTOGRAM_ALPHA);
- curves_calculate_curve (curves_dialog);
- }
-
- curves_update (curves_dialog, GRAPH | DRAW);
- }
-
- static void
- curves_motion (Tool *tool,
- GdkEventMotion *mevent,
- gpointer gdisp_ptr)
- {
- gint x, y;
- GDisplay *gdisp;
- GimpDrawable *drawable;
-
- gdisp = (GDisplay *) gdisp_ptr;
-
- if(!curves_dialog ||
- !gdisp ||
- !(drawable = gimage_active_drawable (gdisp->gimage)))
- return;
-
- gdisplay_untransform_coords (gdisp, mevent->x, mevent->y, &x, &y, FALSE, FALSE);
- curves_colour_update (tool, gdisp, drawable, x, y);
- curves_update (curves_dialog, GRAPH | DRAW);
- }
-
- static void
- curves_control (Tool *tool,
- ToolAction action,
- gpointer gdisp_ptr)
- {
- switch (action)
- {
- case PAUSE:
- break;
-
- case RESUME:
- break;
-
- case HALT:
- curves_dialog_hide ();
- break;
-
- default:
- break;
- }
- }
-
- Tool *
- tools_new_curves (void)
- {
- Tool *tool;
- Curves *private;
-
- /* The tool options */
- if (!curves_options)
- {
- curves_options = tool_options_new (_("Curves"));
- tools_register (CURVES, curves_options);
- }
-
- tool = tools_new_tool (CURVES);
- private = g_new0 (Curves, 1);
-
- tool->scroll_lock = TRUE; /* Disallow scrolling */
- tool->preserve = FALSE; /* Don't preserve on drawable change */
-
- tool->private = (void *) private;
-
- tool->button_press_func = curves_button_press;
- tool->button_release_func = curves_button_release;
- tool->motion_func = curves_motion;
- tool->control_func = curves_control;
-
- return tool;
- }
-
- void
- curves_dialog_hide (void)
- {
- if (curves_dialog)
- curves_cancel_callback (NULL, (gpointer) curves_dialog);
- }
-
- void
- tools_free_curves (Tool *tool)
- {
- Curves *private;
-
- private = (Curves *) tool->private;
-
- /* Close the color select dialog */
- curves_dialog_hide ();
-
- g_free (private);
- }
-
- void
- curves_initialize (GDisplay *gdisp)
- {
- gint i, j;
-
- if (drawable_indexed (gimage_active_drawable (gdisp->gimage)))
- {
- g_message (_("Curves for indexed drawables cannot be adjusted."));
- return;
- }
-
- /* The curves dialog */
- if (!curves_dialog)
- {
- curves_dialog = curves_dialog_new ();
- }
-
- /* Initialize the values */
- curves_dialog->channel = GIMP_HISTOGRAM_VALUE;
- for (i = 0; i < 5; i++)
- for (j = 0; j < 256; j++)
- curves_dialog->curve[i][j] = j;
-
- for (i = 0; i < 5; i++)
- {
- curves_channel_reset (i);
- }
-
- curves_dialog->drawable = gimage_active_drawable (gdisp->gimage);
- curves_dialog->color = drawable_color (curves_dialog->drawable);
- curves_dialog->image_map = image_map_create (gdisp, curves_dialog->drawable);
-
- /* check for alpha channel */
- if (drawable_has_alpha (curves_dialog->drawable))
- gtk_widget_set_sensitive (channel_items[4], TRUE);
- else
- gtk_widget_set_sensitive (channel_items[4], FALSE);
-
- /* hide or show the channel menu based on image type */
- if (curves_dialog->color)
- for (i = 0; i < 4; i++)
- gtk_widget_set_sensitive (channel_items[i], TRUE);
- else
- for (i = 1; i < 4; i++)
- gtk_widget_set_sensitive (channel_items[i], FALSE);
-
- /* set the current selection */
- gtk_option_menu_set_history (GTK_OPTION_MENU (curves_dialog->channel_menu),
- curves_dialog->channel);
-
- gimp_lut_setup (curves_dialog->lut,
- (GimpLutFunc) curves_lut_func,
- (void *) curves_dialog,
- gimp_drawable_bytes (curves_dialog->drawable));
-
- if (!GTK_WIDGET_VISIBLE (curves_dialog->shell))
- gtk_widget_show (curves_dialog->shell);
-
- curves_update (curves_dialog, GRAPH | DRAW);
- }
-
- void
- curves_free (void)
- {
- if (curves_dialog)
- {
- if (curves_dialog->image_map)
- {
- active_tool->preserve = TRUE;
- image_map_abort (curves_dialog->image_map);
- active_tool->preserve = FALSE;
-
- curves_dialog->image_map = NULL;
- }
-
- if (curves_dialog->pixmap)
- gdk_pixmap_unref (curves_dialog->pixmap);
-
- gtk_widget_destroy (curves_dialog->shell);
- }
- }
-
- /*******************/
- /* Curves dialog */
- /*******************/
-
- static CurvesDialog *
- curves_dialog_new (void)
- {
- CurvesDialog *cd;
- GtkWidget *vbox;
- GtkWidget *hbox;
- GtkWidget *hbbox;
- GtkWidget *label;
- GtkWidget *frame;
- GtkWidget *toggle;
- GtkWidget *channel_hbox;
- GtkWidget *table;
- GtkWidget *button;
- gint i, j;
-
- cd = g_new (CurvesDialog, 1);
- cd->cursor_ind_height = -1;
- cd->cursor_ind_width = -1;
- cd->preview = TRUE;
- cd->pixmap = NULL;
- cd->channel = GIMP_HISTOGRAM_VALUE;
-
- for (i = 0; i < 5; i++)
- cd->curve_type[i] = SMOOTH;
-
- for (i = 0; i < 5; i++)
- for (j = 0; j < 256; j++)
- cd->curve[i][j] = j;
-
- for (i = 0; i < (sizeof (cd->col_value) / sizeof (cd->col_value[0])); i++)
- cd->col_value[i] = 0;
-
- cd->lut = gimp_lut_new ();
-
- /* The shell and main vbox */
- cd->shell = gimp_dialog_new (_("Curves"), "curves",
- tools_help_func, tool_info[CURVES].private_tip,
- GTK_WIN_POS_NONE,
- FALSE, TRUE, FALSE,
-
- _("OK"), curves_ok_callback,
- cd, NULL, NULL, TRUE, FALSE,
- _("Reset"), curves_reset_callback,
- cd, NULL, NULL, FALSE, FALSE,
- _("Cancel"), curves_cancel_callback,
- cd, NULL, NULL, FALSE, TRUE,
-
- NULL);
-
- vbox = gtk_vbox_new (FALSE, 4);
- gtk_container_set_border_width (GTK_CONTAINER (vbox), 4);
- gtk_container_add (GTK_CONTAINER (GTK_DIALOG (cd->shell)->vbox), vbox);
-
- /* The option menu for selecting channels */
- channel_hbox = gtk_hbox_new (FALSE, 4);
- gtk_box_pack_start (GTK_BOX (vbox), channel_hbox, FALSE, FALSE, 0);
-
- label = gtk_label_new (_("Modify Curves for Channel:"));
- gtk_box_pack_start (GTK_BOX (channel_hbox), label, FALSE, FALSE, 0);
-
- cd->channel_menu = gimp_option_menu_new2
- (FALSE, curves_channel_callback,
- cd, (gpointer) cd->channel,
-
- _("Value"), (gpointer) GIMP_HISTOGRAM_VALUE, &channel_items[0],
- _("Red"), (gpointer) GIMP_HISTOGRAM_RED, &channel_items[1],
- _("Green"), (gpointer) GIMP_HISTOGRAM_GREEN, &channel_items[2],
- _("Blue"), (gpointer) GIMP_HISTOGRAM_BLUE, &channel_items[3],
- _("Alpha"), (gpointer) GIMP_HISTOGRAM_ALPHA, &channel_items[4],
-
- NULL);
-
- gtk_box_pack_start (GTK_BOX (channel_hbox), cd->channel_menu, FALSE, FALSE, 2);
-
- gtk_widget_show (label);
- gtk_widget_show (cd->channel_menu);
- gtk_widget_show (channel_hbox);
-
- /* The table for the yrange and the graph */
- table = gtk_table_new (2, 2, FALSE);
- gtk_table_set_col_spacings (GTK_TABLE (table), 2);
- gtk_table_set_row_spacings (GTK_TABLE (table), 2);
- gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
-
- /* The range drawing area */
- frame = gtk_frame_new (NULL);
- gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
- gtk_table_attach (GTK_TABLE (table), frame, 0, 1, 0, 1,
- GTK_EXPAND, GTK_EXPAND, 0, 0);
-
- cd->yrange = gtk_preview_new (GTK_PREVIEW_COLOR);
- gtk_preview_size (GTK_PREVIEW (cd->yrange), YRANGE_WIDTH, YRANGE_HEIGHT);
- gtk_widget_set_events (cd->yrange, RANGE_MASK);
- gtk_container_add (GTK_CONTAINER (frame), cd->yrange);
-
- gtk_signal_connect (GTK_OBJECT (cd->yrange), "event",
- GTK_SIGNAL_FUNC (curves_yrange_events),
- cd);
-
- gtk_widget_show (cd->yrange);
- gtk_widget_show (frame);
-
- /* The curves graph */
- frame = gtk_frame_new (NULL);
- gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
- gtk_table_attach (GTK_TABLE (table), frame, 1, 2, 0, 1,
- GTK_SHRINK | GTK_FILL,
- GTK_SHRINK | GTK_FILL, 0, 0);
-
- cd->graph = gtk_drawing_area_new ();
- gtk_drawing_area_size (GTK_DRAWING_AREA (cd->graph),
- GRAPH_WIDTH + RADIUS * 2,
- GRAPH_HEIGHT + RADIUS * 2);
- gtk_widget_set_events (cd->graph, GRAPH_MASK);
- gtk_container_add (GTK_CONTAINER (frame), cd->graph);
-
- gtk_signal_connect (GTK_OBJECT (cd->graph), "event",
- GTK_SIGNAL_FUNC (curves_graph_events),
- cd);
-
- gtk_widget_show (cd->graph);
- gtk_widget_show (frame);
-
- /* The range drawing area */
- frame = gtk_frame_new (NULL);
- gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
- gtk_table_attach (GTK_TABLE (table), frame, 1, 2, 1, 2,
- GTK_EXPAND, GTK_EXPAND, 0, 0);
-
- cd->xrange = gtk_preview_new (GTK_PREVIEW_COLOR);
- gtk_preview_size (GTK_PREVIEW (cd->xrange), XRANGE_WIDTH, XRANGE_HEIGHT);
- gtk_widget_set_events (cd->xrange, RANGE_MASK);
- gtk_container_add (GTK_CONTAINER (frame), cd->xrange);
-
- gtk_signal_connect (GTK_OBJECT (cd->xrange), "event",
- GTK_SIGNAL_FUNC (curves_xrange_events),
- cd);
-
- gtk_widget_show (cd->xrange);
- gtk_widget_show (frame);
- gtk_widget_show (table);
-
- /* Horizontal box for preview */
- hbox = gtk_hbox_new (FALSE, 4);
- gtk_box_pack_end (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
-
- /* The option menu for selecting the drawing method */
- label = gtk_label_new (_("Curve Type:"));
- gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
- gtk_widget_show (label);
-
- cd->curve_type_menu = gimp_option_menu_new
- (FALSE,
-
- _("Smooth"), curves_smooth_callback, cd, NULL, NULL, TRUE,
- _("Free"), curves_free_callback, cd, NULL, NULL, FALSE,
-
- NULL);
- gtk_box_pack_start (GTK_BOX (hbox), cd->curve_type_menu, FALSE, FALSE, 2);
- gtk_widget_show (cd->curve_type_menu);
-
- gtk_widget_show (hbox);
-
- /* The preview toggle */
- toggle = gtk_check_button_new_with_label (_("Preview"));
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), cd->preview);
- gtk_box_pack_end (GTK_BOX (hbox), toggle, FALSE, FALSE, 0);
-
- gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
- GTK_SIGNAL_FUNC (curves_preview_update),
- cd);
-
- gtk_widget_show (toggle);
- gtk_widget_show (hbox);
-
- /* Horizontal button box for load / save */
- hbbox = gtk_hbutton_box_new ();
- gtk_button_box_set_spacing (GTK_BUTTON_BOX (hbbox), 4);
- gtk_button_box_set_layout (GTK_BUTTON_BOX (hbbox), GTK_BUTTONBOX_SPREAD);
- gtk_box_pack_end (GTK_BOX (vbox), hbbox, FALSE, FALSE, 0);
-
- button = gtk_button_new_with_label (_("Load"));
- GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
- gtk_box_pack_start (GTK_BOX (hbbox), button, FALSE, FALSE, 0);
- gtk_signal_connect (GTK_OBJECT (button), "clicked",
- GTK_SIGNAL_FUNC (curves_load_callback),
- cd->shell);
- gtk_widget_show (button);
-
- button = gtk_button_new_with_label (_("Save"));
- GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
- gtk_box_pack_start (GTK_BOX (hbbox), button, FALSE, FALSE, 0);
- gtk_signal_connect (GTK_OBJECT (button), "clicked",
- GTK_SIGNAL_FUNC (curves_save_callback),
- cd->shell);
- gtk_widget_show (button);
-
- gtk_widget_show (hbbox);
- gtk_widget_show (vbox);
-
- return cd;
- }
-
- static void
- curve_print_loc (CurvesDialog *cd,
- gint xpos,
- gint ypos)
- {
- gchar buf[32];
- gint width;
- gint ascent;
- gint descent;
-
- if (cd->cursor_ind_width < 0)
- {
- /* Calc max extents */
- gdk_string_extents (cd->graph->style->font,
- "x:888 y:888",
- NULL,
- NULL,
- &width,
- &ascent,
- &descent);
-
- cd->cursor_ind_width = width;
- cd->cursor_ind_height = ascent + descent;
- cd->cursor_ind_ascent = ascent;
- }
-
- if (xpos >= 0 && xpos <= 255 && ypos >=0 && ypos <= 255)
- {
- g_snprintf (buf, sizeof (buf), "x:%d y:%d",xpos,ypos);
-
- gdk_draw_rectangle (cd->graph->window,
- cd->graph->style->bg_gc[GTK_STATE_ACTIVE],
- TRUE, RADIUS*2 + 2 , RADIUS*2 + 2,
- cd->cursor_ind_width+4,
- cd->cursor_ind_height+5);
-
- gdk_draw_rectangle (cd->graph->window,
- cd->graph->style->black_gc,
- FALSE, RADIUS*2 + 2 , RADIUS*2 + 2,
- cd->cursor_ind_width+3,
- cd->cursor_ind_height+4);
-
- gdk_draw_string (cd->graph->window,
- cd->graph->style->font,
- cd->graph->style->black_gc,
- RADIUS*2 + 4,
- RADIUS*2 + 5 + cd->cursor_ind_ascent,
- buf);
- }
- }
-
- /* TODO: preview alpha channel stuff correctly. -- austin, 20/May/99 */
- static void
- curves_update (CurvesDialog *cd,
- gint update)
- {
- GdkRectangle area;
- gint i, j;
- gchar buf[32];
- gint offset;
- gint sel_channel;
-
- if(cd->color) {
- sel_channel = cd->channel;
- } else {
- if(cd->channel == 2)
- sel_channel = GIMP_HISTOGRAM_ALPHA;
- else
- sel_channel = GIMP_HISTOGRAM_VALUE;
- }
-
-
- if (update & XRANGE_TOP)
- {
- guchar buf[XRANGE_WIDTH * 3];
-
- switch (sel_channel)
- {
- case GIMP_HISTOGRAM_VALUE:
- case GIMP_HISTOGRAM_ALPHA:
- for (i = 0; i < XRANGE_HEIGHT / 2; i++)
- {
- for (j = 0; j < XRANGE_WIDTH ; j++)
- {
- buf[j*3+0] = cd->curve[sel_channel][j];
- buf[j*3+1] = cd->curve[sel_channel][j];
- buf[j*3+2] = cd->curve[sel_channel][j];
- }
- gtk_preview_draw_row (GTK_PREVIEW (cd->xrange),
- buf, 0, i, XRANGE_WIDTH);
- }
- break;
-
- case GIMP_HISTOGRAM_RED:
- case GIMP_HISTOGRAM_GREEN:
- case GIMP_HISTOGRAM_BLUE:
- {
- for (i = 0; i < XRANGE_HEIGHT / 2; i++)
- {
- for (j = 0; j < XRANGE_WIDTH; j++)
- {
- buf[j*3+0] = cd->curve[GIMP_HISTOGRAM_RED][j];
- buf[j*3+1] = cd->curve[GIMP_HISTOGRAM_GREEN][j];
- buf[j*3+2] = cd->curve[GIMP_HISTOGRAM_BLUE][j];
- }
- gtk_preview_draw_row (GTK_PREVIEW (cd->xrange),
- buf, 0, i, XRANGE_WIDTH);
- }
- break;
- }
-
- default:
- g_warning ("unknown channel type %d, can't happen!?!?",
- cd->channel);
- break;
- }
-
- if (update & DRAW)
- {
- area.x = 0;
- area.y = 0;
- area.width = XRANGE_WIDTH;
- area.height = XRANGE_HEIGHT / 2;
- gtk_widget_draw (cd->xrange, &area);
- }
- }
- if (update & XRANGE_BOTTOM)
- {
- guchar buf[XRANGE_WIDTH * 3];
-
- for (i = 0; i < XRANGE_WIDTH; i++)
- {
- buf[i*3+0] = i;
- buf[i*3+1] = i;
- buf[i*3+2] = i;
- }
-
- for (i = XRANGE_HEIGHT / 2; i < XRANGE_HEIGHT; i++)
- gtk_preview_draw_row (GTK_PREVIEW (cd->xrange), buf, 0, i, XRANGE_WIDTH);
-
- if (update & DRAW)
- {
- area.x = 0;
- area.y = XRANGE_HEIGHT / 2;
- area.width = XRANGE_WIDTH;
- area.height = XRANGE_HEIGHT / 2;
- gtk_widget_draw (cd->xrange, &area);
- }
- }
- if (update & YRANGE)
- {
- guchar buf[YRANGE_WIDTH * 3];
- guchar pix[3];
-
- for (i = 0; i < YRANGE_HEIGHT; i++)
- {
- switch (sel_channel)
- {
- case GIMP_HISTOGRAM_VALUE:
- case GIMP_HISTOGRAM_ALPHA:
- pix[0] = pix[1] = pix[2] = (255 - i);
- break;
-
- case GIMP_HISTOGRAM_RED:
- case GIMP_HISTOGRAM_GREEN:
- case GIMP_HISTOGRAM_BLUE:
- pix[0] = pix[1] = pix[2] = 0;
- pix[sel_channel - 1] = (255 - i);
- break;
-
- default:
- g_warning ("unknown channel type %d, can't happen!?!?",
- cd->channel);
- break;
- }
-
- for (j = 0; j < YRANGE_WIDTH * 3; j++)
- buf[j] = pix[j%3];
-
- gtk_preview_draw_row (GTK_PREVIEW (cd->yrange),
- buf, 0, i, YRANGE_WIDTH);
- }
-
- if (update & DRAW)
- gtk_widget_draw (cd->yrange, NULL);
- }
- if ((update & GRAPH) && (update & DRAW) && cd->pixmap != NULL)
- {
- GdkPoint points[256];
-
- /* Clear the pixmap */
- gdk_draw_rectangle (cd->pixmap, cd->graph->style->bg_gc[GTK_STATE_NORMAL],
- TRUE, 0, 0,
- GRAPH_WIDTH + RADIUS * 2, GRAPH_HEIGHT + RADIUS * 2);
-
- /* Draw the grid lines */
- for (i = 0; i < 5; i++)
- {
- gdk_draw_line (cd->pixmap, cd->graph->style->dark_gc[GTK_STATE_NORMAL],
- RADIUS, i * (GRAPH_HEIGHT / 4) + RADIUS,
- GRAPH_WIDTH + RADIUS, i * (GRAPH_HEIGHT / 4) + RADIUS);
- gdk_draw_line (cd->pixmap, cd->graph->style->dark_gc[GTK_STATE_NORMAL],
- i * (GRAPH_WIDTH / 4) + RADIUS, RADIUS,
- i * (GRAPH_WIDTH / 4) + RADIUS, GRAPH_HEIGHT + RADIUS);
- }
-
- /* Draw the curve */
- for (i = 0; i < 256; i++)
- {
- points[i].x = i + RADIUS;
- points[i].y = 255 - cd->curve[cd->channel][i] + RADIUS;
- }
- gdk_draw_points (cd->pixmap, cd->graph->style->black_gc, points, 256);
-
- /* Draw the points */
- if (cd->curve_type[cd->channel] == SMOOTH)
- for (i = 0; i < 17; i++)
- {
- if (cd->points[cd->channel][i][0] != -1)
- gdk_draw_arc (cd->pixmap, cd->graph->style->black_gc, TRUE,
- cd->points[cd->channel][i][0],
- 255 - cd->points[cd->channel][i][1],
- RADIUS * 2, RADIUS * 2, 0, 23040);
- }
-
- /* draw the colour line */
- gdk_draw_line (cd->pixmap, cd->graph->style->black_gc,
- cd->col_value[sel_channel]+RADIUS,RADIUS,
- cd->col_value[sel_channel]+RADIUS,GRAPH_HEIGHT + RADIUS);
-
- /* and xpos indicator */
- g_snprintf (buf, sizeof (buf), "x:%d",cd->col_value[sel_channel]);
-
- if ((cd->col_value[sel_channel]+RADIUS) < 127)
- {
- offset = RADIUS + 4;
- }
- else
- {
- offset = - gdk_string_width (cd->graph->style->font,buf) - 2;
- }
-
- gdk_draw_string (cd->pixmap,
- cd->graph->style->font,
- cd->graph->style->black_gc,
- cd->col_value[sel_channel]+offset,
- GRAPH_HEIGHT,
- buf);
-
- gdk_draw_pixmap (cd->graph->window, cd->graph->style->black_gc, cd->pixmap,
- 0, 0, 0, 0, GRAPH_WIDTH + RADIUS * 2, GRAPH_HEIGHT + RADIUS * 2);
-
- }
- }
-
- static void
- curves_plot_curve (CurvesDialog *cd,
- gint p1,
- gint p2,
- gint p3,
- gint p4)
- {
- CRMatrix geometry;
- CRMatrix tmp1, tmp2;
- CRMatrix deltas;
- gdouble x, dx, dx2, dx3;
- gdouble y, dy, dy2, dy3;
- gdouble d, d2, d3;
- gint lastx, lasty;
- gint32 newx, newy;
- gint i;
-
- /* construct the geometry matrix from the segment */
- for (i = 0; i < 4; i++)
- {
- geometry[i][2] = 0;
- geometry[i][3] = 0;
- }
-
- for (i = 0; i < 2; i++)
- {
- geometry[0][i] = cd->points[cd->channel][p1][i];
- geometry[1][i] = cd->points[cd->channel][p2][i];
- geometry[2][i] = cd->points[cd->channel][p3][i];
- geometry[3][i] = cd->points[cd->channel][p4][i];
- }
-
- /* subdivide the curve 1000 times */
- /* n can be adjusted to give a finer or coarser curve */
- d = 1.0 / 1000;
- d2 = d * d;
- d3 = d * d * d;
-
- /* construct a temporary matrix for determining the forward differencing deltas */
- tmp2[0][0] = 0; tmp2[0][1] = 0; tmp2[0][2] = 0; tmp2[0][3] = 1;
- tmp2[1][0] = d3; tmp2[1][1] = d2; tmp2[1][2] = d; tmp2[1][3] = 0;
- tmp2[2][0] = 6*d3; tmp2[2][1] = 2*d2; tmp2[2][2] = 0; tmp2[2][3] = 0;
- tmp2[3][0] = 6*d3; tmp2[3][1] = 0; tmp2[3][2] = 0; tmp2[3][3] = 0;
-
- /* compose the basis and geometry matrices */
- curves_CR_compose (CR_basis, geometry, tmp1);
-
- /* compose the above results to get the deltas matrix */
- curves_CR_compose (tmp2, tmp1, deltas);
-
- /* extract the x deltas */
- x = deltas[0][0];
- dx = deltas[1][0];
- dx2 = deltas[2][0];
- dx3 = deltas[3][0];
-
- /* extract the y deltas */
- y = deltas[0][1];
- dy = deltas[1][1];
- dy2 = deltas[2][1];
- dy3 = deltas[3][1];
-
- lastx = CLAMP (x, 0, 255);
- lasty = CLAMP (y, 0, 255);
-
- cd->curve[cd->channel][lastx] = lasty;
-
- /* loop over the curve */
- for (i = 0; i < 1000; i++)
- {
- /* increment the x values */
- x += dx;
- dx += dx2;
- dx2 += dx3;
-
- /* increment the y values */
- y += dy;
- dy += dy2;
- dy2 += dy3;
-
- newx = CLAMP0255 (ROUND (x));
- newy = CLAMP0255 (ROUND (y));
-
- /* if this point is different than the last one...then draw it */
- if ((lastx != newx) || (lasty != newy))
- cd->curve[cd->channel][newx] = newy;
-
- lastx = newx;
- lasty = newy;
- }
- }
-
- void
- curves_calculate_curve (CurvesDialog *cd)
- {
- gint i;
- gint points[17];
- gint num_pts;
- gint p1, p2, p3, p4;
-
- switch (cd->curve_type[cd->channel])
- {
- case GFREE:
- break;
- case SMOOTH:
- /* cycle through the curves */
- num_pts = 0;
- for (i = 0; i < 17; i++)
- if (cd->points[cd->channel][i][0] != -1)
- points[num_pts++] = i;
-
- /* Initialize boundary curve points */
- if (num_pts != 0)
- {
- for (i = 0; i < cd->points[cd->channel][points[0]][0]; i++)
- cd->curve[cd->channel][i] = cd->points[cd->channel][points[0]][1];
- for (i = cd->points[cd->channel][points[num_pts - 1]][0]; i < 256; i++)
- cd->curve[cd->channel][i] = cd->points[cd->channel][points[num_pts - 1]][1];
- }
-
- for (i = 0; i < num_pts - 1; i++)
- {
- p1 = (i == 0) ? points[i] : points[(i - 1)];
- p2 = points[i];
- p3 = points[(i + 1)];
- p4 = (i == (num_pts - 2)) ? points[(num_pts - 1)] : points[(i + 2)];
-
- curves_plot_curve (cd, p1, p2, p3, p4);
- }
- break;
- }
- gimp_lut_setup (cd->lut, (GimpLutFunc) curves_lut_func,
- (void *) cd, gimp_drawable_bytes (cd->drawable));
-
- }
-
- static void
- curves_preview (CurvesDialog *cd)
- {
- if (!cd->image_map)
- {
- g_message ("curves_preview(): No image map");
- return;
- }
-
- active_tool->preserve = TRUE;
- image_map_apply (cd->image_map, (ImageMapApplyFunc)gimp_lut_process_2,
- (void *) cd->lut);
- active_tool->preserve = FALSE;
- }
-
- static void
- curves_channel_callback (GtkWidget *widget,
- gpointer data)
- {
- CurvesDialog *cd;
-
- cd = (CurvesDialog *) data;
-
- gimp_menu_item_update (widget, &cd->channel);
-
- if(!cd->color) {
- if(cd->channel > 1)
- {
- cd->channel = 2;
- }
- else
- {
- cd->channel = 1;
- }
- }
-
- gtk_option_menu_set_history (GTK_OPTION_MENU (cd->curve_type_menu),
- cd->curve_type[cd->channel]);
-
- curves_update (cd, XRANGE_TOP | YRANGE | GRAPH | DRAW);
- }
-
- static void
- curves_smooth_callback (GtkWidget *widget,
- gpointer data)
- {
- CurvesDialog *cd;
- gint i;
- gint32 index;
-
- cd = (CurvesDialog *) data;
-
- if (cd->curve_type[cd->channel] != SMOOTH)
- {
- cd->curve_type[cd->channel] = SMOOTH;
-
- /* pick representative points from the curve and make them control points */
- for (i = 0; i <= 8; i++)
- {
- index = CLAMP0255 (i * 32);
- cd->points[cd->channel][i * 2][0] = index;
- cd->points[cd->channel][i * 2][1] = cd->curve[cd->channel][index];
- }
-
- curves_calculate_curve (cd);
- curves_update (cd, GRAPH | DRAW);
-
- if (cd->preview)
- curves_preview (cd);
- }
- }
-
- static void
- curves_free_callback (GtkWidget *widget,
- gpointer data)
- {
- CurvesDialog *cd;
-
- cd = (CurvesDialog *) data;
-
- if (cd->curve_type[cd->channel] != GFREE)
- {
- cd->curve_type[cd->channel] = GFREE;
- curves_calculate_curve (cd);
- curves_update (cd, GRAPH | DRAW);
-
- if (cd->preview)
- curves_preview (cd);
- }
- }
-
- static void
- curves_channel_reset (int i)
- {
- gint j;
-
- curves_dialog->grab_point = -1;
-
- for (j = 0; j < 17; j++)
- {
- curves_dialog->points[i][j][0] = -1;
- curves_dialog->points[i][j][1] = -1;
- }
- curves_dialog->points[i][0][0] = 0;
- curves_dialog->points[i][0][1] = 0;
- curves_dialog->points[i][16][0] = 255;
- curves_dialog->points[i][16][1] = 255;
- }
-
-
- static void
- curves_reset_callback (GtkWidget *widget,
- gpointer data)
- {
- CurvesDialog *cd;
- gint i;
-
- cd = (CurvesDialog *) data;
-
- /* Initialize the values */
- for (i = 0; i < 256; i++)
- cd->curve[cd->channel][i] = i;
-
- curves_channel_reset (cd->channel);
-
- curves_calculate_curve (cd);
- curves_update (cd, GRAPH | XRANGE_TOP | DRAW);
-
- if (cd->preview)
- curves_preview (cd);
- }
-
- static void
- curves_ok_callback (GtkWidget *widget,
- gpointer data)
- {
- CurvesDialog *cd;
-
- cd = (CurvesDialog *) data;
-
- gimp_dialog_hide (cd->shell);
-
- active_tool->preserve = TRUE; /* We're about to dirty... */
-
- if (!cd->preview)
- image_map_apply (cd->image_map, (ImageMapApplyFunc)gimp_lut_process_2,
- (void *) cd->lut);
-
- if (cd->image_map)
- image_map_commit (cd->image_map);
-
- active_tool->preserve = FALSE;
-
- cd->image_map = NULL;
-
- active_tool->gdisp_ptr = NULL;
- active_tool->drawable = NULL;
- }
-
- static void
- curves_cancel_callback (GtkWidget *widget,
- gpointer data)
- {
- CurvesDialog *cd;
-
- cd = (CurvesDialog *) data;
-
- gimp_dialog_hide (cd->shell);
-
- if (cd->image_map)
- {
- active_tool->preserve = TRUE;
- image_map_abort (cd->image_map);
- active_tool->preserve = FALSE;
-
- gdisplays_flush ();
- cd->image_map = NULL;
- }
-
- active_tool->gdisp_ptr = NULL;
- active_tool->drawable = NULL;
- }
-
- static void
- curves_load_callback (GtkWidget *widget,
- gpointer data)
- {
- if (!file_dlg)
- file_dialog_create (GTK_WIDGET (data));
- else if (GTK_WIDGET_VISIBLE (file_dlg))
- return;
-
- load_save = TRUE;
-
- gtk_window_set_title (GTK_WINDOW (file_dlg), _("Load Curves"));
- gtk_widget_show (file_dlg);
- }
-
- static void
- curves_save_callback (GtkWidget *widget,
- gpointer data)
- {
- if (!file_dlg)
- file_dialog_create (GTK_WIDGET (data));
- else if (GTK_WIDGET_VISIBLE (file_dlg))
- return;
-
- load_save = FALSE;
-
- gtk_window_set_title (GTK_WINDOW (file_dlg), _("Save Curves"));
- gtk_widget_show (file_dlg);
- }
-
- static void
- curves_preview_update (GtkWidget *widget,
- gpointer data)
- {
- CurvesDialog *cd;
-
- cd = (CurvesDialog *) data;
-
- if (GTK_TOGGLE_BUTTON (widget)->active)
- {
- cd->preview = TRUE;
- curves_preview (cd);
- }
- else
- {
- cd->preview = FALSE;
- if (cd->image_map)
- {
- active_tool->preserve = TRUE;
- image_map_clear (cd->image_map);
- active_tool->preserve = FALSE;
- gdisplays_flush ();
- }
- }
- }
-
- static gint
- curves_graph_events (GtkWidget *widget,
- GdkEvent *event,
- CurvesDialog *cd)
- {
- static GdkCursorType cursor_type = GDK_TOP_LEFT_ARROW;
- GdkCursorType new_type;
- GdkEventButton *bevent;
- GdkEventMotion *mevent;
- gint i;
- gint tx, ty;
- gint x, y;
- gint closest_point;
- gint distance;
- gint x1, x2, y1, y2;
-
- new_type = GDK_X_CURSOR;
- closest_point = 0;
-
- /* get the pointer position */
- gdk_window_get_pointer (cd->graph->window, &tx, &ty, NULL);
- x = CLAMP ((tx - RADIUS), 0, 255);
- y = CLAMP ((ty - RADIUS), 0, 255);
-
- distance = G_MAXINT;
- for (i = 0; i < 17; i++)
- {
- if (cd->points[cd->channel][i][0] != -1)
- if (abs (x - cd->points[cd->channel][i][0]) < distance)
- {
- distance = abs (x - cd->points[cd->channel][i][0]);
- closest_point = i;
- }
- }
- if (distance > MIN_DISTANCE)
- closest_point = (x + 8) / 16;
-
- switch (event->type)
- {
- case GDK_EXPOSE:
- if (cd->pixmap == NULL)
- cd->pixmap = gdk_pixmap_new (cd->graph->window,
- GRAPH_WIDTH + RADIUS * 2,
- GRAPH_HEIGHT + RADIUS * 2, -1);
-
- curves_update (cd, GRAPH | DRAW);
- break;
-
- case GDK_BUTTON_PRESS:
- bevent = (GdkEventButton *) event;
- new_type = GDK_TCROSS;
-
- switch (cd->curve_type[cd->channel])
- {
- case SMOOTH:
- /* determine the leftmost and rightmost points */
- cd->leftmost = -1;
- for (i = closest_point - 1; i >= 0; i--)
- if (cd->points[cd->channel][i][0] != -1)
- {
- cd->leftmost = cd->points[cd->channel][i][0];
- break;
- }
- cd->rightmost = 256;
- for (i = closest_point + 1; i < 17; i++)
- if (cd->points[cd->channel][i][0] != -1)
- {
- cd->rightmost = cd->points[cd->channel][i][0];
- break;
- }
-
- cd->grab_point = closest_point;
- cd->points[cd->channel][cd->grab_point][0] = x;
- cd->points[cd->channel][cd->grab_point][1] = 255 - y;
-
- break;
-
- case GFREE:
- cd->curve[cd->channel][x] = 255 - y;
- cd->grab_point = x;
- cd->last = y;
- break;
- }
-
- curves_calculate_curve (cd);
- curves_update (cd, GRAPH | XRANGE_TOP | DRAW);
- gtk_grab_add (widget);
-
- break;
-
- case GDK_BUTTON_RELEASE:
- new_type = GDK_FLEUR;
- cd->grab_point = -1;
-
- if (cd->preview)
- curves_preview (cd);
-
- gtk_grab_remove (widget);
-
- break;
-
- case GDK_MOTION_NOTIFY:
- mevent = (GdkEventMotion *) event;
-
- if (mevent->is_hint)
- {
- mevent->x = tx;
- mevent->y = ty;
- }
-
- switch (cd->curve_type[cd->channel])
- {
- case SMOOTH:
- /* If no point is grabbed... */
- if (cd->grab_point == -1)
- {
- if (cd->points[cd->channel][closest_point][0] != -1)
- new_type = GDK_FLEUR;
- else
- new_type = GDK_TCROSS;
- }
- /* Else, drag the grabbed point */
- else
- {
- new_type = GDK_TCROSS;
-
- cd->points[cd->channel][cd->grab_point][0] = -1;
-
- if (x > cd->leftmost && x < cd->rightmost)
- {
- closest_point = (x + 8) / 16;
- if (cd->points[cd->channel][closest_point][0] == -1)
- cd->grab_point = closest_point;
- cd->points[cd->channel][cd->grab_point][0] = x;
- cd->points[cd->channel][cd->grab_point][1] = 255 - y;
- }
-
- curves_calculate_curve (cd);
- curves_update (cd, GRAPH | XRANGE_TOP | DRAW);
- }
- break;
-
- case GFREE:
- if (cd->grab_point != -1)
- {
- if (cd->grab_point > x)
- {
- x1 = x;
- x2 = cd->grab_point;
- y1 = y;
- y2 = cd->last;
- }
- else
- {
- x1 = cd->grab_point;
- x2 = x;
- y1 = cd->last;
- y2 = y;
- }
-
- if (x2 != x1)
- for (i = x1; i <= x2; i++)
- cd->curve[cd->channel][i] = 255 - (y1 + ((y2 - y1) * (i - x1)) / (x2 - x1));
- else
- cd->curve[cd->channel][x] = 255 - y;
-
- cd->grab_point = x;
- cd->last = y;
-
- curves_update (cd, GRAPH | XRANGE_TOP | DRAW);
- }
-
- if (mevent->state & GDK_BUTTON1_MASK)
- new_type = GDK_TCROSS;
- else
- new_type = GDK_PENCIL;
- break;
- }
-
- if (new_type != cursor_type)
- {
- cursor_type = new_type;
- change_win_cursor (cd->graph->window, cursor_type,
- TOOL_TYPE_NONE, CURSOR_MODIFIER_NONE, FALSE);
- }
-
- curve_print_loc (cd, x, 255 - y);
-
- break;
-
- default:
- break;
- }
-
- return FALSE;
- }
-
- static gint
- curves_xrange_events (GtkWidget *widget,
- GdkEvent *event,
- CurvesDialog *cd)
- {
- switch (event->type)
- {
- case GDK_EXPOSE:
- curves_update (cd, XRANGE_TOP | XRANGE_BOTTOM);
- break;
-
- case GDK_DELETE:
- break;
-
- default:
- break;
- }
-
- return FALSE;
- }
-
- static gint
- curves_yrange_events (GtkWidget *widget,
- GdkEvent *event,
- CurvesDialog *cd)
- {
- switch (event->type)
- {
- case GDK_EXPOSE:
- curves_update (cd, YRANGE);
- break;
-
- default:
- break;
- }
-
- return FALSE;
- }
-
- static void
- curves_CR_compose (CRMatrix a,
- CRMatrix b,
- CRMatrix ab)
- {
- gint i, j;
-
- for (i = 0; i < 4; i++)
- {
- for (j = 0; j < 4; j++)
- {
- ab[i][j] = (a[i][0] * b[0][j] +
- a[i][1] * b[1][j] +
- a[i][2] * b[2][j] +
- a[i][3] * b[3][j]);
- }
- }
- }
-
-
- static void
- file_dialog_create (GtkWidget *parent)
- {
- gchar *temp;
-
- file_dlg = gtk_file_selection_new (_("Load/Save Curves"));
- gtk_window_set_wmclass (GTK_WINDOW (file_dlg), "load_save_curves", "Gimp");
- gtk_window_set_position (GTK_WINDOW (file_dlg), GTK_WIN_POS_MOUSE);
-
- gtk_container_set_border_width (GTK_CONTAINER (file_dlg), 2);
- gtk_container_set_border_width (GTK_CONTAINER (GTK_FILE_SELECTION (file_dlg)->button_area), 2);
-
- gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (file_dlg)->cancel_button),
- "clicked", GTK_SIGNAL_FUNC (file_dialog_cancel_callback),
- NULL);
- gtk_signal_connect (GTK_OBJECT (file_dlg), "delete_event",
- GTK_SIGNAL_FUNC (file_dialog_cancel_callback),
- NULL);
- gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (file_dlg)->ok_button),
- "clicked", GTK_SIGNAL_FUNC (file_dialog_ok_callback),
- NULL);
-
- gtk_signal_connect (GTK_OBJECT (parent), "unmap",
- GTK_SIGNAL_FUNC (file_dialog_cancel_callback),
- NULL);
-
- temp = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "curves" G_DIR_SEPARATOR_S,
- gimp_directory ());
- gtk_file_selection_set_filename (GTK_FILE_SELECTION (file_dlg), temp);
- g_free (temp);
-
- gimp_help_connect_help_accel (file_dlg, tools_help_func,
- tool_info[CURVES].private_tip);
- }
-
- static void
- file_dialog_ok_callback (GtkWidget *widget,
- gpointer data)
- {
- FILE *f;
- gchar *filename;
-
- filename = gtk_file_selection_get_filename (GTK_FILE_SELECTION (file_dlg));
-
- if (load_save)
- {
- f = fopen (filename, "rt");
-
- if (!f)
- {
- g_message (_("Unable to open file %s"), filename);
- return;
- }
-
- if (!curves_read_from_file (f))
- {
- g_message (("Error in reading file %s"), filename);
- return;
- }
-
- fclose (f);
- }
- else
- {
- f = fopen (filename, "wt");
-
- if (!f)
- {
- g_message (_("Unable to open file %s"), filename);
- return;
- }
-
- curves_write_to_file (f);
-
- fclose (f);
- }
-
- file_dialog_cancel_callback (file_dlg, NULL);
- }
-
- static void
- file_dialog_cancel_callback (GtkWidget *widget,
- gpointer data)
- {
- gimp_dialog_hide (file_dlg);
- }
-
- static gboolean
- curves_read_from_file (FILE *f)
- {
- gint i, j;
- gint fields;
- gchar buf[50];
- gint index[5][17];
- gint value[5][17];
- gint current_channel;
-
- if (!fgets (buf, 50, f))
- return FALSE;
-
- if (strcmp (buf, "# GIMP Curves File\n") != 0)
- return FALSE;
-
- for (i = 0; i < 5; i++)
- {
- for (j = 0; j < 17; j++)
- {
- fields = fscanf (f, "%d %d ", &index[i][j], &value[i][j]);
- if (fields != 2)
- {
- g_print ("fields != 2");
- return FALSE;
- }
- }
- }
-
- for (i = 0; i < 5; i++)
- {
- curves_dialog->curve_type[i] = SMOOTH;
- for (j = 0; j < 17; j++)
- {
- curves_dialog->points[i][j][0] = index[i][j];
- curves_dialog->points[i][j][1] = value[i][j];
- }
- }
-
- /* this is ugly, but works ... */
- current_channel = curves_dialog->channel;
- for (i = 0; i < 5; i++)
- {
- curves_dialog->channel = i;
- curves_calculate_curve (curves_dialog);
- }
- curves_dialog->channel = current_channel;
-
- curves_update (curves_dialog, ALL);
- gtk_option_menu_set_history (GTK_OPTION_MENU (curves_dialog->curve_type_menu),
- SMOOTH);
-
- if (curves_dialog->preview)
- curves_preview (curves_dialog);
-
- return TRUE;
- }
-
- static void
- curves_write_to_file (FILE *f)
- {
- gint i, j;
- gint32 index;
-
- for (i = 0; i < 5; i++)
- if (curves_dialog->curve_type[i] == GFREE)
- {
- /* pick representative points from the curve and make them control points */
- for (j = 0; j <= 8; j++)
- {
- index = CLAMP0255 (j * 32);
- curves_dialog->points[i][j * 2][0] = index;
- curves_dialog->points[i][j * 2][1] = curves_dialog->curve[i][index];
- }
- }
-
- fprintf (f, "# GIMP Curves File\n");
-
- for (i = 0; i < 5; i++)
- {
- for (j = 0; j < 17; j++)
- fprintf (f, "%d %d ", curves_dialog->points[i][j][0],
- curves_dialog->points[i][j][1]);
-
- fprintf (f, "\n");
- }
- }
-
-