mirror of https://github.com/GNOME/gimp.git
configure.in app/Makefile.am moved all tool sources to app/tools
2001-01-22 Sven Neumann <sven@gimp.org> * configure.in * app/Makefile.am * app/tools/Makefile.am: moved all tool sources to app/tools * app/app_procs.c * app/brush_select.c * app/commands.c * app/context_manager.c * app/convert.c * app/cursorutil.c * app/devices.c * app/disp_callbacks.c * app/edit_selection.c * app/gdisplay.c * app/gimage.c * app/gimage_mask.c * app/gimpbrush.c * app/gimpbrushgenerated.c * app/gimpbrushpipe.c * app/gimpdnd.c * app/gimprc.c * app/global_edit.c * app/info_window.c * app/interface.c * app/menus.c * app/path.c * app/paths_dialog.c * app/paths_dialogP.h * app/scale.c * app/scroll.c * app/undo.c * app/pdb/color_cmds.c * app/pdb/text_tool_cmds.c * app/pdb/tools_cmds.c * po/POTFILES.in * tools/kernelgen.c * tools/pdbgen/Makefile.am * tools/pdbgen/enums.pl * tools/pdbgen/pdb/color.pdb * tools/pdbgen/pdb/text_tool.pdb * tools/pdbgen/pdb/tools.pdb: changed accordingly
This commit is contained in:
parent
47b036faf0
commit
fafae590e3
44
ChangeLog
44
ChangeLog
|
@ -1,3 +1,47 @@
|
|||
2001-01-22 Sven Neumann <sven@gimp.org>
|
||||
|
||||
* configure.in
|
||||
* app/Makefile.am
|
||||
* app/tools/Makefile.am: moved all tool sources to app/tools
|
||||
|
||||
* app/app_procs.c
|
||||
* app/brush_select.c
|
||||
* app/commands.c
|
||||
* app/context_manager.c
|
||||
* app/convert.c
|
||||
* app/cursorutil.c
|
||||
* app/devices.c
|
||||
* app/disp_callbacks.c
|
||||
* app/edit_selection.c
|
||||
* app/gdisplay.c
|
||||
* app/gimage.c
|
||||
* app/gimage_mask.c
|
||||
* app/gimpbrush.c
|
||||
* app/gimpbrushgenerated.c
|
||||
* app/gimpbrushpipe.c
|
||||
* app/gimpdnd.c
|
||||
* app/gimprc.c
|
||||
* app/global_edit.c
|
||||
* app/info_window.c
|
||||
* app/interface.c
|
||||
* app/menus.c
|
||||
* app/path.c
|
||||
* app/paths_dialog.c
|
||||
* app/paths_dialogP.h
|
||||
* app/scale.c
|
||||
* app/scroll.c
|
||||
* app/undo.c
|
||||
* app/pdb/color_cmds.c
|
||||
* app/pdb/text_tool_cmds.c
|
||||
* app/pdb/tools_cmds.c
|
||||
* po/POTFILES.in
|
||||
* tools/kernelgen.c
|
||||
* tools/pdbgen/Makefile.am
|
||||
* tools/pdbgen/enums.pl
|
||||
* tools/pdbgen/pdb/color.pdb
|
||||
* tools/pdbgen/pdb/text_tool.pdb
|
||||
* tools/pdbgen/pdb/tools.pdb: changed accordingly
|
||||
|
||||
2001-01-22 Daniel Egger <egger@suse.de>
|
||||
|
||||
* libgimp/gimpcolor.c: #include "gimppalette_pdb.h"
|
||||
|
|
4
TODO.xml
4
TODO.xml
|
@ -49,7 +49,7 @@
|
|||
</contact>
|
||||
</entry>
|
||||
|
||||
<entry size="big" difficulty="medium" status="0%" target="1.4">
|
||||
<entry size="big" difficulty="medium" status="10%" target="1.4">
|
||||
<title>Code reorganization</title>
|
||||
<description>
|
||||
<p>
|
||||
|
@ -63,7 +63,7 @@
|
|||
</contact>
|
||||
</entry>
|
||||
|
||||
<entry size="medium" difficulty="medium" status="20%" target="1.4">
|
||||
<entry size="medium" difficulty="medium" status="40%" target="1.4">
|
||||
<title>Unify color data types</title>
|
||||
<description>
|
||||
<p>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
## Process this file with automake to produce Makefile.in
|
||||
|
||||
SUBDIRS = pdb
|
||||
SUBDIRS = pdb tools
|
||||
|
||||
scriptdata =
|
||||
|
||||
|
@ -15,8 +15,6 @@ bin_PROGRAMS = gimp
|
|||
gimp_SOURCES = \
|
||||
about_dialog.c \
|
||||
about_dialog.h \
|
||||
airbrush.c \
|
||||
airbrush.h \
|
||||
app_procs.c \
|
||||
app_procs.h \
|
||||
appenums.h \
|
||||
|
@ -27,17 +25,8 @@ gimp_SOURCES = \
|
|||
authors.h \
|
||||
batch.c \
|
||||
batch.h \
|
||||
bezier_select.c \
|
||||
bezier_select.h \
|
||||
bezier_selectP.h \
|
||||
blend.c \
|
||||
blend.h \
|
||||
blob.c \
|
||||
blob.h \
|
||||
boundary.c \
|
||||
boundary.h \
|
||||
brightness_contrast.c \
|
||||
brightness_contrast.h \
|
||||
brush_edit.c \
|
||||
brush_edit.h \
|
||||
brush_header.h \
|
||||
|
@ -45,28 +34,18 @@ gimp_SOURCES = \
|
|||
brush_scale.h \
|
||||
brush_select.c \
|
||||
brush_select.h \
|
||||
bucket_fill.c \
|
||||
bucket_fill.h \
|
||||
by_color_select.c \
|
||||
by_color_select.h \
|
||||
channel.c \
|
||||
channel.h \
|
||||
channels_dialog.c \
|
||||
channels_dialog.h \
|
||||
channel_ops.c \
|
||||
channel_ops.h \
|
||||
clone.c \
|
||||
clone.h \
|
||||
color_area.c \
|
||||
color_area.h \
|
||||
color_balance.c \
|
||||
color_balance.h \
|
||||
color_notebook.c \
|
||||
color_notebook.h \
|
||||
color_panel.c \
|
||||
color_panel.h \
|
||||
color_picker.c \
|
||||
color_picker.h \
|
||||
color_select.c \
|
||||
color_select.h \
|
||||
color_transfer.c \
|
||||
|
@ -81,14 +60,8 @@ gimp_SOURCES = \
|
|||
context_manager.h \
|
||||
convert.c \
|
||||
convert.h \
|
||||
convolve.c \
|
||||
convolve.h \
|
||||
crop.c \
|
||||
crop.h \
|
||||
cursorutil.c \
|
||||
cursorutil.h \
|
||||
curves.c \
|
||||
curves.h \
|
||||
datafiles.c \
|
||||
datafiles.h \
|
||||
desaturate.c \
|
||||
|
@ -102,8 +75,6 @@ gimp_SOURCES = \
|
|||
disp_callbacks.h \
|
||||
docindex.c \
|
||||
docindex.h \
|
||||
dodgeburn.c \
|
||||
dodgeburn.h \
|
||||
draw_core.c \
|
||||
draw_core.h \
|
||||
drawable.c \
|
||||
|
@ -111,10 +82,6 @@ gimp_SOURCES = \
|
|||
drawable_pvt.h \
|
||||
edit_selection.c \
|
||||
edit_selection.h \
|
||||
ellipse_select.c \
|
||||
ellipse_select.h \
|
||||
eraser.c \
|
||||
eraser.h \
|
||||
errorconsole.c \
|
||||
errorconsole.h \
|
||||
errors.c \
|
||||
|
@ -124,17 +91,11 @@ gimp_SOURCES = \
|
|||
fileops.c \
|
||||
fileops.h \
|
||||
fileopsP.h \
|
||||
flip_tool.c \
|
||||
flip_tool.h \
|
||||
floating_sel.c \
|
||||
floating_sel.h \
|
||||
file_new_dialog.c \
|
||||
file_new_dialog.h \
|
||||
free_select.c \
|
||||
free_select.h \
|
||||
fsdither.h \
|
||||
fuzzy_select.c \
|
||||
fuzzy_select.h \
|
||||
gdisplay.c \
|
||||
gdisplay.h \
|
||||
gdisplay_ops.c \
|
||||
|
@ -208,10 +169,6 @@ gimp_SOURCES = \
|
|||
gximage.h \
|
||||
histogramwidget.c \
|
||||
histogramwidget.h \
|
||||
histogram_tool.c \
|
||||
histogram_tool.h \
|
||||
hue_saturation.c \
|
||||
hue_saturation.h \
|
||||
image_map.c \
|
||||
image_map.h \
|
||||
image_new.c \
|
||||
|
@ -224,14 +181,10 @@ gimp_SOURCES = \
|
|||
info_dialog.h \
|
||||
info_window.c \
|
||||
info_window.h \
|
||||
ink.c \
|
||||
ink.h \
|
||||
interface.c \
|
||||
interface.h \
|
||||
invert.c \
|
||||
invert.h \
|
||||
iscissors.c \
|
||||
iscissors.h \
|
||||
layer.c \
|
||||
layer.h \
|
||||
layer_select.c \
|
||||
|
@ -242,22 +195,14 @@ gimp_SOURCES = \
|
|||
lc_dialog.c \
|
||||
lc_dialog.h \
|
||||
lc_dialogP.h \
|
||||
levels.c \
|
||||
levels.h \
|
||||
lut_funcs.c \
|
||||
lut_funcs.h \
|
||||
magnify.c \
|
||||
magnify.h \
|
||||
main.c \
|
||||
marching_ants.h \
|
||||
measure.c \
|
||||
measure.h \
|
||||
menus.c \
|
||||
menus.h \
|
||||
module_db.c \
|
||||
module_db.h \
|
||||
move.c \
|
||||
move.h \
|
||||
nav_window.c \
|
||||
nav_window.h \
|
||||
ops_buttons.c \
|
||||
|
@ -269,14 +214,8 @@ gimp_SOURCES = \
|
|||
palette_select.c \
|
||||
palette_select.h \
|
||||
paletteP.h \
|
||||
paint_core.c \
|
||||
paint_core.h \
|
||||
paint_core_kernels.h \
|
||||
paint_funcs.c \
|
||||
paint_funcs.h \
|
||||
paint_options.h \
|
||||
paintbrush.c \
|
||||
paintbrush.h \
|
||||
parasitelist.c \
|
||||
parasitelist.h \
|
||||
path.c \
|
||||
|
@ -291,10 +230,6 @@ gimp_SOURCES = \
|
|||
pattern_select.h \
|
||||
patterns.c \
|
||||
patterns.h \
|
||||
pencil.c \
|
||||
pencil.h \
|
||||
perspective_tool.c \
|
||||
perspective_tool.h \
|
||||
pixel_processor.c \
|
||||
pixel_processor.h \
|
||||
pixel_region.c \
|
||||
|
@ -303,25 +238,16 @@ gimp_SOURCES = \
|
|||
pixmaps2.h \
|
||||
plug_in.c \
|
||||
plug_in.h \
|
||||
posterize.c \
|
||||
posterize.h \
|
||||
preferences_dialog.c \
|
||||
preferences_dialog.h \
|
||||
qmask.c \
|
||||
qmask.h \
|
||||
rect_select.c \
|
||||
rect_select.h \
|
||||
rect_selectP.h \
|
||||
resolution_calibrate.c \
|
||||
resolution_calibrate.h \
|
||||
resize.c \
|
||||
resize.h \
|
||||
rotate_tool.c \
|
||||
rotate_tool.h \
|
||||
scale.c \
|
||||
scale.h \
|
||||
scale_tool.c \
|
||||
scale_tool.h \
|
||||
scan_convert.c \
|
||||
scan_convert.h \
|
||||
scroll.c \
|
||||
|
@ -331,16 +257,8 @@ gimp_SOURCES = \
|
|||
selection_options.h \
|
||||
session.h \
|
||||
session.c \
|
||||
shear_tool.c \
|
||||
shear_tool.h \
|
||||
smudge.c \
|
||||
smudge.h \
|
||||
temp_buf.c \
|
||||
temp_buf.h \
|
||||
text_tool.c \
|
||||
text_tool.h \
|
||||
threshold.c \
|
||||
threshold.h \
|
||||
tile.c \
|
||||
tile.h \
|
||||
tile_pvt.h \
|
||||
|
@ -353,14 +271,6 @@ gimp_SOURCES = \
|
|||
tile_swap.h \
|
||||
tips_dialog.c \
|
||||
tips_dialog.h \
|
||||
tool_options.c \
|
||||
tool_options.h \
|
||||
tools.c \
|
||||
tools.h \
|
||||
transform_core.c \
|
||||
transform_core.h \
|
||||
transform_tool.c \
|
||||
transform_tool.h \
|
||||
undo.c \
|
||||
undo.h \
|
||||
undo_history.c \
|
||||
|
@ -400,6 +310,7 @@ INCLUDES = \
|
|||
|
||||
gimp_LDADD = \
|
||||
pdb/libapppdb.la \
|
||||
tools/libapptools.la \
|
||||
$(top_builddir)/libgimp/libgimpi.a \
|
||||
$(GTK_LIBS) \
|
||||
$(GIMP_THREAD_LIBS) \
|
||||
|
|
|
@ -68,13 +68,14 @@
|
|||
#include "scale.h"
|
||||
#include "selection.h"
|
||||
#include "tips_dialog.h"
|
||||
#include "tools.h"
|
||||
#include "undo.h"
|
||||
|
||||
#ifdef DISPLAY_FILTERS
|
||||
#include "gdisplay_color_ui.h"
|
||||
#endif /* DISPLAY_FILTERS */
|
||||
|
||||
#include "tools/tools.h"
|
||||
|
||||
#include "libgimp/gimphelpui.h"
|
||||
#include "libgimp/gimpmath.h"
|
||||
|
||||
|
|
440
app/airbrush.c
440
app/airbrush.c
|
@ -1,440 +0,0 @@
|
|||
/* 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 <gtk/gtk.h>
|
||||
|
||||
#include "apptypes.h"
|
||||
|
||||
#include "appenv.h"
|
||||
#include "airbrush.h"
|
||||
#include "drawable.h"
|
||||
#include "gdisplay.h"
|
||||
#include "gradient.h"
|
||||
#include "gimpimage.h"
|
||||
#include "gimpbrush.h"
|
||||
#include "gimpcontext.h"
|
||||
#include "gimpui.h"
|
||||
#include "paint_funcs.h"
|
||||
#include "paint_core.h"
|
||||
#include "paint_options.h"
|
||||
#include "selection.h"
|
||||
#include "temp_buf.h"
|
||||
#include "tools.h"
|
||||
|
||||
#include "libgimp/gimpintl.h"
|
||||
|
||||
|
||||
/* The maximum amount of pressure that can be exerted */
|
||||
#define MAX_PRESSURE 0.075
|
||||
|
||||
/* Default pressure setting */
|
||||
#define AIRBRUSH_PRESSURE_DEFAULT 10.0
|
||||
#define AIRBRUSH_INCREMENTAL_DEFAULT FALSE
|
||||
|
||||
#define OFF 0
|
||||
#define ON 1
|
||||
|
||||
/* the airbrush structures */
|
||||
|
||||
typedef struct _AirbrushTimeout AirbrushTimeout;
|
||||
|
||||
struct _AirbrushTimeout
|
||||
{
|
||||
PaintCore *paint_core;
|
||||
GimpDrawable *drawable;
|
||||
};
|
||||
|
||||
typedef struct _AirbrushOptions AirbrushOptions;
|
||||
|
||||
struct _AirbrushOptions
|
||||
{
|
||||
PaintOptions paint_options;
|
||||
|
||||
gdouble rate;
|
||||
gdouble rate_d;
|
||||
GtkObject *rate_w;
|
||||
|
||||
gdouble pressure;
|
||||
gdouble pressure_d;
|
||||
GtkObject *pressure_w;
|
||||
};
|
||||
|
||||
|
||||
/* local function prototypes */
|
||||
|
||||
static gpointer airbrush_paint_func (PaintCore *paint_core,
|
||||
GimpDrawable *drawable,
|
||||
PaintState state);
|
||||
static gpointer airbrush_non_gui_paint_func (PaintCore *paint_core,
|
||||
GimpDrawable *drawable,
|
||||
PaintState state);
|
||||
|
||||
|
||||
/* the airbrush tool options */
|
||||
static AirbrushOptions *airbrush_options = NULL;
|
||||
|
||||
/* local variables */
|
||||
static gint timer; /* timer for successive paint applications */
|
||||
static gint timer_state = OFF; /* state of airbrush tool */
|
||||
static AirbrushTimeout airbrush_timeout;
|
||||
|
||||
static gdouble non_gui_pressure;
|
||||
static gboolean non_gui_incremental;
|
||||
|
||||
/* forward function declarations */
|
||||
static void airbrush_motion (PaintCore *, GimpDrawable *,
|
||||
PaintPressureOptions *,
|
||||
gdouble, PaintApplicationMode);
|
||||
static gint airbrush_time_out (gpointer);
|
||||
|
||||
|
||||
/* functions */
|
||||
|
||||
static void
|
||||
airbrush_options_reset (void)
|
||||
{
|
||||
AirbrushOptions *options = airbrush_options;
|
||||
|
||||
paint_options_reset ((PaintOptions *) options);
|
||||
|
||||
gtk_adjustment_set_value (GTK_ADJUSTMENT (options->rate_w),
|
||||
options->rate_d);
|
||||
gtk_adjustment_set_value (GTK_ADJUSTMENT (options->pressure_w),
|
||||
options->pressure_d);
|
||||
}
|
||||
|
||||
static AirbrushOptions *
|
||||
airbrush_options_new (void)
|
||||
{
|
||||
AirbrushOptions *options;
|
||||
|
||||
GtkWidget *vbox;
|
||||
GtkWidget *table;
|
||||
GtkWidget *scale;
|
||||
|
||||
/* the new airbrush tool options structure */
|
||||
options = g_new (AirbrushOptions, 1);
|
||||
paint_options_init ((PaintOptions *) options,
|
||||
AIRBRUSH,
|
||||
airbrush_options_reset);
|
||||
options->rate = options->rate_d = 80.0;
|
||||
options->pressure = options->pressure_d = AIRBRUSH_PRESSURE_DEFAULT;
|
||||
|
||||
/* the main vbox */
|
||||
vbox = ((ToolOptions *) options)->main_vbox;
|
||||
|
||||
/* the rate scale */
|
||||
table = gtk_table_new (2, 2, FALSE);
|
||||
gtk_table_set_col_spacing (GTK_TABLE (table), 0, 4);
|
||||
gtk_table_set_row_spacings (GTK_TABLE (table), 1);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
|
||||
|
||||
options->rate_w =
|
||||
gtk_adjustment_new (options->rate_d, 0.0, 150.0, 1.0, 1.0, 0.0);
|
||||
scale = gtk_hscale_new (GTK_ADJUSTMENT (options->rate_w));
|
||||
gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_TOP);
|
||||
gtk_range_set_update_policy (GTK_RANGE (scale), GTK_UPDATE_DELAYED);
|
||||
gtk_signal_connect (GTK_OBJECT (options->rate_w), "value_changed",
|
||||
GTK_SIGNAL_FUNC (gimp_double_adjustment_update),
|
||||
&options->rate);
|
||||
gimp_table_attach_aligned (GTK_TABLE (table), 0, 0,
|
||||
_("Rate:"), 1.0, 1.0,
|
||||
scale, 1, FALSE);
|
||||
|
||||
/* the pressure scale */
|
||||
options->pressure_w =
|
||||
gtk_adjustment_new (options->pressure_d, 0.0, 100.0, 1.0, 1.0, 0.0);
|
||||
scale = gtk_hscale_new (GTK_ADJUSTMENT (options->pressure_w));
|
||||
gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_TOP);
|
||||
gtk_range_set_update_policy (GTK_RANGE (scale), GTK_UPDATE_DELAYED);
|
||||
gtk_signal_connect (GTK_OBJECT (options->pressure_w), "value_changed",
|
||||
GTK_SIGNAL_FUNC (gimp_double_adjustment_update),
|
||||
&options->pressure);
|
||||
gimp_table_attach_aligned (GTK_TABLE (table), 0, 1,
|
||||
_("Pressure:"), 1.0, 1.0,
|
||||
scale, 1, FALSE);
|
||||
|
||||
gtk_widget_show (table);
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
Tool *
|
||||
tools_new_airbrush (void)
|
||||
{
|
||||
Tool * tool;
|
||||
PaintCore * private;
|
||||
|
||||
/* The tool options */
|
||||
if (! airbrush_options)
|
||||
{
|
||||
airbrush_options = airbrush_options_new ();
|
||||
tools_register (AIRBRUSH, (ToolOptions *) airbrush_options);
|
||||
}
|
||||
|
||||
tool = paint_core_new (AIRBRUSH);
|
||||
|
||||
private = (PaintCore *) tool->private;
|
||||
private->paint_func = airbrush_paint_func;
|
||||
private->pick_colors = TRUE;
|
||||
private->flags |= TOOL_CAN_HANDLE_CHANGING_BRUSH;
|
||||
|
||||
return tool;
|
||||
}
|
||||
|
||||
static gpointer
|
||||
airbrush_paint_func (PaintCore *paint_core,
|
||||
GimpDrawable *drawable,
|
||||
PaintState state)
|
||||
{
|
||||
GimpBrush *brush;
|
||||
gdouble rate;
|
||||
|
||||
if (!drawable)
|
||||
return NULL;
|
||||
|
||||
brush = gimp_context_get_brush (NULL);
|
||||
switch (state)
|
||||
{
|
||||
case INIT_PAINT :
|
||||
/* timer_state = OFF; */
|
||||
if (timer_state == ON)
|
||||
{
|
||||
g_warning ("killing stray timer, please report to lewing@gimp.org");
|
||||
gtk_timeout_remove (timer);
|
||||
}
|
||||
timer_state = OFF;
|
||||
break;
|
||||
|
||||
case MOTION_PAINT :
|
||||
if (timer_state == ON)
|
||||
gtk_timeout_remove (timer);
|
||||
timer_state = OFF;
|
||||
|
||||
airbrush_motion (paint_core, drawable,
|
||||
airbrush_options->paint_options.pressure_options,
|
||||
airbrush_options->pressure,
|
||||
airbrush_options->paint_options.incremental ?
|
||||
INCREMENTAL : CONSTANT);
|
||||
|
||||
if (airbrush_options->rate != 0.0)
|
||||
{
|
||||
airbrush_timeout.paint_core = paint_core;
|
||||
airbrush_timeout.drawable = drawable;
|
||||
rate = airbrush_options->paint_options.pressure_options->rate ?
|
||||
(10000 / (airbrush_options->rate * 2.0 * paint_core->curpressure)) :
|
||||
(10000 / airbrush_options->rate);
|
||||
timer = gtk_timeout_add (rate, airbrush_time_out, NULL);
|
||||
timer_state = ON;
|
||||
}
|
||||
break;
|
||||
|
||||
case FINISH_PAINT :
|
||||
if (timer_state == ON)
|
||||
gtk_timeout_remove (timer);
|
||||
timer_state = OFF;
|
||||
break;
|
||||
|
||||
default :
|
||||
break;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
tools_free_airbrush (Tool *tool)
|
||||
{
|
||||
if (timer_state == ON)
|
||||
gtk_timeout_remove (timer);
|
||||
timer_state = OFF;
|
||||
|
||||
paint_core_free (tool);
|
||||
}
|
||||
|
||||
|
||||
static gint
|
||||
airbrush_time_out (gpointer client_data)
|
||||
{
|
||||
/* service the timer */
|
||||
airbrush_motion (airbrush_timeout.paint_core,
|
||||
airbrush_timeout.drawable,
|
||||
airbrush_options->paint_options.pressure_options,
|
||||
airbrush_options->pressure,
|
||||
airbrush_options->paint_options.incremental ?
|
||||
INCREMENTAL : CONSTANT);
|
||||
gdisplays_flush ();
|
||||
|
||||
/* restart the timer */
|
||||
if (airbrush_options->rate != 0.0)
|
||||
{
|
||||
if (airbrush_options->paint_options.pressure_options->rate)
|
||||
{
|
||||
/* set a new timer */
|
||||
timer = gtk_timeout_add ((10000 / (airbrush_options->rate * 2.0 * airbrush_timeout.paint_core->curpressure)),
|
||||
airbrush_time_out, NULL);
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
airbrush_motion (PaintCore *paint_core,
|
||||
GimpDrawable *drawable,
|
||||
PaintPressureOptions *pressure_options,
|
||||
double pressure,
|
||||
PaintApplicationMode mode)
|
||||
{
|
||||
GImage *gimage;
|
||||
TempBuf *area;
|
||||
guchar col[MAX_CHANNELS];
|
||||
gdouble scale;
|
||||
|
||||
if (!drawable)
|
||||
return;
|
||||
|
||||
if (! (gimage = gimp_drawable_gimage (drawable)))
|
||||
return;
|
||||
|
||||
if (pressure_options->size)
|
||||
scale = paint_core->curpressure;
|
||||
else
|
||||
scale = 1.0;
|
||||
|
||||
if (! (area = paint_core_get_paint_area (paint_core, drawable, scale)))
|
||||
return;
|
||||
|
||||
/* color the pixels */
|
||||
if (pressure_options->color)
|
||||
{
|
||||
GimpRGB color;
|
||||
|
||||
gradient_get_color_at (gimp_context_get_gradient (NULL),
|
||||
paint_core->curpressure, &color);
|
||||
|
||||
gimp_rgba_get_uchar (&color,
|
||||
&col[RED_PIX],
|
||||
&col[GREEN_PIX],
|
||||
&col[BLUE_PIX],
|
||||
&col[ALPHA_PIX]);
|
||||
|
||||
mode = INCREMENTAL;
|
||||
color_pixels (temp_buf_data (area), col,
|
||||
area->width * area->height, area->bytes);
|
||||
}
|
||||
else if (paint_core->brush && paint_core->brush->pixmap)
|
||||
{
|
||||
mode = INCREMENTAL;
|
||||
paint_core_color_area_with_pixmap (paint_core, gimage, drawable, area,
|
||||
scale, SOFT);
|
||||
}
|
||||
else
|
||||
{
|
||||
gimp_image_get_foreground (gimage, drawable, col);
|
||||
col[area->bytes - 1] = OPAQUE_OPACITY;
|
||||
color_pixels (temp_buf_data (area), col,
|
||||
area->width * area->height, area->bytes);
|
||||
}
|
||||
|
||||
if (pressure_options->pressure)
|
||||
pressure = pressure * 2.0 * paint_core->curpressure;
|
||||
|
||||
/* paste the newly painted area to the image */
|
||||
paint_core_paste_canvas (paint_core, drawable,
|
||||
MIN (pressure, 255),
|
||||
(gint) (gimp_context_get_opacity (NULL) * 255),
|
||||
gimp_context_get_paint_mode (NULL),
|
||||
SOFT, scale, mode);
|
||||
}
|
||||
|
||||
static gpointer
|
||||
airbrush_non_gui_paint_func (PaintCore *paint_core,
|
||||
GimpDrawable *drawable,
|
||||
PaintState state)
|
||||
{
|
||||
airbrush_motion (paint_core, drawable, &non_gui_pressure_options,
|
||||
non_gui_pressure, non_gui_incremental);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gboolean
|
||||
airbrush_non_gui_default (GimpDrawable *drawable,
|
||||
gint num_strokes,
|
||||
gdouble *stroke_array)
|
||||
{
|
||||
AirbrushOptions *options = airbrush_options;
|
||||
gdouble pressure = AIRBRUSH_PRESSURE_DEFAULT;
|
||||
|
||||
if(options)
|
||||
pressure = options->pressure;
|
||||
|
||||
return airbrush_non_gui (drawable, pressure, num_strokes, stroke_array);
|
||||
}
|
||||
|
||||
gboolean
|
||||
airbrush_non_gui (GimpDrawable *drawable,
|
||||
gdouble pressure,
|
||||
gint num_strokes,
|
||||
gdouble *stroke_array)
|
||||
{
|
||||
gint i;
|
||||
|
||||
if (paint_core_init (&non_gui_paint_core, drawable,
|
||||
stroke_array[0], stroke_array[1]))
|
||||
{
|
||||
/* Set the paint core's paint func */
|
||||
non_gui_paint_core.paint_func = airbrush_non_gui_paint_func;
|
||||
|
||||
non_gui_pressure = pressure;
|
||||
|
||||
non_gui_paint_core.startx = non_gui_paint_core.lastx = stroke_array[0];
|
||||
non_gui_paint_core.starty = non_gui_paint_core.lasty = stroke_array[1];
|
||||
|
||||
airbrush_non_gui_paint_func (&non_gui_paint_core, drawable, 0);
|
||||
|
||||
for (i = 1; i < num_strokes; i++)
|
||||
{
|
||||
non_gui_paint_core.curx = stroke_array[i * 2 + 0];
|
||||
non_gui_paint_core.cury = stroke_array[i * 2 + 1];
|
||||
|
||||
paint_core_interpolate (&non_gui_paint_core, drawable);
|
||||
|
||||
non_gui_paint_core.lastx = non_gui_paint_core.curx;
|
||||
non_gui_paint_core.lasty = non_gui_paint_core.cury;
|
||||
}
|
||||
|
||||
/* Finish the painting */
|
||||
paint_core_finish (&non_gui_paint_core, drawable, -1);
|
||||
|
||||
/* Cleanup */
|
||||
paint_core_cleanup ();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
/* 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.
|
||||
*/
|
||||
|
||||
#ifndef __AIRBRUSH_H__
|
||||
#define __AIRBRUSH_H__
|
||||
|
||||
|
||||
gboolean airbrush_non_gui (GimpDrawable *drawable,
|
||||
gdouble pressure,
|
||||
gint num_strokes,
|
||||
gdouble *stroke_array);
|
||||
gboolean airbrush_non_gui_default (GimpDrawable *drawable,
|
||||
gint num_strokes,
|
||||
gdouble *stroke_array);
|
||||
|
||||
Tool * tools_new_airbrush (void);
|
||||
void tools_free_airbrush (Tool *tool);
|
||||
|
||||
|
||||
#endif /* __AIRBRUSH_H__ */
|
1841
app/airbrush_blob.c
1841
app/airbrush_blob.c
File diff suppressed because it is too large
Load Diff
|
@ -1,153 +0,0 @@
|
|||
/* airbrush_blob.h: routines for manipulating scan converted convex
|
||||
* polygons.
|
||||
*
|
||||
* Copyright 1998, Owen Taylor <otaylor@gtk.org>
|
||||
*
|
||||
* > Please contact the above author before modifying the copy <
|
||||
* > of this file in the GIMP distribution. Thanks. <
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __AIRBRUSHBLOB_H__
|
||||
#define __AIRBRUSHBLOB_H__
|
||||
|
||||
typedef enum {
|
||||
CROSS = 0,
|
||||
CROSS_LEFT = 1,
|
||||
CROSS_RIGHT = 2,
|
||||
CROSS_WHOLE_LINE = 3,
|
||||
CROSS_NORMAL = 4
|
||||
} CrossType;
|
||||
|
||||
typedef enum {
|
||||
RIGHT_LEFT = 0,
|
||||
LEFT_RIGHT = 1,
|
||||
TOP_BOT = 2,
|
||||
BOT_TOP = 3,
|
||||
NONE = 4
|
||||
} MoveType;
|
||||
|
||||
/* The AirBlob, which is a abstract of a real AirBrushBlob */
|
||||
|
||||
typedef struct _AirBlob AirBlob;
|
||||
typedef struct _AirPoint AirPoint;
|
||||
typedef struct _SupportLine SupportLine;
|
||||
|
||||
|
||||
struct _AirPoint {
|
||||
int x;
|
||||
int y;
|
||||
};
|
||||
|
||||
struct _SupportLine {
|
||||
double size;
|
||||
double dist;
|
||||
};
|
||||
|
||||
struct _AirBlob {
|
||||
double direction_abs;
|
||||
double direction;
|
||||
double ycenter;
|
||||
double xcenter;
|
||||
SupportLine main_line;
|
||||
SupportLine minor_line;
|
||||
SupportLine maincross_line;
|
||||
SupportLine minorcross_line;
|
||||
};
|
||||
|
||||
|
||||
/* The AirLine is a reslut of a AirBlob */
|
||||
typedef struct _AirLine AirLine;
|
||||
|
||||
struct _AirLine {
|
||||
int xcenter;
|
||||
int ycenter;
|
||||
AirPoint line[16];
|
||||
int min_x, min_y;
|
||||
int max_x, max_y;
|
||||
int width, height;
|
||||
int nlines;
|
||||
};
|
||||
|
||||
|
||||
typedef struct _AirBrushBlobPoint AirBrushBlobPoint;
|
||||
typedef struct _AirBrushBlobSpan AirBrushBlobSpan;
|
||||
typedef struct _AirBrushBlob AirBrushBlob;
|
||||
|
||||
struct _AirBrushBlobPoint {
|
||||
int x;
|
||||
int y;
|
||||
};
|
||||
|
||||
struct _AirBrushBlobSpan {
|
||||
int left;
|
||||
double angle_left;
|
||||
double angle_left_abs;
|
||||
double dist_left;
|
||||
int right;
|
||||
double angle_right;
|
||||
double angle_right_abs;
|
||||
double dist_right;
|
||||
|
||||
CrossType cross_type;
|
||||
int x_cross;
|
||||
|
||||
int center;
|
||||
double dist;
|
||||
|
||||
};
|
||||
|
||||
struct _AirBrushBlob {
|
||||
int y;
|
||||
int height;
|
||||
int width;
|
||||
int min_x;
|
||||
int max_x;
|
||||
MoveType move;
|
||||
double direction_abs;
|
||||
double direction;
|
||||
CrossType cross;
|
||||
AirBrushBlobSpan data[1];
|
||||
};
|
||||
|
||||
|
||||
typedef struct _AirBrush AirBrush;
|
||||
|
||||
struct _AirBrush {
|
||||
AirBrushBlob airbrush_blob;
|
||||
AirBlob airblob;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
AirBlob *create_air_blob (double xc, double yc, double xt, double yt, double xr, double yr, double xb, double yb, double xl, double yl, double direction_abs, double direction);
|
||||
AirBlob *trans_air_blob(AirBlob *airblob_last, AirBlob *airblob_present, double dist, int xc, int yc);
|
||||
AirLine *create_air_line(AirBlob *airblob);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
AirBrushBlob *airbrush_blob_convex_union (AirBrushBlob *b1, AirBrushBlob *b2);
|
||||
AirBrushBlob *airbrush_blob_ellipse (double xc, double yc, double xt, double yt, double xr, double yr, double xb, double yb, double xl, double yl);
|
||||
void airbrush_blob_bounds (AirBrushBlob *b, int *x, int *y, int *width, int *height);
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /* __AIRBRUSHBLOB_H__ */
|
|
@ -46,7 +46,6 @@
|
|||
#include "batch.h"
|
||||
#include "brush_select.h"
|
||||
#include "color_transfer.h"
|
||||
#include "curves.h"
|
||||
#include "colormaps.h"
|
||||
#include "context_manager.h"
|
||||
#include "devices.h"
|
||||
|
@ -65,11 +64,9 @@
|
|||
#include "gradient_select.h"
|
||||
#include "gradient.h"
|
||||
#include "gximage.h"
|
||||
#include "hue_saturation.h"
|
||||
#include "image_render.h"
|
||||
#include "interface.h"
|
||||
#include "lc_dialog.h"
|
||||
#include "levels.h"
|
||||
#include "menus.h"
|
||||
#include "paint_funcs.h"
|
||||
#include "palette.h"
|
||||
|
@ -81,7 +78,6 @@
|
|||
#include "temp_buf.h"
|
||||
#include "tile_swap.h"
|
||||
#include "tips_dialog.h"
|
||||
#include "tools.h"
|
||||
#include "undo.h"
|
||||
#include "unitrc.h"
|
||||
#include "xcf.h"
|
||||
|
@ -97,6 +93,11 @@
|
|||
#include "color_select.h"
|
||||
#include "gimpparasite.h"
|
||||
|
||||
#include "tools/curves.h"
|
||||
#include "tools/hue_saturation.h"
|
||||
#include "tools/levels.h"
|
||||
#include "tools/tools.h"
|
||||
|
||||
#include "pdb/internal_procs.h"
|
||||
|
||||
#include "libgimp/gimplimits.h"
|
||||
|
|
3676
app/bezier_select.c
3676
app/bezier_select.c
File diff suppressed because it is too large
Load Diff
|
@ -1,29 +0,0 @@
|
|||
/* 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.
|
||||
*/
|
||||
|
||||
#ifndef __BEZIER_SELECT_H__
|
||||
#define __BEZIER_SELECT_H__
|
||||
|
||||
|
||||
Tool * tools_new_bezier_select (void);
|
||||
void tools_free_bezier_select (Tool *tool);
|
||||
|
||||
gboolean bezier_tool_selected (void);
|
||||
|
||||
|
||||
#endif /* __BEZIER_SELECT_H__ */
|
|
@ -1,116 +0,0 @@
|
|||
/* 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.
|
||||
*/
|
||||
|
||||
#ifndef __BEZIER_SELECTP_H__
|
||||
#define __BEZIER_SELECTP_H__
|
||||
|
||||
#include "draw_core.h"
|
||||
|
||||
#define BEZIER_START 1
|
||||
#define BEZIER_ADD 2
|
||||
#define BEZIER_EDIT 4
|
||||
#define BEZIER_DRAG 8
|
||||
|
||||
#define BEZIER_ANCHOR 1
|
||||
#define BEZIER_CONTROL 2
|
||||
#define BEZIER_MOVE 3
|
||||
|
||||
#define IMAGE_COORDS 1
|
||||
#define AA_IMAGE_COORDS 2
|
||||
#define SCREEN_COORDS 3
|
||||
|
||||
#define SUBDIVIDE 1000
|
||||
|
||||
enum { EXTEND_EDIT, EXTEND_ADD, EXTEND_REMOVE, EXTEND_NEW };
|
||||
|
||||
struct _BezierPoint
|
||||
{
|
||||
gint type; /* type of point (anchor/control/move) */
|
||||
gdouble x, y; /* location of point in image space */
|
||||
gint sx, sy; /* location of point in screen space */
|
||||
BezierPoint *next; /* next point on curve */
|
||||
BezierPoint *prev; /* prev point on curve */
|
||||
BezierPoint *next_curve; /* Next curve segment */
|
||||
gint pointflags; /* Status of point 0 = not selected
|
||||
* 1 = selected
|
||||
*/
|
||||
};
|
||||
|
||||
struct _BezierSelect
|
||||
{
|
||||
gint state; /* start, add, edit or drag */
|
||||
gint draw; /* all or part */
|
||||
gint closed; /* is the last curve closed */
|
||||
DrawCore *core; /* Core drawing object */
|
||||
BezierPoint *points; /* the curve */
|
||||
BezierPoint *cur_anchor; /* the current active anchor point */
|
||||
BezierPoint *cur_control; /* the current active control point */
|
||||
BezierPoint *last_point; /* the last point on the curve */
|
||||
gint num_points; /* number of points in the curve */
|
||||
Channel *mask; /* null if the curve is open */
|
||||
GSList **scanlines; /* used in converting a curve */
|
||||
};
|
||||
|
||||
/* All data that are passed to the bezier_draw_curve must
|
||||
* have this structure as the first element.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
gint count;
|
||||
} CountCurves;
|
||||
|
||||
typedef void (* BezierPointsFunc) (BezierSelect *bezier_sel,
|
||||
GdkPoint *points,
|
||||
gint n_points,
|
||||
gpointer data);
|
||||
|
||||
/* Functions */
|
||||
gint bezier_select_load (GDisplay *gdisp,
|
||||
BezierPoint *points,
|
||||
gint n_points,
|
||||
gint closed);
|
||||
void bezier_draw_curve (BezierSelect *bezier_sel,
|
||||
BezierPointsFunc func,
|
||||
gint coord,
|
||||
gpointer data);
|
||||
void bezier_select_reset (BezierSelect *bezier_sel);
|
||||
void bezier_select_free (BezierSelect *bezier_sel);
|
||||
void bezier_add_point (BezierSelect *bezier_sel,
|
||||
gint type,
|
||||
gdouble x,
|
||||
gdouble y);
|
||||
void bezier_paste_bezierselect_to_current (GDisplay *gdisp,
|
||||
BezierSelect *bezier_sel);
|
||||
void bezier_select_mode (gint);
|
||||
void bezier_stroke (BezierSelect *bezier_sel,
|
||||
GDisplay *gdisp,
|
||||
gint subdivisions,
|
||||
gint open_path);
|
||||
void bezier_to_selection (BezierSelect *bezier_sel,
|
||||
GDisplay *gdisp);
|
||||
gint bezier_distance_along (BezierSelect *bezier_sel,
|
||||
gint open_path,
|
||||
gdouble dist,
|
||||
gint *x,
|
||||
gint *y,
|
||||
gdouble *gradient);
|
||||
void bezier_draw (GDisplay *gdisp,
|
||||
BezierSelect *bezier_sel);
|
||||
|
||||
#endif /* __BEZIER_SELECTP_H__ */
|
1695
app/blend.c
1695
app/blend.c
File diff suppressed because it is too large
Load Diff
78
app/blend.h
78
app/blend.h
|
@ -1,78 +0,0 @@
|
|||
/* 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.
|
||||
*/
|
||||
|
||||
#ifndef __BLEND_H__
|
||||
#define __BLEND_H__
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
LINEAR,
|
||||
BILINEAR,
|
||||
RADIAL,
|
||||
SQUARE,
|
||||
CONICAL_SYMMETRIC,
|
||||
CONICAL_ASYMMETRIC,
|
||||
SHAPEBURST_ANGULAR,
|
||||
SHAPEBURST_SPHERICAL,
|
||||
SHAPEBURST_DIMPLED,
|
||||
SPIRAL_CLOCKWISE,
|
||||
SPIRAL_ANTICLOCKWISE,
|
||||
GRADIENT_TYPE_LAST /*< skip >*/
|
||||
} GradientType;
|
||||
|
||||
typedef enum /*< chop=_MODE >*/
|
||||
{
|
||||
FG_BG_RGB_MODE,
|
||||
FG_BG_HSV_MODE,
|
||||
FG_TRANS_MODE,
|
||||
CUSTOM_MODE,
|
||||
BLEND_MODE_LAST /*< skip >*/
|
||||
} BlendMode;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
REPEAT_NONE,
|
||||
REPEAT_SAWTOOTH,
|
||||
REPEAT_TRIANGULAR,
|
||||
REPEAT_LAST /*< skip >*/
|
||||
} RepeatMode;
|
||||
|
||||
void blend (GimpImage *gimage,
|
||||
GimpDrawable *drawable,
|
||||
BlendMode blend_mode,
|
||||
gint paint_mode,
|
||||
GradientType gradient_type,
|
||||
gdouble opacity,
|
||||
gdouble offset,
|
||||
RepeatMode repeat,
|
||||
gint supersample,
|
||||
gint max_depth,
|
||||
gdouble threshold,
|
||||
gdouble startx,
|
||||
gdouble starty,
|
||||
gdouble endx,
|
||||
gdouble endy,
|
||||
GimpProgressFunc progress_callback,
|
||||
gpointer progress_data);
|
||||
|
||||
Tool * tools_new_blend (void);
|
||||
void tools_free_blend (Tool *tool);
|
||||
|
||||
|
||||
#endif /* __BLEND_H__ */
|
774
app/blob.c
774
app/blob.c
|
@ -1,774 +0,0 @@
|
|||
/* blob.c: routines for manipulating scan converted convex
|
||||
* polygons.
|
||||
*
|
||||
* Copyright 1998-1999, Owen Taylor <otaylor@gtk.org>
|
||||
*
|
||||
* > Please contact the above author before modifying the copy <
|
||||
* > of this file in the GIMP distribution. Thanks. <
|
||||
*
|
||||
* 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 <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "apptypes.h"
|
||||
|
||||
#include "appenv.h"
|
||||
#include "blob.h"
|
||||
|
||||
#include "libgimp/gimpmath.h"
|
||||
|
||||
|
||||
static Blob *
|
||||
blob_new (int y, int height)
|
||||
{
|
||||
Blob *result;
|
||||
|
||||
result = g_malloc (sizeof (Blob) + sizeof(BlobSpan) * (height-1));
|
||||
result->y = y;
|
||||
result->height = height;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
typedef enum {
|
||||
EDGE_NONE = 0,
|
||||
EDGE_LEFT = 1 << 0,
|
||||
EDGE_RIGHT = 1 << 1
|
||||
} EdgeType;
|
||||
|
||||
static void
|
||||
blob_fill (Blob *b, EdgeType *present)
|
||||
{
|
||||
int start;
|
||||
int x1, x2, i1, i2;
|
||||
int i;
|
||||
|
||||
/* Mark empty lines at top and bottom as unused */
|
||||
|
||||
start = 0;
|
||||
while (!(present[start]))
|
||||
{
|
||||
b->data[start].left = 0;
|
||||
b->data[start].right = -1;
|
||||
start++;
|
||||
}
|
||||
if (present[start] != (EDGE_RIGHT | EDGE_LEFT))
|
||||
{
|
||||
if (present[start] == EDGE_RIGHT)
|
||||
b->data[start].left = b->data[start].right;
|
||||
else
|
||||
b->data[start].right = b->data[start].left;
|
||||
|
||||
present[start] = EDGE_RIGHT | EDGE_LEFT;
|
||||
}
|
||||
|
||||
for (i=b->height-1;!present[i];i--)
|
||||
{
|
||||
b->data[i].left = 0;
|
||||
b->data[i].right = -1;
|
||||
}
|
||||
if (present[i] != (EDGE_RIGHT | EDGE_LEFT))
|
||||
{
|
||||
if (present[i] == EDGE_RIGHT)
|
||||
b->data[i].left = b->data[i].right;
|
||||
else
|
||||
b->data[i].right = b->data[i].left;
|
||||
|
||||
present[i] = EDGE_RIGHT | EDGE_LEFT;
|
||||
}
|
||||
|
||||
|
||||
/* Restore missing edges */
|
||||
|
||||
/* We fill only interior regions of convex hull, as if we were filling
|
||||
polygons. But since we draw ellipses with nearest points, not interior
|
||||
points, maybe it would look better if we did the same here. Probably
|
||||
not a big deal either way after anti-aliasing */
|
||||
|
||||
/* left edge */
|
||||
for (i1=start; i1<b->height-2; i1++)
|
||||
{
|
||||
/* Find empty gaps */
|
||||
if (!(present[i1+1] & EDGE_LEFT))
|
||||
{
|
||||
int increment; /* fractional part */
|
||||
int denom; /* denominator of fraction */
|
||||
int step; /* integral step */
|
||||
int frac; /* fractional step */
|
||||
int reverse;
|
||||
|
||||
/* find bottom of gap */
|
||||
i2 = i1+2;
|
||||
while (!(present[i2] & EDGE_LEFT) && i2 < b->height) i2++;
|
||||
|
||||
if (i2 < b->height)
|
||||
{
|
||||
denom = i2-i1;
|
||||
x1 = b->data[i1].left;
|
||||
x2 = b->data[i2].left;
|
||||
step = (x2-x1)/denom;
|
||||
frac = x2-x1 - step*denom;
|
||||
if (frac < 0)
|
||||
{
|
||||
frac = -frac;
|
||||
reverse = 1;
|
||||
}
|
||||
else
|
||||
reverse = 0;
|
||||
|
||||
increment = 0;
|
||||
for (i=i1+1; i<i2; i++)
|
||||
{
|
||||
x1 += step;
|
||||
increment += frac;
|
||||
if (increment >= denom)
|
||||
{
|
||||
increment -= denom;
|
||||
x1 += reverse ? -1 : 1;
|
||||
}
|
||||
if (increment == 0 || reverse)
|
||||
b->data[i].left = x1;
|
||||
else
|
||||
b->data[i].left = x1 + 1;
|
||||
}
|
||||
}
|
||||
i1 = i2-1; /* advance to next possibility */
|
||||
}
|
||||
}
|
||||
|
||||
/* right edge */
|
||||
for (i1=start; i1<b->height-2; i1++)
|
||||
{
|
||||
/* Find empty gaps */
|
||||
if (!(present[i1+1] & EDGE_RIGHT))
|
||||
{
|
||||
int increment; /* fractional part */
|
||||
int denom; /* denominator of fraction */
|
||||
int step; /* integral step */
|
||||
int frac; /* fractional step */
|
||||
int reverse;
|
||||
|
||||
/* find bottom of gap */
|
||||
i2 = i1+2;
|
||||
while (!(present[i2] & EDGE_RIGHT) && i2 < b->height) i2++;
|
||||
|
||||
if (i2 < b->height)
|
||||
{
|
||||
denom = i2-i1;
|
||||
x1 = b->data[i1].right;
|
||||
x2 = b->data[i2].right;
|
||||
step = (x2-x1)/denom;
|
||||
frac = x2-x1 - step*denom;
|
||||
if (frac < 0)
|
||||
{
|
||||
frac = -frac;
|
||||
reverse = 1;
|
||||
}
|
||||
else
|
||||
reverse = 0;
|
||||
|
||||
increment = 0;
|
||||
for (i=i1+1; i<i2; i++)
|
||||
{
|
||||
x1 += step;
|
||||
increment += frac;
|
||||
if (increment >= denom)
|
||||
{
|
||||
increment -= denom;
|
||||
x1 += reverse ? -1 : 1;
|
||||
}
|
||||
if (reverse && increment != 0)
|
||||
b->data[i].right = x1 - 1;
|
||||
else
|
||||
b->data[i].right = x1;
|
||||
}
|
||||
}
|
||||
i1 = i2-1; /* advance to next possibility */
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
blob_make_convex (Blob *b, EdgeType *present)
|
||||
{
|
||||
int x1, x2, y1, y2, i1, i2;
|
||||
int i;
|
||||
int start;
|
||||
|
||||
/* Walk through edges, deleting points that aren't on convex hull */
|
||||
|
||||
start = 0;
|
||||
while (!(present[start])) start++;
|
||||
|
||||
/* left edge */
|
||||
|
||||
i1 = start-1;
|
||||
i2 = start;
|
||||
x1 = b->data[start].left - b->data[start].right;
|
||||
y1 = 0;
|
||||
|
||||
for (i=start+1;i<b->height;i++)
|
||||
{
|
||||
if (!(present[i] & EDGE_LEFT))
|
||||
continue;
|
||||
|
||||
x2 = b->data[i].left - b->data[i2].left;
|
||||
y2 = i-i2;
|
||||
|
||||
while (x2*y1 - x1*y2 < 0) /* clockwise rotation */
|
||||
{
|
||||
present[i2] &= ~EDGE_LEFT;
|
||||
i2 = i1;
|
||||
while (!(present[--i1] & EDGE_LEFT) && i1>=start);
|
||||
|
||||
if (i1<start)
|
||||
{
|
||||
x1 = b->data[start].left - b->data[start].right;
|
||||
y1 = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
x1 = b->data[i2].left - b->data[i1].left;
|
||||
y1 = i2 - i1;
|
||||
}
|
||||
x2 = b->data[i].left - b->data[i2].left;
|
||||
y2 = i - i2;
|
||||
}
|
||||
x1 = x2;
|
||||
y1 = y2;
|
||||
i1 = i2;
|
||||
i2 = i;
|
||||
}
|
||||
|
||||
/* Right edge */
|
||||
|
||||
i1 = start -1;
|
||||
i2 = start;
|
||||
x1 = b->data[start].right - b->data[start].left;
|
||||
y1 = 0;
|
||||
|
||||
for (i=start+1;i<b->height;i++)
|
||||
{
|
||||
if (!(present[i] & EDGE_RIGHT))
|
||||
continue;
|
||||
|
||||
x2 = b->data[i].right - b->data[i2].right;
|
||||
y2 = i-i2;
|
||||
|
||||
while (x2*y1 - x1*y2 > 0) /* counter-clockwise rotation */
|
||||
{
|
||||
present[i2] &= ~EDGE_RIGHT;
|
||||
i2 = i1;
|
||||
while (!(present[--i1] & EDGE_RIGHT) && i1>=start);
|
||||
|
||||
if (i1<start)
|
||||
{
|
||||
x1 = b->data[start].right - b->data[start].left;
|
||||
y1 = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
x1 = b->data[i2].right - b->data[i1].right;
|
||||
y1 = i2 - i1;
|
||||
}
|
||||
x2 = b->data[i].right - b->data[i2].right;
|
||||
y2 = i - i2;
|
||||
}
|
||||
x1 = x2;
|
||||
y1 = y2;
|
||||
i1 = i2;
|
||||
i2 = i;
|
||||
}
|
||||
|
||||
blob_fill (b, present);
|
||||
}
|
||||
|
||||
Blob *
|
||||
blob_convex_union (Blob *b1, Blob *b2)
|
||||
{
|
||||
Blob *result;
|
||||
int y;
|
||||
int i, j;
|
||||
EdgeType *present;
|
||||
|
||||
/* Create the storage for the result */
|
||||
|
||||
y = MIN(b1->y,b2->y);
|
||||
result = blob_new (y, MAX(b1->y+b1->height,b2->y+b2->height)-y);
|
||||
|
||||
if (result->height == 0)
|
||||
return result;
|
||||
|
||||
present = g_new0 (EdgeType, result->height);
|
||||
|
||||
/* Initialize spans from original objects */
|
||||
|
||||
for (i=0, j=b1->y-y; i<b1->height; i++,j++)
|
||||
{
|
||||
if (b1->data[i].right >= b1->data[i].left)
|
||||
{
|
||||
present[j] = EDGE_LEFT | EDGE_RIGHT;
|
||||
result->data[j].left = b1->data[i].left;
|
||||
result->data[j].right = b1->data[i].right;
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0, j=b2->y-y; i<b2->height; i++,j++)
|
||||
{
|
||||
if (b2->data[i].right >= b2->data[i].left)
|
||||
{
|
||||
if (present[j])
|
||||
{
|
||||
if (result->data[j].left > b2->data[i].left)
|
||||
result->data[j].left = b2->data[i].left;
|
||||
if (result->data[j].right < b2->data[i].right)
|
||||
result->data[j].right = b2->data[i].right;
|
||||
}
|
||||
else
|
||||
{
|
||||
present[j] = EDGE_LEFT | EDGE_RIGHT;
|
||||
result->data[j].left = b2->data[i].left;
|
||||
result->data[j].right = b2->data[i].right;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
blob_make_convex (result, present);
|
||||
|
||||
g_free (present);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
blob_line_add_pixel (Blob *b, int x, int y)
|
||||
{
|
||||
if (b->data[y-b->y].left > b->data[y-b->y].right)
|
||||
b->data[y-b->y].left = b->data[y-b->y].right = x;
|
||||
else
|
||||
{
|
||||
b->data[y-b->y].left = MIN (b->data[y-b->y].left, x);
|
||||
b->data[y-b->y].right = MAX (b->data[y-b->y].right, x);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
blob_line (Blob *b, int x0, int y0, int x1, int y1)
|
||||
{
|
||||
int dx, dy, d;
|
||||
int incrE, incrNE;
|
||||
int x, y;
|
||||
|
||||
int xstep = 1;
|
||||
int ystep = 1;
|
||||
|
||||
dx = x1 - x0;
|
||||
dy = y1 - y0;
|
||||
|
||||
if (dx < 0)
|
||||
{
|
||||
dx = -dx;
|
||||
xstep = -1;
|
||||
}
|
||||
|
||||
if (dy < 0)
|
||||
{
|
||||
dy = -dy;
|
||||
ystep = -1;
|
||||
}
|
||||
|
||||
/* for (y = y0; y != y1 + ystep ; y += ystep)
|
||||
{
|
||||
b->data[y-b->y].left = 0;
|
||||
b->data[y-b->y].right = -1;
|
||||
}*/
|
||||
|
||||
x = x0;
|
||||
y = y0;
|
||||
|
||||
if (dy < dx)
|
||||
{
|
||||
d = 2*dy - dx; /* initial value of d */
|
||||
incrE = 2 * dy; /* increment used for move to E */
|
||||
incrNE = 2 * (dy-dx); /* increment used for move to NE */
|
||||
|
||||
blob_line_add_pixel (b, x, y);
|
||||
|
||||
while (x != x1)
|
||||
{
|
||||
if (d <= 0)
|
||||
{
|
||||
d += incrE;
|
||||
x += xstep;
|
||||
}
|
||||
else
|
||||
{
|
||||
d += incrNE;
|
||||
x += xstep;
|
||||
y += ystep;
|
||||
}
|
||||
blob_line_add_pixel (b, x, y);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
d = 2*dx - dy; /* initial value of d */
|
||||
incrE = 2 * dx; /* increment used for move to E */
|
||||
incrNE = 2 * (dx-dy); /* increment used for move to NE */
|
||||
|
||||
blob_line_add_pixel (b, x, y);
|
||||
|
||||
while (y != y1)
|
||||
{
|
||||
if (d <= 0)
|
||||
{
|
||||
d += incrE;
|
||||
y += ystep;
|
||||
}
|
||||
else
|
||||
{
|
||||
d += incrNE;
|
||||
x += xstep;
|
||||
y += ystep;
|
||||
}
|
||||
blob_line_add_pixel (b, x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define TABLE_SIZE 256
|
||||
|
||||
#define ELLIPSE_SHIFT 2
|
||||
#define TABLE_SHIFT 12
|
||||
#define TOTAL_SHIFT (ELLIPSE_SHIFT + TABLE_SHIFT)
|
||||
|
||||
/*
|
||||
* The choose of this values limits the maximal image_size to
|
||||
* 16384 x 16384 pixels. The values will overflow as soon as
|
||||
* x or y > INT_MAX / (1 << (ELLIPSE_SHIFT + TABLE_SHIFT)) / SUBSAMPLE
|
||||
*
|
||||
* Alternatively the code could be change the code as follows:
|
||||
*
|
||||
* xc_base = floor (xc)
|
||||
* xc_shift = 0.5 + (xc - xc_base) * (1 << TOTAL_SHIFT);
|
||||
*
|
||||
* gint x = xc_base + (xc_shift + c * xp_shift + s * xq_shift +
|
||||
* (1 << (TOTAL_SHIFT - 1))) >> TOTAL_SHIFT;
|
||||
*
|
||||
* which would change the limit from the image to the ellipse size
|
||||
*/
|
||||
|
||||
static int trig_initialized = 0;
|
||||
static int trig_table[TABLE_SIZE];
|
||||
|
||||
/* Return blob for the given (convex) polygon
|
||||
*/
|
||||
Blob *
|
||||
blob_polygon (BlobPoint *points, int npoints)
|
||||
{
|
||||
int i;
|
||||
int im1;
|
||||
int ip1;
|
||||
int ymin, ymax;
|
||||
Blob *result;
|
||||
EdgeType *present;
|
||||
|
||||
ymax = points[0].y;
|
||||
ymin = points[0].y;
|
||||
|
||||
for (i=1; i < npoints; i++)
|
||||
{
|
||||
if (points[i].y > ymax)
|
||||
ymax = points[i].y;
|
||||
if (points[i].y < ymin)
|
||||
ymin = points[i].y;
|
||||
}
|
||||
|
||||
result = blob_new (ymin, ymax - ymin + 1);
|
||||
present = g_new0 (EdgeType, result->height);
|
||||
|
||||
im1 = npoints - 1;
|
||||
i = 0;
|
||||
ip1 = 1;
|
||||
|
||||
for (; i < npoints ; i++)
|
||||
{
|
||||
int sides = 0;
|
||||
int j = points[i].y - ymin;
|
||||
|
||||
if (points[i].y < points[im1].y)
|
||||
sides |= EDGE_RIGHT;
|
||||
else if (points[i].y > points[im1].y)
|
||||
sides |= EDGE_LEFT;
|
||||
|
||||
if (points[ip1].y < points[i].y)
|
||||
sides |= EDGE_RIGHT;
|
||||
else if (points[ip1].y > points[i].y)
|
||||
sides |= EDGE_LEFT;
|
||||
|
||||
if (sides & EDGE_RIGHT)
|
||||
{
|
||||
if (present[j] & EDGE_RIGHT)
|
||||
{
|
||||
result->data[j].right = MAX (result->data[j].right, points[i].x);
|
||||
}
|
||||
else
|
||||
{
|
||||
present[j] |= EDGE_RIGHT;
|
||||
result->data[j].right = points[i].x;
|
||||
}
|
||||
}
|
||||
|
||||
if (sides & EDGE_LEFT)
|
||||
{
|
||||
if (present[j] & EDGE_LEFT)
|
||||
{
|
||||
result->data[j].left = MIN (result->data[j].left, points[i].x);
|
||||
}
|
||||
else
|
||||
{
|
||||
present[j] |= EDGE_LEFT;
|
||||
result->data[j].left = points[i].x;
|
||||
}
|
||||
}
|
||||
|
||||
im1 = i;
|
||||
ip1++;
|
||||
if (ip1 == npoints)
|
||||
ip1 = 0;
|
||||
}
|
||||
|
||||
blob_fill (result, present);
|
||||
g_free (present);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Scan convert a square specified by _offsets_ of major and
|
||||
minor axes, and by center into a blob */
|
||||
Blob *
|
||||
blob_square (double xc, double yc, double xp, double yp, double xq, double yq)
|
||||
{
|
||||
BlobPoint points[4];
|
||||
|
||||
/* Make sure we order points ccw */
|
||||
|
||||
if (xp * yq - yq * xp < 0)
|
||||
{
|
||||
xq = -xq;
|
||||
yq = -yq;
|
||||
}
|
||||
|
||||
points[0].x = xc + xp + xq;
|
||||
points[0].y = yc + yp + yq;
|
||||
points[1].x = xc + xp - xq;
|
||||
points[1].y = yc + yp - yq;
|
||||
points[2].x = xc - xp - xq;
|
||||
points[2].y = yc - yp - yq;
|
||||
points[3].x = xc - xp + xq;
|
||||
points[3].y = yc - yp + yq;
|
||||
|
||||
return blob_polygon (points, 4);
|
||||
}
|
||||
|
||||
/* Scan convert a diamond specified by _offsets_ of major and
|
||||
minor axes, and by center into a blob */
|
||||
Blob *
|
||||
blob_diamond (double xc, double yc, double xp, double yp, double xq, double yq)
|
||||
{
|
||||
BlobPoint points[4];
|
||||
|
||||
/* Make sure we order points ccw */
|
||||
|
||||
if (xp * yq - yq * xp < 0)
|
||||
{
|
||||
xq = -xq;
|
||||
yq = -yq;
|
||||
}
|
||||
|
||||
points[0].x = xc + xp;
|
||||
points[0].y = yc + yp;
|
||||
points[1].x = xc - xq;
|
||||
points[1].y = yc - yq;
|
||||
points[2].x = xc - xp;
|
||||
points[2].y = yc - yp;
|
||||
points[3].x = xc + xq;
|
||||
points[3].y = yc + yq;
|
||||
|
||||
return blob_polygon (points, 4);
|
||||
}
|
||||
|
||||
/* Scan convert an ellipse specified by _offsets_ of major and
|
||||
minor axes, and by center into a blob */
|
||||
Blob *
|
||||
blob_ellipse (double xc, double yc, double xp, double yp, double xq, double yq)
|
||||
{
|
||||
int i;
|
||||
Blob *r;
|
||||
gdouble r1, r2;
|
||||
gint maxy, miny;
|
||||
gint step;
|
||||
double max_radius;
|
||||
|
||||
gint xc_shift, yc_shift;
|
||||
gint xp_shift, yp_shift;
|
||||
gint xq_shift, yq_shift;
|
||||
|
||||
EdgeType *present;
|
||||
|
||||
if (!trig_initialized)
|
||||
{
|
||||
trig_initialized = 1;
|
||||
for (i=0; i<256; i++)
|
||||
trig_table[i] = 0.5 + sin(i * (G_PI / 128.)) * (1 << TABLE_SHIFT);
|
||||
}
|
||||
|
||||
/* Make sure we traverse ellipse in ccw direction */
|
||||
|
||||
if (xp * yq - yq * xp < 0)
|
||||
{
|
||||
xq = -xq;
|
||||
yq = -yq;
|
||||
|
||||
}
|
||||
|
||||
/* Compute bounds as if we were drawing a rectangle */
|
||||
|
||||
maxy = ceil (yc + fabs (yp) + fabs(yq));
|
||||
miny = floor (yc - fabs (yp) - fabs(yq));
|
||||
|
||||
r = blob_new (miny, maxy - miny + 1);
|
||||
present = g_new0 (EdgeType, r->height);
|
||||
|
||||
/* Figure out a step that will draw most of the points */
|
||||
|
||||
r1 = sqrt (xp * xp + yp * yp);
|
||||
r2 = sqrt (xq * xq + yq * yq);
|
||||
max_radius = MAX (r1, r2);
|
||||
step = TABLE_SIZE;
|
||||
|
||||
while (step > 1 && (TABLE_SIZE / step < 4*max_radius))
|
||||
step >>= 1;
|
||||
|
||||
/* Fill in the edge points */
|
||||
|
||||
xc_shift = 0.5 + xc * (1 << TOTAL_SHIFT);
|
||||
yc_shift = 0.5 + yc * (1 << TOTAL_SHIFT);
|
||||
xp_shift = 0.5 + xp * (1 << ELLIPSE_SHIFT);
|
||||
yp_shift = 0.5 + yp * (1 << ELLIPSE_SHIFT);
|
||||
xq_shift = 0.5 + xq * (1 << ELLIPSE_SHIFT);
|
||||
yq_shift = 0.5 + yq * (1 << ELLIPSE_SHIFT);
|
||||
|
||||
for (i = 0 ; i < TABLE_SIZE ; i += step)
|
||||
{
|
||||
gint s = trig_table[i];
|
||||
gint c = trig_table[(TABLE_SIZE + TABLE_SIZE/4 - i) % TABLE_SIZE];
|
||||
|
||||
gint x = (xc_shift + c * xp_shift + s * xq_shift +
|
||||
(1 << (TOTAL_SHIFT - 1))) >> TOTAL_SHIFT;
|
||||
gint y = ((yc_shift + c * yp_shift + s * yq_shift +
|
||||
(1 << (TOTAL_SHIFT - 1))) >> TOTAL_SHIFT) - r->y;
|
||||
|
||||
gint dydi = c * yq_shift - s * yp_shift;
|
||||
|
||||
if (dydi <= 0) /* left edge */
|
||||
{
|
||||
if (present[y] & EDGE_LEFT)
|
||||
{
|
||||
r->data[y].left = MIN (r->data[y].left, x);
|
||||
}
|
||||
else
|
||||
{
|
||||
present[y] |= EDGE_LEFT;
|
||||
r->data[y].left = x;
|
||||
}
|
||||
}
|
||||
|
||||
if (dydi >= 0) /* right edge */
|
||||
{
|
||||
if (present[y] & EDGE_RIGHT)
|
||||
{
|
||||
r->data[y].right = MAX (r->data[y].right, x);
|
||||
}
|
||||
else
|
||||
{
|
||||
present[y] |= EDGE_RIGHT;
|
||||
r->data[y].right = x;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Now fill in missing points */
|
||||
|
||||
blob_fill (r, present);
|
||||
g_free (present);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
void
|
||||
blob_bounds(Blob *b, int *x, int *y, int *width, int *height)
|
||||
{
|
||||
int i;
|
||||
int x0, x1, y0, y1;
|
||||
|
||||
i = 0;
|
||||
while (i<b->height && b->data[i].left > b->data[i].right)
|
||||
i++;
|
||||
|
||||
if (i<b->height)
|
||||
{
|
||||
y0 = b->y + i;
|
||||
x0 = b->data[i].left;
|
||||
x1 = b->data[i].right + 1;
|
||||
while (i<b->height && b->data[i].left <= b->data[i].right)
|
||||
{
|
||||
x0 = MIN(b->data[i].left, x0);
|
||||
x1 = MAX(b->data[i].right+1, x1);
|
||||
i++;
|
||||
}
|
||||
y1 = b->y + i;
|
||||
}
|
||||
else
|
||||
{
|
||||
x0 = y0 = 0;
|
||||
x1 = y1 = 0;
|
||||
}
|
||||
|
||||
*x = x0;
|
||||
*y = y0;
|
||||
*width = x1 - x0;
|
||||
*height = y1 - y0;
|
||||
}
|
||||
|
||||
void
|
||||
blob_dump(Blob *b) {
|
||||
int i,j;
|
||||
for (i=0; i<b->height; i++)
|
||||
{
|
||||
for (j=0;j<b->data[i].left;j++)
|
||||
putchar(' ');
|
||||
for (j=b->data[i].left;j<=b->data[i].right;j++)
|
||||
putchar('*');
|
||||
putchar('\n');
|
||||
}
|
||||
}
|
82
app/blob.h
82
app/blob.h
|
@ -1,82 +0,0 @@
|
|||
/* blob.h: routines for manipulating scan converted convex
|
||||
* polygons.
|
||||
*
|
||||
* Copyright 1998, Owen Taylor <otaylor@gtk.org>
|
||||
*
|
||||
* > Please contact the above author before modifying the copy <
|
||||
* > of this file in the GIMP distribution. Thanks. <
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __BLOB_H__
|
||||
#define __BLOB_H__
|
||||
|
||||
|
||||
typedef struct _BlobPoint BlobPoint;
|
||||
typedef struct _BlobSpan BlobSpan;
|
||||
typedef struct _Blob Blob;
|
||||
|
||||
struct _BlobPoint
|
||||
{
|
||||
gint x;
|
||||
gint y;
|
||||
};
|
||||
|
||||
struct _BlobSpan
|
||||
{
|
||||
gint left;
|
||||
gint right;
|
||||
};
|
||||
|
||||
struct _Blob
|
||||
{
|
||||
gint y;
|
||||
gint height;
|
||||
BlobSpan data[1];
|
||||
};
|
||||
|
||||
|
||||
Blob * blob_convex_union (Blob *b1,
|
||||
Blob *b2);
|
||||
Blob * blob_polygon (BlobPoint *points,
|
||||
gint npoints);
|
||||
Blob * blob_square (gdouble xc,
|
||||
gdouble yc,
|
||||
gdouble xp,
|
||||
gdouble yp,
|
||||
gdouble xq,
|
||||
gdouble yq);
|
||||
Blob * blob_diamond (gdouble xc,
|
||||
gdouble yc,
|
||||
gdouble xp,
|
||||
gdouble yp,
|
||||
gdouble xq,
|
||||
gdouble yq);
|
||||
Blob * blob_ellipse (gdouble xc,
|
||||
gdouble yc,
|
||||
gdouble xp,
|
||||
gdouble yp,
|
||||
gdouble xq,
|
||||
gdouble yq);
|
||||
void blob_bounds (Blob *b,
|
||||
gint *x,
|
||||
gint *y,
|
||||
gint *width,
|
||||
gint *height);
|
||||
|
||||
|
||||
#endif /* __BLOB_H__ */
|
|
@ -1,499 +0,0 @@
|
|||
/* 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 <gtk/gtk.h>
|
||||
|
||||
#include "apptypes.h"
|
||||
|
||||
#include "appenv.h"
|
||||
#include "brightness_contrast.h"
|
||||
#include "drawable.h"
|
||||
#include "gimpcontext.h"
|
||||
#include "gimplut.h"
|
||||
#include "gimpui.h"
|
||||
#include "gdisplay.h"
|
||||
#include "gimpimage.h"
|
||||
#include "image_map.h"
|
||||
#include "lut_funcs.h"
|
||||
#include "tool_options.h"
|
||||
#include "tools.h"
|
||||
|
||||
#include "libgimp/gimpintl.h"
|
||||
|
||||
#define SLIDER_WIDTH 200
|
||||
|
||||
#define BRIGHTNESS 0x1
|
||||
#define CONTRAST 0x2
|
||||
#define ALL (BRIGHTNESS | CONTRAST)
|
||||
|
||||
/* the brightness-contrast structures */
|
||||
|
||||
typedef struct _BrightnessContrast BrightnessContrast;
|
||||
|
||||
struct _BrightnessContrast
|
||||
{
|
||||
gint x, y; /* coords for last mouse click */
|
||||
};
|
||||
|
||||
typedef struct _BrightnessContrastDialog BrightnessContrastDialog;
|
||||
|
||||
struct _BrightnessContrastDialog
|
||||
{
|
||||
GtkWidget *shell;
|
||||
GtkWidget *gimage_name;
|
||||
|
||||
GtkAdjustment *brightness_data;
|
||||
GtkAdjustment *contrast_data;
|
||||
|
||||
GimpDrawable *drawable;
|
||||
ImageMap image_map;
|
||||
|
||||
gdouble brightness;
|
||||
gdouble contrast;
|
||||
|
||||
gboolean preview;
|
||||
|
||||
GimpLut *lut;
|
||||
};
|
||||
|
||||
|
||||
/* the brightness-contrast tool options */
|
||||
static ToolOptions *brightness_contrast_options = NULL;
|
||||
|
||||
/* the brightness-contrast dialog */
|
||||
static BrightnessContrastDialog *brightness_contrast_dialog = NULL;
|
||||
|
||||
|
||||
/* brightness contrast action functions */
|
||||
|
||||
static void brightness_contrast_control (Tool *tool,
|
||||
ToolAction action,
|
||||
GDisplay *gdisp);
|
||||
|
||||
static BrightnessContrastDialog * brightness_contrast_dialog_new (void);
|
||||
|
||||
static void brightness_contrast_update (BrightnessContrastDialog *,
|
||||
gint);
|
||||
static void brightness_contrast_preview (BrightnessContrastDialog *);
|
||||
static void brightness_contrast_reset_callback (GtkWidget *, gpointer);
|
||||
static void brightness_contrast_ok_callback (GtkWidget *, gpointer);
|
||||
static void brightness_contrast_cancel_callback (GtkWidget *, gpointer);
|
||||
static void brightness_contrast_preview_update (GtkWidget *, gpointer);
|
||||
static void brightness_contrast_brightness_adjustment_update (GtkAdjustment *,
|
||||
gpointer);
|
||||
static void brightness_contrast_contrast_adjustment_update (GtkAdjustment *,
|
||||
gpointer);
|
||||
|
||||
/* brightness-contrast select action functions */
|
||||
|
||||
static void
|
||||
brightness_contrast_control (Tool *tool,
|
||||
ToolAction action,
|
||||
GDisplay *gdisp)
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
case PAUSE:
|
||||
break;
|
||||
|
||||
case RESUME:
|
||||
break;
|
||||
|
||||
case HALT:
|
||||
brightness_contrast_dialog_hide ();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Tool *
|
||||
tools_new_brightness_contrast (void)
|
||||
{
|
||||
Tool * tool;
|
||||
BrightnessContrast * private;
|
||||
|
||||
/* The tool options */
|
||||
if (!brightness_contrast_options)
|
||||
{
|
||||
brightness_contrast_options =
|
||||
tool_options_new (_("Brightness-Contrast"));
|
||||
tools_register (BRIGHTNESS_CONTRAST, brightness_contrast_options);
|
||||
}
|
||||
|
||||
tool = tools_new_tool (BRIGHTNESS_CONTRAST);
|
||||
private = g_new0 (BrightnessContrast, 1);
|
||||
|
||||
tool->scroll_lock = TRUE; /* Disallow scrolling */
|
||||
tool->preserve = FALSE; /* Don't preserve on drawable change */
|
||||
|
||||
tool->private = (void *) private;
|
||||
|
||||
tool->control_func = brightness_contrast_control;
|
||||
|
||||
return tool;
|
||||
}
|
||||
|
||||
void
|
||||
brightness_contrast_dialog_hide (void)
|
||||
{
|
||||
if (brightness_contrast_dialog)
|
||||
brightness_contrast_cancel_callback (NULL,
|
||||
(gpointer) brightness_contrast_dialog);
|
||||
}
|
||||
|
||||
void
|
||||
tools_free_brightness_contrast (Tool *tool)
|
||||
{
|
||||
BrightnessContrast * bc;
|
||||
|
||||
bc = (BrightnessContrast *) tool->private;
|
||||
|
||||
/* Close the brightness-contrast dialog */
|
||||
brightness_contrast_dialog_hide ();
|
||||
|
||||
g_free (bc);
|
||||
}
|
||||
|
||||
void
|
||||
brightness_contrast_initialize (GDisplay *gdisp)
|
||||
{
|
||||
if (gimp_drawable_is_indexed (gimp_image_active_drawable (gdisp->gimage)))
|
||||
{
|
||||
g_message (_("Brightness-Contrast does not operate on indexed drawables."));
|
||||
return;
|
||||
}
|
||||
|
||||
/* The brightness-contrast dialog */
|
||||
if (!brightness_contrast_dialog)
|
||||
brightness_contrast_dialog = brightness_contrast_dialog_new ();
|
||||
else
|
||||
if (!GTK_WIDGET_VISIBLE (brightness_contrast_dialog->shell))
|
||||
gtk_widget_show (brightness_contrast_dialog->shell);
|
||||
|
||||
brightness_contrast_dialog->brightness = 0.0;
|
||||
brightness_contrast_dialog->contrast = 0.0;
|
||||
|
||||
brightness_contrast_dialog->drawable =
|
||||
gimp_image_active_drawable (gdisp->gimage);
|
||||
brightness_contrast_dialog->image_map =
|
||||
image_map_create (gdisp, brightness_contrast_dialog->drawable);
|
||||
|
||||
brightness_contrast_update (brightness_contrast_dialog, ALL);
|
||||
}
|
||||
|
||||
/********************************/
|
||||
/* Brightness Contrast dialog */
|
||||
/********************************/
|
||||
|
||||
static BrightnessContrastDialog *
|
||||
brightness_contrast_dialog_new (void)
|
||||
{
|
||||
BrightnessContrastDialog *bcd;
|
||||
GtkWidget *vbox;
|
||||
GtkWidget *hbox;
|
||||
GtkWidget *table;
|
||||
GtkWidget *label;
|
||||
GtkWidget *abox;
|
||||
GtkWidget *spinbutton;
|
||||
GtkWidget *slider;
|
||||
GtkWidget *toggle;
|
||||
GtkObject *data;
|
||||
|
||||
bcd = g_new (BrightnessContrastDialog, 1);
|
||||
bcd->preview = TRUE;
|
||||
|
||||
bcd->lut = gimp_lut_new ();
|
||||
|
||||
/* The shell and main vbox */
|
||||
bcd->shell =
|
||||
gimp_dialog_new (_("Brightness-Contrast"), "brightness_contrast",
|
||||
tools_help_func, NULL,
|
||||
GTK_WIN_POS_NONE,
|
||||
FALSE, TRUE, FALSE,
|
||||
|
||||
_("OK"), brightness_contrast_ok_callback,
|
||||
bcd, NULL, NULL, TRUE, FALSE,
|
||||
_("Reset"), brightness_contrast_reset_callback,
|
||||
bcd, NULL, NULL, TRUE, FALSE,
|
||||
_("Cancel"), brightness_contrast_cancel_callback,
|
||||
bcd, 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 (bcd->shell)->vbox), vbox);
|
||||
|
||||
/* The table containing sliders */
|
||||
table = gtk_table_new (2, 3, FALSE);
|
||||
gtk_table_set_col_spacings (GTK_TABLE (table), 4);
|
||||
gtk_table_set_row_spacings (GTK_TABLE (table), 2);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
|
||||
|
||||
/* Create the brightness scale widget */
|
||||
label = gtk_label_new (_("Brightness:"));
|
||||
gtk_misc_set_alignment (GTK_MISC (label), 1.0, 1.0);
|
||||
gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,
|
||||
GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
|
||||
|
||||
data = gtk_adjustment_new (0, -127, 127.0, 1.0, 10.0, 0.0);
|
||||
bcd->brightness_data = GTK_ADJUSTMENT (data);
|
||||
slider = gtk_hscale_new (GTK_ADJUSTMENT (data));
|
||||
gtk_widget_set_usize (slider, SLIDER_WIDTH, -1);
|
||||
gtk_scale_set_digits (GTK_SCALE (slider), 0);
|
||||
gtk_scale_set_value_pos (GTK_SCALE (slider), GTK_POS_TOP);
|
||||
gtk_range_set_update_policy (GTK_RANGE (slider), GTK_UPDATE_DELAYED);
|
||||
gtk_table_attach_defaults (GTK_TABLE (table), slider, 1, 2, 0, 1);
|
||||
|
||||
abox = gtk_vbox_new (FALSE, 0);
|
||||
spinbutton = gtk_spin_button_new (bcd->brightness_data, 1.0, 0);
|
||||
gtk_widget_set_usize (spinbutton, 75, -1);
|
||||
gtk_box_pack_end (GTK_BOX (abox), spinbutton, FALSE, FALSE, 0);
|
||||
gtk_table_attach (GTK_TABLE (table), abox, 2, 3, 0, 1,
|
||||
GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
|
||||
|
||||
gtk_signal_connect (GTK_OBJECT (data), "value_changed",
|
||||
GTK_SIGNAL_FUNC (brightness_contrast_brightness_adjustment_update),
|
||||
bcd);
|
||||
|
||||
gtk_widget_show (label);
|
||||
gtk_widget_show (slider);
|
||||
gtk_widget_show (spinbutton);
|
||||
gtk_widget_show (abox);
|
||||
|
||||
/* Create the contrast scale widget */
|
||||
label = gtk_label_new (_("Contrast:"));
|
||||
gtk_misc_set_alignment (GTK_MISC (label), 1.0, 1.0);
|
||||
gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2,
|
||||
GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
|
||||
|
||||
data = gtk_adjustment_new (0, -127.0, 127.0, 1.0, 10.0, 0.0);
|
||||
bcd->contrast_data = GTK_ADJUSTMENT (data);
|
||||
slider = gtk_hscale_new (GTK_ADJUSTMENT (data));
|
||||
gtk_widget_set_usize (slider, SLIDER_WIDTH, -1);
|
||||
gtk_scale_set_digits (GTK_SCALE (slider), 0);
|
||||
gtk_scale_set_value_pos (GTK_SCALE (slider), GTK_POS_TOP);
|
||||
gtk_range_set_update_policy (GTK_RANGE (slider), GTK_UPDATE_DELAYED);
|
||||
gtk_table_attach_defaults (GTK_TABLE (table), slider, 1, 2, 1, 2);
|
||||
|
||||
abox = gtk_vbox_new (FALSE, 0);
|
||||
spinbutton = gtk_spin_button_new (bcd->contrast_data, 1.0, 0);
|
||||
gtk_widget_set_usize (spinbutton, 75, -1);
|
||||
gtk_box_pack_end (GTK_BOX (abox), spinbutton, FALSE, FALSE, 0);
|
||||
gtk_table_attach (GTK_TABLE (table), abox, 2, 3, 1, 2,
|
||||
GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
|
||||
|
||||
gtk_signal_connect (GTK_OBJECT (data), "value_changed",
|
||||
GTK_SIGNAL_FUNC (brightness_contrast_contrast_adjustment_update),
|
||||
bcd);
|
||||
|
||||
gtk_widget_show (label);
|
||||
gtk_widget_show (slider);
|
||||
gtk_widget_show (spinbutton);
|
||||
gtk_widget_show (abox);
|
||||
|
||||
/* Horizontal box for preview toggle button */
|
||||
hbox = gtk_hbox_new (FALSE, 4);
|
||||
gtk_box_pack_end (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
|
||||
|
||||
/* The preview toggle */
|
||||
toggle = gtk_check_button_new_with_label (_("Preview"));
|
||||
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), bcd->preview);
|
||||
gtk_box_pack_end (GTK_BOX (hbox), toggle, FALSE, FALSE, 0);
|
||||
gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
|
||||
GTK_SIGNAL_FUNC (brightness_contrast_preview_update),
|
||||
bcd);
|
||||
|
||||
gtk_widget_show (toggle);
|
||||
gtk_widget_show (hbox);
|
||||
|
||||
gtk_widget_show (table);
|
||||
gtk_widget_show (vbox);
|
||||
gtk_widget_show (bcd->shell);
|
||||
|
||||
return bcd;
|
||||
}
|
||||
|
||||
static void
|
||||
brightness_contrast_update (BrightnessContrastDialog *bcd,
|
||||
gint update)
|
||||
{
|
||||
if (update & BRIGHTNESS)
|
||||
{
|
||||
gtk_adjustment_set_value (bcd->brightness_data, bcd->brightness);
|
||||
}
|
||||
if (update & CONTRAST)
|
||||
{
|
||||
gtk_adjustment_set_value (bcd->contrast_data, bcd->contrast);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
brightness_contrast_preview (BrightnessContrastDialog *bcd)
|
||||
{
|
||||
if (!bcd->image_map)
|
||||
{
|
||||
g_message ("brightness_contrast_preview(): No image map");
|
||||
return;
|
||||
}
|
||||
|
||||
active_tool->preserve = TRUE;
|
||||
brightness_contrast_lut_setup (bcd->lut, bcd->brightness / 255.0,
|
||||
bcd->contrast / 127.0,
|
||||
gimp_drawable_bytes (bcd->drawable));
|
||||
image_map_apply (bcd->image_map, (ImageMapApplyFunc) gimp_lut_process_2,
|
||||
(void *) bcd->lut);
|
||||
active_tool->preserve = FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
brightness_contrast_reset_callback (GtkWidget *widget,
|
||||
gpointer data)
|
||||
{
|
||||
BrightnessContrastDialog *bcd;
|
||||
|
||||
bcd = (BrightnessContrastDialog *) data;
|
||||
|
||||
bcd->brightness = 0.0;
|
||||
bcd->contrast = 0.0;
|
||||
|
||||
brightness_contrast_update (bcd, ALL);
|
||||
|
||||
if (bcd->preview)
|
||||
brightness_contrast_preview (bcd);
|
||||
}
|
||||
|
||||
static void
|
||||
brightness_contrast_ok_callback (GtkWidget *widget,
|
||||
gpointer data)
|
||||
{
|
||||
BrightnessContrastDialog *bcd;
|
||||
|
||||
bcd = (BrightnessContrastDialog *) data;
|
||||
|
||||
gimp_dialog_hide (bcd->shell);
|
||||
|
||||
active_tool->preserve = TRUE;
|
||||
|
||||
if (!bcd->preview)
|
||||
{
|
||||
brightness_contrast_lut_setup (bcd->lut, bcd->brightness / 255.0,
|
||||
bcd->contrast / 127.0,
|
||||
gimp_drawable_bytes (bcd->drawable));
|
||||
image_map_apply (bcd->image_map, (ImageMapApplyFunc) gimp_lut_process_2,
|
||||
(void *) bcd->lut);
|
||||
}
|
||||
|
||||
if (bcd->image_map)
|
||||
image_map_commit (bcd->image_map);
|
||||
|
||||
active_tool->preserve = FALSE;
|
||||
|
||||
bcd->image_map = NULL;
|
||||
|
||||
active_tool->gdisp = NULL;
|
||||
active_tool->drawable = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
brightness_contrast_cancel_callback (GtkWidget *widget,
|
||||
gpointer data)
|
||||
{
|
||||
BrightnessContrastDialog *bcd;
|
||||
|
||||
bcd = (BrightnessContrastDialog *) data;
|
||||
|
||||
gimp_dialog_hide (bcd->shell);
|
||||
|
||||
if (bcd->image_map)
|
||||
{
|
||||
active_tool->preserve = TRUE;
|
||||
image_map_abort (bcd->image_map);
|
||||
active_tool->preserve = FALSE;
|
||||
|
||||
bcd->image_map = NULL;
|
||||
gdisplays_flush ();
|
||||
}
|
||||
|
||||
active_tool->gdisp = NULL;
|
||||
active_tool->drawable = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
brightness_contrast_preview_update (GtkWidget *widget,
|
||||
gpointer data)
|
||||
{
|
||||
BrightnessContrastDialog *bcd;
|
||||
|
||||
bcd = (BrightnessContrastDialog *) data;
|
||||
|
||||
if (GTK_TOGGLE_BUTTON (widget)->active)
|
||||
{
|
||||
bcd->preview = TRUE;
|
||||
brightness_contrast_preview (bcd);
|
||||
}
|
||||
else
|
||||
{
|
||||
bcd->preview = FALSE;
|
||||
if (bcd->image_map)
|
||||
{
|
||||
active_tool->preserve = TRUE;
|
||||
image_map_clear (bcd->image_map);
|
||||
active_tool->preserve = FALSE;
|
||||
gdisplays_flush ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
brightness_contrast_brightness_adjustment_update (GtkAdjustment *adjustment,
|
||||
gpointer data)
|
||||
{
|
||||
BrightnessContrastDialog *bcd;
|
||||
|
||||
bcd = (BrightnessContrastDialog *) data;
|
||||
|
||||
if (bcd->brightness != adjustment->value)
|
||||
{
|
||||
bcd->brightness = adjustment->value;
|
||||
|
||||
if (bcd->preview)
|
||||
brightness_contrast_preview (bcd);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
brightness_contrast_contrast_adjustment_update (GtkAdjustment *adjustment,
|
||||
gpointer data)
|
||||
{
|
||||
BrightnessContrastDialog *bcd;
|
||||
|
||||
bcd = (BrightnessContrastDialog *) data;
|
||||
|
||||
if (bcd->contrast != adjustment->value)
|
||||
{
|
||||
bcd->contrast = adjustment->value;
|
||||
|
||||
if (bcd->preview)
|
||||
brightness_contrast_preview (bcd);
|
||||
}
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
/* 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.
|
||||
*/
|
||||
|
||||
#ifndef __BRIGHTNESS_CONTRAST_H__
|
||||
#define __BRIGHTNESS_CONTRAST_H__
|
||||
|
||||
|
||||
Tool * tools_new_brightness_contrast (void);
|
||||
void tools_free_brightness_contrast (Tool *tool);
|
||||
|
||||
void brightness_contrast_dialog_hide (void);
|
||||
|
||||
void brightness_contrast_initialize (GDisplay *gdisp);
|
||||
|
||||
|
||||
#endif /* __BRIGHTNESS_CONTRAST_H__ */
|
|
@ -37,10 +37,11 @@
|
|||
#include "gimplist.h"
|
||||
#include "gimprc.h"
|
||||
#include "gimpui.h"
|
||||
#include "paint_options.h"
|
||||
#include "session.h"
|
||||
#include "temp_buf.h"
|
||||
|
||||
#include "tools/paint_options.h"
|
||||
|
||||
#include "pdb/procedural_db.h"
|
||||
|
||||
#include "libgimp/gimphelpui.h"
|
||||
|
|
|
@ -1,663 +0,0 @@
|
|||
/* 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 <gtk/gtk.h>
|
||||
#include <gdk/gdkkeysyms.h>
|
||||
|
||||
#include "apptypes.h"
|
||||
|
||||
#include "appenv.h"
|
||||
#include "bucket_fill.h"
|
||||
#include "channel.h"
|
||||
#include "cursorutil.h"
|
||||
#include "drawable.h"
|
||||
#include "fuzzy_select.h"
|
||||
#include "gdisplay.h"
|
||||
#include "gimpimage.h"
|
||||
#include "gimage_mask.h"
|
||||
#include "gimpcontext.h"
|
||||
#include "gimprc.h"
|
||||
#include "gimpui.h"
|
||||
#include "paint_funcs.h"
|
||||
#include "paint_options.h"
|
||||
#include "patterns.h"
|
||||
#include "pixel_region.h"
|
||||
#include "selection.h"
|
||||
#include "temp_buf.h"
|
||||
#include "tile_manager.h"
|
||||
#include "tools.h"
|
||||
#include "undo.h"
|
||||
|
||||
#include "pdb/procedural_db.h"
|
||||
|
||||
#include "libgimp/gimpintl.h"
|
||||
|
||||
|
||||
/* the bucket fill structures */
|
||||
|
||||
typedef struct _BucketTool BucketTool;
|
||||
|
||||
struct _BucketTool
|
||||
{
|
||||
gint target_x; /* starting x coord */
|
||||
gint target_y; /* starting y coord */
|
||||
};
|
||||
|
||||
typedef struct _BucketOptions BucketOptions;
|
||||
|
||||
struct _BucketOptions
|
||||
{
|
||||
PaintOptions paint_options;
|
||||
|
||||
gboolean sample_merged;
|
||||
gboolean sample_merged_d;
|
||||
GtkWidget *sample_merged_w;
|
||||
|
||||
gdouble threshold;
|
||||
/* gdouble threshold_d; (from gimprc) */
|
||||
GtkObject *threshold_w;
|
||||
|
||||
BucketFillMode fill_mode;
|
||||
BucketFillMode fill_mode_d;
|
||||
GtkWidget *fill_mode_w[3];
|
||||
};
|
||||
|
||||
|
||||
/* the bucket fill tool options */
|
||||
static BucketOptions *bucket_options = NULL;
|
||||
|
||||
|
||||
/* local function prototypes */
|
||||
|
||||
static void bucket_fill_button_press (Tool *tool,
|
||||
GdkEventButton *bevent,
|
||||
GDisplay *gdisp);
|
||||
static void bucket_fill_button_release (Tool *tool,
|
||||
GdkEventButton *bevent,
|
||||
GDisplay *gdisp);
|
||||
static void bucket_fill_cursor_update (Tool *tool,
|
||||
GdkEventMotion *mevent,
|
||||
GDisplay *gdisp);
|
||||
|
||||
static void bucket_fill_line_color (guchar *,
|
||||
guchar *,
|
||||
guchar *,
|
||||
gboolean ,
|
||||
gint ,
|
||||
gint );
|
||||
static void bucket_fill_line_pattern (guchar *,
|
||||
guchar *,
|
||||
TempBuf *,
|
||||
gboolean ,
|
||||
gint ,
|
||||
gint ,
|
||||
gint ,
|
||||
gint );
|
||||
|
||||
|
||||
/* functions */
|
||||
|
||||
static void
|
||||
bucket_options_reset (void)
|
||||
{
|
||||
BucketOptions *options = bucket_options;
|
||||
|
||||
paint_options_reset ((PaintOptions *) options);
|
||||
|
||||
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->sample_merged_w),
|
||||
options->sample_merged_d);
|
||||
gtk_adjustment_set_value (GTK_ADJUSTMENT (options->threshold_w),
|
||||
default_threshold);
|
||||
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->fill_mode_w[options->fill_mode_d]), TRUE);
|
||||
}
|
||||
|
||||
static BucketOptions *
|
||||
bucket_options_new (void)
|
||||
{
|
||||
BucketOptions *options;
|
||||
|
||||
GtkWidget *vbox;
|
||||
GtkWidget *hbox;
|
||||
GtkWidget *label;
|
||||
GtkWidget *scale;
|
||||
GtkWidget *frame;
|
||||
|
||||
/* the new bucket fill tool options structure */
|
||||
options = g_new (BucketOptions, 1);
|
||||
paint_options_init ((PaintOptions *) options,
|
||||
BUCKET_FILL,
|
||||
bucket_options_reset);
|
||||
options->sample_merged = options->sample_merged_d = FALSE;
|
||||
options->threshold = default_threshold;
|
||||
options->fill_mode = options->fill_mode_d = FG_BUCKET_FILL;
|
||||
|
||||
/* the main vbox */
|
||||
vbox = ((ToolOptions *) options)->main_vbox;
|
||||
|
||||
/* the sample merged toggle */
|
||||
options->sample_merged_w =
|
||||
gtk_check_button_new_with_label (_("Sample Merged"));
|
||||
gtk_signal_connect (GTK_OBJECT (options->sample_merged_w), "toggled",
|
||||
GTK_SIGNAL_FUNC (gimp_toggle_button_update),
|
||||
&options->sample_merged);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), options->sample_merged_w, FALSE, FALSE, 0);
|
||||
gtk_widget_show (options->sample_merged_w);
|
||||
|
||||
/* the threshold scale */
|
||||
hbox = gtk_hbox_new (FALSE, 4);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
|
||||
|
||||
label = gtk_label_new (_("Threshold:"));
|
||||
gtk_misc_set_alignment (GTK_MISC (label), 1.0, 1.0);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
|
||||
gtk_widget_show (label);
|
||||
|
||||
options->threshold_w =
|
||||
gtk_adjustment_new (default_threshold, 1.0, 255.0, 1.0, 1.0, 0.0);
|
||||
scale = gtk_hscale_new (GTK_ADJUSTMENT (options->threshold_w));
|
||||
gtk_box_pack_start (GTK_BOX (hbox), scale, TRUE, TRUE, 0);
|
||||
gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_TOP);
|
||||
gtk_range_set_update_policy (GTK_RANGE (scale), GTK_UPDATE_DELAYED);
|
||||
gtk_signal_connect (GTK_OBJECT (options->threshold_w), "value_changed",
|
||||
GTK_SIGNAL_FUNC (gimp_double_adjustment_update),
|
||||
&options->threshold);
|
||||
gtk_widget_show (scale);
|
||||
|
||||
gtk_widget_show (hbox);
|
||||
|
||||
/* fill type */
|
||||
frame =
|
||||
gimp_radio_group_new2 (TRUE, _("Fill Type"),
|
||||
gimp_radio_button_update,
|
||||
&options->fill_mode, (gpointer) options->fill_mode,
|
||||
|
||||
_("FG Color Fill"),
|
||||
(gpointer) FG_BUCKET_FILL,
|
||||
&options->fill_mode_w[0],
|
||||
_("BG Color Fill"),
|
||||
(gpointer) BG_BUCKET_FILL,
|
||||
&options->fill_mode_w[1],
|
||||
_("Pattern Fill"),
|
||||
(gpointer) PATTERN_BUCKET_FILL,
|
||||
&options->fill_mode_w[2],
|
||||
|
||||
NULL);
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
|
||||
gtk_widget_show (frame);
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
/* bucket fill action functions */
|
||||
|
||||
static void
|
||||
bucket_fill_button_press (Tool *tool,
|
||||
GdkEventButton *bevent,
|
||||
GDisplay *gdisp)
|
||||
{
|
||||
BucketTool *bucket_tool;
|
||||
gboolean use_offsets;
|
||||
|
||||
bucket_tool = (BucketTool *) tool->private;
|
||||
|
||||
use_offsets = (bucket_options->sample_merged) ? FALSE : TRUE;
|
||||
|
||||
gdisplay_untransform_coords (gdisp, bevent->x, bevent->y,
|
||||
&bucket_tool->target_x,
|
||||
&bucket_tool->target_y, FALSE, use_offsets);
|
||||
|
||||
/* Make the tool active and set the gdisplay which owns it */
|
||||
gdk_pointer_grab (gdisp->canvas->window, FALSE,
|
||||
GDK_POINTER_MOTION_HINT_MASK |
|
||||
GDK_BUTTON1_MOTION_MASK |
|
||||
GDK_BUTTON_RELEASE_MASK,
|
||||
NULL, NULL, bevent->time);
|
||||
|
||||
/* Make the tool active and set the gdisplay which owns it */
|
||||
tool->gdisp = gdisp;
|
||||
tool->state = ACTIVE;
|
||||
}
|
||||
|
||||
static void
|
||||
bucket_fill_button_release (Tool *tool,
|
||||
GdkEventButton *bevent,
|
||||
GDisplay *gdisp)
|
||||
{
|
||||
BucketTool *bucket_tool;
|
||||
Argument *return_vals;
|
||||
gint nreturn_vals;
|
||||
|
||||
bucket_tool = (BucketTool *) tool->private;
|
||||
|
||||
gdk_pointer_ungrab (bevent->time);
|
||||
gdk_flush ();
|
||||
|
||||
/* if the 3rd button isn't pressed, fill the selected region */
|
||||
if (! (bevent->state & GDK_BUTTON3_MASK))
|
||||
{
|
||||
return_vals =
|
||||
procedural_db_run_proc ("gimp_bucket_fill",
|
||||
&nreturn_vals,
|
||||
PDB_DRAWABLE, gimp_drawable_get_ID (gimp_image_active_drawable (gdisp->gimage)),
|
||||
PDB_INT32, (gint32) bucket_options->fill_mode,
|
||||
PDB_INT32, (gint32) gimp_context_get_paint_mode (NULL),
|
||||
PDB_FLOAT, (gdouble) gimp_context_get_opacity (NULL) * 100,
|
||||
PDB_FLOAT, (gdouble) bucket_options->threshold,
|
||||
PDB_INT32, (gint32) bucket_options->sample_merged,
|
||||
PDB_FLOAT, (gdouble) bucket_tool->target_x,
|
||||
PDB_FLOAT, (gdouble) bucket_tool->target_y,
|
||||
PDB_END);
|
||||
|
||||
if (return_vals && return_vals[0].value.pdb_int == PDB_SUCCESS)
|
||||
gdisplays_flush ();
|
||||
else
|
||||
g_message (_("Bucket Fill operation failed."));
|
||||
|
||||
procedural_db_destroy_args (return_vals, nreturn_vals);
|
||||
}
|
||||
|
||||
tool->state = INACTIVE;
|
||||
}
|
||||
|
||||
static void
|
||||
bucket_fill_cursor_update (Tool *tool,
|
||||
GdkEventMotion *mevent,
|
||||
GDisplay *gdisp)
|
||||
{
|
||||
Layer *layer;
|
||||
GdkCursorType ctype = GDK_TOP_LEFT_ARROW;
|
||||
CursorModifier cmodifier = CURSOR_MODIFIER_NONE;
|
||||
gint x, y;
|
||||
gint off_x, off_y;
|
||||
|
||||
gdisplay_untransform_coords (gdisp, mevent->x, mevent->y,
|
||||
&x, &y, FALSE, FALSE);
|
||||
if ((layer = gimp_image_get_active_layer (gdisp->gimage)))
|
||||
{
|
||||
gimp_drawable_offsets (GIMP_DRAWABLE (layer), &off_x, &off_y);
|
||||
|
||||
if (x >= off_x && y >= off_y &&
|
||||
x < (off_x + gimp_drawable_width (GIMP_DRAWABLE (layer))) &&
|
||||
y < (off_y + gimp_drawable_height (GIMP_DRAWABLE (layer))))
|
||||
{
|
||||
/* One more test--is there a selected region?
|
||||
* if so, is cursor inside?
|
||||
*/
|
||||
if (gimage_mask_is_empty (gdisp->gimage) ||
|
||||
gimage_mask_value (gdisp->gimage, x, y))
|
||||
{
|
||||
ctype = GIMP_MOUSE_CURSOR;
|
||||
|
||||
switch (bucket_options->fill_mode)
|
||||
{
|
||||
case FG_BUCKET_FILL:
|
||||
cmodifier = CURSOR_MODIFIER_FOREGROUND;
|
||||
break;
|
||||
case BG_BUCKET_FILL:
|
||||
cmodifier = CURSOR_MODIFIER_BACKGROUND;
|
||||
break;
|
||||
case PATTERN_BUCKET_FILL:
|
||||
cmodifier = CURSOR_MODIFIER_PATTERN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gdisplay_install_tool_cursor (gdisp, ctype,
|
||||
BUCKET_FILL,
|
||||
cmodifier,
|
||||
FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
bucket_fill_modifier_key_func (Tool *tool,
|
||||
GdkEventKey *kevent,
|
||||
GDisplay *gdisp)
|
||||
{
|
||||
switch (kevent->keyval)
|
||||
{
|
||||
case GDK_Alt_L: case GDK_Alt_R:
|
||||
break;
|
||||
case GDK_Shift_L: case GDK_Shift_R:
|
||||
break;
|
||||
case GDK_Control_L: case GDK_Control_R:
|
||||
switch (bucket_options->fill_mode)
|
||||
{
|
||||
case FG_BUCKET_FILL:
|
||||
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (bucket_options->fill_mode_w[BG_BUCKET_FILL]), TRUE);
|
||||
break;
|
||||
case BG_BUCKET_FILL:
|
||||
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (bucket_options->fill_mode_w[FG_BUCKET_FILL]), TRUE);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
bucket_fill (GimpImage *gimage,
|
||||
GimpDrawable *drawable,
|
||||
BucketFillMode fill_mode,
|
||||
gint paint_mode,
|
||||
gdouble opacity,
|
||||
gdouble threshold,
|
||||
gboolean sample_merged,
|
||||
gdouble x,
|
||||
gdouble y)
|
||||
{
|
||||
TileManager *buf_tiles;
|
||||
PixelRegion bufPR, maskPR;
|
||||
Channel *mask = NULL;
|
||||
gint bytes;
|
||||
gboolean has_alpha;
|
||||
gint x1, y1, x2, y2;
|
||||
guchar col [MAX_CHANNELS];
|
||||
guchar *d1, *d2;
|
||||
GPattern *pattern;
|
||||
TempBuf *pat_buf;
|
||||
gboolean new_buf = FALSE;
|
||||
|
||||
pat_buf = NULL;
|
||||
|
||||
if (fill_mode == FG_BUCKET_FILL)
|
||||
gimp_image_get_foreground (gimage, drawable, col);
|
||||
else if (fill_mode == BG_BUCKET_FILL)
|
||||
gimp_image_get_background (gimage, drawable, col);
|
||||
else if (fill_mode == PATTERN_BUCKET_FILL)
|
||||
{
|
||||
pattern = gimp_context_get_pattern (NULL);
|
||||
|
||||
if (!pattern)
|
||||
{
|
||||
g_message (_("No available patterns for this operation."));
|
||||
return;
|
||||
}
|
||||
|
||||
/* If the pattern doesn't match the image in terms of color type,
|
||||
* transform it. (ie pattern is RGB, image is indexed)
|
||||
*/
|
||||
if (((pattern->mask->bytes == 3) && !gimp_drawable_is_rgb (drawable)) ||
|
||||
((pattern->mask->bytes == 1) && !gimp_drawable_is_gray (drawable)))
|
||||
{
|
||||
int size;
|
||||
|
||||
if ((pattern->mask->bytes == 1) && gimp_drawable_is_rgb (drawable))
|
||||
pat_buf = temp_buf_new (pattern->mask->width, pattern->mask->height,
|
||||
3, 0, 0, NULL);
|
||||
else
|
||||
pat_buf = temp_buf_new (pattern->mask->width, pattern->mask->height,
|
||||
1, 0, 0, NULL);
|
||||
|
||||
d1 = temp_buf_data (pattern->mask);
|
||||
d2 = temp_buf_data (pat_buf);
|
||||
|
||||
size = pattern->mask->width * pattern->mask->height;
|
||||
while (size--)
|
||||
{
|
||||
gimp_image_transform_color (gimage, drawable, d1, d2,
|
||||
(pattern->mask->bytes == 3) ? RGB : GRAY);
|
||||
d1 += pattern->mask->bytes;
|
||||
d2 += pat_buf->bytes;
|
||||
}
|
||||
|
||||
new_buf = TRUE;
|
||||
}
|
||||
else
|
||||
pat_buf = pattern->mask;
|
||||
}
|
||||
|
||||
gimp_add_busy_cursors ();
|
||||
|
||||
bytes = gimp_drawable_bytes (drawable);
|
||||
has_alpha = gimp_drawable_has_alpha (drawable);
|
||||
|
||||
/* If there is no selection mask, the do a seed bucket
|
||||
* fill...To do this, calculate a new contiguous region
|
||||
*/
|
||||
if (! gimp_drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2))
|
||||
{
|
||||
mask = find_contiguous_region (gimage, drawable, TRUE, (int) threshold,
|
||||
(int) x, (int) y, sample_merged);
|
||||
|
||||
channel_bounds (mask, &x1, &y1, &x2, &y2);
|
||||
|
||||
/* make sure we handle the mask correctly if it was sample-merged */
|
||||
if (sample_merged)
|
||||
{
|
||||
gint off_x, off_y;
|
||||
|
||||
/* Limit the channel bounds to the drawable's extents */
|
||||
gimp_drawable_offsets (drawable, &off_x, &off_y);
|
||||
x1 = CLAMP (x1, off_x, (off_x + gimp_drawable_width (drawable)));
|
||||
y1 = CLAMP (y1, off_y, (off_y + gimp_drawable_height (drawable)));
|
||||
x2 = CLAMP (x2, off_x, (off_x + gimp_drawable_width (drawable)));
|
||||
y2 = CLAMP (y2, off_y, (off_y + gimp_drawable_height (drawable)));
|
||||
|
||||
pixel_region_init (&maskPR, gimp_drawable_data (GIMP_DRAWABLE (mask)),
|
||||
x1, y1, (x2 - x1), (y2 - y1), TRUE);
|
||||
|
||||
/* translate mask bounds to drawable coords */
|
||||
x1 -= off_x;
|
||||
y1 -= off_y;
|
||||
x2 -= off_x;
|
||||
y2 -= off_y;
|
||||
}
|
||||
else
|
||||
pixel_region_init (&maskPR, gimp_drawable_data (GIMP_DRAWABLE (mask)),
|
||||
x1, y1, (x2 - x1), (y2 - y1), TRUE);
|
||||
|
||||
/* if the gimage doesn't have an alpha channel,
|
||||
* make sure that the temp buf does. We need the
|
||||
* alpha channel to fill with the region calculated above
|
||||
*/
|
||||
if (! has_alpha)
|
||||
{
|
||||
bytes ++;
|
||||
has_alpha = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
buf_tiles = tile_manager_new ((x2 - x1), (y2 - y1), bytes);
|
||||
pixel_region_init (&bufPR, buf_tiles, 0, 0, (x2 - x1), (y2 - y1), TRUE);
|
||||
|
||||
if (mask)
|
||||
bucket_fill_region (fill_mode, &bufPR, &maskPR, col, pat_buf, x1, y1, has_alpha);
|
||||
else
|
||||
bucket_fill_region (fill_mode, &bufPR, NULL, col, pat_buf, x1, y1, has_alpha);
|
||||
|
||||
pixel_region_init (&bufPR, buf_tiles, 0, 0, (x2 - x1), (y2 - y1), FALSE);
|
||||
gimp_image_apply_image (gimage, drawable, &bufPR, TRUE,
|
||||
(opacity * 255) / 100, paint_mode, NULL, x1, y1);
|
||||
|
||||
/* update the image */
|
||||
drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1));
|
||||
|
||||
/* free the temporary buffer */
|
||||
tile_manager_destroy (buf_tiles);
|
||||
|
||||
/* free the mask */
|
||||
if (mask)
|
||||
channel_delete (mask);
|
||||
|
||||
if (new_buf)
|
||||
temp_buf_free (pat_buf);
|
||||
|
||||
gimp_remove_busy_cursors (NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
bucket_fill_line_color (guchar *buf,
|
||||
guchar *mask,
|
||||
guchar *col,
|
||||
gboolean has_alpha,
|
||||
gint bytes,
|
||||
gint width)
|
||||
{
|
||||
gint alpha, b;
|
||||
|
||||
alpha = (has_alpha) ? bytes - 1 : bytes;
|
||||
while (width--)
|
||||
{
|
||||
for (b = 0; b < alpha; b++)
|
||||
buf[b] = col[b];
|
||||
|
||||
if (has_alpha)
|
||||
{
|
||||
if (mask)
|
||||
buf[alpha] = *mask++;
|
||||
else
|
||||
buf[alpha] = OPAQUE_OPACITY;
|
||||
}
|
||||
|
||||
buf += bytes;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
bucket_fill_line_pattern (guchar *buf,
|
||||
guchar *mask,
|
||||
TempBuf *pattern,
|
||||
gboolean has_alpha,
|
||||
gint bytes,
|
||||
gint x,
|
||||
gint y,
|
||||
gint width)
|
||||
{
|
||||
guchar *pat, *p;
|
||||
gint alpha, b;
|
||||
gint i;
|
||||
|
||||
/* Get a pointer to the appropriate scanline of the pattern buffer */
|
||||
pat = temp_buf_data (pattern) +
|
||||
(y % pattern->height) * pattern->width * pattern->bytes;
|
||||
|
||||
alpha = (has_alpha) ? bytes - 1 : bytes;
|
||||
for (i = 0; i < width; i++)
|
||||
{
|
||||
p = pat + ((i + x) % pattern->width) * pattern->bytes;
|
||||
|
||||
for (b = 0; b < alpha; b++)
|
||||
buf[b] = p[b];
|
||||
|
||||
if (has_alpha)
|
||||
{
|
||||
if (mask)
|
||||
buf[alpha] = *mask++;
|
||||
else
|
||||
buf[alpha] = OPAQUE_OPACITY;
|
||||
}
|
||||
|
||||
buf += bytes;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
bucket_fill_region (BucketFillMode fill_mode,
|
||||
PixelRegion *bufPR,
|
||||
PixelRegion *maskPR,
|
||||
guchar *col,
|
||||
TempBuf *pattern,
|
||||
gint off_x,
|
||||
gint off_y,
|
||||
gboolean has_alpha)
|
||||
{
|
||||
guchar *s, *m;
|
||||
gint y;
|
||||
void *pr;
|
||||
|
||||
for (pr = pixel_regions_register (2, bufPR, maskPR);
|
||||
pr != NULL;
|
||||
pr = pixel_regions_process (pr))
|
||||
{
|
||||
s = bufPR->data;
|
||||
if (maskPR)
|
||||
m = maskPR->data;
|
||||
else
|
||||
m = NULL;
|
||||
|
||||
for (y = 0; y < bufPR->h; y++)
|
||||
{
|
||||
switch (fill_mode)
|
||||
{
|
||||
case FG_BUCKET_FILL:
|
||||
case BG_BUCKET_FILL:
|
||||
bucket_fill_line_color (s, m, col, has_alpha, bufPR->bytes, bufPR->w);
|
||||
break;
|
||||
case PATTERN_BUCKET_FILL:
|
||||
bucket_fill_line_pattern (s, m, pattern, has_alpha, bufPR->bytes,
|
||||
off_x + bufPR->x, off_y + y + bufPR->y, bufPR->w);
|
||||
break;
|
||||
}
|
||||
s += bufPR->rowstride;
|
||||
|
||||
if (maskPR)
|
||||
m += maskPR->rowstride;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**********************************/
|
||||
/* Global bucket fill functions */
|
||||
/**********************************/
|
||||
|
||||
Tool *
|
||||
tools_new_bucket_fill (void)
|
||||
{
|
||||
Tool *tool;
|
||||
BucketTool *private;
|
||||
|
||||
/* The tool options */
|
||||
if (! bucket_options)
|
||||
{
|
||||
bucket_options = bucket_options_new ();
|
||||
tools_register (BUCKET_FILL, (ToolOptions *) bucket_options);
|
||||
|
||||
/* press all default buttons */
|
||||
bucket_options_reset ();
|
||||
}
|
||||
|
||||
tool = tools_new_tool (BUCKET_FILL);
|
||||
private = g_new0 (BucketTool, 1);
|
||||
|
||||
tool->scroll_lock = TRUE; /* Disallow scrolling */
|
||||
|
||||
tool->private = (gpointer) private;
|
||||
|
||||
tool->button_press_func = bucket_fill_button_press;
|
||||
tool->button_release_func = bucket_fill_button_release;
|
||||
tool->modifier_key_func = bucket_fill_modifier_key_func;
|
||||
tool->cursor_update_func = bucket_fill_cursor_update;
|
||||
|
||||
return tool;
|
||||
}
|
||||
|
||||
void
|
||||
tools_free_bucket_fill (Tool *tool)
|
||||
{
|
||||
BucketTool *bucket_tool;
|
||||
|
||||
bucket_tool = (BucketTool *) tool->private;
|
||||
|
||||
g_free (bucket_tool);
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
/* 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.
|
||||
*/
|
||||
|
||||
#ifndef __BUCKET_FILL_H__
|
||||
#define __BUCKET_FILL_H__
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
FG_BUCKET_FILL,
|
||||
BG_BUCKET_FILL,
|
||||
PATTERN_BUCKET_FILL
|
||||
} BucketFillMode;
|
||||
|
||||
|
||||
void bucket_fill (GimpImage *gimage,
|
||||
GimpDrawable *drawable,
|
||||
BucketFillMode fill_mode,
|
||||
gint paint_mode,
|
||||
gdouble opacity,
|
||||
gdouble threshold,
|
||||
gboolean sample_merged,
|
||||
gdouble x,
|
||||
gdouble y);
|
||||
|
||||
void bucket_fill_region (BucketFillMode fill_mode,
|
||||
PixelRegion *bufPR,
|
||||
PixelRegion *maskPR,
|
||||
guchar *col,
|
||||
TempBuf *pattern,
|
||||
gint off_x,
|
||||
gint off_y,
|
||||
gboolean has_alpha);
|
||||
|
||||
Tool * tools_new_bucket_fill (void);
|
||||
void tools_free_bucket_fill (Tool *tool);
|
||||
|
||||
|
||||
#endif /* __BUCKET_FILL_H__ */
|
File diff suppressed because it is too large
Load Diff
|
@ -1,40 +0,0 @@
|
|||
/* 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.
|
||||
*/
|
||||
|
||||
#ifndef __BY_COLOR_SELECT_H__
|
||||
#define __BY_COLOR_SELECT_H__
|
||||
|
||||
|
||||
Tool * tools_new_by_color_select (void);
|
||||
void tools_free_by_color_select (Tool *tool);
|
||||
|
||||
void by_color_select_initialize (GDisplay *gdisp);
|
||||
void by_color_select_initialize_by_image (GImage *gimage);
|
||||
|
||||
void by_color_select (GimpImage *gimage,
|
||||
GimpDrawable *drawable,
|
||||
guchar *color,
|
||||
gint threshold,
|
||||
SelectOps op,
|
||||
gboolean antialias,
|
||||
gboolean feather,
|
||||
gdouble feather_radius,
|
||||
gboolean sample_merged);
|
||||
|
||||
|
||||
#endif /* __BY_COLOR_SELECT_H__ */
|
773
app/clone.c
773
app/clone.c
|
@ -1,773 +0,0 @@
|
|||
/* 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 <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "apptypes.h"
|
||||
|
||||
#include "appenv.h"
|
||||
#include "draw_core.h"
|
||||
#include "drawable.h"
|
||||
#include "gdisplay.h"
|
||||
#include "gimage_mask.h"
|
||||
#include "gimpcontext.h"
|
||||
#include "gimpimage.h"
|
||||
#include "gimpui.h"
|
||||
#include "paint_funcs.h"
|
||||
#include "paint_core.h"
|
||||
#include "paint_options.h"
|
||||
#include "patterns.h"
|
||||
#include "pixel_region.h"
|
||||
#include "clone.h"
|
||||
#include "selection.h"
|
||||
#include "temp_buf.h"
|
||||
#include "tools.h"
|
||||
#include "cursorutil.h"
|
||||
|
||||
#include "libgimp/gimpintl.h"
|
||||
|
||||
|
||||
#define TARGET_HEIGHT 15
|
||||
#define TARGET_WIDTH 15
|
||||
|
||||
/* default types */
|
||||
#define CLONE_DEFAULT_TYPE IMAGE_CLONE
|
||||
#define CLONE_DEFAULT_ALIGNED ALIGN_NO
|
||||
|
||||
/* the clone structures */
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ALIGN_NO,
|
||||
ALIGN_YES,
|
||||
ALIGN_REGISTERED
|
||||
} AlignType;
|
||||
|
||||
typedef struct _CloneOptions CloneOptions;
|
||||
|
||||
struct _CloneOptions
|
||||
{
|
||||
PaintOptions paint_options;
|
||||
|
||||
CloneType type;
|
||||
CloneType type_d;
|
||||
GtkWidget *type_w[2]; /* 2 radio buttons */
|
||||
|
||||
AlignType aligned;
|
||||
AlignType aligned_d;
|
||||
GtkWidget *aligned_w[3]; /* 3 radio buttons */
|
||||
};
|
||||
|
||||
|
||||
/* forward function declarations */
|
||||
|
||||
static gpointer clone_paint_func (PaintCore *paint_core,
|
||||
GimpDrawable *drawable,
|
||||
PaintState state);
|
||||
static void clone_draw (Tool *tool);
|
||||
static void clone_motion (PaintCore *paint_core,
|
||||
GimpDrawable *drawable,
|
||||
GimpDrawable *src_drawable,
|
||||
PaintPressureOptions *pressure_options,
|
||||
CloneType type,
|
||||
gint offset_x,
|
||||
gint offset_y);
|
||||
static void clone_line_image (GImage *dest,
|
||||
GImage *src,
|
||||
GimpDrawable *d_drawable,
|
||||
GimpDrawable *s_drawable,
|
||||
guchar *s,
|
||||
guchar *d,
|
||||
gint has_alpha,
|
||||
gint src_bytes,
|
||||
gint dest_bytes,
|
||||
gint width);
|
||||
static void clone_line_pattern (GImage *dest,
|
||||
GimpDrawable *drawable,
|
||||
GPattern *pattern,
|
||||
guchar *d,
|
||||
gint x,
|
||||
gint y,
|
||||
gint bytes,
|
||||
gint width);
|
||||
|
||||
|
||||
/* the clone tool options */
|
||||
static CloneOptions *clone_options = NULL;
|
||||
|
||||
/* local variables */
|
||||
static gint src_x = 0; /* */
|
||||
static gint src_y = 0; /* position of clone src */
|
||||
static gint dest_x = 0; /* */
|
||||
static gint dest_y = 0; /* position of clone src */
|
||||
static gint offset_x = 0; /* */
|
||||
static gint offset_y = 0; /* offset for cloning */
|
||||
static gint first = TRUE;
|
||||
static gint trans_tx, trans_ty; /* transformed target */
|
||||
static GDisplay *the_src_gdisp = NULL; /* ID of source gdisplay */
|
||||
static GimpDrawable *src_drawable_ = NULL; /* source drawable */
|
||||
|
||||
static GimpDrawable *non_gui_src_drawable;
|
||||
static gint non_gui_offset_x;
|
||||
static gint non_gui_offset_y;
|
||||
static CloneType non_gui_type;
|
||||
|
||||
|
||||
/* functions */
|
||||
|
||||
static void
|
||||
clone_options_reset (void)
|
||||
{
|
||||
CloneOptions *options = clone_options;
|
||||
|
||||
paint_options_reset ((PaintOptions *) options);
|
||||
|
||||
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->type_w[options->type_d]), TRUE);
|
||||
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->aligned_w[options->aligned_d]), TRUE);
|
||||
}
|
||||
|
||||
static CloneOptions *
|
||||
clone_options_new (void)
|
||||
{
|
||||
CloneOptions *options;
|
||||
GtkWidget *vbox;
|
||||
GtkWidget *frame;
|
||||
|
||||
/* the new clone tool options structure */
|
||||
options = g_new (CloneOptions, 1);
|
||||
paint_options_init ((PaintOptions *) options,
|
||||
CLONE,
|
||||
clone_options_reset);
|
||||
options->type = options->type_d = CLONE_DEFAULT_TYPE;
|
||||
options->aligned = options->aligned_d = CLONE_DEFAULT_ALIGNED;
|
||||
|
||||
/* the main vbox */
|
||||
vbox = ((ToolOptions *) options)->main_vbox;
|
||||
|
||||
frame = gimp_radio_group_new2 (TRUE, _("Source"),
|
||||
gimp_radio_button_update,
|
||||
&options->type, (gpointer) options->type,
|
||||
|
||||
_("Image Source"), (gpointer) IMAGE_CLONE,
|
||||
&options->type_w[0],
|
||||
_("Pattern Source"), (gpointer) PATTERN_CLONE,
|
||||
&options->type_w[1],
|
||||
|
||||
NULL);
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
|
||||
gtk_widget_show (frame);
|
||||
|
||||
frame = gimp_radio_group_new2 (TRUE, _("Alignment"),
|
||||
gimp_radio_button_update,
|
||||
&options->aligned, (gpointer) options->aligned,
|
||||
|
||||
_("Non Aligned"), (gpointer) ALIGN_NO,
|
||||
&options->aligned_w[0],
|
||||
_("Aligned"), (gpointer) ALIGN_YES,
|
||||
&options->aligned_w[1],
|
||||
_("Registered"), (gpointer) ALIGN_REGISTERED,
|
||||
&options->aligned_w[2],
|
||||
|
||||
NULL);
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
|
||||
gtk_widget_show (frame);
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
static void
|
||||
clone_src_drawable_destroyed_cb (GimpDrawable *drawable,
|
||||
GimpDrawable **src_drawable)
|
||||
{
|
||||
if (drawable == *src_drawable)
|
||||
{
|
||||
*src_drawable = NULL;
|
||||
the_src_gdisp = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clone_set_src_drawable (GimpDrawable *drawable)
|
||||
{
|
||||
if (src_drawable_ == drawable)
|
||||
return;
|
||||
if (src_drawable_)
|
||||
gtk_signal_disconnect_by_data (GTK_OBJECT (src_drawable_), &src_drawable_);
|
||||
src_drawable_ = drawable;
|
||||
if (drawable)
|
||||
{
|
||||
gtk_signal_connect (GTK_OBJECT (drawable), "destroy",
|
||||
GTK_SIGNAL_FUNC (clone_src_drawable_destroyed_cb),
|
||||
&src_drawable_);
|
||||
}
|
||||
}
|
||||
|
||||
static gpointer
|
||||
clone_paint_func (PaintCore *paint_core,
|
||||
GimpDrawable *drawable,
|
||||
PaintState state)
|
||||
{
|
||||
GDisplay *gdisp;
|
||||
GDisplay *src_gdisp;
|
||||
gint x1, y1, x2, y2;
|
||||
static gint orig_src_x, orig_src_y;
|
||||
|
||||
gdisp = (GDisplay *) active_tool->gdisp;
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case PRETRACE_PAINT:
|
||||
draw_core_pause (paint_core->core, active_tool);
|
||||
break;
|
||||
|
||||
case MOTION_PAINT:
|
||||
x1 = paint_core->curx;
|
||||
y1 = paint_core->cury;
|
||||
x2 = paint_core->lastx;
|
||||
y2 = paint_core->lasty;
|
||||
|
||||
/* If the control key is down, move the src target and return */
|
||||
if (paint_core->state & GDK_CONTROL_MASK)
|
||||
{
|
||||
src_x = x1;
|
||||
src_y = y1;
|
||||
first = TRUE;
|
||||
}
|
||||
/* otherwise, update the target */
|
||||
else
|
||||
{
|
||||
dest_x = x1;
|
||||
dest_y = y1;
|
||||
|
||||
if (clone_options->aligned == ALIGN_REGISTERED)
|
||||
{
|
||||
offset_x = 0;
|
||||
offset_y = 0;
|
||||
}
|
||||
else if (first)
|
||||
{
|
||||
offset_x = src_x - dest_x;
|
||||
offset_y = src_y - dest_y;
|
||||
first = FALSE;
|
||||
}
|
||||
|
||||
src_x = dest_x + offset_x;
|
||||
src_y = dest_y + offset_y;
|
||||
|
||||
clone_motion (paint_core, drawable, src_drawable_,
|
||||
clone_options->paint_options.pressure_options,
|
||||
clone_options->type, offset_x, offset_y);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case INIT_PAINT:
|
||||
if (paint_core->state & GDK_CONTROL_MASK)
|
||||
{
|
||||
the_src_gdisp = gdisp;
|
||||
clone_set_src_drawable(drawable);
|
||||
src_x = paint_core->curx;
|
||||
src_y = paint_core->cury;
|
||||
first = TRUE;
|
||||
}
|
||||
else if (clone_options->aligned == ALIGN_NO)
|
||||
{
|
||||
first = TRUE;
|
||||
orig_src_x = src_x;
|
||||
orig_src_y = src_y;
|
||||
}
|
||||
if (clone_options->type == PATTERN_CLONE)
|
||||
if (! gimp_context_get_pattern (NULL))
|
||||
g_message (_("No patterns available for this operation."));
|
||||
break;
|
||||
|
||||
case FINISH_PAINT:
|
||||
draw_core_stop (paint_core->core, active_tool);
|
||||
if (clone_options->aligned == ALIGN_NO && !first)
|
||||
{
|
||||
src_x = orig_src_x;
|
||||
src_y = orig_src_y;
|
||||
}
|
||||
return NULL;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Calculate the coordinates of the target */
|
||||
src_gdisp = the_src_gdisp;
|
||||
if (!src_gdisp)
|
||||
{
|
||||
the_src_gdisp = gdisp;
|
||||
src_gdisp = the_src_gdisp;
|
||||
}
|
||||
|
||||
if (state == INIT_PAINT)
|
||||
/* Initialize the tool drawing core */
|
||||
draw_core_start (paint_core->core,
|
||||
src_gdisp->canvas->window,
|
||||
active_tool);
|
||||
else if (state == POSTTRACE_PAINT)
|
||||
{
|
||||
/* Find the target cursor's location onscreen */
|
||||
gdisplay_transform_coords (src_gdisp, src_x, src_y,
|
||||
&trans_tx, &trans_ty, 1);
|
||||
draw_core_resume (paint_core->core, active_tool);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
clone_cursor_update (Tool *tool,
|
||||
GdkEventMotion *mevent,
|
||||
GDisplay *gdisp)
|
||||
{
|
||||
Layer *layer;
|
||||
GdkCursorType ctype = GDK_TOP_LEFT_ARROW;
|
||||
gint x, y;
|
||||
|
||||
gdisplay_untransform_coords (gdisp, (double) mevent->x, (double) mevent->y,
|
||||
&x, &y, TRUE, FALSE);
|
||||
|
||||
if ((layer = gimp_image_get_active_layer (gdisp->gimage)))
|
||||
{
|
||||
int off_x, off_y;
|
||||
|
||||
gimp_drawable_offsets (GIMP_DRAWABLE (layer), &off_x, &off_y);
|
||||
|
||||
if (x >= off_x && y >= off_y &&
|
||||
x < (off_x + gimp_drawable_width (GIMP_DRAWABLE (layer))) &&
|
||||
y < (off_y + gimp_drawable_height (GIMP_DRAWABLE (layer))))
|
||||
{
|
||||
/* One more test--is there a selected region?
|
||||
* if so, is cursor inside?
|
||||
*/
|
||||
if (gimage_mask_is_empty (gdisp->gimage))
|
||||
ctype = GIMP_MOUSE_CURSOR;
|
||||
else if (gimage_mask_value (gdisp->gimage, x, y))
|
||||
ctype = GIMP_MOUSE_CURSOR;
|
||||
}
|
||||
}
|
||||
|
||||
if (clone_options->type == IMAGE_CLONE)
|
||||
{
|
||||
if (mevent->state & GDK_CONTROL_MASK)
|
||||
ctype = GIMP_CROSSHAIR_SMALL_CURSOR;
|
||||
else if (!src_drawable_)
|
||||
ctype = GIMP_BAD_CURSOR;
|
||||
}
|
||||
|
||||
gdisplay_install_tool_cursor (gdisp, ctype,
|
||||
ctype == GIMP_CROSSHAIR_SMALL_CURSOR ?
|
||||
TOOL_TYPE_NONE : CLONE,
|
||||
CURSOR_MODIFIER_NONE,
|
||||
FALSE);
|
||||
}
|
||||
|
||||
Tool *
|
||||
tools_new_clone (void)
|
||||
{
|
||||
Tool * tool;
|
||||
PaintCore * private;
|
||||
|
||||
/* The tool options */
|
||||
if (! clone_options)
|
||||
{
|
||||
clone_options = clone_options_new ();
|
||||
tools_register (CLONE, (ToolOptions *) clone_options);
|
||||
|
||||
/* press all default buttons */
|
||||
clone_options_reset ();
|
||||
}
|
||||
|
||||
tool = paint_core_new (CLONE);
|
||||
/* the clone tool provides its own cursor_update_function
|
||||
until I figure out somethinh nicer -- Sven */
|
||||
tool->cursor_update_func = clone_cursor_update;
|
||||
|
||||
private = (PaintCore *) tool->private;
|
||||
private->paint_func = clone_paint_func;
|
||||
private->core->draw_func = clone_draw;
|
||||
private->flags |= TOOL_TRACES_ON_WINDOW;
|
||||
|
||||
return tool;
|
||||
}
|
||||
|
||||
void
|
||||
tools_free_clone (Tool *tool)
|
||||
{
|
||||
paint_core_free (tool);
|
||||
}
|
||||
|
||||
static void
|
||||
clone_draw (Tool *tool)
|
||||
{
|
||||
PaintCore * paint_core;
|
||||
|
||||
paint_core = (PaintCore *) tool->private;
|
||||
|
||||
if (paint_core->core->gc != NULL && clone_options->type == IMAGE_CLONE)
|
||||
{
|
||||
gdk_draw_line (paint_core->core->win, paint_core->core->gc,
|
||||
trans_tx - (TARGET_WIDTH >> 1), trans_ty,
|
||||
trans_tx + (TARGET_WIDTH >> 1), trans_ty);
|
||||
gdk_draw_line (paint_core->core->win, paint_core->core->gc,
|
||||
trans_tx, trans_ty - (TARGET_HEIGHT >> 1),
|
||||
trans_tx, trans_ty + (TARGET_HEIGHT >> 1));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clone_motion (PaintCore *paint_core,
|
||||
GimpDrawable *drawable,
|
||||
GimpDrawable *src_drawable,
|
||||
PaintPressureOptions *pressure_options,
|
||||
CloneType type,
|
||||
int offset_x,
|
||||
int offset_y)
|
||||
{
|
||||
GImage *gimage;
|
||||
GImage *src_gimage = NULL;
|
||||
unsigned char * s;
|
||||
unsigned char * d;
|
||||
TempBuf * orig;
|
||||
TempBuf * area;
|
||||
void * pr;
|
||||
int y;
|
||||
int x1, y1, x2, y2;
|
||||
int has_alpha = -1;
|
||||
PixelRegion srcPR, destPR;
|
||||
GPattern *pattern;
|
||||
gint opacity;
|
||||
gdouble scale;
|
||||
|
||||
pr = NULL;
|
||||
pattern = NULL;
|
||||
|
||||
/* Make sure we still have a source if we are doing image cloning */
|
||||
if (type == IMAGE_CLONE)
|
||||
{
|
||||
if (!src_drawable)
|
||||
return;
|
||||
if (! (src_gimage = gimp_drawable_gimage (src_drawable)))
|
||||
return;
|
||||
/* Determine whether the source image has an alpha channel */
|
||||
has_alpha = gimp_drawable_has_alpha (src_drawable);
|
||||
}
|
||||
|
||||
/* We always need a destination image */
|
||||
if (! (gimage = gimp_drawable_gimage (drawable)))
|
||||
return;
|
||||
|
||||
if (pressure_options->size)
|
||||
scale = paint_core->curpressure;
|
||||
else
|
||||
scale = 1.0;
|
||||
|
||||
/* Get a region which can be used to paint to */
|
||||
if (! (area = paint_core_get_paint_area (paint_core, drawable, scale)))
|
||||
return;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case IMAGE_CLONE:
|
||||
/* Set the paint area to transparent */
|
||||
temp_buf_data_clear (area);
|
||||
|
||||
/* If the source gimage is different from the destination,
|
||||
* then we should copy straight from the destination image
|
||||
* to the canvas.
|
||||
* Otherwise, we need a call to get_orig_image to make sure
|
||||
* we get a copy of the unblemished (offset) image
|
||||
*/
|
||||
if (src_drawable != drawable)
|
||||
{
|
||||
x1 = CLAMP (area->x + offset_x, 0, gimp_drawable_width (src_drawable));
|
||||
y1 = CLAMP (area->y + offset_y, 0, gimp_drawable_height (src_drawable));
|
||||
x2 = CLAMP (area->x + offset_x + area->width,
|
||||
0, gimp_drawable_width (src_drawable));
|
||||
y2 = CLAMP (area->y + offset_y + area->height,
|
||||
0, gimp_drawable_height (src_drawable));
|
||||
|
||||
if (!(x2 - x1) || !(y2 - y1))
|
||||
return;
|
||||
|
||||
pixel_region_init (&srcPR, gimp_drawable_data (src_drawable),
|
||||
x1, y1, (x2 - x1), (y2 - y1), FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
x1 = CLAMP (area->x + offset_x, 0, gimp_drawable_width (drawable));
|
||||
y1 = CLAMP (area->y + offset_y, 0, gimp_drawable_height (drawable));
|
||||
x2 = CLAMP (area->x + offset_x + area->width,
|
||||
0, gimp_drawable_width (drawable));
|
||||
y2 = CLAMP (area->y + offset_y + area->height,
|
||||
0, gimp_drawable_height (drawable));
|
||||
|
||||
if (!(x2 - x1) || !(y2 - y1))
|
||||
return;
|
||||
|
||||
/* get the original image */
|
||||
orig = paint_core_get_orig_image (paint_core, drawable, x1, y1, x2, y2);
|
||||
|
||||
srcPR.bytes = orig->bytes;
|
||||
srcPR.x = 0; srcPR.y = 0;
|
||||
srcPR.w = x2 - x1;
|
||||
srcPR.h = y2 - y1;
|
||||
srcPR.rowstride = srcPR.bytes * orig->width;
|
||||
srcPR.data = temp_buf_data (orig);
|
||||
}
|
||||
|
||||
offset_x = x1 - (area->x + offset_x);
|
||||
offset_y = y1 - (area->y + offset_y);
|
||||
|
||||
/* configure the destination */
|
||||
destPR.bytes = area->bytes;
|
||||
destPR.x = 0; destPR.y = 0;
|
||||
destPR.w = srcPR.w;
|
||||
destPR.h = srcPR.h;
|
||||
destPR.rowstride = destPR.bytes * area->width;
|
||||
destPR.data = temp_buf_data (area) + offset_y * destPR.rowstride +
|
||||
offset_x * destPR.bytes;
|
||||
|
||||
pr = pixel_regions_register (2, &srcPR, &destPR);
|
||||
break;
|
||||
|
||||
case PATTERN_CLONE:
|
||||
pattern = gimp_context_get_pattern (NULL);
|
||||
|
||||
if (!pattern)
|
||||
return;
|
||||
|
||||
destPR.bytes = area->bytes;
|
||||
destPR.x = 0; destPR.y = 0;
|
||||
destPR.w = area->width;
|
||||
destPR.h = area->height;
|
||||
destPR.rowstride = destPR.bytes * area->width;
|
||||
destPR.data = temp_buf_data (area);
|
||||
|
||||
pr = pixel_regions_register (1, &destPR);
|
||||
break;
|
||||
}
|
||||
|
||||
for (; pr != NULL; pr = pixel_regions_process (pr))
|
||||
{
|
||||
s = srcPR.data;
|
||||
d = destPR.data;
|
||||
for (y = 0; y < destPR.h; y++)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case IMAGE_CLONE:
|
||||
clone_line_image (gimage, src_gimage, drawable, src_drawable, s, d,
|
||||
has_alpha, srcPR.bytes, destPR.bytes, destPR.w);
|
||||
s += srcPR.rowstride;
|
||||
break;
|
||||
case PATTERN_CLONE:
|
||||
clone_line_pattern (gimage, drawable, pattern, d,
|
||||
area->x + offset_x, area->y + y + offset_y,
|
||||
destPR.bytes, destPR.w);
|
||||
break;
|
||||
}
|
||||
|
||||
d += destPR.rowstride;
|
||||
}
|
||||
}
|
||||
|
||||
opacity = 255.0 * gimp_context_get_opacity (NULL);
|
||||
if (pressure_options->opacity)
|
||||
opacity = opacity * 2.0 * paint_core->curpressure;
|
||||
|
||||
/* paste the newly painted canvas to the gimage which is being worked on */
|
||||
paint_core_paste_canvas (paint_core, drawable,
|
||||
MIN (opacity, 255),
|
||||
(int) (gimp_context_get_opacity (NULL) * 255),
|
||||
gimp_context_get_paint_mode (NULL),
|
||||
pressure_options->pressure ? PRESSURE : SOFT,
|
||||
scale, CONSTANT);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
clone_line_image (GImage *dest,
|
||||
GImage *src,
|
||||
GimpDrawable *d_drawable,
|
||||
GimpDrawable *s_drawable,
|
||||
unsigned char *s,
|
||||
unsigned char *d,
|
||||
int has_alpha,
|
||||
int src_bytes,
|
||||
int dest_bytes,
|
||||
int width)
|
||||
{
|
||||
unsigned char rgb[3];
|
||||
int src_alpha, dest_alpha;
|
||||
|
||||
src_alpha = src_bytes - 1;
|
||||
dest_alpha = dest_bytes - 1;
|
||||
|
||||
while (width--)
|
||||
{
|
||||
gimp_image_get_color (src, gimp_drawable_type (s_drawable), rgb, s);
|
||||
gimp_image_transform_color (dest, d_drawable, rgb, d, RGB);
|
||||
|
||||
if (has_alpha)
|
||||
d[dest_alpha] = s[src_alpha];
|
||||
else
|
||||
d[dest_alpha] = OPAQUE_OPACITY;
|
||||
|
||||
s += src_bytes;
|
||||
d += dest_bytes;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clone_line_pattern (GImage *dest,
|
||||
GimpDrawable *drawable,
|
||||
GPattern *pattern,
|
||||
unsigned char *d,
|
||||
int x,
|
||||
int y,
|
||||
int bytes,
|
||||
int width)
|
||||
{
|
||||
guchar *pat, *p;
|
||||
gint color, alpha;
|
||||
gint i;
|
||||
|
||||
/* Make sure x, y are positive */
|
||||
while (x < 0)
|
||||
x += pattern->mask->width;
|
||||
while (y < 0)
|
||||
y += pattern->mask->height;
|
||||
|
||||
/* Get a pointer to the appropriate scanline of the pattern buffer */
|
||||
pat = temp_buf_data (pattern->mask) +
|
||||
(y % pattern->mask->height) * pattern->mask->width * pattern->mask->bytes;
|
||||
color = (pattern->mask->bytes == 3) ? RGB : GRAY;
|
||||
|
||||
alpha = bytes - 1;
|
||||
|
||||
for (i = 0; i < width; i++)
|
||||
{
|
||||
p = pat + ((i + x) % pattern->mask->width) * pattern->mask->bytes;
|
||||
|
||||
gimp_image_transform_color (dest, drawable, p, d, color);
|
||||
|
||||
d[alpha] = OPAQUE_OPACITY;
|
||||
|
||||
d += bytes;
|
||||
}
|
||||
}
|
||||
|
||||
static gpointer
|
||||
clone_non_gui_paint_func (PaintCore *paint_core,
|
||||
GimpDrawable *drawable,
|
||||
PaintState state)
|
||||
{
|
||||
clone_motion (paint_core, drawable, non_gui_src_drawable,
|
||||
&non_gui_pressure_options,
|
||||
non_gui_type, non_gui_offset_x, non_gui_offset_y);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gboolean
|
||||
clone_non_gui_default (GimpDrawable *drawable,
|
||||
gint num_strokes,
|
||||
gdouble *stroke_array)
|
||||
{
|
||||
GimpDrawable *src_drawable = NULL;
|
||||
CloneType clone_type = CLONE_DEFAULT_TYPE;
|
||||
gdouble local_src_x = 0.0;
|
||||
gdouble local_src_y = 0.0;
|
||||
CloneOptions *options = clone_options;
|
||||
|
||||
if (options)
|
||||
{
|
||||
clone_type = options->type;
|
||||
src_drawable = src_drawable_;
|
||||
local_src_x = src_x;
|
||||
local_src_y = src_y;
|
||||
}
|
||||
|
||||
return clone_non_gui (drawable,
|
||||
src_drawable,
|
||||
clone_type,
|
||||
local_src_x,local_src_y,
|
||||
num_strokes, stroke_array);
|
||||
}
|
||||
|
||||
gboolean
|
||||
clone_non_gui (GimpDrawable *drawable,
|
||||
GimpDrawable *src_drawable,
|
||||
CloneType clone_type,
|
||||
gdouble src_x,
|
||||
gdouble src_y,
|
||||
gint num_strokes,
|
||||
gdouble *stroke_array)
|
||||
{
|
||||
gint i;
|
||||
|
||||
if (paint_core_init (&non_gui_paint_core, drawable,
|
||||
stroke_array[0], stroke_array[1]))
|
||||
{
|
||||
/* Set the paint core's paint func */
|
||||
non_gui_paint_core.paint_func = clone_non_gui_paint_func;
|
||||
|
||||
non_gui_type = clone_type;
|
||||
|
||||
non_gui_src_drawable = src_drawable;
|
||||
|
||||
non_gui_paint_core.startx = non_gui_paint_core.lastx = stroke_array[0];
|
||||
non_gui_paint_core.starty = non_gui_paint_core.lasty = stroke_array[1];
|
||||
|
||||
non_gui_offset_x = (int) (src_x - non_gui_paint_core.startx);
|
||||
non_gui_offset_y = (int) (src_y - non_gui_paint_core.starty);
|
||||
|
||||
clone_non_gui_paint_func (&non_gui_paint_core, drawable, 0);
|
||||
|
||||
for (i = 1; i < num_strokes; i++)
|
||||
{
|
||||
non_gui_paint_core.curx = stroke_array[i * 2 + 0];
|
||||
non_gui_paint_core.cury = stroke_array[i * 2 + 1];
|
||||
|
||||
paint_core_interpolate (&non_gui_paint_core, drawable);
|
||||
|
||||
non_gui_paint_core.lastx = non_gui_paint_core.curx;
|
||||
non_gui_paint_core.lasty = non_gui_paint_core.cury;
|
||||
}
|
||||
|
||||
/* Finish the painting */
|
||||
paint_core_finish (&non_gui_paint_core, drawable, -1);
|
||||
|
||||
/* Cleanup */
|
||||
paint_core_cleanup ();
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
}
|
44
app/clone.h
44
app/clone.h
|
@ -1,44 +0,0 @@
|
|||
/* 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.
|
||||
*/
|
||||
|
||||
#ifndef __CLONE_H__
|
||||
#define __CLONE_H__
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
IMAGE_CLONE,
|
||||
PATTERN_CLONE
|
||||
} CloneType;
|
||||
|
||||
|
||||
gboolean clone_non_gui (GimpDrawable *drawable,
|
||||
GimpDrawable *src_drawable,
|
||||
CloneType clone_type,
|
||||
gdouble src_x,
|
||||
gdouble src_y,
|
||||
gint num_strokes,
|
||||
gdouble *stroke_array);
|
||||
gboolean clone_non_gui_default (GimpDrawable *drawable,
|
||||
gint num_strokes,
|
||||
gdouble *stroke_array);
|
||||
Tool * tools_new_clone (void);
|
||||
void tools_free_clone (Tool *tool);
|
||||
|
||||
|
||||
#endif /* __CLONE_H__ */
|
|
@ -1,749 +0,0 @@
|
|||
/* 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 <gtk/gtk.h>
|
||||
|
||||
#include "apptypes.h"
|
||||
|
||||
#include "appenv.h"
|
||||
#include "color_balance.h"
|
||||
#include "color_transfer.h"
|
||||
#include "drawable.h"
|
||||
#include "gdisplay.h"
|
||||
#include "gimpimage.h"
|
||||
#include "gimpui.h"
|
||||
#include "image_map.h"
|
||||
#include "pixel_region.h"
|
||||
#include "tools.h"
|
||||
#include "tool_options.h"
|
||||
|
||||
#include "libgimp/gimpintl.h"
|
||||
#include "libgimp/gimpmath.h"
|
||||
#include "libgimp/gimpcolorspace.h"
|
||||
|
||||
|
||||
#define CYAN_RED 0x1
|
||||
#define MAGENTA_GREEN 0x2
|
||||
#define YELLOW_BLUE 0x4
|
||||
#define ALL (CYAN_RED | MAGENTA_GREEN | YELLOW_BLUE)
|
||||
|
||||
/* the color balance structures */
|
||||
|
||||
typedef struct _ColorBalance ColorBalance;
|
||||
|
||||
struct _ColorBalance
|
||||
{
|
||||
gint x, y; /* coords for last mouse click */
|
||||
};
|
||||
|
||||
/* the color balance tool options */
|
||||
static ToolOptions *color_balance_options = NULL;
|
||||
|
||||
/* the color balance dialog */
|
||||
static ColorBalanceDialog *color_balance_dialog = NULL;
|
||||
|
||||
|
||||
/* color balance action functions */
|
||||
|
||||
static void color_balance_control (Tool *tool,
|
||||
ToolAction action,
|
||||
GDisplay *gdisp);
|
||||
|
||||
static ColorBalanceDialog * color_balance_dialog_new (void);
|
||||
|
||||
static void color_balance_update (ColorBalanceDialog *cbd,
|
||||
gint );
|
||||
static void color_balance_preview (ColorBalanceDialog *cbd);
|
||||
static void color_balance_reset_callback (GtkWidget *widget,
|
||||
gpointer data);
|
||||
static void color_balance_ok_callback (GtkWidget *widget,
|
||||
gpointer data);
|
||||
static void color_balance_cancel_callback (GtkWidget *widget,
|
||||
gpointer data);
|
||||
static void color_balance_range_callback (GtkWidget *widget,
|
||||
gpointer data);
|
||||
static void color_balance_preserve_update (GtkWidget *widget,
|
||||
gpointer data);
|
||||
static void color_balance_preview_update (GtkWidget *widget,
|
||||
gpointer data);
|
||||
static void color_balance_cr_adjustment_update (GtkAdjustment *adj,
|
||||
gpointer data);
|
||||
static void color_balance_mg_adjustment_update (GtkAdjustment *adj,
|
||||
gpointer data);
|
||||
static void color_balance_yb_adjustment_update (GtkAdjustment *adj,
|
||||
gpointer data);
|
||||
|
||||
/* color balance machinery */
|
||||
|
||||
void
|
||||
color_balance (PixelRegion *srcPR,
|
||||
PixelRegion *destPR,
|
||||
void *data)
|
||||
{
|
||||
ColorBalanceDialog *cbd;
|
||||
guchar *src, *s;
|
||||
guchar *dest, *d;
|
||||
gboolean alpha;
|
||||
gint r, g, b;
|
||||
gint r_n, g_n, b_n;
|
||||
gint w, h;
|
||||
|
||||
cbd = (ColorBalanceDialog *) data;
|
||||
|
||||
h = srcPR->h;
|
||||
src = srcPR->data;
|
||||
dest = destPR->data;
|
||||
alpha = (srcPR->bytes == 4) ? TRUE : FALSE;
|
||||
|
||||
while (h--)
|
||||
{
|
||||
w = srcPR->w;
|
||||
s = src;
|
||||
d = dest;
|
||||
while (w--)
|
||||
{
|
||||
r = s[RED_PIX];
|
||||
g = s[GREEN_PIX];
|
||||
b = s[BLUE_PIX];
|
||||
|
||||
r_n = cbd->r_lookup[r];
|
||||
g_n = cbd->g_lookup[g];
|
||||
b_n = cbd->b_lookup[b];
|
||||
|
||||
if (cbd->preserve_luminosity)
|
||||
{
|
||||
gimp_rgb_to_hls_int (&r_n, &g_n, &b_n);
|
||||
g_n = gimp_rgb_to_l_int (r, g, b);
|
||||
gimp_hls_to_rgb_int (&r_n, &g_n, &b_n);
|
||||
}
|
||||
|
||||
d[RED_PIX] = r_n;
|
||||
d[GREEN_PIX] = g_n;
|
||||
d[BLUE_PIX] = b_n;
|
||||
|
||||
if (alpha)
|
||||
d[ALPHA_PIX] = s[ALPHA_PIX];
|
||||
|
||||
s += srcPR->bytes;
|
||||
d += destPR->bytes;
|
||||
}
|
||||
|
||||
src += srcPR->rowstride;
|
||||
dest += destPR->rowstride;
|
||||
}
|
||||
}
|
||||
|
||||
/* color balance action functions */
|
||||
|
||||
static void
|
||||
color_balance_control (Tool *tool,
|
||||
ToolAction action,
|
||||
GDisplay *gdisp)
|
||||
{
|
||||
ColorBalance * color_bal;
|
||||
|
||||
color_bal = (ColorBalance *) tool->private;
|
||||
|
||||
switch (action)
|
||||
{
|
||||
case PAUSE:
|
||||
break;
|
||||
|
||||
case RESUME:
|
||||
break;
|
||||
|
||||
case HALT:
|
||||
color_balance_dialog_hide ();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Tool *
|
||||
tools_new_color_balance (void)
|
||||
{
|
||||
Tool * tool;
|
||||
ColorBalance * private;
|
||||
|
||||
/* The tool options */
|
||||
if (!color_balance_options)
|
||||
{
|
||||
color_balance_options = tool_options_new (_("Color Balance"));
|
||||
tools_register (COLOR_BALANCE, color_balance_options);
|
||||
}
|
||||
|
||||
tool = tools_new_tool (COLOR_BALANCE);
|
||||
private = g_new0 (ColorBalance, 1);
|
||||
|
||||
tool->scroll_lock = TRUE; /* Disallow scrolling */
|
||||
tool->preserve = FALSE; /* Don't preserve on drawable change */
|
||||
|
||||
tool->private = (void *) private;
|
||||
|
||||
tool->control_func = color_balance_control;
|
||||
|
||||
return tool;
|
||||
}
|
||||
|
||||
void
|
||||
color_balance_dialog_hide (void)
|
||||
{
|
||||
if (color_balance_dialog)
|
||||
color_balance_cancel_callback (NULL, (gpointer) color_balance_dialog);
|
||||
}
|
||||
|
||||
void
|
||||
tools_free_color_balance (Tool *tool)
|
||||
{
|
||||
ColorBalance * color_bal;
|
||||
|
||||
color_bal = (ColorBalance *) tool->private;
|
||||
|
||||
/* Close the color select dialog */
|
||||
color_balance_dialog_hide ();
|
||||
|
||||
g_free (color_bal);
|
||||
}
|
||||
|
||||
void
|
||||
color_balance_initialize (GDisplay *gdisp)
|
||||
{
|
||||
gint i;
|
||||
|
||||
if (! gimp_drawable_is_rgb (gimp_image_active_drawable (gdisp->gimage)))
|
||||
{
|
||||
g_message (_("Color balance operates only on RGB color drawables."));
|
||||
return;
|
||||
}
|
||||
|
||||
/* The color balance dialog */
|
||||
if (!color_balance_dialog)
|
||||
color_balance_dialog = color_balance_dialog_new ();
|
||||
else
|
||||
if (!GTK_WIDGET_VISIBLE (color_balance_dialog->shell))
|
||||
gtk_widget_show (color_balance_dialog->shell);
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
color_balance_dialog->cyan_red[i] = 0.0;
|
||||
color_balance_dialog->magenta_green[i] = 0.0;
|
||||
color_balance_dialog->yellow_blue[i] = 0.0;
|
||||
}
|
||||
|
||||
color_balance_dialog->drawable = gimp_image_active_drawable (gdisp->gimage);
|
||||
color_balance_dialog->image_map =
|
||||
image_map_create (gdisp, color_balance_dialog->drawable);
|
||||
|
||||
color_balance_update (color_balance_dialog, ALL);
|
||||
}
|
||||
|
||||
/**************************/
|
||||
/* Color Balance dialog */
|
||||
/**************************/
|
||||
|
||||
static ColorBalanceDialog *
|
||||
color_balance_dialog_new (void)
|
||||
{
|
||||
ColorBalanceDialog *cbd;
|
||||
GtkWidget *vbox;
|
||||
GtkWidget *hbox;
|
||||
GtkWidget *table;
|
||||
GtkWidget *start_label;
|
||||
GtkWidget *end_label;
|
||||
GtkWidget *label;
|
||||
GtkWidget *spinbutton;
|
||||
GtkWidget *slider;
|
||||
GtkWidget *toggle;
|
||||
GtkWidget *radio_button;
|
||||
GtkObject *data;
|
||||
GSList *group = NULL;
|
||||
gint i;
|
||||
|
||||
gchar *appl_mode_names[] =
|
||||
{
|
||||
N_("Shadows"),
|
||||
N_("Midtones"),
|
||||
N_("Highlights")
|
||||
};
|
||||
|
||||
cbd = g_new (ColorBalanceDialog, 1);
|
||||
cbd->preserve_luminosity = TRUE;
|
||||
cbd->preview = TRUE;
|
||||
cbd->application_mode = SHADOWS;
|
||||
|
||||
/* The shell and main vbox */
|
||||
cbd->shell = gimp_dialog_new (_("Color Balance"), "color_balance",
|
||||
tools_help_func, NULL,
|
||||
GTK_WIN_POS_NONE,
|
||||
FALSE, TRUE, FALSE,
|
||||
|
||||
_("OK"), color_balance_ok_callback,
|
||||
cbd, NULL, NULL, TRUE, FALSE,
|
||||
_("Reset"), color_balance_reset_callback,
|
||||
cbd, NULL, NULL, TRUE, FALSE,
|
||||
_("Cancel"), color_balance_cancel_callback,
|
||||
cbd, 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 (cbd->shell)->vbox), vbox);
|
||||
|
||||
/* Horizontal box for application mode */
|
||||
hbox = gtk_hbox_new (FALSE, 4);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
|
||||
|
||||
label = gtk_label_new (_("Color Levels:"));
|
||||
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
|
||||
gtk_widget_show (label);
|
||||
|
||||
/* cyan-red spinbutton */
|
||||
data = gtk_adjustment_new (0, -100.0, 100.0, 1.0, 10.0, 0.0);
|
||||
cbd->cyan_red_data = GTK_ADJUSTMENT (data);
|
||||
|
||||
spinbutton = gtk_spin_button_new (cbd->cyan_red_data, 1.0, 0);
|
||||
gtk_widget_set_usize (spinbutton, 75, -1);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), spinbutton, FALSE, FALSE, 0);
|
||||
gtk_widget_show (spinbutton);
|
||||
|
||||
/* magenta-green spinbutton */
|
||||
data = gtk_adjustment_new (0, -100.0, 100.0, 1.0, 10.0, 0.0);
|
||||
cbd->magenta_green_data = GTK_ADJUSTMENT (data);
|
||||
|
||||
spinbutton = gtk_spin_button_new (cbd->magenta_green_data, 1.0, 0);
|
||||
gtk_widget_set_usize (spinbutton, 75, -1);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), spinbutton, FALSE, FALSE, 0);
|
||||
gtk_widget_show (spinbutton);
|
||||
|
||||
/* yellow-blue spinbutton */
|
||||
data = gtk_adjustment_new (0, -100.0, 100.0, 1.0, 10.0, 0.0);
|
||||
cbd->yellow_blue_data = GTK_ADJUSTMENT (data);
|
||||
|
||||
spinbutton = gtk_spin_button_new (cbd->yellow_blue_data, 1.0, 0);
|
||||
gtk_widget_set_usize (spinbutton, 75, -1);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), spinbutton, FALSE, FALSE, 0);
|
||||
gtk_widget_show (spinbutton);
|
||||
|
||||
gtk_widget_show (hbox);
|
||||
|
||||
/* The table containing sliders */
|
||||
table = gtk_table_new (3, 3, FALSE);
|
||||
gtk_table_set_col_spacings (GTK_TABLE (table), 4);
|
||||
gtk_table_set_row_spacings (GTK_TABLE (table), 2);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
|
||||
|
||||
/* Create the cyan-red scale widget */
|
||||
start_label = gtk_label_new (_("Cyan"));
|
||||
gtk_misc_set_alignment (GTK_MISC (start_label), 1.0, 1.0);
|
||||
gtk_table_attach (GTK_TABLE (table), start_label, 0, 1, 0, 1,
|
||||
GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
|
||||
|
||||
slider = gtk_hscale_new (cbd->cyan_red_data);
|
||||
gtk_scale_set_digits (GTK_SCALE (slider), 0);
|
||||
gtk_scale_set_value_pos (GTK_SCALE (slider), GTK_POS_TOP);
|
||||
gtk_range_set_update_policy (GTK_RANGE (slider), GTK_UPDATE_DELAYED);
|
||||
gtk_table_attach_defaults (GTK_TABLE (table), slider, 1, 2, 0, 1);
|
||||
|
||||
gtk_signal_connect (GTK_OBJECT (cbd->cyan_red_data), "value_changed",
|
||||
GTK_SIGNAL_FUNC (color_balance_cr_adjustment_update),
|
||||
cbd);
|
||||
|
||||
end_label = gtk_label_new (_("Red"));
|
||||
gtk_misc_set_alignment (GTK_MISC (end_label), 0.0, 1.0);
|
||||
gtk_table_attach (GTK_TABLE (table), end_label, 2, 3, 0, 1,
|
||||
GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
|
||||
|
||||
gtk_widget_show (start_label);
|
||||
gtk_widget_show (end_label);
|
||||
gtk_widget_show (slider);
|
||||
|
||||
/* Create the magenta-green scale widget */
|
||||
start_label = gtk_label_new (_("Magenta"));
|
||||
gtk_misc_set_alignment (GTK_MISC (start_label), 1.0, 1.0);
|
||||
gtk_table_attach (GTK_TABLE (table), start_label, 0, 1, 1, 2,
|
||||
GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
|
||||
|
||||
slider = gtk_hscale_new (cbd->magenta_green_data);
|
||||
gtk_scale_set_digits (GTK_SCALE (slider), 0);
|
||||
gtk_scale_set_value_pos (GTK_SCALE (slider), GTK_POS_TOP);
|
||||
gtk_range_set_update_policy (GTK_RANGE (slider), GTK_UPDATE_DELAYED);
|
||||
gtk_table_attach_defaults (GTK_TABLE (table), slider, 1, 2, 1, 2);
|
||||
|
||||
gtk_signal_connect (GTK_OBJECT (cbd->magenta_green_data), "value_changed",
|
||||
GTK_SIGNAL_FUNC (color_balance_mg_adjustment_update),
|
||||
cbd);
|
||||
|
||||
end_label = gtk_label_new (_("Green"));
|
||||
gtk_misc_set_alignment (GTK_MISC (end_label), 0.0, 1.0);
|
||||
gtk_table_attach (GTK_TABLE (table), end_label, 2, 3, 1, 2,
|
||||
GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
|
||||
|
||||
gtk_widget_show (start_label);
|
||||
gtk_widget_show (end_label);
|
||||
gtk_widget_show (slider);
|
||||
|
||||
/* Create the yellow-blue scale widget */
|
||||
start_label = gtk_label_new (_("Yellow"));
|
||||
gtk_misc_set_alignment (GTK_MISC (start_label), 1.0, 1.0);
|
||||
gtk_table_attach (GTK_TABLE (table), start_label, 0, 1, 2, 3,
|
||||
GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
|
||||
|
||||
slider = gtk_hscale_new (cbd->yellow_blue_data);
|
||||
gtk_scale_set_digits (GTK_SCALE (slider), 0);
|
||||
gtk_scale_set_value_pos (GTK_SCALE (slider), GTK_POS_TOP);
|
||||
gtk_range_set_update_policy (GTK_RANGE (slider), GTK_UPDATE_DELAYED);
|
||||
gtk_table_attach_defaults (GTK_TABLE (table), slider, 1, 2, 2, 3);
|
||||
|
||||
gtk_signal_connect (GTK_OBJECT (cbd->yellow_blue_data), "value_changed",
|
||||
GTK_SIGNAL_FUNC (color_balance_yb_adjustment_update),
|
||||
cbd);
|
||||
|
||||
end_label = gtk_label_new (_("Blue"));
|
||||
gtk_misc_set_alignment (GTK_MISC (end_label), 0.0, 1.0);
|
||||
gtk_table_attach (GTK_TABLE (table), end_label, 2, 3, 2, 3,
|
||||
GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
|
||||
|
||||
gtk_widget_show (start_label);
|
||||
gtk_widget_show (end_label);
|
||||
gtk_widget_show (slider);
|
||||
|
||||
gtk_widget_show (table);
|
||||
|
||||
/* Horizontal box for application mode */
|
||||
hbox = gtk_hbox_new (TRUE, 4);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
|
||||
|
||||
/* the radio buttons for application mode */
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
radio_button =
|
||||
gtk_radio_button_new_with_label (group, gettext (appl_mode_names[i]));
|
||||
group = gtk_radio_button_group (GTK_RADIO_BUTTON (radio_button));
|
||||
gtk_box_pack_start (GTK_BOX (hbox), radio_button, TRUE, FALSE, 0);
|
||||
|
||||
gtk_object_set_user_data (GTK_OBJECT (radio_button), (gpointer) i);
|
||||
gtk_signal_connect (GTK_OBJECT (radio_button), "toggled",
|
||||
GTK_SIGNAL_FUNC (color_balance_range_callback),
|
||||
cbd);
|
||||
|
||||
gtk_widget_show (radio_button);
|
||||
}
|
||||
|
||||
gtk_widget_show (hbox);
|
||||
|
||||
/* Horizontal box for preview and preserve luminosity toggle buttons */
|
||||
hbox = gtk_hbox_new (FALSE, 4);
|
||||
gtk_box_pack_end (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
|
||||
|
||||
/* The preserve luminosity toggle */
|
||||
toggle = gtk_check_button_new_with_label (_("Preserve Luminosity"));
|
||||
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle),
|
||||
cbd->preserve_luminosity);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), toggle, FALSE, FALSE, 0);
|
||||
gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
|
||||
GTK_SIGNAL_FUNC (color_balance_preserve_update),
|
||||
cbd);
|
||||
gtk_widget_show (toggle);
|
||||
|
||||
/* The preview toggle */
|
||||
toggle = gtk_check_button_new_with_label (_("Preview"));
|
||||
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), cbd->preview);
|
||||
gtk_box_pack_end (GTK_BOX (hbox), toggle, FALSE, FALSE, 0);
|
||||
gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
|
||||
GTK_SIGNAL_FUNC (color_balance_preview_update),
|
||||
cbd);
|
||||
gtk_widget_show (toggle);
|
||||
|
||||
gtk_widget_show (hbox);
|
||||
|
||||
gtk_widget_show (vbox);
|
||||
gtk_widget_show (cbd->shell);
|
||||
|
||||
return cbd;
|
||||
}
|
||||
|
||||
static void
|
||||
color_balance_update (ColorBalanceDialog *cbd,
|
||||
gint update)
|
||||
{
|
||||
if (update & CYAN_RED)
|
||||
{
|
||||
gtk_adjustment_set_value (cbd->cyan_red_data,
|
||||
cbd->cyan_red[cbd->application_mode]);
|
||||
}
|
||||
if (update & MAGENTA_GREEN)
|
||||
{
|
||||
gtk_adjustment_set_value (cbd->magenta_green_data,
|
||||
cbd->magenta_green[cbd->application_mode]);
|
||||
}
|
||||
if (update & YELLOW_BLUE)
|
||||
{
|
||||
gtk_adjustment_set_value (cbd->yellow_blue_data,
|
||||
cbd->yellow_blue[cbd->application_mode]);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
color_balance_create_lookup_tables (ColorBalanceDialog *cbd)
|
||||
{
|
||||
gdouble *cyan_red_transfer[3];
|
||||
gdouble *magenta_green_transfer[3];
|
||||
gdouble *yellow_blue_transfer[3];
|
||||
gint i;
|
||||
gint32 r_n, g_n, b_n;
|
||||
|
||||
/* Set the transfer arrays (for speed) */
|
||||
cyan_red_transfer[SHADOWS] = (cbd->cyan_red[SHADOWS] > 0) ? shadows_add : shadows_sub;
|
||||
cyan_red_transfer[MIDTONES] = (cbd->cyan_red[MIDTONES] > 0) ? midtones_add : midtones_sub;
|
||||
cyan_red_transfer[HIGHLIGHTS] = (cbd->cyan_red[HIGHLIGHTS] > 0) ? highlights_add : highlights_sub;
|
||||
magenta_green_transfer[SHADOWS] = (cbd->magenta_green[SHADOWS] > 0) ? shadows_add : shadows_sub;
|
||||
magenta_green_transfer[MIDTONES] = (cbd->magenta_green[MIDTONES] > 0) ? midtones_add : midtones_sub;
|
||||
magenta_green_transfer[HIGHLIGHTS] = (cbd->magenta_green[HIGHLIGHTS] > 0) ? highlights_add : highlights_sub;
|
||||
yellow_blue_transfer[SHADOWS] = (cbd->yellow_blue[SHADOWS] > 0) ? shadows_add : shadows_sub;
|
||||
yellow_blue_transfer[MIDTONES] = (cbd->yellow_blue[MIDTONES] > 0) ? midtones_add : midtones_sub;
|
||||
yellow_blue_transfer[HIGHLIGHTS] = (cbd->yellow_blue[HIGHLIGHTS] > 0) ? highlights_add : highlights_sub;
|
||||
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
r_n = i;
|
||||
g_n = i;
|
||||
b_n = i;
|
||||
|
||||
r_n += cbd->cyan_red[SHADOWS] * cyan_red_transfer[SHADOWS][r_n];
|
||||
r_n = CLAMP0255 (r_n);
|
||||
r_n += cbd->cyan_red[MIDTONES] * cyan_red_transfer[MIDTONES][r_n];
|
||||
r_n = CLAMP0255 (r_n);
|
||||
r_n += cbd->cyan_red[HIGHLIGHTS] * cyan_red_transfer[HIGHLIGHTS][r_n];
|
||||
r_n = CLAMP0255 (r_n);
|
||||
|
||||
g_n += cbd->magenta_green[SHADOWS] * magenta_green_transfer[SHADOWS][g_n];
|
||||
g_n = CLAMP0255 (g_n);
|
||||
g_n += cbd->magenta_green[MIDTONES] * magenta_green_transfer[MIDTONES][g_n];
|
||||
g_n = CLAMP0255 (g_n);
|
||||
g_n += cbd->magenta_green[HIGHLIGHTS] * magenta_green_transfer[HIGHLIGHTS][g_n];
|
||||
g_n = CLAMP0255 (g_n);
|
||||
|
||||
b_n += cbd->yellow_blue[SHADOWS] * yellow_blue_transfer[SHADOWS][b_n];
|
||||
b_n = CLAMP0255 (b_n);
|
||||
b_n += cbd->yellow_blue[MIDTONES] * yellow_blue_transfer[MIDTONES][b_n];
|
||||
b_n = CLAMP0255 (b_n);
|
||||
b_n += cbd->yellow_blue[HIGHLIGHTS] * yellow_blue_transfer[HIGHLIGHTS][b_n];
|
||||
b_n = CLAMP0255 (b_n);
|
||||
|
||||
cbd->r_lookup[i] = r_n;
|
||||
cbd->g_lookup[i] = g_n;
|
||||
cbd->b_lookup[i] = b_n;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
color_balance_preview (ColorBalanceDialog *cbd)
|
||||
{
|
||||
if (!cbd->image_map)
|
||||
{
|
||||
g_message ("color_balance_preview(): No image map");
|
||||
return;
|
||||
}
|
||||
|
||||
active_tool->preserve = TRUE;
|
||||
color_balance_create_lookup_tables (cbd);
|
||||
image_map_apply (cbd->image_map, color_balance, (void *) cbd);
|
||||
active_tool->preserve = FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
color_balance_reset_callback (GtkWidget *widget,
|
||||
gpointer data)
|
||||
{
|
||||
ColorBalanceDialog *cbd;
|
||||
|
||||
cbd = (ColorBalanceDialog *) data;
|
||||
|
||||
cbd->cyan_red[cbd->application_mode] = 0.0;
|
||||
cbd->magenta_green[cbd->application_mode] = 0.0;
|
||||
cbd->yellow_blue[cbd->application_mode] = 0.0;
|
||||
|
||||
color_balance_update (cbd, ALL);
|
||||
|
||||
if (cbd->preview)
|
||||
color_balance_preview (cbd);
|
||||
}
|
||||
|
||||
static void
|
||||
color_balance_ok_callback (GtkWidget *widget,
|
||||
gpointer data)
|
||||
{
|
||||
ColorBalanceDialog *cbd;
|
||||
|
||||
cbd = (ColorBalanceDialog *) data;
|
||||
|
||||
gimp_dialog_hide (cbd->shell);
|
||||
|
||||
active_tool->preserve = TRUE;
|
||||
|
||||
if (!cbd->preview)
|
||||
image_map_apply (cbd->image_map, color_balance, (void *) cbd);
|
||||
|
||||
if (cbd->image_map)
|
||||
image_map_commit (cbd->image_map);
|
||||
|
||||
active_tool->preserve = FALSE;
|
||||
|
||||
cbd->image_map = NULL;
|
||||
|
||||
active_tool->gdisp = NULL;
|
||||
active_tool->drawable = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
color_balance_cancel_callback (GtkWidget *widget,
|
||||
gpointer data)
|
||||
{
|
||||
ColorBalanceDialog *cbd;
|
||||
|
||||
cbd = (ColorBalanceDialog *) data;
|
||||
|
||||
gimp_dialog_hide (cbd->shell);
|
||||
|
||||
if (cbd->image_map)
|
||||
{
|
||||
active_tool->preserve = TRUE;
|
||||
image_map_abort (cbd->image_map);
|
||||
active_tool->preserve = FALSE;
|
||||
|
||||
gdisplays_flush ();
|
||||
cbd->image_map = NULL;
|
||||
}
|
||||
|
||||
active_tool->gdisp = NULL;
|
||||
active_tool->drawable = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
color_balance_range_callback (GtkWidget *widget,
|
||||
gpointer data)
|
||||
{
|
||||
ColorBalanceDialog *cbd;
|
||||
TransferMode range;
|
||||
|
||||
cbd = (ColorBalanceDialog *) data;
|
||||
|
||||
range = (TransferMode) gtk_object_get_user_data (GTK_OBJECT (widget));
|
||||
cbd->application_mode = range;
|
||||
|
||||
color_balance_update (cbd, ALL);
|
||||
}
|
||||
|
||||
static void
|
||||
color_balance_preserve_update (GtkWidget *widget,
|
||||
gpointer data)
|
||||
{
|
||||
ColorBalanceDialog *cbd;
|
||||
|
||||
cbd = (ColorBalanceDialog *) data;
|
||||
|
||||
if (GTK_TOGGLE_BUTTON (widget)->active)
|
||||
cbd->preserve_luminosity = TRUE;
|
||||
else
|
||||
cbd->preserve_luminosity = FALSE;
|
||||
|
||||
if (cbd->preview)
|
||||
color_balance_preview (cbd);
|
||||
}
|
||||
|
||||
static void
|
||||
color_balance_preview_update (GtkWidget *widget,
|
||||
gpointer data)
|
||||
{
|
||||
ColorBalanceDialog *cbd;
|
||||
|
||||
cbd = (ColorBalanceDialog *) data;
|
||||
|
||||
if (GTK_TOGGLE_BUTTON (widget)->active)
|
||||
{
|
||||
cbd->preview = TRUE;
|
||||
color_balance_preview (cbd);
|
||||
}
|
||||
else
|
||||
{
|
||||
cbd->preview = FALSE;
|
||||
if (cbd->image_map)
|
||||
{
|
||||
active_tool->preserve = TRUE;
|
||||
image_map_clear (cbd->image_map);
|
||||
active_tool->preserve = FALSE;
|
||||
gdisplays_flush ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
color_balance_cr_adjustment_update (GtkAdjustment *adjustment,
|
||||
gpointer data)
|
||||
{
|
||||
ColorBalanceDialog *cbd;
|
||||
|
||||
cbd = (ColorBalanceDialog *) data;
|
||||
|
||||
if (cbd->cyan_red[cbd->application_mode] != adjustment->value)
|
||||
{
|
||||
cbd->cyan_red[cbd->application_mode] = adjustment->value;
|
||||
|
||||
if (cbd->preview)
|
||||
color_balance_preview (cbd);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
color_balance_mg_adjustment_update (GtkAdjustment *adjustment,
|
||||
gpointer data)
|
||||
{
|
||||
ColorBalanceDialog *cbd;
|
||||
|
||||
cbd = (ColorBalanceDialog *) data;
|
||||
|
||||
if (cbd->magenta_green[cbd->application_mode] != adjustment->value)
|
||||
{
|
||||
cbd->magenta_green[cbd->application_mode] = adjustment->value;
|
||||
|
||||
if (cbd->preview)
|
||||
color_balance_preview (cbd);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
color_balance_yb_adjustment_update (GtkAdjustment *adjustment,
|
||||
gpointer data)
|
||||
{
|
||||
ColorBalanceDialog *cbd;
|
||||
|
||||
cbd = (ColorBalanceDialog *) data;
|
||||
|
||||
if (cbd->yellow_blue[cbd->application_mode] != adjustment->value)
|
||||
{
|
||||
cbd->yellow_blue[cbd->application_mode] = adjustment->value;
|
||||
|
||||
if (cbd->preview)
|
||||
color_balance_preview (cbd);
|
||||
}
|
||||
}
|
|
@ -1,68 +0,0 @@
|
|||
/* 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.
|
||||
*/
|
||||
|
||||
#ifndef __COLOR_BALANCE_H__
|
||||
#define __COLOR_BALANCE_H__
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SHADOWS,
|
||||
MIDTONES,
|
||||
HIGHLIGHTS
|
||||
} TransferMode;
|
||||
|
||||
typedef struct _ColorBalanceDialog ColorBalanceDialog;
|
||||
|
||||
struct _ColorBalanceDialog
|
||||
{
|
||||
GtkWidget *shell;
|
||||
|
||||
GtkAdjustment *cyan_red_data;
|
||||
GtkAdjustment *magenta_green_data;
|
||||
GtkAdjustment *yellow_blue_data;
|
||||
|
||||
GimpDrawable *drawable;
|
||||
ImageMap image_map;
|
||||
|
||||
gdouble cyan_red[3];
|
||||
gdouble magenta_green[3];
|
||||
gdouble yellow_blue[3];
|
||||
|
||||
guchar r_lookup[256];
|
||||
guchar g_lookup[256];
|
||||
guchar b_lookup[256];
|
||||
|
||||
gboolean preserve_luminosity;
|
||||
gboolean preview;
|
||||
TransferMode application_mode;
|
||||
};
|
||||
|
||||
Tool * tools_new_color_balance (void);
|
||||
void tools_free_color_balance (Tool *tool);
|
||||
|
||||
void color_balance_initialize (GDisplay *gdisp);
|
||||
void color_balance_dialog_hide (void);
|
||||
void color_balance (PixelRegion *srcPR,
|
||||
PixelRegion *destPR,
|
||||
void *data);
|
||||
|
||||
void color_balance_create_lookup_tables (ColorBalanceDialog *cbd);
|
||||
|
||||
|
||||
#endif /* __COLOR_BALANCE_H__ */
|
|
@ -1,824 +0,0 @@
|
|||
/* 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 <gtk/gtk.h>
|
||||
|
||||
#include "apptypes.h"
|
||||
|
||||
#include "libgimp/gimpcolorarea.h"
|
||||
|
||||
#include "appenv.h"
|
||||
#include "color_picker.h"
|
||||
#include "draw_core.h"
|
||||
#include "drawable.h"
|
||||
#include "gdisplay.h"
|
||||
#include "gimpimage.h"
|
||||
#include "gimpui.h"
|
||||
#include "gimprc.h"
|
||||
#include "cursorutil.h"
|
||||
#include "info_dialog.h"
|
||||
#include "palette.h"
|
||||
#include "tools.h"
|
||||
#include "tool_options.h"
|
||||
|
||||
#include "libgimp/gimpintl.h"
|
||||
|
||||
|
||||
/* maximum information buffer size */
|
||||
#define MAX_INFO_BUF 8
|
||||
|
||||
/* the color picker structures */
|
||||
|
||||
typedef struct _ColorPickerOptions ColorPickerOptions;
|
||||
|
||||
struct _ColorPickerOptions
|
||||
{
|
||||
ToolOptions tool_options;
|
||||
|
||||
gboolean sample_merged;
|
||||
gboolean sample_merged_d;
|
||||
GtkWidget *sample_merged_w;
|
||||
|
||||
gboolean sample_average;
|
||||
gboolean sample_average_d;
|
||||
GtkWidget *sample_average_w;
|
||||
|
||||
gdouble average_radius;
|
||||
gdouble average_radius_d;
|
||||
GtkObject *average_radius_w;
|
||||
|
||||
gboolean update_active;
|
||||
gboolean update_active_d;
|
||||
GtkWidget *update_active_w;
|
||||
};
|
||||
|
||||
typedef struct _ColorPickerTool ColorPickerTool;
|
||||
|
||||
struct _ColorPickerTool
|
||||
{
|
||||
DrawCore *core; /* Core select object */
|
||||
|
||||
gint centerx; /* starting x coord */
|
||||
gint centery; /* starting y coord */
|
||||
};
|
||||
|
||||
/* the color picker tool options */
|
||||
static ColorPickerOptions * color_picker_options = NULL;
|
||||
|
||||
/* the color value */
|
||||
gint col_value[5] = { 0, 0, 0, 0, 0 };
|
||||
|
||||
/* the color picker dialog */
|
||||
static gint update_type;
|
||||
static GimpImageType sample_type;
|
||||
static InfoDialog *color_picker_info = NULL;
|
||||
static GtkWidget *color_area = NULL;
|
||||
static gchar red_buf [MAX_INFO_BUF];
|
||||
static gchar green_buf [MAX_INFO_BUF];
|
||||
static gchar blue_buf [MAX_INFO_BUF];
|
||||
static gchar alpha_buf [MAX_INFO_BUF];
|
||||
static gchar index_buf [MAX_INFO_BUF];
|
||||
static gchar gray_buf [MAX_INFO_BUF];
|
||||
static gchar hex_buf [MAX_INFO_BUF];
|
||||
|
||||
|
||||
/* local function prototypes */
|
||||
|
||||
static void color_picker_button_press (Tool *tool,
|
||||
GdkEventButton *bevent,
|
||||
GDisplay *gdisp);
|
||||
static void color_picker_button_release (Tool *tool,
|
||||
GdkEventButton *bevent,
|
||||
GDisplay *gdisp);
|
||||
static void color_picker_motion (Tool *tool,
|
||||
GdkEventMotion *mevent,
|
||||
GDisplay *gdisp);
|
||||
static void color_picker_cursor_update (Tool *tool,
|
||||
GdkEventMotion *mevent,
|
||||
GDisplay *gdisp);
|
||||
static void color_picker_control (Tool *tool,
|
||||
ToolAction action,
|
||||
GDisplay *gdisp);
|
||||
|
||||
static void color_picker_info_window_close_callback (GtkWidget *widget,
|
||||
gpointer data);
|
||||
static void color_picker_info_update (Tool *tool,
|
||||
gboolean valid);
|
||||
|
||||
static gboolean pick_color_do (GimpImage *gimage,
|
||||
GimpDrawable *drawable,
|
||||
gint x,
|
||||
gint y,
|
||||
gboolean sample_merged,
|
||||
gboolean sample_average,
|
||||
gdouble average_radius,
|
||||
gboolean update_active,
|
||||
gint final);
|
||||
|
||||
/* functions */
|
||||
|
||||
static void
|
||||
color_picker_options_reset (void)
|
||||
{
|
||||
ColorPickerOptions *options = color_picker_options;
|
||||
|
||||
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->sample_merged_w),
|
||||
options->sample_merged_d);
|
||||
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->sample_average_w),
|
||||
options->sample_average_d);
|
||||
gtk_adjustment_set_value (GTK_ADJUSTMENT (options->average_radius_w),
|
||||
options->average_radius_d);
|
||||
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->update_active_w),
|
||||
options->update_active_d);
|
||||
}
|
||||
|
||||
static ColorPickerOptions *
|
||||
color_picker_options_new (void)
|
||||
{
|
||||
ColorPickerOptions *options;
|
||||
|
||||
GtkWidget *vbox;
|
||||
GtkWidget *abox;
|
||||
GtkWidget *table;
|
||||
GtkWidget *label;
|
||||
GtkWidget *scale;
|
||||
|
||||
/* the new color picker tool options structure */
|
||||
options = g_new (ColorPickerOptions, 1);
|
||||
tool_options_init ((ToolOptions *) options,
|
||||
_("Color Picker"),
|
||||
color_picker_options_reset);
|
||||
options->sample_merged = options->sample_merged_d = FALSE;
|
||||
options->sample_average = options->sample_average_d = FALSE;
|
||||
options->average_radius = options->average_radius_d = 1.0;
|
||||
options->update_active = options->update_active_d = TRUE;
|
||||
|
||||
/* the main vbox */
|
||||
vbox = options->tool_options.main_vbox;
|
||||
|
||||
/* the sample merged toggle button */
|
||||
options->sample_merged_w =
|
||||
gtk_check_button_new_with_label (_("Sample Merged"));
|
||||
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->sample_merged_w),
|
||||
options->sample_merged_d);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), options->sample_merged_w, FALSE, FALSE, 0);
|
||||
gtk_signal_connect (GTK_OBJECT (options->sample_merged_w), "toggled",
|
||||
GTK_SIGNAL_FUNC (gimp_toggle_button_update),
|
||||
&options->sample_merged);
|
||||
gtk_widget_show (options->sample_merged_w);
|
||||
|
||||
/* the sample average options */
|
||||
table = gtk_table_new (2, 2, FALSE);
|
||||
gtk_table_set_col_spacing (GTK_TABLE (table), 0, 4);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
|
||||
|
||||
options->sample_average_w =
|
||||
gtk_check_button_new_with_label (_("Sample Average"));
|
||||
gtk_table_attach (GTK_TABLE (table), options->sample_average_w, 0, 1, 0, 1,
|
||||
GTK_SHRINK | GTK_FILL, GTK_SHRINK, 0, 0);
|
||||
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->sample_average_w),
|
||||
options->sample_average_d);
|
||||
gtk_signal_connect (GTK_OBJECT (options->sample_average_w), "toggled",
|
||||
GTK_SIGNAL_FUNC (gimp_toggle_button_update),
|
||||
&options->sample_average);
|
||||
gtk_widget_show (options->sample_average_w);
|
||||
|
||||
label = gtk_label_new (_("Radius:"));
|
||||
gtk_misc_set_alignment (GTK_MISC (label), 1.0, 1.0);
|
||||
gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2,
|
||||
GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
|
||||
gtk_widget_show (label);
|
||||
|
||||
/* the feather radius scale */
|
||||
abox = gtk_alignment_new (0.5, 1.0, 1.0, 0.0);
|
||||
gtk_table_attach (GTK_TABLE (table), abox, 1, 2, 0, 2,
|
||||
GTK_EXPAND | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
|
||||
gtk_widget_show (abox);
|
||||
|
||||
options->average_radius_w =
|
||||
gtk_adjustment_new (options->average_radius_d, 1.0, 15.0, 2.0, 2.0, 0.0);
|
||||
scale = gtk_hscale_new (GTK_ADJUSTMENT (options->average_radius_w));
|
||||
gtk_scale_set_digits (GTK_SCALE (scale), 0);
|
||||
gtk_container_add (GTK_CONTAINER (abox), scale);
|
||||
gtk_widget_set_sensitive (scale, options->sample_average_d);
|
||||
gtk_object_set_data (GTK_OBJECT (options->sample_average_w), "set_sensitive",
|
||||
scale);
|
||||
gtk_widget_set_sensitive (label, options->sample_average_d);
|
||||
gtk_object_set_data (GTK_OBJECT (scale), "set_sensitive",
|
||||
label);
|
||||
gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_TOP);
|
||||
gtk_range_set_update_policy (GTK_RANGE (scale), GTK_UPDATE_DELAYED);
|
||||
gtk_signal_connect (GTK_OBJECT (options->average_radius_w), "value_changed",
|
||||
GTK_SIGNAL_FUNC (gimp_double_adjustment_update),
|
||||
&options->average_radius);
|
||||
gtk_widget_show (scale);
|
||||
gtk_widget_show (table);
|
||||
|
||||
/* the update active color toggle button */
|
||||
options->update_active_w =
|
||||
gtk_check_button_new_with_label (_("Update Active Color"));
|
||||
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->update_active_w),
|
||||
options->update_active_d);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), options->update_active_w, FALSE, FALSE, 0);
|
||||
gtk_signal_connect (GTK_OBJECT (options->update_active_w), "toggled",
|
||||
GTK_SIGNAL_FUNC (gimp_toggle_button_update),
|
||||
&options->update_active);
|
||||
gtk_widget_show (options->update_active_w);
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
static void
|
||||
color_picker_button_press (Tool *tool,
|
||||
GdkEventButton *bevent,
|
||||
GDisplay *gdisp)
|
||||
{
|
||||
ColorPickerTool *cp_tool;
|
||||
gint x, y;
|
||||
|
||||
cp_tool = (ColorPickerTool *) tool->private;
|
||||
|
||||
/* Make the tool active and set it's gdisplay & drawable */
|
||||
tool->gdisp = gdisp;
|
||||
tool->drawable = gimp_image_active_drawable (gdisp->gimage);
|
||||
tool->state = ACTIVE;
|
||||
|
||||
/* create the info dialog if it doesn't exist */
|
||||
if (! color_picker_info)
|
||||
{
|
||||
GtkWidget *hbox;
|
||||
GtkWidget *frame;
|
||||
GimpRGB color;
|
||||
|
||||
color_picker_info = info_dialog_new (_("Color Picker"),
|
||||
tools_help_func, NULL);
|
||||
|
||||
/* if the gdisplay is for a color image, the dialog must have RGB */
|
||||
switch (gimp_drawable_type (tool->drawable))
|
||||
{
|
||||
case RGB_GIMAGE: case RGBA_GIMAGE:
|
||||
info_dialog_add_label (color_picker_info, _("Red:"), red_buf);
|
||||
info_dialog_add_label (color_picker_info, _("Green:"), green_buf);
|
||||
info_dialog_add_label (color_picker_info, _("Blue:"), blue_buf);
|
||||
info_dialog_add_label (color_picker_info, _("Alpha:"), alpha_buf);
|
||||
info_dialog_add_label (color_picker_info, _("Hex Triplet:"), hex_buf);
|
||||
break;
|
||||
|
||||
case INDEXED_GIMAGE: case INDEXEDA_GIMAGE:
|
||||
info_dialog_add_label (color_picker_info, _("Index:"), index_buf);
|
||||
info_dialog_add_label (color_picker_info, _("Red:"), red_buf);
|
||||
info_dialog_add_label (color_picker_info, _("Green:"), green_buf);
|
||||
info_dialog_add_label (color_picker_info, _("Blue:"), blue_buf);
|
||||
info_dialog_add_label (color_picker_info, _("Alpha:"), alpha_buf);
|
||||
info_dialog_add_label (color_picker_info, _("Hex Triplet"), hex_buf);
|
||||
break;
|
||||
|
||||
case GRAY_GIMAGE: case GRAYA_GIMAGE:
|
||||
info_dialog_add_label (color_picker_info, _("Intensity:"), gray_buf);
|
||||
info_dialog_add_label (color_picker_info, _("Alpha:"), alpha_buf);
|
||||
info_dialog_add_label (color_picker_info, _("Hex Triplet:"), hex_buf);
|
||||
break;
|
||||
|
||||
default :
|
||||
break;
|
||||
}
|
||||
|
||||
hbox = gtk_hbox_new (FALSE, 4);
|
||||
gtk_box_pack_start (GTK_BOX (color_picker_info->vbox), hbox,
|
||||
FALSE, FALSE, 0);
|
||||
gtk_widget_show (hbox);
|
||||
|
||||
gtk_widget_reparent (color_picker_info->info_table, hbox);
|
||||
|
||||
frame = gtk_frame_new (NULL);
|
||||
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, FALSE, 0);
|
||||
|
||||
gimp_rgba_set (&color, 0.0, 0.0, 0.0, 0.0);
|
||||
color_area =
|
||||
gimp_color_area_new (&color,
|
||||
gimp_drawable_has_alpha (tool->drawable) ?
|
||||
GIMP_COLOR_AREA_LARGE_CHECKS :
|
||||
GIMP_COLOR_AREA_FLAT,
|
||||
GDK_BUTTON1_MASK | GDK_BUTTON2_MASK);
|
||||
gtk_widget_set_usize (color_area, 48, 64);
|
||||
gtk_drag_dest_unset (color_area);
|
||||
gtk_container_add (GTK_CONTAINER (frame), color_area);
|
||||
gtk_widget_show (color_area);
|
||||
gtk_widget_show (frame);
|
||||
|
||||
/* create the action area */
|
||||
gimp_dialog_create_action_area
|
||||
(GTK_DIALOG (color_picker_info->shell),
|
||||
|
||||
_("Close"), color_picker_info_window_close_callback,
|
||||
color_picker_info, NULL, NULL, TRUE, FALSE,
|
||||
|
||||
NULL);
|
||||
}
|
||||
|
||||
/* Keep the coordinates of the target */
|
||||
gdisplay_untransform_coords (gdisp, bevent->x, bevent->y,
|
||||
&cp_tool->centerx, &cp_tool->centery, FALSE, 1);
|
||||
|
||||
gdk_pointer_grab (gdisp->canvas->window, FALSE,
|
||||
(GDK_POINTER_MOTION_HINT_MASK |
|
||||
GDK_BUTTON1_MOTION_MASK |
|
||||
GDK_BUTTON_RELEASE_MASK),
|
||||
NULL, NULL, bevent->time);
|
||||
|
||||
/* First, transform the coordinates to gimp image space */
|
||||
gdisplay_untransform_coords (gdisp, bevent->x, bevent->y, &x, &y,
|
||||
FALSE, FALSE);
|
||||
|
||||
/* if the shift key is down, create a new color.
|
||||
* otherwise, modify the current color.
|
||||
*/
|
||||
if (bevent->state & GDK_SHIFT_MASK)
|
||||
{
|
||||
color_picker_info_update
|
||||
(tool, pick_color_do (gdisp->gimage, tool->drawable, x, y,
|
||||
color_picker_options->sample_merged,
|
||||
color_picker_options->sample_average,
|
||||
color_picker_options->average_radius,
|
||||
color_picker_options->update_active,
|
||||
COLOR_NEW));
|
||||
update_type = COLOR_UPDATE_NEW;
|
||||
}
|
||||
else
|
||||
{
|
||||
color_picker_info_update
|
||||
(tool, pick_color_do (gdisp->gimage, tool->drawable, x, y,
|
||||
color_picker_options->sample_merged,
|
||||
color_picker_options->sample_average,
|
||||
color_picker_options->average_radius,
|
||||
color_picker_options->update_active,
|
||||
COLOR_UPDATE));
|
||||
update_type = COLOR_UPDATE;
|
||||
}
|
||||
|
||||
/* Start drawing the colorpicker tool */
|
||||
draw_core_start (cp_tool->core, gdisp->canvas->window, tool);
|
||||
}
|
||||
|
||||
static void
|
||||
color_picker_button_release (Tool *tool,
|
||||
GdkEventButton *bevent,
|
||||
GDisplay *gdisp)
|
||||
{
|
||||
ColorPickerTool *cp_tool;
|
||||
gint x, y;
|
||||
|
||||
gdk_pointer_ungrab (bevent->time);
|
||||
gdk_flush ();
|
||||
|
||||
cp_tool = (ColorPickerTool *) tool->private;
|
||||
|
||||
/* First, transform the coordinates to gimp image space */
|
||||
gdisplay_untransform_coords (gdisp, bevent->x, bevent->y, &x, &y,
|
||||
FALSE, FALSE);
|
||||
|
||||
color_picker_info_update
|
||||
(tool, pick_color_do (gdisp->gimage, tool->drawable, x, y,
|
||||
color_picker_options->sample_merged,
|
||||
color_picker_options->sample_average,
|
||||
color_picker_options->average_radius,
|
||||
color_picker_options->update_active,
|
||||
update_type));
|
||||
|
||||
draw_core_stop (cp_tool->core, tool);
|
||||
tool->state = INACTIVE;
|
||||
}
|
||||
|
||||
static void
|
||||
color_picker_motion (Tool *tool,
|
||||
GdkEventMotion *mevent,
|
||||
GDisplay *gdisp)
|
||||
{
|
||||
ColorPickerTool *cp_tool;
|
||||
gint x, y;
|
||||
|
||||
cp_tool = (ColorPickerTool *) tool->private;
|
||||
|
||||
/* undraw the current tool */
|
||||
draw_core_pause (cp_tool->core, tool);
|
||||
|
||||
/* First, transform the coordinates to gimp image space */
|
||||
gdisplay_untransform_coords (gdisp, mevent->x, mevent->y, &x, &y,
|
||||
FALSE, FALSE);
|
||||
|
||||
gdisplay_untransform_coords (gdisp, mevent->x, mevent->y,
|
||||
&cp_tool->centerx, &cp_tool->centery,
|
||||
FALSE, TRUE);
|
||||
|
||||
color_picker_info_update
|
||||
(tool, pick_color_do (gdisp->gimage, tool->drawable, x, y,
|
||||
color_picker_options->sample_merged,
|
||||
color_picker_options->sample_average,
|
||||
color_picker_options->average_radius,
|
||||
color_picker_options->update_active,
|
||||
update_type));
|
||||
|
||||
/* redraw the current tool */
|
||||
draw_core_resume (cp_tool->core, tool);
|
||||
}
|
||||
|
||||
static void
|
||||
color_picker_cursor_update (Tool *tool,
|
||||
GdkEventMotion *mevent,
|
||||
GDisplay *gdisp)
|
||||
{
|
||||
gint x, y;
|
||||
|
||||
gdisplay_untransform_coords (gdisp, mevent->x, mevent->y, &x, &y,
|
||||
FALSE, FALSE);
|
||||
|
||||
/* We used to use the following code here:
|
||||
*
|
||||
* if (gimp_image_pick_correlate_layer (gdisp->gimage, x, y)) { ... }
|
||||
*/
|
||||
|
||||
if (gdisp->gimage &&
|
||||
x > 0 && x < gdisp->gimage->width &&
|
||||
y > 0 && y < gdisp->gimage->height)
|
||||
{
|
||||
gdisplay_install_tool_cursor (gdisp, GIMP_COLOR_PICKER_CURSOR,
|
||||
COLOR_PICKER,
|
||||
CURSOR_MODIFIER_NONE,
|
||||
FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
gdisplay_install_tool_cursor (gdisp, GIMP_BAD_CURSOR,
|
||||
COLOR_PICKER,
|
||||
CURSOR_MODIFIER_NONE,
|
||||
FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
color_picker_control (Tool *tool,
|
||||
ToolAction action,
|
||||
GDisplay *gdisp)
|
||||
{
|
||||
ColorPickerTool *cp_tool;
|
||||
|
||||
cp_tool = (ColorPickerTool *) tool->private;
|
||||
|
||||
switch (action)
|
||||
{
|
||||
case PAUSE :
|
||||
draw_core_pause (cp_tool->core, tool);
|
||||
break;
|
||||
|
||||
case RESUME :
|
||||
draw_core_resume (cp_tool->core, tool);
|
||||
break;
|
||||
|
||||
case HALT :
|
||||
draw_core_stop (cp_tool->core, tool);
|
||||
info_dialog_popdown (color_picker_info);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
typedef guchar * (*GetColorFunc) (GimpObject *object,
|
||||
gint x,
|
||||
gint y);
|
||||
|
||||
|
||||
static gboolean
|
||||
pick_color_do (GimpImage *gimage,
|
||||
GimpDrawable *drawable,
|
||||
gint x,
|
||||
gint y,
|
||||
gboolean sample_merged,
|
||||
gboolean sample_average,
|
||||
gdouble average_radius,
|
||||
gboolean update_active,
|
||||
gint final)
|
||||
{
|
||||
guchar *color;
|
||||
gint offx, offy;
|
||||
gint has_alpha;
|
||||
gint is_indexed;
|
||||
GetColorFunc get_color_func;
|
||||
GimpObject *get_color_obj;
|
||||
|
||||
|
||||
if (!drawable && !sample_merged)
|
||||
return FALSE;
|
||||
|
||||
if (!sample_merged)
|
||||
{
|
||||
gimp_drawable_offsets (drawable, &offx, &offy);
|
||||
x -= offx;
|
||||
y -= offy;
|
||||
|
||||
sample_type = gimp_drawable_type (drawable);
|
||||
is_indexed = gimp_drawable_is_indexed (drawable);
|
||||
|
||||
get_color_func = (GetColorFunc) gimp_drawable_get_color_at;
|
||||
get_color_obj = GIMP_OBJECT (drawable);
|
||||
}
|
||||
else
|
||||
{
|
||||
sample_type = gimp_image_composite_type (gimage);
|
||||
is_indexed = FALSE;
|
||||
|
||||
get_color_func = (GetColorFunc) gimp_image_get_color_at;
|
||||
get_color_obj = GIMP_OBJECT (gimage);
|
||||
}
|
||||
|
||||
has_alpha = GIMP_IMAGE_TYPE_HAS_ALPHA (sample_type);
|
||||
|
||||
if (!(color = (* get_color_func) (get_color_obj, x, y)))
|
||||
return FALSE;
|
||||
|
||||
if (sample_average)
|
||||
{
|
||||
gint i, j;
|
||||
gint count = 0;
|
||||
gint color_avg[4] = { 0, 0, 0, 0 };
|
||||
guchar *tmp_color;
|
||||
gint radius = (gint) average_radius;
|
||||
|
||||
for (i = x - radius; i <= x + radius; i++)
|
||||
for (j = y - radius; j <= y + radius; j++)
|
||||
if ((tmp_color = (* get_color_func) (get_color_obj, i, j)))
|
||||
{
|
||||
count++;
|
||||
|
||||
color_avg[RED_PIX] += tmp_color[RED_PIX];
|
||||
color_avg[GREEN_PIX] += tmp_color[GREEN_PIX];
|
||||
color_avg[BLUE_PIX] += tmp_color[BLUE_PIX];
|
||||
if (has_alpha)
|
||||
color_avg[ALPHA_PIX] += tmp_color[ALPHA_PIX];
|
||||
|
||||
g_free (tmp_color);
|
||||
}
|
||||
|
||||
color[RED_PIX] = (guchar) (color_avg[RED_PIX] / count);
|
||||
color[GREEN_PIX] = (guchar) (color_avg[GREEN_PIX] / count);
|
||||
color[BLUE_PIX] = (guchar) (color_avg[BLUE_PIX] / count);
|
||||
if (has_alpha)
|
||||
color[ALPHA_PIX] = (guchar) (color_avg[ALPHA_PIX] / count);
|
||||
|
||||
is_indexed = FALSE;
|
||||
}
|
||||
|
||||
col_value[RED_PIX] = color[RED_PIX];
|
||||
col_value[GREEN_PIX] = color[GREEN_PIX];
|
||||
col_value[BLUE_PIX] = color[BLUE_PIX];
|
||||
if (has_alpha)
|
||||
col_value[ALPHA_PIX] = color[ALPHA_PIX];
|
||||
if (is_indexed)
|
||||
col_value[4] = color[4];
|
||||
|
||||
if (update_active)
|
||||
palette_set_active_color (col_value [RED_PIX],
|
||||
col_value [GREEN_PIX],
|
||||
col_value [BLUE_PIX],
|
||||
final);
|
||||
|
||||
g_free (color);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
pick_color (GimpImage *gimage,
|
||||
GimpDrawable *drawable,
|
||||
gint x,
|
||||
gint y,
|
||||
gboolean sample_merged,
|
||||
gboolean sample_average,
|
||||
gdouble average_radius,
|
||||
gint final)
|
||||
{
|
||||
return pick_color_do (gimage, drawable,
|
||||
x, y,
|
||||
sample_merged,
|
||||
sample_average,
|
||||
average_radius,
|
||||
TRUE,
|
||||
final);
|
||||
}
|
||||
|
||||
static void
|
||||
colorpicker_draw (Tool *tool)
|
||||
{
|
||||
ColorPickerTool *cp_tool;
|
||||
gint tx, ty;
|
||||
gint radiusx, radiusy;
|
||||
gint cx, cy;
|
||||
|
||||
if (! color_picker_options->sample_average)
|
||||
return;
|
||||
|
||||
cp_tool = (ColorPickerTool *) tool->private;
|
||||
|
||||
gdisplay_transform_coords (tool->gdisp, cp_tool->centerx, cp_tool->centery,
|
||||
&tx, &ty, TRUE);
|
||||
|
||||
radiusx = SCALEX (tool->gdisp, color_picker_options->average_radius);
|
||||
radiusy = SCALEY (tool->gdisp, color_picker_options->average_radius);
|
||||
cx = SCALEX (tool->gdisp, 1);
|
||||
cy = SCALEY (tool->gdisp, 1);
|
||||
|
||||
/* Draw the circle around the collecting area */
|
||||
gdk_draw_rectangle (cp_tool->core->win, cp_tool->core->gc, 0,
|
||||
tx - radiusx,
|
||||
ty - radiusy,
|
||||
2 * radiusx + cx, 2 * radiusy + cy);
|
||||
|
||||
if (radiusx > 1 && radiusy > 1)
|
||||
{
|
||||
gdk_draw_rectangle (cp_tool->core->win, cp_tool->core->gc, 0,
|
||||
tx - radiusx + 2,
|
||||
ty - radiusy + 2,
|
||||
2 * radiusx + cx - 4, 2 * radiusy + cy - 4);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
color_picker_info_update (Tool *tool,
|
||||
gboolean valid)
|
||||
{
|
||||
if (!valid)
|
||||
{
|
||||
if (GTK_WIDGET_IS_SENSITIVE (color_area))
|
||||
gtk_widget_set_sensitive (color_area, FALSE);
|
||||
|
||||
g_snprintf (red_buf, MAX_INFO_BUF, _("N/A"));
|
||||
g_snprintf (green_buf, MAX_INFO_BUF, _("N/A"));
|
||||
g_snprintf (blue_buf, MAX_INFO_BUF, _("N/A"));
|
||||
g_snprintf (alpha_buf, MAX_INFO_BUF, _("N/A"));
|
||||
g_snprintf (index_buf, MAX_INFO_BUF, _("N/A"));
|
||||
g_snprintf (gray_buf, MAX_INFO_BUF, _("N/A"));
|
||||
g_snprintf (hex_buf, MAX_INFO_BUF, _("N/A"));
|
||||
}
|
||||
else
|
||||
{
|
||||
GimpRGB color;
|
||||
guchar r = 0;
|
||||
guchar g = 0;
|
||||
guchar b = 0;
|
||||
guchar a = 0;
|
||||
|
||||
if (! GTK_WIDGET_IS_SENSITIVE (color_area))
|
||||
gtk_widget_set_sensitive (color_area, TRUE);
|
||||
|
||||
switch (sample_type)
|
||||
{
|
||||
case RGB_GIMAGE: case RGBA_GIMAGE:
|
||||
g_snprintf (index_buf, MAX_INFO_BUF, _("N/A"));
|
||||
g_snprintf (red_buf, MAX_INFO_BUF, "%d", col_value [RED_PIX]);
|
||||
g_snprintf (green_buf, MAX_INFO_BUF, "%d", col_value [GREEN_PIX]);
|
||||
g_snprintf (blue_buf, MAX_INFO_BUF, "%d", col_value [BLUE_PIX]);
|
||||
if (sample_type == RGBA_GIMAGE)
|
||||
g_snprintf (alpha_buf, MAX_INFO_BUF, "%d", col_value [ALPHA_PIX]);
|
||||
else
|
||||
g_snprintf (alpha_buf, MAX_INFO_BUF, _("N/A"));
|
||||
g_snprintf (hex_buf, MAX_INFO_BUF, "#%.2x%.2x%.2x",
|
||||
col_value [RED_PIX],
|
||||
col_value [GREEN_PIX],
|
||||
col_value [BLUE_PIX]);
|
||||
|
||||
r = col_value [RED_PIX];
|
||||
g = col_value [GREEN_PIX];
|
||||
b = col_value [BLUE_PIX];
|
||||
if (sample_type == RGBA_GIMAGE)
|
||||
a = col_value [ALPHA_PIX];
|
||||
break;
|
||||
|
||||
case INDEXED_GIMAGE: case INDEXEDA_GIMAGE:
|
||||
g_snprintf (index_buf, MAX_INFO_BUF, "%d", col_value [4]);
|
||||
g_snprintf (red_buf, MAX_INFO_BUF, "%d", col_value [RED_PIX]);
|
||||
g_snprintf (green_buf, MAX_INFO_BUF, "%d", col_value [GREEN_PIX]);
|
||||
g_snprintf (blue_buf, MAX_INFO_BUF, "%d", col_value [BLUE_PIX]);
|
||||
if (sample_type == INDEXEDA_GIMAGE)
|
||||
g_snprintf (alpha_buf, MAX_INFO_BUF, "%d", col_value [ALPHA_PIX]);
|
||||
else
|
||||
g_snprintf (alpha_buf, MAX_INFO_BUF, _("N/A"));
|
||||
g_snprintf (hex_buf, MAX_INFO_BUF, "#%.2x%.2x%.2x",
|
||||
col_value [RED_PIX],
|
||||
col_value [GREEN_PIX],
|
||||
col_value [BLUE_PIX]);
|
||||
|
||||
r = col_value [RED_PIX];
|
||||
g = col_value [GREEN_PIX];
|
||||
b = col_value [BLUE_PIX];
|
||||
if (sample_type == INDEXEDA_GIMAGE)
|
||||
a = col_value [ALPHA_PIX];
|
||||
break;
|
||||
|
||||
case GRAY_GIMAGE: case GRAYA_GIMAGE:
|
||||
g_snprintf (gray_buf, MAX_INFO_BUF, "%d", col_value [GRAY_PIX]);
|
||||
if (sample_type == GRAYA_GIMAGE)
|
||||
g_snprintf (alpha_buf, MAX_INFO_BUF, "%d", col_value [ALPHA_PIX]);
|
||||
else
|
||||
g_snprintf (alpha_buf, MAX_INFO_BUF, _("N/A"));
|
||||
g_snprintf (hex_buf, MAX_INFO_BUF, "#%.2x%.2x%.2x",
|
||||
col_value [GRAY_PIX],
|
||||
col_value [GRAY_PIX],
|
||||
col_value [GRAY_PIX]);
|
||||
|
||||
r = col_value [GRAY_PIX];
|
||||
g = col_value [GRAY_PIX];
|
||||
b = col_value [GRAY_PIX];
|
||||
if (sample_type == GRAYA_GIMAGE)
|
||||
a = col_value [ALPHA_PIX];
|
||||
break;
|
||||
}
|
||||
|
||||
gimp_rgba_set_uchar (&color, r, g, b, a);
|
||||
|
||||
gimp_color_area_set_color (GIMP_COLOR_AREA (color_area), &color);
|
||||
}
|
||||
|
||||
info_dialog_update (color_picker_info);
|
||||
info_dialog_popup (color_picker_info);
|
||||
}
|
||||
|
||||
static void
|
||||
color_picker_info_window_close_callback (GtkWidget *widget,
|
||||
gpointer client_data)
|
||||
{
|
||||
info_dialog_popdown ((InfoDialog *) client_data);
|
||||
}
|
||||
|
||||
Tool *
|
||||
tools_new_color_picker ()
|
||||
{
|
||||
Tool * tool;
|
||||
ColorPickerTool * private;
|
||||
|
||||
/* The tool options */
|
||||
if (! color_picker_options)
|
||||
{
|
||||
color_picker_options = color_picker_options_new ();
|
||||
tools_register (COLOR_PICKER, (ToolOptions *) color_picker_options);
|
||||
}
|
||||
|
||||
tool = tools_new_tool (COLOR_PICKER);
|
||||
private = g_new0 (ColorPickerTool, 1);
|
||||
|
||||
private->core = draw_core_new (colorpicker_draw);
|
||||
|
||||
tool->preserve = FALSE; /* Don't preserve on drawable change */
|
||||
|
||||
tool->private = (void *) private;
|
||||
|
||||
tool->button_press_func = color_picker_button_press;
|
||||
tool->button_release_func = color_picker_button_release;
|
||||
tool->motion_func = color_picker_motion;
|
||||
tool->cursor_update_func = color_picker_cursor_update;
|
||||
tool->control_func = color_picker_control;
|
||||
|
||||
return tool;
|
||||
}
|
||||
|
||||
void
|
||||
tools_free_color_picker (Tool *tool)
|
||||
{
|
||||
ColorPickerTool * cp_tool;
|
||||
|
||||
cp_tool = (ColorPickerTool *) tool->private;
|
||||
|
||||
if (tool->state == ACTIVE)
|
||||
draw_core_stop (cp_tool->core, tool);
|
||||
|
||||
draw_core_free (cp_tool->core);
|
||||
|
||||
if (color_picker_info)
|
||||
{
|
||||
info_dialog_free (color_picker_info);
|
||||
color_picker_info = NULL;
|
||||
|
||||
color_area = NULL;
|
||||
}
|
||||
|
||||
g_free (cp_tool);
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
/* 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.
|
||||
*/
|
||||
|
||||
#ifndef __COLOR_PICKER_H__
|
||||
#define __COLOR_PICKER_H__
|
||||
|
||||
|
||||
extern gint col_value[5];
|
||||
|
||||
|
||||
gboolean pick_color (GimpImage *gimage,
|
||||
GimpDrawable *drawable,
|
||||
gint x,
|
||||
gint y,
|
||||
gboolean sample_merged,
|
||||
gboolean sample_average,
|
||||
double average_radius,
|
||||
gint final);
|
||||
|
||||
Tool * tools_new_color_picker (void);
|
||||
void tools_free_color_picker (Tool *tool);
|
||||
|
||||
|
||||
#endif /* __COLOR_PICKER_H__ */
|
|
@ -68,13 +68,14 @@
|
|||
#include "scale.h"
|
||||
#include "selection.h"
|
||||
#include "tips_dialog.h"
|
||||
#include "tools.h"
|
||||
#include "undo.h"
|
||||
|
||||
#ifdef DISPLAY_FILTERS
|
||||
#include "gdisplay_color_ui.h"
|
||||
#endif /* DISPLAY_FILTERS */
|
||||
|
||||
#include "tools/tools.h"
|
||||
|
||||
#include "libgimp/gimphelpui.h"
|
||||
#include "libgimp/gimpmath.h"
|
||||
|
||||
|
|
|
@ -28,8 +28,9 @@
|
|||
#include "gdisplay.h"
|
||||
#include "gimpcontext.h"
|
||||
#include "gimprc.h"
|
||||
#include "paint_options.h"
|
||||
#include "tools.h"
|
||||
|
||||
#include "tools/paint_options.h"
|
||||
#include "tools/tools.h"
|
||||
|
||||
|
||||
static GimpContext * global_tool_context;
|
||||
|
|
|
@ -94,30 +94,31 @@
|
|||
#include "apptypes.h"
|
||||
|
||||
#include "appenv.h"
|
||||
#include "brightness_contrast.h"
|
||||
#include "color_balance.h"
|
||||
#include "convert.h"
|
||||
#include "cursorutil.h"
|
||||
#include "curves.h"
|
||||
#include "drawable.h"
|
||||
#include "floating_sel.h"
|
||||
#include "fsdither.h"
|
||||
#include "gdisplay.h"
|
||||
#include "gimpimage.h"
|
||||
#include "gimpui.h"
|
||||
#include "hue_saturation.h"
|
||||
#include "layer.h"
|
||||
#include "levels.h"
|
||||
#include "undo.h"
|
||||
#include "palette.h"
|
||||
#include "gimppalette.h"
|
||||
#include "palette_select.h"
|
||||
#include "pixel_region.h"
|
||||
#include "posterize.h"
|
||||
#include "threshold.h"
|
||||
#include "tile_manager.h"
|
||||
#include "tile_manager_pvt.h" /* ick ick ick. */
|
||||
|
||||
#include "tools/brightness_contrast.h"
|
||||
#include "tools/color_balance.h"
|
||||
#include "tools/curves.h"
|
||||
#include "tools/hue_saturation.h"
|
||||
#include "tools/levels.h"
|
||||
#include "tools/posterize.h"
|
||||
#include "tools/threshold.h"
|
||||
|
||||
#include "libgimp/gimpcolorspace.h"
|
||||
#include "libgimp/gimphelpui.h"
|
||||
#include "libgimp/gimpmath.h"
|
||||
|
|
696
app/convolve.c
696
app/convolve.c
|
@ -1,696 +0,0 @@
|
|||
/* 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 <gtk/gtk.h>
|
||||
#include <gdk/gdkkeysyms.h>
|
||||
|
||||
#include "apptypes.h"
|
||||
|
||||
#include "appenv.h"
|
||||
#include "drawable.h"
|
||||
#include "convolve.h"
|
||||
#include "gdisplay.h"
|
||||
#include "gimpbrush.h"
|
||||
#include "gimpcontext.h"
|
||||
#include "gimpui.h"
|
||||
#include "paint_funcs.h"
|
||||
#include "paint_core.h"
|
||||
#include "paint_options.h"
|
||||
#include "pixel_region.h"
|
||||
#include "selection.h"
|
||||
#include "temp_buf.h"
|
||||
#include "tools.h"
|
||||
#include "gimage.h"
|
||||
|
||||
#include "libgimp/gimpintl.h"
|
||||
|
||||
|
||||
#define FIELD_COLS 4
|
||||
#define MIN_BLUR 64 /* (8/9 original pixel) */
|
||||
#define MAX_BLUR 0.25 /* (1/33 original pixel) */
|
||||
#define MIN_SHARPEN -512
|
||||
#define MAX_SHARPEN -64
|
||||
|
||||
/* defaults */
|
||||
#define DEFAULT_CONVOLVE_RATE 50.0
|
||||
#define DEFAULT_CONVOLVE_TYPE BLUR_CONVOLVE
|
||||
|
||||
|
||||
/* Different clip relationships between a blur-blob and edges:
|
||||
see convolve_motion */
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CONVOLVE_NCLIP, /* Left or top edge */
|
||||
CONVOLVE_NOT_CLIPPED, /* No edges */
|
||||
CONVOLVE_PCLIP /* Right or bottom edge */
|
||||
} ConvolveClipType;
|
||||
|
||||
|
||||
/* the convolve structures */
|
||||
|
||||
typedef struct _ConvolveOptions ConvolveOptions;
|
||||
|
||||
struct _ConvolveOptions
|
||||
{
|
||||
PaintOptions paint_options;
|
||||
|
||||
ConvolveType type;
|
||||
ConvolveType type_d;
|
||||
GtkWidget *type_w[2];
|
||||
|
||||
gdouble rate;
|
||||
gdouble rate_d;
|
||||
GtkObject *rate_w;
|
||||
};
|
||||
|
||||
|
||||
/* forward function declarations */
|
||||
static void calculate_matrix (ConvolveType type,
|
||||
gdouble rate);
|
||||
static void integer_matrix (gfloat *source,
|
||||
gint *dest,
|
||||
gint size);
|
||||
static void copy_matrix (gfloat *src,
|
||||
gfloat *dest,
|
||||
gint size);
|
||||
static gint sum_matrix (gint *matrix,
|
||||
gint size);
|
||||
|
||||
static gpointer convolve_paint_func (PaintCore *paint_core,
|
||||
GimpDrawable *drawable,
|
||||
PaintState state);
|
||||
static void convolve_motion (PaintCore *paint_core,
|
||||
GimpDrawable *drawable,
|
||||
PaintPressureOptions *pressure_options,
|
||||
ConvolveType type,
|
||||
gdouble rate);
|
||||
|
||||
|
||||
/* the convolve tool options */
|
||||
static ConvolveOptions * convolve_options = NULL;
|
||||
|
||||
/* local variables */
|
||||
static gint matrix [25];
|
||||
static gint matrix_size;
|
||||
static gint matrix_divisor;
|
||||
|
||||
static ConvolveType non_gui_type;
|
||||
static gdouble non_gui_rate;
|
||||
|
||||
static gfloat custom_matrix [25] =
|
||||
{
|
||||
0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0,
|
||||
0, 0, 1, 0, 0,
|
||||
0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0,
|
||||
};
|
||||
|
||||
static gfloat blur_matrix [25] =
|
||||
{
|
||||
0, 0, 0, 0, 0,
|
||||
0, 1, 1, 1, 0,
|
||||
0, 1, MIN_BLUR, 1, 0,
|
||||
0, 1, 1, 1, 0,
|
||||
0, 0 ,0, 0, 0,
|
||||
};
|
||||
|
||||
static gfloat sharpen_matrix [25] =
|
||||
{
|
||||
0, 0, 0, 0, 0,
|
||||
0, 1, 1, 1, 0,
|
||||
0, 1, MIN_SHARPEN, 1, 0,
|
||||
0, 1, 1, 1, 0,
|
||||
0, 0, 0, 0, 0,
|
||||
};
|
||||
|
||||
|
||||
/* functions */
|
||||
|
||||
static void
|
||||
convolve_options_reset (void)
|
||||
{
|
||||
ConvolveOptions *options = convolve_options;
|
||||
|
||||
paint_options_reset ((PaintOptions *) options);
|
||||
|
||||
gtk_adjustment_set_value (GTK_ADJUSTMENT (options->rate_w), options->rate_d);
|
||||
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->type_w[options->type_d]), TRUE);
|
||||
}
|
||||
|
||||
static ConvolveOptions *
|
||||
convolve_options_new (void)
|
||||
{
|
||||
ConvolveOptions *options;
|
||||
|
||||
GtkWidget *vbox;
|
||||
GtkWidget *hbox;
|
||||
GtkWidget *label;
|
||||
GtkWidget *scale;
|
||||
GtkWidget *frame;
|
||||
|
||||
/* the new convolve tool options structure */
|
||||
options = g_new (ConvolveOptions, 1);
|
||||
paint_options_init ((PaintOptions *) options,
|
||||
CONVOLVE,
|
||||
convolve_options_reset);
|
||||
options->type = options->type_d = DEFAULT_CONVOLVE_TYPE;
|
||||
options->rate = options->rate_d = DEFAULT_CONVOLVE_RATE;
|
||||
|
||||
/* the main vbox */
|
||||
vbox = ((ToolOptions *) options)->main_vbox;
|
||||
|
||||
/* the rate scale */
|
||||
hbox = gtk_hbox_new (FALSE, 4);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
|
||||
|
||||
label = gtk_label_new (_("Rate:"));
|
||||
gtk_misc_set_alignment (GTK_MISC (label), 1.0, 1.0);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
|
||||
gtk_widget_show (label);
|
||||
|
||||
options->rate_w =
|
||||
gtk_adjustment_new (options->rate_d, 0.0, 100.0, 1.0, 1.0, 0.0);
|
||||
scale = gtk_hscale_new (GTK_ADJUSTMENT (options->rate_w));
|
||||
gtk_box_pack_start (GTK_BOX (hbox), scale, TRUE, TRUE, 0);
|
||||
gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_TOP);
|
||||
gtk_range_set_update_policy (GTK_RANGE (scale), GTK_UPDATE_DELAYED);
|
||||
gtk_signal_connect (GTK_OBJECT (options->rate_w), "value_changed",
|
||||
GTK_SIGNAL_FUNC (gimp_double_adjustment_update),
|
||||
&options->rate);
|
||||
gtk_widget_show (scale);
|
||||
gtk_widget_show (hbox);
|
||||
|
||||
frame = gimp_radio_group_new2 (TRUE, _("Convolve Type"),
|
||||
gimp_radio_button_update,
|
||||
&options->type, (gpointer) options->type,
|
||||
|
||||
_("Blur"), (gpointer) BLUR_CONVOLVE,
|
||||
&options->type_w[0],
|
||||
_("Sharpen"), (gpointer) SHARPEN_CONVOLVE,
|
||||
&options->type_w[1],
|
||||
|
||||
NULL);
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
|
||||
gtk_widget_show (frame);
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
static gpointer
|
||||
convolve_paint_func (PaintCore *paint_core,
|
||||
GimpDrawable *drawable,
|
||||
PaintState state)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case MOTION_PAINT:
|
||||
convolve_motion (paint_core, drawable,
|
||||
convolve_options->paint_options.pressure_options,
|
||||
convolve_options->type, convolve_options->rate);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
convolve_modifier_key_func (Tool *tool,
|
||||
GdkEventKey *kevent,
|
||||
GDisplay *gdisp)
|
||||
{
|
||||
switch (kevent->keyval)
|
||||
{
|
||||
case GDK_Alt_L:
|
||||
case GDK_Alt_R:
|
||||
break;
|
||||
case GDK_Shift_L:
|
||||
case GDK_Shift_R:
|
||||
if (kevent->state & GDK_CONTROL_MASK) /* reset tool toggle */
|
||||
{
|
||||
switch (convolve_options->type)
|
||||
{
|
||||
case BLUR_CONVOLVE:
|
||||
gtk_toggle_button_set_active
|
||||
(GTK_TOGGLE_BUTTON (convolve_options->type_w[SHARPEN_CONVOLVE]),
|
||||
TRUE);
|
||||
break;
|
||||
case SHARPEN_CONVOLVE:
|
||||
gtk_toggle_button_set_active
|
||||
(GTK_TOGGLE_BUTTON (convolve_options->type_w[BLUR_CONVOLVE]),
|
||||
TRUE);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GDK_Control_L:
|
||||
case GDK_Control_R:
|
||||
if ( !(kevent->state & GDK_SHIFT_MASK) ) /* shift enables line draw mode */
|
||||
{
|
||||
switch (convolve_options->type)
|
||||
{
|
||||
case BLUR_CONVOLVE:
|
||||
gtk_toggle_button_set_active
|
||||
(GTK_TOGGLE_BUTTON (convolve_options->type_w[SHARPEN_CONVOLVE]),
|
||||
TRUE);
|
||||
break;
|
||||
case SHARPEN_CONVOLVE:
|
||||
gtk_toggle_button_set_active
|
||||
(GTK_TOGGLE_BUTTON (convolve_options->type_w[BLUR_CONVOLVE]),
|
||||
TRUE);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
tool->toggled = (convolve_options->type == SHARPEN_CONVOLVE);
|
||||
}
|
||||
|
||||
static void
|
||||
convolve_cursor_update_func (Tool *tool,
|
||||
GdkEventMotion *mevent,
|
||||
GDisplay *gdisp)
|
||||
{
|
||||
tool->toggled = (convolve_options->type == SHARPEN_CONVOLVE);
|
||||
|
||||
paint_core_cursor_update (tool, mevent, gdisp);
|
||||
}
|
||||
|
||||
Tool *
|
||||
tools_new_convolve (void)
|
||||
{
|
||||
Tool *tool;
|
||||
PaintCore *private;
|
||||
|
||||
/* The tool options */
|
||||
if (! convolve_options)
|
||||
{
|
||||
convolve_options = convolve_options_new ();
|
||||
tools_register (CONVOLVE, (ToolOptions *) convolve_options);
|
||||
|
||||
/* press all default buttons */
|
||||
convolve_options_reset ();
|
||||
}
|
||||
|
||||
tool = paint_core_new (CONVOLVE);
|
||||
tool->modifier_key_func = convolve_modifier_key_func;
|
||||
tool->cursor_update_func = convolve_cursor_update_func;
|
||||
|
||||
private = (PaintCore *) tool->private;
|
||||
private->paint_func = convolve_paint_func;
|
||||
|
||||
return tool;
|
||||
}
|
||||
|
||||
void
|
||||
tools_free_convolve (Tool *tool)
|
||||
{
|
||||
paint_core_free (tool);
|
||||
}
|
||||
|
||||
static void
|
||||
convolve_motion (PaintCore *paint_core,
|
||||
GimpDrawable *drawable,
|
||||
PaintPressureOptions *pressure_options,
|
||||
ConvolveType type,
|
||||
double rate)
|
||||
{
|
||||
TempBuf *area;
|
||||
guchar *temp_data;
|
||||
PixelRegion srcPR;
|
||||
PixelRegion destPR;
|
||||
gdouble scale;
|
||||
ConvolveClipType area_hclip = CONVOLVE_NOT_CLIPPED;
|
||||
ConvolveClipType area_vclip = CONVOLVE_NOT_CLIPPED;
|
||||
gint marginx = 0;
|
||||
gint marginy = 0;
|
||||
|
||||
if (! gimp_drawable_gimage (drawable))
|
||||
return;
|
||||
|
||||
/* If the image type is indexed, don't convolve */
|
||||
if (gimp_drawable_is_indexed (drawable))
|
||||
return;
|
||||
|
||||
/* If the brush is smaller than the convolution matrix, don't convolve */
|
||||
|
||||
if ((paint_core->brush->mask->width < matrix_size) ||
|
||||
(paint_core->brush->mask->height < matrix_size))
|
||||
return;
|
||||
|
||||
if (pressure_options->size)
|
||||
scale = paint_core->curpressure;
|
||||
else
|
||||
scale = 1.0;
|
||||
|
||||
/* Get image region around current brush (mask bbox + 1 pixel) */
|
||||
if (! (area = paint_core_get_paint_area (paint_core, drawable, scale)))
|
||||
return;
|
||||
|
||||
/* configure the source pixel region */
|
||||
pixel_region_init (&srcPR, gimp_drawable_data (drawable),
|
||||
area->x, area->y, area->width, area->height, FALSE);
|
||||
|
||||
/* Configure the destination pixel region - a paint_core TempBuf */
|
||||
|
||||
destPR.bytes = area->bytes;
|
||||
destPR.tiles = NULL;
|
||||
destPR.x = 0;
|
||||
destPR.y = 0;
|
||||
destPR.w = area->width;
|
||||
destPR.h = area->height;
|
||||
destPR.rowstride = area->width * destPR.bytes;
|
||||
destPR.data = temp_buf_data (area);
|
||||
|
||||
if (pressure_options->rate)
|
||||
rate = rate * 2.0 * paint_core->curpressure;
|
||||
|
||||
calculate_matrix (type, rate);
|
||||
|
||||
/* Image region near edges? If so, paint area will be clipped */
|
||||
/* with respect to brush mask + 1 pixel border (# 19285) */
|
||||
|
||||
if((marginx = (gint)paint_core->curx - paint_core->brush->mask->width/2 - 1) != area->x)
|
||||
area_hclip = CONVOLVE_NCLIP;
|
||||
else
|
||||
if((marginx = area->width - paint_core->brush->mask->width - 2) != 0)
|
||||
area_hclip = CONVOLVE_PCLIP;
|
||||
|
||||
if((marginy = (gint)paint_core->cury - paint_core->brush->mask->height/2 - 1) != area->y)
|
||||
area_vclip = CONVOLVE_NCLIP;
|
||||
else
|
||||
if((marginy = area->height - paint_core->brush->mask->height - 2) != 0)
|
||||
area_vclip = CONVOLVE_PCLIP;
|
||||
|
||||
/* Has the TempBuf been clipped by a canvas edge or two ? */
|
||||
if((area_hclip == CONVOLVE_NOT_CLIPPED) && (area_vclip == CONVOLVE_NOT_CLIPPED))
|
||||
{
|
||||
/* No clipping... */
|
||||
/* Standard case: copy src to temp. convolve temp to dest. */
|
||||
/* Brush defines pipe size and no edge adjustments are needed. */
|
||||
|
||||
/* If the source has no alpha, then add alpha pixels */
|
||||
/* Because paint_core.c is alpha-only code. See below. */
|
||||
|
||||
PixelRegion tempPR;
|
||||
|
||||
tempPR.x = 0;
|
||||
tempPR.y = 0;
|
||||
tempPR.w = area->width;
|
||||
tempPR.h = area->height;
|
||||
tempPR.tiles = NULL;
|
||||
|
||||
if (! gimp_drawable_has_alpha (drawable))
|
||||
{
|
||||
/* note: this particular approach needlessly convolves the totally-
|
||||
opaque alpha channel. A faster approach would be to keep
|
||||
tempPR the same number of bytes as srcPR, and extend the
|
||||
paint_core_replace_canvas API to handle non-alpha images. */
|
||||
|
||||
tempPR.bytes = srcPR.bytes + 1;
|
||||
tempPR.rowstride = tempPR.bytes * tempPR.w;
|
||||
temp_data = g_malloc (tempPR.h * tempPR.rowstride);
|
||||
tempPR.data = temp_data;
|
||||
add_alpha_region (&srcPR, &tempPR);
|
||||
}
|
||||
else
|
||||
{
|
||||
tempPR.bytes = srcPR.bytes;
|
||||
tempPR.rowstride = tempPR.bytes * tempPR.w;
|
||||
temp_data = g_malloc (tempPR.h * tempPR.rowstride);
|
||||
tempPR.data = temp_data;
|
||||
copy_region (&srcPR, &tempPR);
|
||||
}
|
||||
|
||||
/* Convolve the region */
|
||||
|
||||
tempPR.x = 0;
|
||||
tempPR.y = 0;
|
||||
tempPR.w = area->width;
|
||||
tempPR.h = area->height;
|
||||
tempPR.data = temp_data;
|
||||
convolve_region (&tempPR, &destPR, matrix, matrix_size,
|
||||
matrix_divisor, NORMAL_CONVOL);
|
||||
|
||||
/* Free the allocated temp space */
|
||||
g_free (temp_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* TempBuf clipping has occured on at least one edge... */
|
||||
/* Edge case: expand area under brush margin px on near edge(s), convolve */
|
||||
/* expanded buffers. copy src -> ovrsz1 convolve ovrsz1 -> ovrsz2 */
|
||||
/* copy-with-crop ovrsz2 -> dest */
|
||||
|
||||
PixelRegion ovrsz1PR;
|
||||
PixelRegion ovrsz2PR;
|
||||
guchar *ovrsz1_data = NULL;
|
||||
guchar *ovrsz2_data = NULL;
|
||||
guchar *fillcolor = gimp_drawable_get_color_at (drawable,
|
||||
CLAMP ((gint) paint_core->curx, 0, gimp_drawable_width (drawable) - 1),
|
||||
CLAMP ((gint) paint_core->cury, 0, gimp_drawable_height (drawable) - 1));
|
||||
|
||||
marginx *= (marginx < 0) ? -1 : 0;
|
||||
marginy *= (marginy < 0) ? -1 : 0;
|
||||
|
||||
ovrsz2PR.x = 0;
|
||||
ovrsz2PR.y = 0;
|
||||
ovrsz2PR.w = area->width + marginx;
|
||||
ovrsz2PR.h = area->height + marginy;
|
||||
ovrsz2PR.bytes = (gimp_drawable_has_alpha (drawable))? srcPR.bytes : srcPR.bytes + 1;
|
||||
ovrsz2PR.offx = 0;
|
||||
ovrsz2PR.offy = 0;
|
||||
ovrsz2PR.rowstride = ovrsz2PR.bytes * ovrsz2PR.w;
|
||||
ovrsz2PR.tiles = NULL;
|
||||
ovrsz2_data = g_malloc (ovrsz2PR.h * ovrsz2PR.rowstride);
|
||||
ovrsz2PR.data = ovrsz2_data;
|
||||
|
||||
ovrsz1PR.x = 0;
|
||||
ovrsz1PR.y = 0;
|
||||
ovrsz1PR.w = area->width + marginx;
|
||||
ovrsz1PR.h = area->height + marginy;
|
||||
ovrsz1PR.bytes = (gimp_drawable_has_alpha (drawable))? srcPR.bytes : srcPR.bytes + 1;
|
||||
ovrsz1PR.offx = 0;
|
||||
ovrsz1PR.offy = 0;
|
||||
ovrsz1PR.rowstride = ovrsz2PR.bytes * ovrsz2PR.w;
|
||||
ovrsz1PR.tiles = NULL;
|
||||
ovrsz1_data = g_malloc (ovrsz1PR.h * ovrsz1PR.rowstride);
|
||||
ovrsz1PR.data = ovrsz1_data;
|
||||
color_region (&ovrsz1PR, (const guchar *)fillcolor);
|
||||
|
||||
ovrsz1PR.x = (area_hclip == CONVOLVE_NCLIP)? marginx : 0;
|
||||
ovrsz1PR.y = (area_vclip == CONVOLVE_NCLIP)? marginy : 0;
|
||||
ovrsz1PR.w = area->width;
|
||||
ovrsz1PR.h = area->height;
|
||||
ovrsz1PR.data = ovrsz1_data + (ovrsz1PR.rowstride * ovrsz1PR.y) + (ovrsz1PR.bytes * ovrsz1PR.x);
|
||||
|
||||
if (! gimp_drawable_has_alpha (drawable))
|
||||
add_alpha_region (&srcPR, &ovrsz1PR);
|
||||
else
|
||||
copy_region (&srcPR, &ovrsz1PR);
|
||||
|
||||
/* Convolve the region */
|
||||
|
||||
ovrsz1PR.x = 0;
|
||||
ovrsz1PR.y = 0;
|
||||
ovrsz1PR.w = area->width + marginx;
|
||||
ovrsz1PR.h = area->height + marginy;
|
||||
ovrsz1PR.data = ovrsz1_data;
|
||||
convolve_region (&ovrsz1PR, &ovrsz2PR, matrix, matrix_size,
|
||||
matrix_divisor, NORMAL_CONVOL);
|
||||
|
||||
/* Crop and copy to destination */
|
||||
|
||||
ovrsz2PR.x = (area_hclip == CONVOLVE_NCLIP)? marginx : 0;
|
||||
ovrsz2PR.y = (area_vclip == CONVOLVE_NCLIP)? marginy : 0;
|
||||
ovrsz2PR.w = area->width;
|
||||
ovrsz2PR.h = area->height;
|
||||
ovrsz2PR.data = ovrsz2_data + (ovrsz2PR.rowstride * ovrsz2PR.y) + (ovrsz2PR.bytes * ovrsz2PR.x);
|
||||
copy_region (&ovrsz2PR, &destPR);
|
||||
g_free(ovrsz1_data);
|
||||
g_free(ovrsz2_data);
|
||||
g_free(fillcolor);
|
||||
}
|
||||
|
||||
/* paste the newly painted canvas to the gimage which is being worked on */
|
||||
paint_core_replace_canvas (paint_core, drawable, OPAQUE_OPACITY,
|
||||
(int) (gimp_context_get_opacity (NULL) * 255),
|
||||
pressure_options->pressure ? PRESSURE : SOFT,
|
||||
scale, INCREMENTAL);
|
||||
}
|
||||
|
||||
static void
|
||||
calculate_matrix (ConvolveType type,
|
||||
double rate)
|
||||
{
|
||||
float percent;
|
||||
|
||||
/* find percent of tool pressure */
|
||||
percent = MIN (rate / 100.0, 1.0);
|
||||
|
||||
/* get the appropriate convolution matrix and size and divisor */
|
||||
switch (type)
|
||||
{
|
||||
case BLUR_CONVOLVE:
|
||||
matrix_size = 5;
|
||||
blur_matrix [12] = MIN_BLUR + percent * (MAX_BLUR - MIN_BLUR);
|
||||
copy_matrix (blur_matrix, custom_matrix, matrix_size);
|
||||
break;
|
||||
|
||||
case SHARPEN_CONVOLVE:
|
||||
matrix_size = 5;
|
||||
sharpen_matrix [12] = MIN_SHARPEN + percent * (MAX_SHARPEN - MIN_SHARPEN);
|
||||
copy_matrix (sharpen_matrix, custom_matrix, matrix_size);
|
||||
break;
|
||||
|
||||
case CUSTOM_CONVOLVE:
|
||||
matrix_size = 5;
|
||||
break;
|
||||
}
|
||||
|
||||
integer_matrix (custom_matrix, matrix, matrix_size);
|
||||
matrix_divisor = sum_matrix (matrix, matrix_size);
|
||||
|
||||
if (!matrix_divisor)
|
||||
matrix_divisor = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
integer_matrix (gfloat *source,
|
||||
gint *dest,
|
||||
gint size)
|
||||
{
|
||||
gint i;
|
||||
|
||||
#define PRECISION 10000
|
||||
|
||||
for (i = 0; i < size*size; i++)
|
||||
*dest++ = (gint) (*source ++ * PRECISION);
|
||||
}
|
||||
|
||||
static void
|
||||
copy_matrix (gfloat *src,
|
||||
gfloat *dest,
|
||||
gint size)
|
||||
{
|
||||
gint i;
|
||||
|
||||
for (i = 0; i < size*size; i++)
|
||||
*dest++ = *src++;
|
||||
}
|
||||
|
||||
static int
|
||||
sum_matrix (gint *matrix,
|
||||
gint size)
|
||||
{
|
||||
gint sum = 0;
|
||||
|
||||
size *= size;
|
||||
|
||||
while (size --)
|
||||
sum += *matrix++;
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
|
||||
static gpointer
|
||||
convolve_non_gui_paint_func (PaintCore *paint_core,
|
||||
GimpDrawable *drawable,
|
||||
PaintState state)
|
||||
{
|
||||
convolve_motion (paint_core, drawable, &non_gui_pressure_options,
|
||||
non_gui_type, non_gui_rate);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gboolean
|
||||
convolve_non_gui_default (GimpDrawable *drawable,
|
||||
gint num_strokes,
|
||||
gdouble *stroke_array)
|
||||
{
|
||||
gdouble rate = DEFAULT_CONVOLVE_RATE;
|
||||
ConvolveType type = DEFAULT_CONVOLVE_TYPE;
|
||||
ConvolveOptions *options = convolve_options;
|
||||
|
||||
if (options)
|
||||
{
|
||||
rate = options->rate;
|
||||
type = options->type;
|
||||
}
|
||||
|
||||
return convolve_non_gui (drawable, rate, type, num_strokes, stroke_array);
|
||||
}
|
||||
|
||||
gboolean
|
||||
convolve_non_gui (GimpDrawable *drawable,
|
||||
double rate,
|
||||
ConvolveType type,
|
||||
gint num_strokes,
|
||||
gdouble *stroke_array)
|
||||
{
|
||||
gint i;
|
||||
|
||||
if (paint_core_init (&non_gui_paint_core, drawable,
|
||||
stroke_array[0], stroke_array[1]))
|
||||
{
|
||||
/* Set the paint core's paint func */
|
||||
non_gui_paint_core.paint_func = convolve_non_gui_paint_func;
|
||||
|
||||
non_gui_type = type;
|
||||
non_gui_rate = rate;
|
||||
|
||||
non_gui_paint_core.startx = non_gui_paint_core.lastx = stroke_array[0];
|
||||
non_gui_paint_core.starty = non_gui_paint_core.lasty = stroke_array[1];
|
||||
|
||||
convolve_non_gui_paint_func (&non_gui_paint_core, drawable, 0);
|
||||
|
||||
for (i = 1; i < num_strokes; i++)
|
||||
{
|
||||
non_gui_paint_core.curx = stroke_array[i * 2 + 0];
|
||||
non_gui_paint_core.cury = stroke_array[i * 2 + 1];
|
||||
|
||||
paint_core_interpolate (&non_gui_paint_core, drawable);
|
||||
|
||||
non_gui_paint_core.lastx = non_gui_paint_core.curx;
|
||||
non_gui_paint_core.lasty = non_gui_paint_core.cury;
|
||||
}
|
||||
|
||||
/* Finish the painting */
|
||||
paint_core_finish (&non_gui_paint_core, drawable, -1);
|
||||
|
||||
/* Cleanup */
|
||||
paint_core_cleanup ();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
/* 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.
|
||||
*/
|
||||
|
||||
#ifndef __CONVOLVE_H__
|
||||
#define __CONVOLVE_H__
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
BLUR_CONVOLVE,
|
||||
SHARPEN_CONVOLVE,
|
||||
CUSTOM_CONVOLVE
|
||||
} ConvolveType;
|
||||
|
||||
|
||||
gboolean convolve_non_gui (GimpDrawable *drawable,
|
||||
gdouble rate,
|
||||
ConvolveType type,
|
||||
gint num_strokes,
|
||||
gdouble *stroke_array);
|
||||
gboolean convolve_non_gui_default (GimpDrawable *drawable,
|
||||
gint num_strokes,
|
||||
gdouble *stroke_array);
|
||||
|
||||
Tool * tools_new_convolve (void);
|
||||
void tools_free_convolve (Tool *tool);
|
||||
|
||||
|
||||
#endif /* __CONVOLVE_H__ */
|
|
@ -38,9 +38,10 @@
|
|||
#include "paint_funcs.h"
|
||||
#include "pixel_region.h"
|
||||
#include "tile_manager.h"
|
||||
#include "tools.h"
|
||||
#include "undo.h"
|
||||
|
||||
#include "tools/tools.h"
|
||||
|
||||
#include "libgimp/gimpintl.h"
|
||||
|
||||
#include "tile_manager_pvt.h"
|
||||
|
|
|
@ -50,9 +50,11 @@
|
|||
#include "gimprc.h"
|
||||
#include "patterns.h"
|
||||
#include "pattern_header.h"
|
||||
#include "paint_core.h"
|
||||
#include "temp_buf.h"
|
||||
|
||||
/* this needs to go away */
|
||||
#include "tools/paint_core.h"
|
||||
|
||||
#include "libgimp/gimpintl.h"
|
||||
|
||||
|
||||
|
|
|
@ -50,9 +50,11 @@
|
|||
#include "gimprc.h"
|
||||
#include "patterns.h"
|
||||
#include "pattern_header.h"
|
||||
#include "paint_core.h"
|
||||
#include "temp_buf.h"
|
||||
|
||||
/* this needs to go away */
|
||||
#include "tools/paint_core.h"
|
||||
|
||||
#include "libgimp/gimpintl.h"
|
||||
|
||||
|
||||
|
|
|
@ -33,11 +33,13 @@
|
|||
|
||||
#include "appenv.h"
|
||||
#include "gimpbrushgenerated.h"
|
||||
#include "paint_core.h"
|
||||
#include "gimprc.h"
|
||||
#include "gimpbrush.h"
|
||||
#include "temp_buf.h"
|
||||
|
||||
/* this needs to go away */
|
||||
#include "tools/paint_core.h"
|
||||
|
||||
#include "libgimp/gimpmath.h"
|
||||
|
||||
|
||||
|
|
|
@ -33,11 +33,13 @@
|
|||
|
||||
#include "appenv.h"
|
||||
#include "gimpbrushgenerated.h"
|
||||
#include "paint_core.h"
|
||||
#include "gimprc.h"
|
||||
#include "gimpbrush.h"
|
||||
#include "temp_buf.h"
|
||||
|
||||
/* this needs to go away */
|
||||
#include "tools/paint_core.h"
|
||||
|
||||
#include "libgimp/gimpmath.h"
|
||||
|
||||
|
||||
|
|
|
@ -33,11 +33,13 @@
|
|||
|
||||
#include "appenv.h"
|
||||
#include "gimpbrushgenerated.h"
|
||||
#include "paint_core.h"
|
||||
#include "gimprc.h"
|
||||
#include "gimpbrush.h"
|
||||
#include "temp_buf.h"
|
||||
|
||||
/* this needs to go away */
|
||||
#include "tools/paint_core.h"
|
||||
|
||||
#include "libgimp/gimpmath.h"
|
||||
|
||||
|
||||
|
|
|
@ -48,9 +48,11 @@
|
|||
#include "patterns.h"
|
||||
#include "gimpbrush.h"
|
||||
#include "gimpbrushpipe.h"
|
||||
#include "paint_core.h"
|
||||
#include "gimprc.h"
|
||||
|
||||
/* this needs to go away */
|
||||
#include "tools/paint_core.h"
|
||||
|
||||
#include "libgimp/gimpmath.h"
|
||||
#include "libgimp/gimpparasiteio.h"
|
||||
|
||||
|
|
|
@ -48,9 +48,11 @@
|
|||
#include "patterns.h"
|
||||
#include "gimpbrush.h"
|
||||
#include "gimpbrushpipe.h"
|
||||
#include "paint_core.h"
|
||||
#include "gimprc.h"
|
||||
|
||||
/* this needs to go away */
|
||||
#include "tools/paint_core.h"
|
||||
|
||||
#include "libgimp/gimpmath.h"
|
||||
#include "libgimp/gimpparasiteio.h"
|
||||
|
||||
|
|
|
@ -38,9 +38,10 @@
|
|||
#include "paint_funcs.h"
|
||||
#include "pixel_region.h"
|
||||
#include "tile_manager.h"
|
||||
#include "tools.h"
|
||||
#include "undo.h"
|
||||
|
||||
#include "tools/tools.h"
|
||||
|
||||
#include "libgimp/gimpintl.h"
|
||||
|
||||
#include "tile_manager_pvt.h"
|
||||
|
|
|
@ -94,30 +94,31 @@
|
|||
#include "apptypes.h"
|
||||
|
||||
#include "appenv.h"
|
||||
#include "brightness_contrast.h"
|
||||
#include "color_balance.h"
|
||||
#include "convert.h"
|
||||
#include "cursorutil.h"
|
||||
#include "curves.h"
|
||||
#include "drawable.h"
|
||||
#include "floating_sel.h"
|
||||
#include "fsdither.h"
|
||||
#include "gdisplay.h"
|
||||
#include "gimpimage.h"
|
||||
#include "gimpui.h"
|
||||
#include "hue_saturation.h"
|
||||
#include "layer.h"
|
||||
#include "levels.h"
|
||||
#include "undo.h"
|
||||
#include "palette.h"
|
||||
#include "gimppalette.h"
|
||||
#include "palette_select.h"
|
||||
#include "pixel_region.h"
|
||||
#include "posterize.h"
|
||||
#include "threshold.h"
|
||||
#include "tile_manager.h"
|
||||
#include "tile_manager_pvt.h" /* ick ick ick. */
|
||||
|
||||
#include "tools/brightness_contrast.h"
|
||||
#include "tools/color_balance.h"
|
||||
#include "tools/curves.h"
|
||||
#include "tools/hue_saturation.h"
|
||||
#include "tools/levels.h"
|
||||
#include "tools/posterize.h"
|
||||
#include "tools/threshold.h"
|
||||
|
||||
#include "libgimp/gimpcolorspace.h"
|
||||
#include "libgimp/gimphelpui.h"
|
||||
#include "libgimp/gimpmath.h"
|
||||
|
|
|
@ -31,14 +31,16 @@
|
|||
#include "gimage_mask.h"
|
||||
#include "gimprc.h"
|
||||
#include "layer.h"
|
||||
#include "paint_core.h"
|
||||
#include "paint_funcs.h"
|
||||
#include "paint_options.h"
|
||||
#include "pixel_region.h"
|
||||
#include "tile_manager.h"
|
||||
#include "tile_manager_pvt.h"
|
||||
#include "undo.h"
|
||||
|
||||
#include "tools/paint_core.h"
|
||||
#include "tools/paint_options.h"
|
||||
#include "tools/tools.h"
|
||||
|
||||
#include "pdb/procedural_db.h"
|
||||
|
||||
#include "libgimp/gimpintl.h"
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
#include "apptypes.h"
|
||||
|
||||
#include "appenv.h"
|
||||
#include "by_color_select.h"
|
||||
#include "channel.h"
|
||||
#include "draw_core.h"
|
||||
#include "drawable.h"
|
||||
|
@ -38,7 +37,6 @@
|
|||
#include "gimpparasite.h"
|
||||
#include "gimprc.h"
|
||||
#include "layer.h"
|
||||
#include "paint_core.h"
|
||||
#include "paint_funcs.h"
|
||||
#include "parasitelist.h"
|
||||
#include "path_transform.h"
|
||||
|
@ -46,10 +44,13 @@
|
|||
#include "tile_manager.h"
|
||||
#include "tile_manager_pvt.h"
|
||||
#include "tile.h"
|
||||
#include "tools.h"
|
||||
#include "transform_core.h"
|
||||
#include "undo.h"
|
||||
|
||||
#include "tools/by_color_select.h"
|
||||
#include "tools/paint_core.h"
|
||||
#include "tools/tools.h"
|
||||
#include "tools/transform_core.h"
|
||||
|
||||
#include "libgimp/gimpparasite.h"
|
||||
|
||||
#include "libgimp/gimpintl.h"
|
||||
|
|
|
@ -51,7 +51,6 @@
|
|||
#include "scale.h"
|
||||
#include "scroll.h"
|
||||
#include "selection.h"
|
||||
#include "tools.h"
|
||||
#include "undo.h"
|
||||
|
||||
|
||||
|
@ -59,7 +58,8 @@
|
|||
#include "gdisplay_color.h"
|
||||
#endif /* DISPLAY_FILTERS */
|
||||
|
||||
#include "bezier_selectP.h"
|
||||
#include "tools/bezier_selectP.h"
|
||||
#include "tools/tools.h"
|
||||
|
||||
#include "libgimp/gimpmath.h"
|
||||
|
||||
|
|
1598
app/crop.c
1598
app/crop.c
File diff suppressed because it is too large
Load Diff
43
app/crop.h
43
app/crop.h
|
@ -1,43 +0,0 @@
|
|||
/* 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.
|
||||
*/
|
||||
|
||||
#ifndef __CROP_H__
|
||||
#define __CROP_H__
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CROP_CROP,
|
||||
RESIZE_CROP
|
||||
} CropType;
|
||||
|
||||
|
||||
void crop_draw (Tool *tool);
|
||||
void crop_image (GimpImage *gimage,
|
||||
gint x1,
|
||||
gint y1,
|
||||
gint x2,
|
||||
gint y2,
|
||||
gboolean layer_only,
|
||||
gboolean crop_layers);
|
||||
|
||||
Tool * tools_new_crop (void);
|
||||
void tools_free_crop (Tool *tool);
|
||||
|
||||
|
||||
#endif /* __CROP_H__ */
|
|
@ -26,7 +26,8 @@
|
|||
#include "cursorutil.h"
|
||||
#include "dialog_handler.h"
|
||||
#include "gdisplay.h" /* for gdisplay_*_override_cursor() */
|
||||
#include "tools.h"
|
||||
|
||||
#include "tools/tools.h"
|
||||
|
||||
#include "cursors/mouse.xbm"
|
||||
#include "cursors/mouse_mask.xbm"
|
||||
|
|
1821
app/curves.c
1821
app/curves.c
File diff suppressed because it is too large
Load Diff
76
app/curves.h
76
app/curves.h
|
@ -1,76 +0,0 @@
|
|||
/* 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.
|
||||
*/
|
||||
|
||||
#ifndef __CURVES_H__
|
||||
#define __CURVES_H__
|
||||
|
||||
|
||||
#define SMOOTH 0
|
||||
#define GFREE 1
|
||||
|
||||
|
||||
typedef struct _CurvesDialog CurvesDialog;
|
||||
|
||||
struct _CurvesDialog
|
||||
{
|
||||
GtkWidget *shell;
|
||||
|
||||
GtkWidget *channel_menu;
|
||||
GtkWidget *xrange;
|
||||
GtkWidget *yrange;
|
||||
GtkWidget *graph;
|
||||
GdkPixmap *pixmap;
|
||||
GtkWidget *curve_type_menu;
|
||||
|
||||
GimpDrawable *drawable;
|
||||
ImageMap image_map;
|
||||
|
||||
gint color;
|
||||
gint channel;
|
||||
gboolean preview;
|
||||
|
||||
gint grab_point;
|
||||
gint last;
|
||||
gint leftmost;
|
||||
gint rightmost;
|
||||
gint curve_type[5];
|
||||
gint points[5][17][2];
|
||||
guchar curve[5][256];
|
||||
gint col_value[5];
|
||||
|
||||
gint cursor_ind_height;
|
||||
gint cursor_ind_width;
|
||||
gint cursor_ind_ascent;
|
||||
|
||||
GimpLut *lut;
|
||||
};
|
||||
|
||||
Tool * tools_new_curves (void);
|
||||
void tools_free_curves (Tool *tool);
|
||||
|
||||
void curves_dialog_hide (void);
|
||||
void curves_initialize (GDisplay *gdisp);
|
||||
void curves_free (void);
|
||||
gfloat curves_lut_func (CurvesDialog *cd,
|
||||
gint nchannels,
|
||||
gint channel,
|
||||
gfloat value);
|
||||
void curves_calculate_curve (CurvesDialog *cd);
|
||||
|
||||
|
||||
#endif /* __CURVES_H__ */
|
|
@ -39,7 +39,8 @@
|
|||
#include "gradient_header.h"
|
||||
#include "patterns.h"
|
||||
#include "session.h"
|
||||
#include "tools.h"
|
||||
|
||||
#include "tools/tools.h"
|
||||
|
||||
#include "libgimp/gimpenv.h"
|
||||
#include "libgimp/gimpcolorarea.h"
|
||||
|
|
|
@ -34,7 +34,8 @@
|
|||
#include "info_dialog.h"
|
||||
#include "info_window.h"
|
||||
#include "scroll.h"
|
||||
#include "tools.h"
|
||||
|
||||
#include "tools/tools.h"
|
||||
|
||||
#include "pdb/procedural_db.h"
|
||||
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
#include "apptypes.h"
|
||||
|
||||
#include "appenv.h"
|
||||
#include "bucket_fill.h"
|
||||
#include "cursorutil.h"
|
||||
#include "devices.h"
|
||||
#include "dialog_handler.h"
|
||||
|
@ -39,7 +38,6 @@
|
|||
#include "info_window.h"
|
||||
#include "layer.h"
|
||||
#include "layer_select.h"
|
||||
#include "move.h"
|
||||
#include "paint_funcs.h"
|
||||
#include "patterns.h"
|
||||
#include "pixel_region.h"
|
||||
|
@ -48,9 +46,12 @@
|
|||
#include "selection.h"
|
||||
#include "temp_buf.h"
|
||||
#include "tile_manager.h"
|
||||
#include "tools.h"
|
||||
#include "undo.h"
|
||||
|
||||
#include "tools/bucket_fill.h"
|
||||
#include "tools/move.h"
|
||||
#include "tools/tools.h"
|
||||
|
||||
#include "libgimp/gimpintl.h"
|
||||
|
||||
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
#include "apptypes.h"
|
||||
|
||||
#include "appenv.h"
|
||||
#include "bucket_fill.h"
|
||||
#include "cursorutil.h"
|
||||
#include "devices.h"
|
||||
#include "dialog_handler.h"
|
||||
|
@ -39,7 +38,6 @@
|
|||
#include "info_window.h"
|
||||
#include "layer.h"
|
||||
#include "layer_select.h"
|
||||
#include "move.h"
|
||||
#include "paint_funcs.h"
|
||||
#include "patterns.h"
|
||||
#include "pixel_region.h"
|
||||
|
@ -48,9 +46,12 @@
|
|||
#include "selection.h"
|
||||
#include "temp_buf.h"
|
||||
#include "tile_manager.h"
|
||||
#include "tools.h"
|
||||
#include "undo.h"
|
||||
|
||||
#include "tools/bucket_fill.h"
|
||||
#include "tools/move.h"
|
||||
#include "tools/tools.h"
|
||||
|
||||
#include "libgimp/gimpintl.h"
|
||||
|
||||
|
||||
|
|
|
@ -31,7 +31,8 @@
|
|||
#include "gimprc.h"
|
||||
#include "nav_window.h"
|
||||
#include "scale.h"
|
||||
#include "tools.h"
|
||||
|
||||
#include "tools/tools.h"
|
||||
|
||||
|
||||
void
|
||||
|
|
|
@ -30,7 +30,8 @@
|
|||
#include "scale.h"
|
||||
#include "scroll.h"
|
||||
#include "nav_window.h"
|
||||
#include "tools.h"
|
||||
|
||||
#include "tools/tools.h"
|
||||
|
||||
|
||||
/* This is the delay before dithering begins
|
||||
|
|
|
@ -51,7 +51,6 @@
|
|||
#include "scale.h"
|
||||
#include "scroll.h"
|
||||
#include "selection.h"
|
||||
#include "tools.h"
|
||||
#include "undo.h"
|
||||
|
||||
|
||||
|
@ -59,7 +58,8 @@
|
|||
#include "gdisplay_color.h"
|
||||
#endif /* DISPLAY_FILTERS */
|
||||
|
||||
#include "bezier_selectP.h"
|
||||
#include "tools/bezier_selectP.h"
|
||||
#include "tools/tools.h"
|
||||
|
||||
#include "libgimp/gimpmath.h"
|
||||
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
#include "apptypes.h"
|
||||
|
||||
#include "appenv.h"
|
||||
#include "bucket_fill.h"
|
||||
#include "cursorutil.h"
|
||||
#include "devices.h"
|
||||
#include "dialog_handler.h"
|
||||
|
@ -39,7 +38,6 @@
|
|||
#include "info_window.h"
|
||||
#include "layer.h"
|
||||
#include "layer_select.h"
|
||||
#include "move.h"
|
||||
#include "paint_funcs.h"
|
||||
#include "patterns.h"
|
||||
#include "pixel_region.h"
|
||||
|
@ -48,9 +46,12 @@
|
|||
#include "selection.h"
|
||||
#include "temp_buf.h"
|
||||
#include "tile_manager.h"
|
||||
#include "tools.h"
|
||||
#include "undo.h"
|
||||
|
||||
#include "tools/bucket_fill.h"
|
||||
#include "tools/move.h"
|
||||
#include "tools/tools.h"
|
||||
|
||||
#include "libgimp/gimpintl.h"
|
||||
|
||||
|
||||
|
|
|
@ -54,7 +54,8 @@
|
|||
#include "session.h"
|
||||
#include "pixel_region.h"
|
||||
#include "tile_manager.h"
|
||||
#include "tools.h"
|
||||
|
||||
#include "tools/tools.h"
|
||||
|
||||
#include "pixmaps.h"
|
||||
#include "pixmaps/qmasksel.xpm"
|
||||
|
|
|
@ -31,7 +31,8 @@
|
|||
#include "gimprc.h"
|
||||
#include "nav_window.h"
|
||||
#include "scale.h"
|
||||
#include "tools.h"
|
||||
|
||||
#include "tools/tools.h"
|
||||
|
||||
|
||||
void
|
||||
|
|
|
@ -30,7 +30,8 @@
|
|||
#include "scale.h"
|
||||
#include "scroll.h"
|
||||
#include "nav_window.h"
|
||||
#include "tools.h"
|
||||
|
||||
#include "tools/tools.h"
|
||||
|
||||
|
||||
/* This is the delay before dithering begins
|
||||
|
|
|
@ -54,7 +54,8 @@
|
|||
#include "session.h"
|
||||
#include "pixel_region.h"
|
||||
#include "tile_manager.h"
|
||||
#include "tools.h"
|
||||
|
||||
#include "tools/tools.h"
|
||||
|
||||
#include "pixmaps.h"
|
||||
#include "pixmaps/qmasksel.xpm"
|
||||
|
|
667
app/dodgeburn.c
667
app/dodgeburn.c
|
@ -1,667 +0,0 @@
|
|||
/* 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 <gtk/gtk.h>
|
||||
#include <gdk/gdkkeysyms.h>
|
||||
|
||||
#include "apptypes.h"
|
||||
|
||||
#include "appenv.h"
|
||||
#include "drawable.h"
|
||||
#include "dodgeburn.h"
|
||||
#include "gdisplay.h"
|
||||
#include "gimplut.h"
|
||||
#include "gimpcontext.h"
|
||||
#include "gimpui.h"
|
||||
#include "paint_funcs.h"
|
||||
#include "paint_core.h"
|
||||
#include "paint_options.h"
|
||||
#include "pixel_region.h"
|
||||
#include "selection.h"
|
||||
#include "temp_buf.h"
|
||||
#include "tools.h"
|
||||
#include "gimage.h"
|
||||
|
||||
#include "libgimp/gimpmath.h"
|
||||
|
||||
#include "libgimp/gimpintl.h"
|
||||
|
||||
|
||||
/* Default values */
|
||||
|
||||
#define DODGEBURN_DEFAULT_TYPE DODGE
|
||||
#define DODGEBURN_DEFAULT_EXPOSURE 50.0
|
||||
#define DODGEBURN_DEFAULT_MODE DODGEBURN_HIGHLIGHTS
|
||||
|
||||
/* the dodgeburn structures */
|
||||
|
||||
typedef struct _DodgeBurnOptions DodgeBurnOptions;
|
||||
|
||||
struct _DodgeBurnOptions
|
||||
{
|
||||
PaintOptions paint_options;
|
||||
|
||||
DodgeBurnType type;
|
||||
DodgeBurnType type_d;
|
||||
GtkWidget *type_w[2];
|
||||
|
||||
DodgeBurnMode mode; /*highlights, midtones, shadows*/
|
||||
DodgeBurnMode mode_d;
|
||||
GtkWidget *mode_w[3];
|
||||
|
||||
gdouble exposure;
|
||||
gdouble exposure_d;
|
||||
GtkObject *exposure_w;
|
||||
|
||||
GimpLut *lut;
|
||||
};
|
||||
|
||||
|
||||
static gpointer dodgeburn_paint_func (PaintCore *paint_core,
|
||||
GimpDrawable *drawable,
|
||||
PaintState state);
|
||||
|
||||
static void dodgeburn_make_luts (PaintCore *paint_cure,
|
||||
gdouble db_exposure,
|
||||
DodgeBurnType type,
|
||||
DodgeBurnMode mode,
|
||||
GimpLut *lut,
|
||||
GimpDrawable *drawable);
|
||||
|
||||
static gfloat dodgeburn_highlights_lut_func (gpointer user_data,
|
||||
gint nchannels,
|
||||
gint channel,
|
||||
gfloat value);
|
||||
static gfloat dodgeburn_midtones_lut_func (gpointer user_data,
|
||||
gint nchannels,
|
||||
gint channel,
|
||||
gfloat value);
|
||||
static gfloat dodgeburn_shadows_lut_func (gpointer user_data,
|
||||
gint nchannels,
|
||||
gint channel,
|
||||
gfloat value);
|
||||
|
||||
static void dodgeburn_motion (PaintCore *paint_core,
|
||||
PaintPressureOptions *pressure_options,
|
||||
gdouble dodgeburn_exposure,
|
||||
GimpLut *lut,
|
||||
GimpDrawable *drawable);
|
||||
static void dodgeburn_init (PaintCore *paint_cure,
|
||||
GimpDrawable *drawable);
|
||||
static void dodgeburn_finish (PaintCore *paint_core,
|
||||
GimpDrawable *drawable);
|
||||
|
||||
|
||||
/* the dodgeburn tool options */
|
||||
static DodgeBurnOptions * dodgeburn_options = NULL;
|
||||
|
||||
/* Non gui function */
|
||||
static gdouble non_gui_exposure;
|
||||
static GimpLut *non_gui_lut;
|
||||
|
||||
|
||||
/* functions */
|
||||
|
||||
static void
|
||||
dodgeburn_options_reset (void)
|
||||
{
|
||||
DodgeBurnOptions *options = dodgeburn_options;
|
||||
|
||||
paint_options_reset ((PaintOptions *) options);
|
||||
|
||||
gtk_adjustment_set_value (GTK_ADJUSTMENT (options->exposure_w),
|
||||
options->exposure_d);
|
||||
|
||||
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->type_w[options->type_d]), TRUE);
|
||||
|
||||
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->mode_w[options->mode_d]), TRUE);
|
||||
}
|
||||
|
||||
static DodgeBurnOptions *
|
||||
dodgeburn_options_new (void)
|
||||
{
|
||||
DodgeBurnOptions *options;
|
||||
|
||||
GtkWidget *vbox;
|
||||
GtkWidget *hbox;
|
||||
GtkWidget *label;
|
||||
GtkWidget *scale;
|
||||
GtkWidget *frame;
|
||||
|
||||
/* the new dodgeburn tool options structure */
|
||||
options = g_new (DodgeBurnOptions, 1);
|
||||
paint_options_init ((PaintOptions *) options,
|
||||
DODGEBURN,
|
||||
dodgeburn_options_reset);
|
||||
|
||||
options->type = options->type_d = DODGEBURN_DEFAULT_TYPE;
|
||||
options->exposure = options->exposure_d = DODGEBURN_DEFAULT_EXPOSURE;
|
||||
options->mode = options->mode_d = DODGEBURN_DEFAULT_MODE;
|
||||
|
||||
/* the main vbox */
|
||||
vbox = ((ToolOptions *) options)->main_vbox;
|
||||
|
||||
/* the exposure scale */
|
||||
hbox = gtk_hbox_new (FALSE, 4);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
|
||||
|
||||
label = gtk_label_new (_("Exposure:"));
|
||||
gtk_misc_set_alignment (GTK_MISC (label), 1.0, 1.0);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
|
||||
gtk_widget_show (label);
|
||||
|
||||
options->exposure_w =
|
||||
gtk_adjustment_new (options->exposure_d, 0.0, 100.0, 1.0, 1.0, 0.0);
|
||||
scale = gtk_hscale_new (GTK_ADJUSTMENT (options->exposure_w));
|
||||
gtk_box_pack_start (GTK_BOX (hbox), scale, TRUE, TRUE, 0);
|
||||
gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_TOP);
|
||||
gtk_range_set_update_policy (GTK_RANGE (scale), GTK_UPDATE_DELAYED);
|
||||
|
||||
gtk_signal_connect (GTK_OBJECT (options->exposure_w), "value_changed",
|
||||
GTK_SIGNAL_FUNC (gimp_double_adjustment_update),
|
||||
&options->exposure);
|
||||
|
||||
gtk_widget_show (scale);
|
||||
gtk_widget_show (hbox);
|
||||
|
||||
/* the type (dodge or burn) */
|
||||
frame = gimp_radio_group_new2 (TRUE, _("Type"),
|
||||
gimp_radio_button_update,
|
||||
&options->type, (gpointer) options->type,
|
||||
|
||||
_("Dodge"), (gpointer) DODGE,
|
||||
&options->type_w[0],
|
||||
_("Burn"), (gpointer) BURN,
|
||||
&options->type_w[1],
|
||||
|
||||
NULL);
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
|
||||
gtk_widget_show (frame);
|
||||
|
||||
/* mode (highlights, midtones, or shadows) */
|
||||
frame =
|
||||
gimp_radio_group_new2 (TRUE, _("Mode"),
|
||||
gimp_radio_button_update,
|
||||
&options->mode, (gpointer) options->mode,
|
||||
|
||||
_("Highlights"), (gpointer) DODGEBURN_HIGHLIGHTS,
|
||||
&options->mode_w[0],
|
||||
_("Midtones"), (gpointer) DODGEBURN_MIDTONES,
|
||||
&options->mode_w[1],
|
||||
_("Shadows"), (gpointer) DODGEBURN_SHADOWS,
|
||||
&options->mode_w[2],
|
||||
|
||||
NULL);
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
|
||||
gtk_widget_show (frame);
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
static gpointer
|
||||
dodgeburn_paint_func (PaintCore *paint_core,
|
||||
GimpDrawable *drawable,
|
||||
PaintState state)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case INIT_PAINT:
|
||||
dodgeburn_init (paint_core, drawable);
|
||||
break;
|
||||
|
||||
case MOTION_PAINT:
|
||||
dodgeburn_motion (paint_core,
|
||||
dodgeburn_options->paint_options.pressure_options,
|
||||
dodgeburn_options->exposure, dodgeburn_options->lut, drawable);
|
||||
break;
|
||||
|
||||
case FINISH_PAINT:
|
||||
dodgeburn_finish (paint_core, drawable);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
dodgeburn_finish (PaintCore *paint_core,
|
||||
GimpDrawable *drawable)
|
||||
{
|
||||
/* Here we destroy the luts to do the painting with.*/
|
||||
if (dodgeburn_options->lut)
|
||||
{
|
||||
gimp_lut_free (dodgeburn_options->lut);
|
||||
dodgeburn_options->lut = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dodgeburn_init (PaintCore *paint_core,
|
||||
GimpDrawable *drawable)
|
||||
{
|
||||
/* Here we create the luts to do the painting with.*/
|
||||
dodgeburn_options->lut = gimp_lut_new ();
|
||||
|
||||
dodgeburn_make_luts (paint_core,
|
||||
dodgeburn_options->exposure,
|
||||
dodgeburn_options->type,
|
||||
dodgeburn_options->mode,
|
||||
dodgeburn_options->lut,
|
||||
drawable);
|
||||
}
|
||||
|
||||
static void
|
||||
dodgeburn_make_luts (PaintCore *paint_core,
|
||||
gdouble db_exposure,
|
||||
DodgeBurnType type,
|
||||
DodgeBurnMode mode,
|
||||
GimpLut *lut,
|
||||
GimpDrawable *drawable)
|
||||
{
|
||||
GimpLutFunc lut_func;
|
||||
gint nchannels = gimp_drawable_bytes (drawable);
|
||||
static gfloat exposure;
|
||||
|
||||
exposure = db_exposure / 100.0;
|
||||
|
||||
/* make the exposure negative if burn for luts*/
|
||||
if (type == BURN)
|
||||
exposure = -exposure;
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case DODGEBURN_HIGHLIGHTS:
|
||||
lut_func = dodgeburn_highlights_lut_func;
|
||||
break;
|
||||
case DODGEBURN_MIDTONES:
|
||||
lut_func = dodgeburn_midtones_lut_func;
|
||||
break;
|
||||
case DODGEBURN_SHADOWS:
|
||||
lut_func = dodgeburn_shadows_lut_func;
|
||||
break;
|
||||
default:
|
||||
lut_func = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
gimp_lut_setup_exact (lut,
|
||||
lut_func, (gpointer) &exposure,
|
||||
nchannels);
|
||||
}
|
||||
|
||||
static void
|
||||
dodgeburn_modifier_key_func (Tool *tool,
|
||||
GdkEventKey *kevent,
|
||||
GDisplay *gdisp)
|
||||
{
|
||||
switch (kevent->keyval)
|
||||
{
|
||||
case GDK_Alt_L:
|
||||
case GDK_Alt_R:
|
||||
break;
|
||||
case GDK_Shift_L:
|
||||
case GDK_Shift_R:
|
||||
if (kevent->state & GDK_CONTROL_MASK) /* reset tool toggle */
|
||||
{
|
||||
switch (dodgeburn_options->type)
|
||||
{
|
||||
case BURN:
|
||||
gtk_toggle_button_set_active
|
||||
(GTK_TOGGLE_BUTTON (dodgeburn_options->type_w[DODGE]), TRUE);
|
||||
break;
|
||||
case DODGE:
|
||||
gtk_toggle_button_set_active
|
||||
(GTK_TOGGLE_BUTTON (dodgeburn_options->type_w[BURN]), TRUE);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GDK_Control_L:
|
||||
case GDK_Control_R:
|
||||
if (! (kevent->state & GDK_SHIFT_MASK)) /* shift enables line draw mode */
|
||||
{
|
||||
switch (dodgeburn_options->type)
|
||||
{
|
||||
case BURN:
|
||||
gtk_toggle_button_set_active
|
||||
(GTK_TOGGLE_BUTTON (dodgeburn_options->type_w[DODGE]), TRUE);
|
||||
break;
|
||||
case DODGE:
|
||||
gtk_toggle_button_set_active
|
||||
(GTK_TOGGLE_BUTTON (dodgeburn_options->type_w[BURN]), TRUE);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
tool->toggled = (dodgeburn_options->type == BURN);
|
||||
}
|
||||
|
||||
static void
|
||||
dodgeburn_cursor_update_func (Tool *tool,
|
||||
GdkEventMotion *mevent,
|
||||
GDisplay *gdisp)
|
||||
{
|
||||
tool->toggled = (dodgeburn_options->type == BURN);
|
||||
|
||||
paint_core_cursor_update (tool, mevent, gdisp);
|
||||
}
|
||||
|
||||
Tool *
|
||||
tools_new_dodgeburn (void)
|
||||
{
|
||||
Tool *tool;
|
||||
PaintCore *private;
|
||||
|
||||
/* The tool options */
|
||||
if (! dodgeburn_options)
|
||||
{
|
||||
dodgeburn_options = dodgeburn_options_new ();
|
||||
tools_register (DODGEBURN, (ToolOptions *) dodgeburn_options);
|
||||
|
||||
/* press all default buttons */
|
||||
dodgeburn_options_reset ();
|
||||
}
|
||||
|
||||
tool = paint_core_new (DODGEBURN);
|
||||
tool->modifier_key_func = dodgeburn_modifier_key_func;
|
||||
tool->cursor_update_func = dodgeburn_cursor_update_func;
|
||||
|
||||
private = (PaintCore *) tool->private;
|
||||
private->paint_func = dodgeburn_paint_func;
|
||||
private->flags |= TOOL_CAN_HANDLE_CHANGING_BRUSH;
|
||||
|
||||
|
||||
return tool;
|
||||
}
|
||||
|
||||
void
|
||||
tools_free_dodgeburn (Tool *tool)
|
||||
{
|
||||
/* delete any luts here */
|
||||
paint_core_free (tool);
|
||||
}
|
||||
|
||||
static void
|
||||
dodgeburn_motion (PaintCore *paint_core,
|
||||
PaintPressureOptions *pressure_options,
|
||||
double dodgeburn_exposure,
|
||||
GimpLut *lut,
|
||||
GimpDrawable *drawable)
|
||||
{
|
||||
GImage *gimage;
|
||||
TempBuf * area;
|
||||
TempBuf * orig;
|
||||
PixelRegion srcPR, destPR, tempPR;
|
||||
guchar *temp_data;
|
||||
gint opacity;
|
||||
gdouble scale;
|
||||
|
||||
if (! (gimage = gimp_drawable_gimage (drawable)))
|
||||
return;
|
||||
|
||||
/* If the image type is indexed, don't dodgeburn */
|
||||
if ((gimp_drawable_type (drawable) == INDEXED_GIMAGE) ||
|
||||
(gimp_drawable_type (drawable) == INDEXEDA_GIMAGE))
|
||||
return;
|
||||
|
||||
if (pressure_options->size)
|
||||
scale = paint_core->curpressure;
|
||||
else
|
||||
scale = 1.0;
|
||||
|
||||
/* Get a region which can be used to paint to */
|
||||
if (! (area = paint_core_get_paint_area (paint_core, drawable, scale)))
|
||||
return;
|
||||
|
||||
/* Constant painting --get a copy of the orig drawable (with
|
||||
no paint from this stroke yet) */
|
||||
|
||||
{
|
||||
gint x1, y1, x2, y2;
|
||||
|
||||
x1 = CLAMP (area->x, 0, gimp_drawable_width (drawable));
|
||||
y1 = CLAMP (area->y, 0, gimp_drawable_height (drawable));
|
||||
x2 = CLAMP (area->x + area->width, 0, gimp_drawable_width (drawable));
|
||||
y2 = CLAMP (area->y + area->height, 0, gimp_drawable_height (drawable));
|
||||
|
||||
if (!(x2 - x1) || !(y2 - y1))
|
||||
return;
|
||||
|
||||
/* get the original untouched image */
|
||||
orig = paint_core_get_orig_image (paint_core, drawable, x1, y1, x2, y2);
|
||||
srcPR.bytes = orig->bytes;
|
||||
srcPR.x = 0;
|
||||
srcPR.y = 0;
|
||||
srcPR.w = x2 - x1;
|
||||
srcPR.h = y2 - y1;
|
||||
srcPR.rowstride = srcPR.bytes * orig->width;
|
||||
srcPR.data = temp_buf_data (orig);
|
||||
}
|
||||
|
||||
/* tempPR will hold the dodgeburned region*/
|
||||
tempPR.bytes = srcPR.bytes;
|
||||
tempPR.x = srcPR.x;
|
||||
tempPR.y = srcPR.y;
|
||||
tempPR.w = srcPR.w;
|
||||
tempPR.h = srcPR.h;
|
||||
tempPR.rowstride = tempPR.bytes * tempPR.w;
|
||||
temp_data = g_malloc (tempPR.h * tempPR.rowstride);
|
||||
tempPR.data = temp_data;
|
||||
|
||||
/* DodgeBurn the region */
|
||||
gimp_lut_process (lut, &srcPR, &tempPR);
|
||||
|
||||
/* The dest is the paint area we got above (= canvas_buf) */
|
||||
destPR.bytes = area->bytes;
|
||||
destPR.x = 0; destPR.y = 0;
|
||||
destPR.w = area->width;
|
||||
destPR.h = area->height;
|
||||
destPR.rowstride = area->width * destPR.bytes;
|
||||
destPR.data = temp_buf_data (area);
|
||||
|
||||
/* Now add an alpha to the dodgeburned region
|
||||
and put this in area = canvas_buf */
|
||||
if (! gimp_drawable_has_alpha (drawable))
|
||||
add_alpha_region (&tempPR, &destPR);
|
||||
else
|
||||
copy_region (&tempPR, &destPR);
|
||||
|
||||
opacity = 255 * gimp_context_get_opacity (NULL);
|
||||
if (pressure_options->opacity)
|
||||
opacity = opacity * 2.0 * paint_core->curpressure;
|
||||
|
||||
/* Replace the newly dodgedburned area (canvas_buf) to the gimage*/
|
||||
paint_core_replace_canvas (paint_core, drawable,
|
||||
MIN (opacity, 255),
|
||||
OPAQUE_OPACITY,
|
||||
pressure_options->pressure ? PRESSURE : SOFT,
|
||||
scale, CONSTANT);
|
||||
|
||||
g_free (temp_data);
|
||||
}
|
||||
|
||||
static gpointer
|
||||
dodgeburn_non_gui_paint_func (PaintCore *paint_core,
|
||||
GimpDrawable *drawable,
|
||||
PaintState state)
|
||||
{
|
||||
dodgeburn_motion (paint_core, &non_gui_pressure_options,
|
||||
non_gui_exposure, non_gui_lut, drawable);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gboolean
|
||||
dodgeburn_non_gui_default (GimpDrawable *drawable,
|
||||
gint num_strokes,
|
||||
gdouble *stroke_array)
|
||||
{
|
||||
gdouble exposure = DODGEBURN_DEFAULT_TYPE;
|
||||
DodgeBurnType type = DODGEBURN_DEFAULT_TYPE;
|
||||
DodgeBurnMode mode = DODGEBURN_DEFAULT_MODE;
|
||||
DodgeBurnOptions *options = dodgeburn_options;
|
||||
|
||||
if (options)
|
||||
{
|
||||
exposure = dodgeburn_options->exposure;
|
||||
type = dodgeburn_options->type;
|
||||
mode = dodgeburn_options->mode;
|
||||
}
|
||||
|
||||
return dodgeburn_non_gui (drawable, exposure, type, mode,
|
||||
num_strokes, stroke_array);
|
||||
}
|
||||
|
||||
gboolean
|
||||
dodgeburn_non_gui (GimpDrawable *drawable,
|
||||
gdouble exposure,
|
||||
DodgeBurnType type,
|
||||
DodgeBurnMode mode,
|
||||
gint num_strokes,
|
||||
gdouble *stroke_array)
|
||||
{
|
||||
gint i;
|
||||
|
||||
if (paint_core_init (&non_gui_paint_core, drawable,
|
||||
stroke_array[0], stroke_array[1]))
|
||||
{
|
||||
/* Set the paint core's paint func */
|
||||
non_gui_paint_core.paint_func = dodgeburn_non_gui_paint_func;
|
||||
|
||||
non_gui_exposure = exposure;
|
||||
non_gui_lut = gimp_lut_new();
|
||||
dodgeburn_make_luts (&non_gui_paint_core,
|
||||
exposure,
|
||||
type,
|
||||
mode,
|
||||
non_gui_lut,
|
||||
drawable);
|
||||
|
||||
non_gui_paint_core.startx = non_gui_paint_core.lastx = stroke_array[0];
|
||||
non_gui_paint_core.starty = non_gui_paint_core.lasty = stroke_array[1];
|
||||
|
||||
dodgeburn_non_gui_paint_func (&non_gui_paint_core, drawable, 0);
|
||||
|
||||
for (i = 1; i < num_strokes; i++)
|
||||
{
|
||||
non_gui_paint_core.curx = stroke_array[i * 2 + 0];
|
||||
non_gui_paint_core.cury = stroke_array[i * 2 + 1];
|
||||
|
||||
paint_core_interpolate (&non_gui_paint_core, drawable);
|
||||
|
||||
non_gui_paint_core.lastx = non_gui_paint_core.curx;
|
||||
non_gui_paint_core.lasty = non_gui_paint_core.cury;
|
||||
}
|
||||
|
||||
/* Finish the painting */
|
||||
paint_core_finish (&non_gui_paint_core, drawable, -1);
|
||||
|
||||
/* Cleanup */
|
||||
paint_core_cleanup ();
|
||||
|
||||
gimp_lut_free (non_gui_lut);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gfloat
|
||||
dodgeburn_highlights_lut_func (gpointer user_data,
|
||||
gint nchannels,
|
||||
gint channel,
|
||||
gfloat value)
|
||||
{
|
||||
gfloat *exposure_ptr = (gfloat *) user_data;
|
||||
gfloat exposure = *exposure_ptr;
|
||||
gfloat factor = 1.0 + exposure * (.333333);
|
||||
|
||||
if ((nchannels == 2 && channel == 1) ||
|
||||
(nchannels == 4 && channel == 3))
|
||||
return value;
|
||||
|
||||
return factor * value;
|
||||
}
|
||||
|
||||
static gfloat
|
||||
dodgeburn_midtones_lut_func (gpointer user_data,
|
||||
gint nchannels,
|
||||
gint channel,
|
||||
gfloat value)
|
||||
{
|
||||
gfloat *exposure_ptr = (gfloat *) user_data;
|
||||
gfloat exposure = *exposure_ptr;
|
||||
gfloat factor;
|
||||
|
||||
if ((nchannels == 2 && channel == 1) ||
|
||||
(nchannels == 4 && channel == 3))
|
||||
return value;
|
||||
|
||||
if (exposure < 0)
|
||||
factor = 1.0 - exposure * (.333333);
|
||||
else
|
||||
factor = 1/(1.0 + exposure);
|
||||
|
||||
return pow (value, factor);
|
||||
}
|
||||
|
||||
static gfloat
|
||||
dodgeburn_shadows_lut_func (gpointer user_data,
|
||||
gint nchannels,
|
||||
gint channel,
|
||||
gfloat value)
|
||||
{
|
||||
gfloat *exposure_ptr = (gfloat *) user_data;
|
||||
gfloat exposure = *exposure_ptr;
|
||||
gfloat new_value;
|
||||
gfloat factor;
|
||||
|
||||
if ( (nchannels == 2 && channel == 1) ||
|
||||
(nchannels == 4 && channel == 3))
|
||||
return value;
|
||||
|
||||
if (exposure >= 0)
|
||||
{
|
||||
factor = 0.333333 * exposure;
|
||||
new_value = factor + value - factor * value;
|
||||
}
|
||||
else /* exposure < 0 */
|
||||
{
|
||||
factor = -0.333333 * exposure;
|
||||
if (value < factor)
|
||||
new_value = 0;
|
||||
else /*factor <= value <=1*/
|
||||
new_value = (value - factor)/(1 - factor);
|
||||
}
|
||||
|
||||
return new_value;
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
/* 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.
|
||||
*/
|
||||
|
||||
#ifndef __DODGEBURN_H__
|
||||
#define __DODGEBURN_H__
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DODGE,
|
||||
BURN
|
||||
} DodgeBurnType;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DODGEBURN_HIGHLIGHTS,
|
||||
DODGEBURN_MIDTONES,
|
||||
DODGEBURN_SHADOWS
|
||||
} DodgeBurnMode;
|
||||
|
||||
|
||||
gboolean dodgeburn_non_gui (GimpDrawable *drawable,
|
||||
gdouble exposure,
|
||||
DodgeBurnType type,
|
||||
DodgeBurnMode mode,
|
||||
gint num_strokes,
|
||||
gdouble *stroke_array);
|
||||
gboolean dodgeburn_non_gui_default (GimpDrawable *drawable,
|
||||
gint num_strokes,
|
||||
gdouble *stroke_array);
|
||||
|
||||
Tool * tools_new_dodgeburn (void);
|
||||
void tools_free_dodgeburn (Tool *tool);
|
||||
|
||||
|
||||
#endif /* __DODGEBURN_H__ */
|
|
@ -31,7 +31,6 @@
|
|||
#include "cursorutil.h"
|
||||
#include "draw_core.h"
|
||||
#include "drawable.h"
|
||||
#include "tools.h"
|
||||
#include "edit_selection.h"
|
||||
#include "floating_sel.h"
|
||||
#include "gimpimage.h"
|
||||
|
@ -43,6 +42,8 @@
|
|||
#include "selection.h"
|
||||
#include "undo.h"
|
||||
|
||||
#include "tools/tools.h"
|
||||
|
||||
#include "libgimp/gimpmath.h"
|
||||
|
||||
#include "libgimp/gimpintl.h"
|
||||
|
|
|
@ -1,165 +0,0 @@
|
|||
/* 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 <stdlib.h>
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "apptypes.h"
|
||||
|
||||
#include "appenv.h"
|
||||
#include "channel.h"
|
||||
#include "draw_core.h"
|
||||
#include "edit_selection.h"
|
||||
#include "ellipse_select.h"
|
||||
#include "gdisplay.h"
|
||||
#include "gimage_mask.h"
|
||||
#include "gimpimage.h"
|
||||
#include "rect_select.h"
|
||||
#include "rect_selectP.h"
|
||||
#include "selection_options.h"
|
||||
#include "tools.h"
|
||||
#include "tool_options.h"
|
||||
|
||||
|
||||
/* the ellipse selection tool options */
|
||||
SelectionOptions * ellipse_options = NULL;
|
||||
|
||||
|
||||
/*************************************/
|
||||
/* Ellipsoidal selection apparatus */
|
||||
|
||||
void
|
||||
ellipse_select (GimpImage *gimage,
|
||||
gint x,
|
||||
gint y,
|
||||
gint w,
|
||||
gint h,
|
||||
SelectOps op,
|
||||
gboolean antialias,
|
||||
gboolean feather,
|
||||
gdouble feather_radius)
|
||||
{
|
||||
Channel *new_mask;
|
||||
|
||||
/* if applicable, replace the current selection */
|
||||
if (op == SELECTION_REPLACE)
|
||||
gimage_mask_clear (gimage);
|
||||
else
|
||||
gimage_mask_undo (gimage);
|
||||
|
||||
/* if feathering for rect, make a new mask with the
|
||||
* rectangle and feather that with the old mask
|
||||
*/
|
||||
if (feather)
|
||||
{
|
||||
new_mask = channel_new_mask (gimage, gimage->width, gimage->height);
|
||||
channel_combine_ellipse (new_mask, CHANNEL_OP_ADD, x, y, w, h, antialias);
|
||||
channel_feather (new_mask, gimp_image_get_mask (gimage),
|
||||
feather_radius,
|
||||
feather_radius,
|
||||
op, 0, 0);
|
||||
channel_delete (new_mask);
|
||||
}
|
||||
else if (op == SELECTION_INTERSECT)
|
||||
{
|
||||
new_mask = channel_new_mask (gimage, gimage->width, gimage->height);
|
||||
channel_combine_ellipse (new_mask, CHANNEL_OP_ADD, x, y, w, h, antialias);
|
||||
channel_combine_mask (gimp_image_get_mask (gimage), new_mask, op, 0, 0);
|
||||
channel_delete (new_mask);
|
||||
}
|
||||
else
|
||||
channel_combine_ellipse (gimp_image_get_mask (gimage), op,
|
||||
x, y, w, h, antialias);
|
||||
}
|
||||
|
||||
void
|
||||
ellipse_select_draw (Tool *tool)
|
||||
{
|
||||
EllipseSelect *ellipse_sel;
|
||||
gint x1, y1;
|
||||
gint x2, y2;
|
||||
|
||||
ellipse_sel = (EllipseSelect *) tool->private;
|
||||
|
||||
x1 = MIN (ellipse_sel->x, ellipse_sel->x + ellipse_sel->w);
|
||||
y1 = MIN (ellipse_sel->y, ellipse_sel->y + ellipse_sel->h);
|
||||
x2 = MAX (ellipse_sel->x, ellipse_sel->x + ellipse_sel->w);
|
||||
y2 = MAX (ellipse_sel->y, ellipse_sel->y + ellipse_sel->h);
|
||||
|
||||
gdisplay_transform_coords (tool->gdisp, x1, y1, &x1, &y1, 0);
|
||||
gdisplay_transform_coords (tool->gdisp, x2, y2, &x2, &y2, 0);
|
||||
|
||||
gdk_draw_arc (ellipse_sel->core->win,
|
||||
ellipse_sel->core->gc, 0,
|
||||
x1, y1, (x2 - x1), (y2 - y1), 0, 23040);
|
||||
}
|
||||
|
||||
static void
|
||||
ellipse_select_options_reset (void)
|
||||
{
|
||||
selection_options_reset (ellipse_options);
|
||||
}
|
||||
|
||||
Tool *
|
||||
tools_new_ellipse_select (void)
|
||||
{
|
||||
Tool *tool;
|
||||
EllipseSelect *private;
|
||||
|
||||
/* The tool options */
|
||||
if (!ellipse_options)
|
||||
{
|
||||
ellipse_options =
|
||||
selection_options_new (ELLIPSE_SELECT, ellipse_select_options_reset);
|
||||
tools_register (ELLIPSE_SELECT, (ToolOptions *) ellipse_options);
|
||||
}
|
||||
|
||||
tool = tools_new_tool (ELLIPSE_SELECT);
|
||||
private = g_new0 (EllipseSelect, 1);
|
||||
|
||||
private->core = draw_core_new (ellipse_select_draw);
|
||||
/* Make the selection static, not blinking */
|
||||
private->x = private->y = 0;
|
||||
private->w = private->h = 0;
|
||||
|
||||
tool->private = (void *) private;
|
||||
|
||||
tool->button_press_func = rect_select_button_press;
|
||||
tool->button_release_func = rect_select_button_release;
|
||||
tool->motion_func = rect_select_motion;
|
||||
tool->modifier_key_func = rect_select_modifier_update;
|
||||
tool->cursor_update_func = rect_select_cursor_update;
|
||||
tool->oper_update_func = rect_select_oper_update;
|
||||
tool->control_func = rect_select_control;
|
||||
|
||||
return tool;
|
||||
}
|
||||
|
||||
void
|
||||
tools_free_ellipse_select (Tool *tool)
|
||||
{
|
||||
EllipseSelect *ellipse_sel;
|
||||
|
||||
ellipse_sel = (EllipseSelect *) tool->private;
|
||||
|
||||
draw_core_free (ellipse_sel->core);
|
||||
g_free (ellipse_sel);
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
/* 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.
|
||||
*/
|
||||
|
||||
#ifndef __ELLIPSE_SELECT_H__
|
||||
#define __ELLIPSE_SELECT_H__
|
||||
|
||||
|
||||
void ellipse_select (GimpImage *gimage,
|
||||
gint x,
|
||||
gint y,
|
||||
gint w,
|
||||
gint h,
|
||||
SelectOps op,
|
||||
gboolean antialias,
|
||||
gboolean feather,
|
||||
gdouble feather_radius);
|
||||
void ellipse_select_draw (Tool *tool);
|
||||
|
||||
Tool * tools_new_ellipse_select (void);
|
||||
void tools_free_ellipse_select (Tool *tool);
|
||||
|
||||
|
||||
#endif /* __ELLIPSE_SELECT_H__ */
|
364
app/eraser.c
364
app/eraser.c
|
@ -1,364 +0,0 @@
|
|||
/* 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 <gtk/gtk.h>
|
||||
#include <gdk/gdkkeysyms.h>
|
||||
|
||||
#include "apptypes.h"
|
||||
|
||||
#include "appenv.h"
|
||||
#include "cursorutil.h"
|
||||
#include "drawable.h"
|
||||
#include "gdisplay.h"
|
||||
#include "gimage_mask.h"
|
||||
#include "gimpcontext.h"
|
||||
#include "gimpimage.h"
|
||||
#include "gimpui.h"
|
||||
#include "paint_funcs.h"
|
||||
#include "paint_core.h"
|
||||
#include "paint_options.h"
|
||||
#include "eraser.h"
|
||||
#include "selection.h"
|
||||
#include "temp_buf.h"
|
||||
#include "tools.h"
|
||||
|
||||
#include "libgimp/gimpintl.h"
|
||||
|
||||
|
||||
/* Defaults */
|
||||
#define ERASER_DEFAULT_HARD FALSE
|
||||
#define ERASER_DEFAULT_INCREMENTAL FALSE
|
||||
#define ERASER_DEFAULT_ANTI_ERASE FALSE
|
||||
|
||||
/* the eraser structures */
|
||||
|
||||
typedef struct _EraserOptions EraserOptions;
|
||||
|
||||
struct _EraserOptions
|
||||
{
|
||||
PaintOptions paint_options;
|
||||
|
||||
gboolean hard;
|
||||
gboolean hard_d;
|
||||
GtkWidget *hard_w;
|
||||
|
||||
gboolean anti_erase;
|
||||
gboolean anti_erase_d;
|
||||
GtkWidget *anti_erase_w;
|
||||
};
|
||||
|
||||
|
||||
/* forward function declarations */
|
||||
static gpointer eraser_paint_func (PaintCore *paint_core,
|
||||
GimpDrawable *drawable,
|
||||
PaintState state);
|
||||
static void eraser_motion (PaintCore *paint_core,
|
||||
GimpDrawable *drawable,
|
||||
PaintPressureOptions *pressure_options,
|
||||
gboolean hard,
|
||||
gboolean incremental,
|
||||
gboolean anti_erase);
|
||||
|
||||
|
||||
/* the eraser tool options */
|
||||
static EraserOptions *eraser_options = NULL;
|
||||
|
||||
/* local variables */
|
||||
static gboolean non_gui_hard;
|
||||
static gboolean non_gui_incremental;
|
||||
static gboolean non_gui_anti_erase;
|
||||
|
||||
|
||||
/* functions */
|
||||
|
||||
static void
|
||||
eraser_options_reset (void)
|
||||
{
|
||||
EraserOptions *options = eraser_options;
|
||||
|
||||
paint_options_reset ((PaintOptions *) options);
|
||||
|
||||
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->hard_w),
|
||||
options->hard_d);
|
||||
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->anti_erase_w),
|
||||
options->anti_erase_d);
|
||||
}
|
||||
|
||||
static EraserOptions *
|
||||
eraser_options_new (void)
|
||||
{
|
||||
EraserOptions *options;
|
||||
|
||||
GtkWidget *vbox;
|
||||
|
||||
/* the new eraser tool options structure */
|
||||
options = g_new (EraserOptions, 1);
|
||||
paint_options_init ((PaintOptions *) options,
|
||||
ERASER,
|
||||
eraser_options_reset);
|
||||
options->hard = options->hard_d = ERASER_DEFAULT_HARD;
|
||||
options->anti_erase = options->anti_erase_d = ERASER_DEFAULT_ANTI_ERASE;
|
||||
|
||||
/* the main vbox */
|
||||
vbox = ((ToolOptions *) options)->main_vbox;
|
||||
|
||||
/* the hard toggle */
|
||||
options->hard_w = gtk_check_button_new_with_label (_("Hard Edge"));
|
||||
gtk_box_pack_start (GTK_BOX (vbox), options->hard_w, FALSE, FALSE, 0);
|
||||
gtk_signal_connect (GTK_OBJECT (options->hard_w), "toggled",
|
||||
GTK_SIGNAL_FUNC (gimp_toggle_button_update),
|
||||
&options->hard);
|
||||
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->hard_w),
|
||||
options->hard_d);
|
||||
gtk_widget_show (options->hard_w);
|
||||
|
||||
/* the anti_erase toggle */
|
||||
options->anti_erase_w = gtk_check_button_new_with_label (_("Anti Erase"));
|
||||
gtk_box_pack_start (GTK_BOX (vbox), options->anti_erase_w, FALSE, FALSE, 0);
|
||||
gtk_signal_connect (GTK_OBJECT (options->anti_erase_w), "toggled",
|
||||
GTK_SIGNAL_FUNC (gimp_toggle_button_update),
|
||||
&options->anti_erase);
|
||||
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->anti_erase_w),
|
||||
options->anti_erase_d);
|
||||
gtk_widget_show (options->anti_erase_w);
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
static void
|
||||
eraser_modifier_key_func (Tool *tool,
|
||||
GdkEventKey *kevent,
|
||||
GDisplay *gdisp)
|
||||
{
|
||||
switch (kevent->keyval)
|
||||
{
|
||||
case GDK_Alt_L:
|
||||
case GDK_Alt_R:
|
||||
break;
|
||||
case GDK_Shift_L:
|
||||
case GDK_Shift_R:
|
||||
if (kevent->state & GDK_CONTROL_MASK) /* reset tool toggle */
|
||||
gtk_toggle_button_set_active
|
||||
(GTK_TOGGLE_BUTTON (eraser_options->anti_erase_w),
|
||||
! eraser_options->anti_erase);
|
||||
break;
|
||||
case GDK_Control_L:
|
||||
case GDK_Control_R:
|
||||
if (!(kevent->state & GDK_SHIFT_MASK)) /* shift enables line draw mode */
|
||||
gtk_toggle_button_set_active
|
||||
(GTK_TOGGLE_BUTTON (eraser_options->anti_erase_w),
|
||||
! eraser_options->anti_erase);
|
||||
break;
|
||||
}
|
||||
|
||||
tool->toggled = eraser_options->anti_erase;
|
||||
}
|
||||
|
||||
|
||||
static gpointer
|
||||
eraser_paint_func (PaintCore *paint_core,
|
||||
GimpDrawable *drawable,
|
||||
PaintState state)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case INIT_PAINT:
|
||||
break;
|
||||
|
||||
case MOTION_PAINT:
|
||||
eraser_motion (paint_core,
|
||||
drawable,
|
||||
eraser_options->paint_options.pressure_options,
|
||||
eraser_options->hard,
|
||||
eraser_options->paint_options.incremental,
|
||||
eraser_options->anti_erase);
|
||||
break;
|
||||
|
||||
case FINISH_PAINT:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Tool *
|
||||
tools_new_eraser (void)
|
||||
{
|
||||
Tool *tool;
|
||||
PaintCore *private;
|
||||
|
||||
/* The tool options */
|
||||
if (! eraser_options)
|
||||
{
|
||||
eraser_options = eraser_options_new ();
|
||||
tools_register (ERASER, (ToolOptions *) eraser_options);
|
||||
}
|
||||
|
||||
tool = paint_core_new (ERASER);
|
||||
|
||||
private = (PaintCore *) tool->private;
|
||||
private->paint_func = eraser_paint_func;
|
||||
private->flags |= TOOL_CAN_HANDLE_CHANGING_BRUSH;
|
||||
tool->modifier_key_func = eraser_modifier_key_func;
|
||||
|
||||
return tool;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
tools_free_eraser (Tool *tool)
|
||||
{
|
||||
paint_core_free (tool);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
eraser_motion (PaintCore *paint_core,
|
||||
GimpDrawable *drawable,
|
||||
PaintPressureOptions *pressure_options,
|
||||
gboolean hard,
|
||||
gboolean incremental,
|
||||
gboolean anti_erase)
|
||||
{
|
||||
GImage *gimage;
|
||||
gint opacity;
|
||||
TempBuf *area;
|
||||
guchar col[MAX_CHANNELS];
|
||||
gdouble scale;
|
||||
|
||||
if (! (gimage = gimp_drawable_gimage (drawable)))
|
||||
return;
|
||||
|
||||
gimp_image_get_background (gimage, drawable, col);
|
||||
|
||||
if (pressure_options->size)
|
||||
scale = paint_core->curpressure;
|
||||
else
|
||||
scale = 1.0;
|
||||
|
||||
/* Get a region which can be used to paint to */
|
||||
if (! (area = paint_core_get_paint_area (paint_core, drawable, scale)))
|
||||
return;
|
||||
|
||||
/* set the alpha channel */
|
||||
col[area->bytes - 1] = OPAQUE_OPACITY;
|
||||
|
||||
/* color the pixels */
|
||||
color_pixels (temp_buf_data (area), col,
|
||||
area->width * area->height, area->bytes);
|
||||
|
||||
opacity = 255 * gimp_context_get_opacity (NULL);
|
||||
if (pressure_options->opacity)
|
||||
opacity = opacity * 2.0 * paint_core->curpressure;
|
||||
|
||||
/* paste the newly painted canvas to the gimage which is being worked on */
|
||||
paint_core_paste_canvas (paint_core, drawable,
|
||||
MIN (opacity, 255),
|
||||
(int) (gimp_context_get_opacity (NULL) * 255),
|
||||
anti_erase ? ANTI_ERASE_MODE : ERASE_MODE,
|
||||
hard ? HARD : (pressure_options->pressure ? PRESSURE : SOFT),
|
||||
scale,
|
||||
incremental ? INCREMENTAL : CONSTANT);
|
||||
}
|
||||
|
||||
|
||||
static gpointer
|
||||
eraser_non_gui_paint_func (PaintCore *paint_core,
|
||||
GimpDrawable *drawable,
|
||||
PaintState state)
|
||||
{
|
||||
eraser_motion (paint_core, drawable,
|
||||
&non_gui_pressure_options,
|
||||
non_gui_hard, non_gui_incremental, non_gui_anti_erase);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gboolean
|
||||
eraser_non_gui_default (GimpDrawable *drawable,
|
||||
gint num_strokes,
|
||||
gdouble *stroke_array)
|
||||
{
|
||||
gboolean hardness = ERASER_DEFAULT_HARD;
|
||||
gboolean method = ERASER_DEFAULT_INCREMENTAL;
|
||||
gboolean anti_erase = ERASER_DEFAULT_ANTI_ERASE;
|
||||
|
||||
EraserOptions *options = eraser_options;
|
||||
|
||||
if (options)
|
||||
{
|
||||
hardness = options->hard;
|
||||
method = options->paint_options.incremental;
|
||||
anti_erase = options->anti_erase;
|
||||
}
|
||||
|
||||
return eraser_non_gui (drawable, num_strokes, stroke_array,
|
||||
hardness, method, anti_erase);
|
||||
}
|
||||
|
||||
gboolean
|
||||
eraser_non_gui (GimpDrawable *drawable,
|
||||
gint num_strokes,
|
||||
gdouble *stroke_array,
|
||||
gint hardness,
|
||||
gint method,
|
||||
gboolean anti_erase)
|
||||
{
|
||||
gint i;
|
||||
|
||||
if (paint_core_init (&non_gui_paint_core, drawable,
|
||||
stroke_array[0], stroke_array[1]))
|
||||
{
|
||||
non_gui_hard = hardness;
|
||||
non_gui_incremental = method;
|
||||
non_gui_anti_erase = anti_erase;
|
||||
|
||||
/* Set the paint core's paint func */
|
||||
non_gui_paint_core.paint_func = eraser_non_gui_paint_func;
|
||||
|
||||
non_gui_paint_core.startx = non_gui_paint_core.lastx = stroke_array[0];
|
||||
non_gui_paint_core.starty = non_gui_paint_core.lasty = stroke_array[1];
|
||||
|
||||
eraser_non_gui_paint_func (&non_gui_paint_core, drawable, 0);
|
||||
|
||||
for (i = 1; i < num_strokes; i++)
|
||||
{
|
||||
non_gui_paint_core.curx = stroke_array[i * 2 + 0];
|
||||
non_gui_paint_core.cury = stroke_array[i * 2 + 1];
|
||||
|
||||
paint_core_interpolate (&non_gui_paint_core, drawable);
|
||||
|
||||
non_gui_paint_core.lastx = non_gui_paint_core.curx;
|
||||
non_gui_paint_core.lasty = non_gui_paint_core.cury;
|
||||
}
|
||||
|
||||
/* Finish the painting */
|
||||
paint_core_finish (&non_gui_paint_core, drawable, -1);
|
||||
|
||||
/* Cleanup */
|
||||
paint_core_cleanup ();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
37
app/eraser.h
37
app/eraser.h
|
@ -1,37 +0,0 @@
|
|||
/* 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.
|
||||
*/
|
||||
|
||||
#ifndef __ERASER_H__
|
||||
#define __ERASER_H__
|
||||
|
||||
|
||||
gboolean eraser_non_gui (GimpDrawable *drawable,
|
||||
gint num_strokes,
|
||||
gdouble *stroke_array,
|
||||
gint hardness,
|
||||
gint method,
|
||||
gboolean anti_erase);
|
||||
gboolean eraser_non_gui_default (GimpDrawable *paint_core,
|
||||
gint num_strokes,
|
||||
gdouble *stroke_array);
|
||||
|
||||
Tool * tools_new_eraser (void);
|
||||
void tools_free_eraser (Tool *tool);
|
||||
|
||||
|
||||
#endif /* __ERASER_H__ */
|
324
app/flip_tool.c
324
app/flip_tool.c
|
@ -1,324 +0,0 @@
|
|||
/* 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 <stdlib.h>
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <gdk/gdkkeysyms.h>
|
||||
|
||||
#include "apptypes.h"
|
||||
|
||||
#include "appenv.h"
|
||||
#include "cursorutil.h"
|
||||
#include "drawable.h"
|
||||
#include "flip_tool.h"
|
||||
#include "gdisplay.h"
|
||||
#include "gimage_mask.h"
|
||||
#include "gimpimage.h"
|
||||
#include "gimpui.h"
|
||||
#include "paint_funcs.h"
|
||||
#include "path_transform.h"
|
||||
#include "pixel_region.h"
|
||||
#include "temp_buf.h"
|
||||
#include "tile_manager.h"
|
||||
#include "tile_manager_pvt.h"
|
||||
#include "tools.h"
|
||||
#include "tool_options.h"
|
||||
#include "transform_core.h"
|
||||
|
||||
#include "libgimp/gimpintl.h"
|
||||
|
||||
|
||||
#define FLIP_INFO 0
|
||||
|
||||
/* the flip structures */
|
||||
|
||||
typedef struct _FlipOptions FlipOptions;
|
||||
|
||||
struct _FlipOptions
|
||||
{
|
||||
ToolOptions tool_options;
|
||||
|
||||
InternalOrientationType type;
|
||||
InternalOrientationType type_d;
|
||||
GtkWidget *type_w[2];
|
||||
};
|
||||
|
||||
|
||||
/* local function prototypes */
|
||||
|
||||
static TileManager * flip_tool_transform (Tool *tool,
|
||||
GDisplay *gdisp,
|
||||
TransformState state);
|
||||
|
||||
|
||||
/* private variables */
|
||||
|
||||
static FlipOptions *flip_options = NULL;
|
||||
|
||||
/* functions */
|
||||
|
||||
/* FIXME: Lame - 1 hacks abound since the code assumes certain values for
|
||||
* the ORIENTATION_FOO constants.
|
||||
*/
|
||||
|
||||
static void
|
||||
flip_options_reset (void)
|
||||
{
|
||||
FlipOptions *options = flip_options;
|
||||
|
||||
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->type_w[options->type_d - 1]), TRUE);
|
||||
}
|
||||
|
||||
static FlipOptions *
|
||||
flip_options_new (void)
|
||||
{
|
||||
FlipOptions *options;
|
||||
|
||||
GtkWidget *vbox;
|
||||
GtkWidget *frame;
|
||||
|
||||
/* the new flip tool options structure */
|
||||
options = g_new (FlipOptions, 1);
|
||||
tool_options_init ((ToolOptions *) options,
|
||||
_("Flip Tool"),
|
||||
flip_options_reset);
|
||||
options->type = options->type_d = ORIENTATION_HORIZONTAL;
|
||||
|
||||
/* the main vbox */
|
||||
vbox = options->tool_options.main_vbox;
|
||||
|
||||
/* tool toggle */
|
||||
frame =
|
||||
gimp_radio_group_new2 (TRUE, _("Tool Toggle"),
|
||||
gimp_radio_button_update,
|
||||
&options->type, (gpointer) options->type,
|
||||
|
||||
_("Horizontal"), (gpointer) ORIENTATION_HORIZONTAL,
|
||||
&options->type_w[0],
|
||||
_("Vertical"), (gpointer) ORIENTATION_VERTICAL,
|
||||
&options->type_w[1],
|
||||
|
||||
NULL);
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
|
||||
gtk_widget_show (frame);
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
static void
|
||||
flip_modifier_key_func (Tool *tool,
|
||||
GdkEventKey *kevent,
|
||||
GDisplay *gdisp)
|
||||
{
|
||||
switch (kevent->keyval)
|
||||
{
|
||||
case GDK_Alt_L: case GDK_Alt_R:
|
||||
break;
|
||||
case GDK_Shift_L: case GDK_Shift_R:
|
||||
break;
|
||||
case GDK_Control_L: case GDK_Control_R:
|
||||
if (flip_options->type == ORIENTATION_HORIZONTAL)
|
||||
{
|
||||
gtk_toggle_button_set_active
|
||||
(GTK_TOGGLE_BUTTON (flip_options->type_w[ORIENTATION_VERTICAL - 1]), TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_toggle_button_set_active
|
||||
(GTK_TOGGLE_BUTTON (flip_options->type_w[ORIENTATION_HORIZONTAL - 1]), TRUE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static TileManager *
|
||||
flip_tool_transform (Tool *tool,
|
||||
GDisplay *gdisp,
|
||||
TransformState state)
|
||||
{
|
||||
TransformCore *transform_core;
|
||||
|
||||
transform_core = (TransformCore *) tool->private;
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case TRANSFORM_INIT:
|
||||
transform_info = NULL;
|
||||
break;
|
||||
|
||||
case TRANSFORM_MOTION:
|
||||
break;
|
||||
|
||||
case TRANSFORM_RECALC:
|
||||
break;
|
||||
|
||||
case TRANSFORM_FINISH:
|
||||
/* transform_core->trans_info[FLIP] *= -1.0;*/
|
||||
return flip_tool_flip (gdisp->gimage,
|
||||
gimp_image_active_drawable (gdisp->gimage),
|
||||
transform_core->original,
|
||||
(int) transform_core->trans_info[FLIP_INFO],
|
||||
flip_options->type);
|
||||
break;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
flip_cursor_update (Tool *tool,
|
||||
GdkEventMotion *mevent,
|
||||
GDisplay *gdisp)
|
||||
{
|
||||
GimpDrawable *drawable;
|
||||
GdkCursorType ctype = GIMP_BAD_CURSOR;
|
||||
|
||||
if ((drawable = gimp_image_active_drawable (gdisp->gimage)))
|
||||
{
|
||||
gint x, y;
|
||||
gint off_x, off_y;
|
||||
|
||||
gimp_drawable_offsets (drawable, &off_x, &off_y);
|
||||
gdisplay_untransform_coords (gdisp,
|
||||
(double) mevent->x, (double) mevent->y,
|
||||
&x, &y, TRUE, FALSE);
|
||||
|
||||
if (x >= off_x && y >= off_y &&
|
||||
x < (off_x + gimp_drawable_width (drawable)) &&
|
||||
y < (off_y + gimp_drawable_height (drawable)))
|
||||
{
|
||||
/* Is there a selected region? If so, is cursor inside? */
|
||||
if (gimage_mask_is_empty (gdisp->gimage) ||
|
||||
gimage_mask_value (gdisp->gimage, x, y))
|
||||
{
|
||||
if (flip_options->type == ORIENTATION_HORIZONTAL)
|
||||
ctype = GDK_SB_H_DOUBLE_ARROW;
|
||||
else
|
||||
ctype = GDK_SB_V_DOUBLE_ARROW;
|
||||
}
|
||||
}
|
||||
}
|
||||
gdisplay_install_tool_cursor (gdisp, ctype,
|
||||
FLIP,
|
||||
CURSOR_MODIFIER_NONE,
|
||||
ctype == GDK_SB_V_DOUBLE_ARROW);
|
||||
}
|
||||
|
||||
Tool *
|
||||
tools_new_flip (void)
|
||||
{
|
||||
Tool *tool;
|
||||
TransformCore *private;
|
||||
|
||||
/* The tool options */
|
||||
if (! flip_options)
|
||||
{
|
||||
flip_options = flip_options_new ();
|
||||
tools_register (FLIP, (ToolOptions *) flip_options);
|
||||
}
|
||||
|
||||
tool = transform_core_new (FLIP, FALSE);
|
||||
private = tool->private;
|
||||
|
||||
private->trans_func = flip_tool_transform;
|
||||
private->trans_info[FLIP_INFO] = -1.0;
|
||||
|
||||
tool->modifier_key_func = flip_modifier_key_func;
|
||||
tool->cursor_update_func = flip_cursor_update;
|
||||
|
||||
return tool;
|
||||
}
|
||||
|
||||
void
|
||||
tools_free_flip_tool (Tool *tool)
|
||||
{
|
||||
transform_core_free (tool);
|
||||
}
|
||||
|
||||
TileManager *
|
||||
flip_tool_flip (GimpImage *gimage,
|
||||
GimpDrawable *drawable,
|
||||
TileManager *orig,
|
||||
gint flip,
|
||||
InternalOrientationType type)
|
||||
{
|
||||
TileManager *new;
|
||||
PixelRegion srcPR, destPR;
|
||||
gint orig_width;
|
||||
gint orig_height;
|
||||
gint orig_bpp;
|
||||
gint i;
|
||||
|
||||
if (! orig)
|
||||
return NULL;
|
||||
|
||||
orig_width = tile_manager_level_width (orig);
|
||||
orig_height = tile_manager_level_height (orig);
|
||||
orig_bpp = tile_manager_level_bpp (orig);
|
||||
|
||||
if (flip > 0)
|
||||
{
|
||||
new = tile_manager_new (orig_width, orig_height, orig_bpp);
|
||||
pixel_region_init (&srcPR, orig,
|
||||
0, 0, orig_width, orig_height, FALSE);
|
||||
pixel_region_init (&destPR, new,
|
||||
0, 0, orig_width, orig_height, TRUE);
|
||||
|
||||
copy_region (&srcPR, &destPR);
|
||||
new->x = orig->x;
|
||||
new->y = orig->y;
|
||||
}
|
||||
else
|
||||
{
|
||||
new = tile_manager_new (orig_width, orig_height, orig_bpp);
|
||||
new->x = orig->x;
|
||||
new->y = orig->y;
|
||||
|
||||
if (type == ORIENTATION_HORIZONTAL)
|
||||
for (i = 0; i < orig->width; i++)
|
||||
{
|
||||
pixel_region_init (&srcPR, orig, i, 0, 1, orig_height, FALSE);
|
||||
pixel_region_init (&destPR, new,
|
||||
(orig_width - i - 1), 0, 1, orig_height, TRUE);
|
||||
copy_region (&srcPR, &destPR);
|
||||
}
|
||||
else
|
||||
for (i = 0; i < orig->height; i++)
|
||||
{
|
||||
pixel_region_init (&srcPR, orig, 0, i, orig_width, 1, FALSE);
|
||||
pixel_region_init (&destPR, new,
|
||||
0, (orig_height - i - 1), orig_width, 1, TRUE);
|
||||
copy_region (&srcPR, &destPR);
|
||||
}
|
||||
|
||||
/* flip locked paths */
|
||||
/* Note that the undo structures etc are setup before we enter this
|
||||
* function.
|
||||
*/
|
||||
if (type == ORIENTATION_HORIZONTAL)
|
||||
path_transform_flip_horz (gimage);
|
||||
else
|
||||
path_transform_flip_vert (gimage);
|
||||
}
|
||||
|
||||
return new;
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
/* 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.
|
||||
*/
|
||||
|
||||
#ifndef __FLIP_TOOL_H__
|
||||
#define __FLIP_TOOL_H__
|
||||
|
||||
|
||||
TileManager * flip_tool_flip (GimpImage *gimage,
|
||||
GimpDrawable *drawable,
|
||||
TileManager *orig,
|
||||
gint flip,
|
||||
InternalOrientationType type);
|
||||
|
||||
Tool * tools_new_flip (void);
|
||||
void tools_free_flip_tool (Tool *tool);
|
||||
|
||||
|
||||
#endif /* __FLIP_TOOL_H__ */
|
|
@ -1,391 +0,0 @@
|
|||
/* 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 <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "apptypes.h"
|
||||
|
||||
#include "appenv.h"
|
||||
#include "channel.h"
|
||||
#include "draw_core.h"
|
||||
#include "edit_selection.h"
|
||||
#include "errors.h"
|
||||
#include "floating_sel.h"
|
||||
#include "free_select.h"
|
||||
#include "gimage_mask.h"
|
||||
#include "gimpimage.h"
|
||||
#include "gdisplay.h"
|
||||
#include "rect_select.h"
|
||||
#include "selection_options.h"
|
||||
#include "scan_convert.h"
|
||||
#include "tools.h"
|
||||
#include "tool_options.h"
|
||||
|
||||
#include "libgimp/gimpmath.h"
|
||||
|
||||
|
||||
#define DEFAULT_MAX_INC 1024
|
||||
#define SUPERSAMPLE 3
|
||||
#define SUPERSAMPLE2 9
|
||||
|
||||
/* the free selection structures */
|
||||
|
||||
typedef struct _FreeSelect FreeSelect;
|
||||
|
||||
struct _FreeSelect
|
||||
{
|
||||
DrawCore *core; /* Core select object */
|
||||
|
||||
SelectOps op; /* selection operation (ADD, SUB, etc) */
|
||||
|
||||
gint current_x; /* these values are updated on every motion event */
|
||||
gint current_y; /* (enables immediate cursor updating on modifier
|
||||
* key events). */
|
||||
|
||||
gint num_pts; /* Number of points in the polygon */
|
||||
};
|
||||
|
||||
|
||||
/* local function prototypes */
|
||||
|
||||
static void free_select_button_press (Tool *tool,
|
||||
GdkEventButton *bevent,
|
||||
GDisplay *gdisp);
|
||||
static void free_select_button_release (Tool *tool,
|
||||
GdkEventButton *bevent,
|
||||
GDisplay *gdisp);
|
||||
static void free_select_motion (Tool *tool,
|
||||
GdkEventMotion *mevent,
|
||||
GDisplay *gdisp);
|
||||
|
||||
|
||||
/* the free selection tool options */
|
||||
static SelectionOptions * free_options = NULL;
|
||||
|
||||
/* The global array of XPoints for drawing the polygon... */
|
||||
static GdkPoint *global_pts = NULL;
|
||||
static gint max_segs = 0;
|
||||
|
||||
|
||||
/* functions */
|
||||
|
||||
static gint
|
||||
add_point (gint num_pts,
|
||||
gint x,
|
||||
gint y)
|
||||
{
|
||||
if (num_pts >= max_segs)
|
||||
{
|
||||
max_segs += DEFAULT_MAX_INC;
|
||||
|
||||
global_pts = (GdkPoint *) g_realloc ((void *) global_pts, sizeof (GdkPoint) * max_segs);
|
||||
|
||||
if (!global_pts)
|
||||
gimp_fatal_error ("add_point(): Unable to reallocate points array in free_select.");
|
||||
}
|
||||
|
||||
global_pts[num_pts].x = x;
|
||||
global_pts[num_pts].y = y;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static Channel *
|
||||
scan_convert (GimpImage *gimage,
|
||||
gint num_pts,
|
||||
ScanConvertPoint *pts,
|
||||
gint width,
|
||||
gint height,
|
||||
gboolean antialias)
|
||||
{
|
||||
Channel *mask;
|
||||
ScanConverter *sc;
|
||||
|
||||
sc = scan_converter_new (width, height, antialias ? SUPERSAMPLE : 1);
|
||||
scan_converter_add_points (sc, num_pts, pts);
|
||||
|
||||
mask = scan_converter_to_channel (sc, gimage);
|
||||
scan_converter_free (sc);
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
|
||||
/*************************************/
|
||||
/* Polygonal selection apparatus */
|
||||
|
||||
void
|
||||
free_select (GImage *gimage,
|
||||
gint num_pts,
|
||||
ScanConvertPoint *pts,
|
||||
SelectOps op,
|
||||
gboolean antialias,
|
||||
gboolean feather,
|
||||
gdouble feather_radius)
|
||||
{
|
||||
Channel *mask;
|
||||
|
||||
/* if applicable, replace the current selection */
|
||||
/* or insure that a floating selection is anchored down... */
|
||||
if (op == SELECTION_REPLACE)
|
||||
gimage_mask_clear (gimage);
|
||||
else
|
||||
gimage_mask_undo (gimage);
|
||||
|
||||
mask = scan_convert (gimage, num_pts, pts,
|
||||
gimage->width, gimage->height, antialias);
|
||||
|
||||
if (mask)
|
||||
{
|
||||
if (feather)
|
||||
channel_feather (mask, gimp_image_get_mask (gimage),
|
||||
feather_radius,
|
||||
feather_radius,
|
||||
op, 0, 0);
|
||||
else
|
||||
channel_combine_mask (gimp_image_get_mask (gimage),
|
||||
mask, op, 0, 0);
|
||||
channel_delete (mask);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
free_select_button_press (Tool *tool,
|
||||
GdkEventButton *bevent,
|
||||
GDisplay *gdisp)
|
||||
{
|
||||
FreeSelect *free_sel;
|
||||
|
||||
free_sel = (FreeSelect *) tool->private;
|
||||
|
||||
gdk_pointer_grab (gdisp->canvas->window, FALSE,
|
||||
GDK_POINTER_MOTION_HINT_MASK |
|
||||
GDK_BUTTON1_MOTION_MASK |
|
||||
GDK_BUTTON_RELEASE_MASK,
|
||||
NULL, NULL, bevent->time);
|
||||
|
||||
tool->state = ACTIVE;
|
||||
tool->gdisp = gdisp;
|
||||
|
||||
switch (free_sel->op)
|
||||
{
|
||||
case SELECTION_MOVE_MASK:
|
||||
init_edit_selection (tool, gdisp, bevent, EDIT_MASK_TRANSLATE);
|
||||
return;
|
||||
case SELECTION_MOVE:
|
||||
init_edit_selection (tool, gdisp, bevent, EDIT_MASK_TO_LAYER_TRANSLATE);
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
add_point (0, bevent->x, bevent->y);
|
||||
free_sel->num_pts = 1;
|
||||
|
||||
draw_core_start (free_sel->core,
|
||||
gdisp->canvas->window,
|
||||
tool);
|
||||
}
|
||||
|
||||
static void
|
||||
free_select_button_release (Tool *tool,
|
||||
GdkEventButton *bevent,
|
||||
GDisplay *gdisp)
|
||||
{
|
||||
FreeSelect *free_sel;
|
||||
ScanConvertPoint *pts;
|
||||
gint i;
|
||||
|
||||
free_sel = (FreeSelect *) tool->private;
|
||||
|
||||
gdk_pointer_ungrab (bevent->time);
|
||||
gdk_flush ();
|
||||
|
||||
draw_core_stop (free_sel->core, tool);
|
||||
|
||||
tool->state = INACTIVE;
|
||||
|
||||
/* First take care of the case where the user "cancels" the action */
|
||||
if (! (bevent->state & GDK_BUTTON3_MASK))
|
||||
{
|
||||
if (free_sel->op == SELECTION_ANCHOR)
|
||||
{
|
||||
/* If there is a floating selection, anchor it */
|
||||
if (gimp_image_floating_sel (gdisp->gimage))
|
||||
floating_sel_anchor (gimp_image_floating_sel (gdisp->gimage));
|
||||
/* Otherwise, clear the selection mask */
|
||||
else
|
||||
gimage_mask_clear (gdisp->gimage);
|
||||
|
||||
gdisplays_flush ();
|
||||
return;
|
||||
}
|
||||
|
||||
pts = g_new (ScanConvertPoint, free_sel->num_pts);
|
||||
|
||||
for (i = 0; i < free_sel->num_pts; i++)
|
||||
{
|
||||
gdisplay_untransform_coords_f (gdisp, global_pts[i].x, global_pts[i].y,
|
||||
&pts[i].x, &pts[i].y, FALSE);
|
||||
}
|
||||
|
||||
free_select (gdisp->gimage, free_sel->num_pts, pts, free_sel->op,
|
||||
free_options->antialias, free_options->feather,
|
||||
free_options->feather_radius);
|
||||
|
||||
g_free (pts);
|
||||
|
||||
gdisplays_flush ();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
free_select_motion (Tool *tool,
|
||||
GdkEventMotion *mevent,
|
||||
GDisplay *gdisp)
|
||||
{
|
||||
FreeSelect *free_sel;
|
||||
|
||||
free_sel = (FreeSelect *) tool->private;
|
||||
|
||||
/* needed for immediate cursor update on modifier event */
|
||||
free_sel->current_x = mevent->x;
|
||||
free_sel->current_y = mevent->y;
|
||||
|
||||
if (tool->state != ACTIVE)
|
||||
return;
|
||||
|
||||
if (free_sel->op == SELECTION_ANCHOR)
|
||||
{
|
||||
free_sel->op = SELECTION_REPLACE;
|
||||
|
||||
rect_select_cursor_update (tool, mevent, gdisp);
|
||||
}
|
||||
|
||||
if (add_point (free_sel->num_pts, mevent->x, mevent->y))
|
||||
{
|
||||
gdk_draw_line (free_sel->core->win, free_sel->core->gc,
|
||||
global_pts[free_sel->num_pts - 1].x,
|
||||
global_pts[free_sel->num_pts - 1].y,
|
||||
global_pts[free_sel->num_pts].x,
|
||||
global_pts[free_sel->num_pts].y);
|
||||
|
||||
free_sel->num_pts ++;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
free_select_control (Tool *tool,
|
||||
ToolAction action,
|
||||
GDisplay *gdisp)
|
||||
{
|
||||
FreeSelect *free_sel;
|
||||
|
||||
free_sel = (FreeSelect *) tool->private;
|
||||
|
||||
switch (action)
|
||||
{
|
||||
case PAUSE:
|
||||
draw_core_pause (free_sel->core, tool);
|
||||
break;
|
||||
|
||||
case RESUME:
|
||||
draw_core_resume (free_sel->core, tool);
|
||||
break;
|
||||
|
||||
case HALT:
|
||||
draw_core_stop (free_sel->core, tool);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
free_select_draw (Tool *tool)
|
||||
{
|
||||
FreeSelect *free_sel;
|
||||
gint i;
|
||||
|
||||
free_sel = (FreeSelect *) tool->private;
|
||||
|
||||
for (i = 1; i < free_sel->num_pts; i++)
|
||||
gdk_draw_line (free_sel->core->win, free_sel->core->gc,
|
||||
global_pts[i - 1].x, global_pts[i - 1].y,
|
||||
global_pts[i].x, global_pts[i].y);
|
||||
}
|
||||
|
||||
static void
|
||||
free_select_options_reset (void)
|
||||
{
|
||||
selection_options_reset (free_options);
|
||||
}
|
||||
|
||||
Tool *
|
||||
tools_new_free_select (void)
|
||||
{
|
||||
Tool *tool;
|
||||
FreeSelect *private;
|
||||
|
||||
/* The tool options */
|
||||
if (!free_options)
|
||||
{
|
||||
free_options =
|
||||
selection_options_new (FREE_SELECT, free_select_options_reset);
|
||||
tools_register (FREE_SELECT, (ToolOptions *) free_options);
|
||||
}
|
||||
|
||||
tool = tools_new_tool (FREE_SELECT);
|
||||
private = g_new0 (FreeSelect, 1);
|
||||
|
||||
private->core = draw_core_new (free_select_draw);
|
||||
private->num_pts = 0;
|
||||
private->op = SELECTION_REPLACE;
|
||||
|
||||
tool->scroll_lock = TRUE; /* Do not allow scrolling */
|
||||
|
||||
tool->private = (void *) private;
|
||||
|
||||
tool->button_press_func = free_select_button_press;
|
||||
tool->button_release_func = free_select_button_release;
|
||||
tool->motion_func = free_select_motion;
|
||||
tool->modifier_key_func = rect_select_modifier_update;
|
||||
tool->cursor_update_func = rect_select_cursor_update;
|
||||
tool->oper_update_func = rect_select_oper_update;
|
||||
tool->control_func = free_select_control;
|
||||
|
||||
return tool;
|
||||
}
|
||||
|
||||
void
|
||||
tools_free_free_select (Tool *tool)
|
||||
{
|
||||
FreeSelect *free_sel;
|
||||
|
||||
free_sel = (FreeSelect *) tool->private;
|
||||
|
||||
draw_core_free (free_sel->core);
|
||||
g_free (free_sel);
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
/* 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.
|
||||
*/
|
||||
|
||||
#ifndef __FREE_SELECT_H__
|
||||
#define __FREE_SELECT_H__
|
||||
|
||||
|
||||
/* free select functions */
|
||||
|
||||
void free_select (GimpImage *gimage,
|
||||
gint num_pts,
|
||||
ScanConvertPoint *pts,
|
||||
SelectOps op,
|
||||
gboolean antialias,
|
||||
gboolean feather,
|
||||
gdouble feather_radius);
|
||||
void free_select_draw (Tool *tool);
|
||||
|
||||
Tool * tools_new_free_select (void);
|
||||
void tools_free_free_select (Tool *tool);
|
||||
|
||||
|
||||
#endif /* __FREE_SELECT_H__ */
|
|
@ -1,688 +0,0 @@
|
|||
/* 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 <stdlib.h>
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "apptypes.h"
|
||||
|
||||
#include "appenv.h"
|
||||
#include "boundary.h"
|
||||
#include "channel.h"
|
||||
#include "cursorutil.h"
|
||||
#include "draw_core.h"
|
||||
#include "drawable.h"
|
||||
#include "edit_selection.h"
|
||||
#include "fuzzy_select.h"
|
||||
#include "gimage_mask.h"
|
||||
#include "gimpimage.h"
|
||||
#include "gimprc.h"
|
||||
#include "gimpui.h"
|
||||
#include "gdisplay.h"
|
||||
#include "pixel_region.h"
|
||||
#include "rect_select.h"
|
||||
#include "selection_options.h"
|
||||
#include "tile_manager.h"
|
||||
#include "tile.h"
|
||||
#include "tools.h"
|
||||
#include "tool_options.h"
|
||||
|
||||
#include "libgimp/gimpmath.h"
|
||||
|
||||
#include "libgimp/gimpintl.h"
|
||||
|
||||
|
||||
/* the fuzzy selection structures */
|
||||
|
||||
typedef struct _FuzzySelect FuzzySelect;
|
||||
|
||||
struct _FuzzySelect
|
||||
{
|
||||
DrawCore *core; /* Core select object */
|
||||
|
||||
gint op; /* selection operation (ADD, SUB, etc) */
|
||||
|
||||
gint current_x; /* these values are updated on every motion event */
|
||||
gint current_y; /* (enables immediate cursor updating on modifier
|
||||
* key events). */
|
||||
|
||||
gint x, y; /* Point from which to execute seed fill */
|
||||
gint first_x; /* */
|
||||
gint first_y; /* variables to keep track of sensitivity */
|
||||
gdouble first_threshold; /* initial value of threshold slider */
|
||||
};
|
||||
|
||||
|
||||
/* fuzzy select action functions */
|
||||
static void fuzzy_select_button_press (Tool *tool,
|
||||
GdkEventButton *bevent,
|
||||
GDisplay *gdisp);
|
||||
static void fuzzy_select_button_release (Tool *tool,
|
||||
GdkEventButton *bevent,
|
||||
GDisplay *gdisp);
|
||||
static void fuzzy_select_motion (Tool *tool,
|
||||
GdkEventMotion *mevent,
|
||||
GDisplay *gdisp);
|
||||
static void fuzzy_select_control (Tool *tool,
|
||||
ToolAction tool_action,
|
||||
GDisplay *gdisp);
|
||||
|
||||
static void fuzzy_select_draw (Tool *tool);
|
||||
|
||||
static GdkSegment * fuzzy_select_calculate (Tool *tool,
|
||||
GDisplay *gdisp,
|
||||
gint *nsegs);
|
||||
|
||||
|
||||
/* the fuzzy selection tool options */
|
||||
static SelectionOptions *fuzzy_options = NULL;
|
||||
|
||||
/* XSegments which make up the fuzzy selection boundary */
|
||||
static GdkSegment *segs = NULL;
|
||||
static gint num_segs = 0;
|
||||
|
||||
Channel * fuzzy_mask = NULL;
|
||||
|
||||
|
||||
/*************************************/
|
||||
/* Fuzzy selection apparatus */
|
||||
|
||||
static gint
|
||||
is_pixel_sufficiently_different (guchar *col1,
|
||||
guchar *col2,
|
||||
gboolean antialias,
|
||||
gint threshold,
|
||||
gint bytes,
|
||||
gboolean has_alpha)
|
||||
{
|
||||
gint diff;
|
||||
gint max;
|
||||
gint b;
|
||||
gint alpha;
|
||||
|
||||
max = 0;
|
||||
alpha = (has_alpha) ? bytes - 1 : bytes;
|
||||
|
||||
/* if there is an alpha channel, never select transparent regions */
|
||||
if (has_alpha && col2[alpha] == 0)
|
||||
return 0;
|
||||
|
||||
for (b = 0; b < bytes; b++)
|
||||
{
|
||||
diff = col1[b] - col2[b];
|
||||
diff = abs (diff);
|
||||
if (diff > max)
|
||||
max = diff;
|
||||
}
|
||||
|
||||
if (antialias)
|
||||
{
|
||||
float aa;
|
||||
|
||||
aa = 1.5 - ((float) max / threshold);
|
||||
if (aa <= 0)
|
||||
return 0;
|
||||
else if (aa < 0.5)
|
||||
return (unsigned char) (aa * 512);
|
||||
else
|
||||
return 255;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (max > threshold)
|
||||
return 0;
|
||||
else
|
||||
return 255;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ref_tiles (TileManager *src,
|
||||
TileManager *mask,
|
||||
Tile **s_tile,
|
||||
Tile **m_tile,
|
||||
gint x,
|
||||
gint y,
|
||||
guchar **s,
|
||||
guchar **m)
|
||||
{
|
||||
if (*s_tile != NULL)
|
||||
tile_release (*s_tile, FALSE);
|
||||
if (*m_tile != NULL)
|
||||
tile_release (*m_tile, TRUE);
|
||||
|
||||
*s_tile = tile_manager_get_tile (src, x, y, TRUE, FALSE);
|
||||
*m_tile = tile_manager_get_tile (mask, x, y, TRUE, TRUE);
|
||||
|
||||
*s = tile_data_pointer (*s_tile, x % TILE_WIDTH, y % TILE_HEIGHT);
|
||||
*m = tile_data_pointer (*m_tile, x % TILE_WIDTH, y % TILE_HEIGHT);
|
||||
}
|
||||
|
||||
static int
|
||||
find_contiguous_segment (guchar *col,
|
||||
PixelRegion *src,
|
||||
PixelRegion *mask,
|
||||
gint width,
|
||||
gint bytes,
|
||||
gboolean has_alpha,
|
||||
gboolean antialias,
|
||||
gint threshold,
|
||||
gint initial,
|
||||
gint *start,
|
||||
gint *end)
|
||||
{
|
||||
guchar *s;
|
||||
guchar *m;
|
||||
guchar diff;
|
||||
Tile *s_tile = NULL;
|
||||
Tile *m_tile = NULL;
|
||||
|
||||
ref_tiles (src->tiles, mask->tiles, &s_tile, &m_tile, src->x, src->y, &s, &m);
|
||||
|
||||
/* check the starting pixel */
|
||||
if (! (diff = is_pixel_sufficiently_different (col, s, antialias,
|
||||
threshold, bytes, has_alpha)))
|
||||
{
|
||||
tile_release (s_tile, FALSE);
|
||||
tile_release (m_tile, TRUE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*m-- = diff;
|
||||
s -= bytes;
|
||||
*start = initial - 1;
|
||||
|
||||
while (*start >= 0 && diff)
|
||||
{
|
||||
if (! ((*start + 1) % TILE_WIDTH))
|
||||
ref_tiles (src->tiles, mask->tiles, &s_tile, &m_tile, *start, src->y, &s, &m);
|
||||
|
||||
diff = is_pixel_sufficiently_different (col, s, antialias,
|
||||
threshold, bytes, has_alpha);
|
||||
if ((*m-- = diff))
|
||||
{
|
||||
s -= bytes;
|
||||
(*start)--;
|
||||
}
|
||||
}
|
||||
|
||||
diff = 1;
|
||||
*end = initial + 1;
|
||||
if (*end % TILE_WIDTH && *end < width)
|
||||
ref_tiles (src->tiles, mask->tiles, &s_tile, &m_tile, *end, src->y, &s, &m);
|
||||
|
||||
while (*end < width && diff)
|
||||
{
|
||||
if (! (*end % TILE_WIDTH))
|
||||
ref_tiles (src->tiles, mask->tiles, &s_tile, &m_tile, *end, src->y, &s, &m);
|
||||
|
||||
diff = is_pixel_sufficiently_different (col, s, antialias,
|
||||
threshold, bytes, has_alpha);
|
||||
if ((*m++ = diff))
|
||||
{
|
||||
s += bytes;
|
||||
(*end)++;
|
||||
}
|
||||
}
|
||||
|
||||
tile_release (s_tile, FALSE);
|
||||
tile_release (m_tile, TRUE);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
find_contiguous_region_helper (PixelRegion *mask,
|
||||
PixelRegion *src,
|
||||
gboolean has_alpha,
|
||||
gboolean antialias,
|
||||
gint threshold,
|
||||
gboolean indexed,
|
||||
gint x,
|
||||
gint y,
|
||||
guchar *col)
|
||||
{
|
||||
gint start, end, i;
|
||||
gint val;
|
||||
gint bytes;
|
||||
|
||||
Tile *tile;
|
||||
|
||||
if (threshold == 0) threshold = 1;
|
||||
if (x < 0 || x >= src->w) return;
|
||||
if (y < 0 || y >= src->h) return;
|
||||
|
||||
tile = tile_manager_get_tile (mask->tiles, x, y, TRUE, FALSE);
|
||||
val = *(guchar *)(tile_data_pointer (tile,
|
||||
x % TILE_WIDTH, y % TILE_HEIGHT));
|
||||
tile_release (tile, FALSE);
|
||||
if (val != 0)
|
||||
return;
|
||||
|
||||
src->x = x;
|
||||
src->y = y;
|
||||
|
||||
bytes = src->bytes;
|
||||
if(indexed)
|
||||
{
|
||||
bytes = has_alpha ? 4 : 3;
|
||||
}
|
||||
|
||||
if (! find_contiguous_segment (col, src, mask, src->w,
|
||||
src->bytes, has_alpha,
|
||||
antialias, threshold, x, &start, &end))
|
||||
return;
|
||||
|
||||
for (i = start + 1; i < end; i++)
|
||||
{
|
||||
find_contiguous_region_helper (mask, src, has_alpha, antialias,
|
||||
threshold, indexed, i, y - 1, col);
|
||||
find_contiguous_region_helper (mask, src, has_alpha, antialias,
|
||||
threshold, indexed, i, y + 1, col);
|
||||
}
|
||||
}
|
||||
|
||||
Channel *
|
||||
find_contiguous_region (GImage *gimage,
|
||||
GimpDrawable *drawable,
|
||||
gboolean antialias,
|
||||
gint threshold,
|
||||
gint x,
|
||||
gint y,
|
||||
gboolean sample_merged)
|
||||
{
|
||||
PixelRegion srcPR, maskPR;
|
||||
Channel *mask;
|
||||
guchar *start;
|
||||
gboolean has_alpha;
|
||||
gboolean indexed;
|
||||
gint type;
|
||||
gint bytes;
|
||||
Tile *tile;
|
||||
|
||||
if (sample_merged)
|
||||
{
|
||||
pixel_region_init (&srcPR, gimp_image_composite (gimage), 0, 0,
|
||||
gimage->width, gimage->height, FALSE);
|
||||
type = gimp_image_composite_type (gimage);
|
||||
has_alpha = (type == RGBA_GIMAGE ||
|
||||
type == GRAYA_GIMAGE ||
|
||||
type == INDEXEDA_GIMAGE);
|
||||
}
|
||||
else
|
||||
{
|
||||
pixel_region_init (&srcPR, gimp_drawable_data (drawable),
|
||||
0, 0,
|
||||
gimp_drawable_width (drawable),
|
||||
gimp_drawable_height (drawable),
|
||||
FALSE);
|
||||
has_alpha = gimp_drawable_has_alpha (drawable);
|
||||
}
|
||||
indexed = gimp_drawable_is_indexed (drawable);
|
||||
bytes = gimp_drawable_bytes (drawable);
|
||||
|
||||
if (indexed)
|
||||
{
|
||||
bytes = has_alpha ? 4 : 3;
|
||||
}
|
||||
mask = channel_new_mask (gimage, srcPR.w, srcPR.h);
|
||||
pixel_region_init (&maskPR, gimp_drawable_data (GIMP_DRAWABLE(mask)),
|
||||
0, 0,
|
||||
gimp_drawable_width (GIMP_DRAWABLE(mask)),
|
||||
gimp_drawable_height (GIMP_DRAWABLE(mask)),
|
||||
TRUE);
|
||||
|
||||
tile = tile_manager_get_tile (srcPR.tiles, x, y, TRUE, FALSE);
|
||||
if (tile)
|
||||
{
|
||||
start = tile_data_pointer (tile, x%TILE_WIDTH, y%TILE_HEIGHT);
|
||||
|
||||
find_contiguous_region_helper (&maskPR, &srcPR, has_alpha, antialias,
|
||||
threshold, bytes, x, y, start);
|
||||
|
||||
tile_release (tile, FALSE);
|
||||
}
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
void
|
||||
fuzzy_select (GImage *gimage,
|
||||
GimpDrawable *drawable,
|
||||
gint op,
|
||||
gboolean feather,
|
||||
gdouble feather_radius)
|
||||
{
|
||||
gint off_x, off_y;
|
||||
|
||||
/* if applicable, replace the current selection */
|
||||
if (op == CHANNEL_OP_REPLACE)
|
||||
gimage_mask_clear (gimage);
|
||||
else
|
||||
gimage_mask_undo (gimage);
|
||||
|
||||
if (drawable) /* NULL if sample_merged is active */
|
||||
gimp_drawable_offsets (drawable, &off_x, &off_y);
|
||||
else
|
||||
off_x = off_y = 0;
|
||||
|
||||
if (feather)
|
||||
channel_feather (fuzzy_mask, gimp_image_get_mask (gimage),
|
||||
feather_radius,
|
||||
feather_radius,
|
||||
op, off_x, off_y);
|
||||
else
|
||||
channel_combine_mask (gimp_image_get_mask (gimage),
|
||||
fuzzy_mask, op, off_x, off_y);
|
||||
|
||||
/* free the fuzzy region struct */
|
||||
channel_delete (fuzzy_mask);
|
||||
fuzzy_mask = NULL;
|
||||
}
|
||||
|
||||
/* fuzzy select action functions */
|
||||
|
||||
static void
|
||||
fuzzy_select_button_press (Tool *tool,
|
||||
GdkEventButton *bevent,
|
||||
GDisplay *gdisp)
|
||||
{
|
||||
FuzzySelect *fuzzy_sel;
|
||||
|
||||
fuzzy_sel = (FuzzySelect *) tool->private;
|
||||
|
||||
fuzzy_sel->x = bevent->x;
|
||||
fuzzy_sel->y = bevent->y;
|
||||
fuzzy_sel->first_x = fuzzy_sel->x;
|
||||
fuzzy_sel->first_y = fuzzy_sel->y;
|
||||
fuzzy_sel->first_threshold = fuzzy_options->threshold;
|
||||
|
||||
gdk_pointer_grab (gdisp->canvas->window, FALSE,
|
||||
GDK_POINTER_MOTION_HINT_MASK |
|
||||
GDK_BUTTON1_MOTION_MASK |
|
||||
GDK_BUTTON_RELEASE_MASK,
|
||||
NULL, NULL, bevent->time);
|
||||
|
||||
tool->state = ACTIVE;
|
||||
tool->gdisp = gdisp;
|
||||
|
||||
if (fuzzy_sel->op == SELECTION_MOVE_MASK)
|
||||
{
|
||||
init_edit_selection (tool, gdisp, bevent, EDIT_MASK_TRANSLATE);
|
||||
return;
|
||||
}
|
||||
else if (fuzzy_sel->op == SELECTION_MOVE)
|
||||
{
|
||||
init_edit_selection (tool, gdisp, bevent, EDIT_MASK_TO_LAYER_TRANSLATE);
|
||||
return;
|
||||
}
|
||||
|
||||
/* calculate the region boundary */
|
||||
segs = fuzzy_select_calculate (tool, gdisp, &num_segs);
|
||||
|
||||
draw_core_start (fuzzy_sel->core,
|
||||
gdisp->canvas->window,
|
||||
tool);
|
||||
}
|
||||
|
||||
static void
|
||||
fuzzy_select_button_release (Tool *tool,
|
||||
GdkEventButton *bevent,
|
||||
GDisplay *gdisp)
|
||||
{
|
||||
FuzzySelect *fuzzy_sel;
|
||||
GimpDrawable *drawable;
|
||||
|
||||
fuzzy_sel = (FuzzySelect *) tool->private;
|
||||
|
||||
gdk_pointer_ungrab (bevent->time);
|
||||
gdk_flush ();
|
||||
|
||||
draw_core_stop (fuzzy_sel->core, tool);
|
||||
tool->state = INACTIVE;
|
||||
|
||||
/* First take care of the case where the user "cancels" the action */
|
||||
if (! (bevent->state & GDK_BUTTON3_MASK))
|
||||
{
|
||||
drawable = (fuzzy_options->sample_merged ?
|
||||
NULL : gimp_image_active_drawable (gdisp->gimage));
|
||||
|
||||
fuzzy_select (gdisp->gimage, drawable, fuzzy_sel->op,
|
||||
fuzzy_options->feather,
|
||||
fuzzy_options->feather_radius);
|
||||
gdisplays_flush ();
|
||||
}
|
||||
|
||||
/* If the segment array is allocated, free it */
|
||||
if (segs)
|
||||
g_free (segs);
|
||||
segs = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
fuzzy_select_motion (Tool *tool,
|
||||
GdkEventMotion *mevent,
|
||||
GDisplay *gdisp)
|
||||
{
|
||||
FuzzySelect *fuzzy_sel;
|
||||
GdkSegment *new_segs;
|
||||
gint num_new_segs;
|
||||
gint diff_x, diff_y;
|
||||
gdouble diff;
|
||||
|
||||
static guint last_time = 0;
|
||||
|
||||
fuzzy_sel = (FuzzySelect *) tool->private;
|
||||
|
||||
/* needed for immediate cursor update on modifier event */
|
||||
fuzzy_sel->current_x = mevent->x;
|
||||
fuzzy_sel->current_y = mevent->y;
|
||||
|
||||
if (tool->state != ACTIVE)
|
||||
return;
|
||||
|
||||
/* don't let the events come in too fast, ignore below a delay of 100 ms */
|
||||
if (ABS (mevent->time - last_time) < 100)
|
||||
return;
|
||||
|
||||
last_time = mevent->time;
|
||||
|
||||
diff_x = mevent->x - fuzzy_sel->first_x;
|
||||
diff_y = mevent->y - fuzzy_sel->first_y;
|
||||
|
||||
diff = ((ABS (diff_x) > ABS (diff_y)) ? diff_x : diff_y) / 2.0;
|
||||
|
||||
gtk_adjustment_set_value (GTK_ADJUSTMENT (fuzzy_options->threshold_w),
|
||||
fuzzy_sel->first_threshold + diff);
|
||||
|
||||
/* calculate the new fuzzy boundary */
|
||||
new_segs = fuzzy_select_calculate (tool, gdisp, &num_new_segs);
|
||||
|
||||
/* stop the current boundary */
|
||||
draw_core_pause (fuzzy_sel->core, tool);
|
||||
|
||||
/* make sure the XSegment array is freed before we assign the new one */
|
||||
if (segs)
|
||||
g_free (segs);
|
||||
segs = new_segs;
|
||||
num_segs = num_new_segs;
|
||||
|
||||
/* start the new boundary */
|
||||
draw_core_resume (fuzzy_sel->core, tool);
|
||||
}
|
||||
|
||||
|
||||
static GdkSegment *
|
||||
fuzzy_select_calculate (Tool *tool,
|
||||
GDisplay *gdisp,
|
||||
gint *nsegs)
|
||||
{
|
||||
PixelRegion maskPR;
|
||||
FuzzySelect *fuzzy_sel;
|
||||
Channel *new;
|
||||
GdkSegment *segs;
|
||||
BoundSeg *bsegs;
|
||||
GimpDrawable *drawable;
|
||||
gint i;
|
||||
gint x, y;
|
||||
gboolean use_offsets;
|
||||
|
||||
fuzzy_sel = (FuzzySelect *) tool->private;
|
||||
drawable = gimp_image_active_drawable (gdisp->gimage);
|
||||
|
||||
gimp_add_busy_cursors ();
|
||||
|
||||
use_offsets = fuzzy_options->sample_merged ? FALSE : TRUE;
|
||||
|
||||
gdisplay_untransform_coords (gdisp, fuzzy_sel->x,
|
||||
fuzzy_sel->y, &x, &y, FALSE, use_offsets);
|
||||
|
||||
new = find_contiguous_region (gdisp->gimage, drawable,
|
||||
fuzzy_options->antialias,
|
||||
fuzzy_options->threshold, x, y,
|
||||
fuzzy_options->sample_merged);
|
||||
|
||||
if (fuzzy_mask)
|
||||
gtk_object_unref (GTK_OBJECT (fuzzy_mask));
|
||||
|
||||
fuzzy_mask = new;
|
||||
|
||||
gtk_object_ref (GTK_OBJECT (fuzzy_mask));
|
||||
gtk_object_sink (GTK_OBJECT (fuzzy_mask));
|
||||
|
||||
/* calculate and allocate a new XSegment array which represents the boundary
|
||||
* of the color-contiguous region
|
||||
*/
|
||||
pixel_region_init (&maskPR, gimp_drawable_data (GIMP_DRAWABLE (fuzzy_mask)),
|
||||
0, 0,
|
||||
gimp_drawable_width (GIMP_DRAWABLE (fuzzy_mask)),
|
||||
gimp_drawable_height (GIMP_DRAWABLE (fuzzy_mask)),
|
||||
FALSE);
|
||||
bsegs = find_mask_boundary (&maskPR, nsegs, WithinBounds,
|
||||
0, 0,
|
||||
gimp_drawable_width (GIMP_DRAWABLE (fuzzy_mask)),
|
||||
gimp_drawable_height (GIMP_DRAWABLE (fuzzy_mask)));
|
||||
|
||||
segs = g_new (GdkSegment, *nsegs);
|
||||
|
||||
for (i = 0; i < *nsegs; i++)
|
||||
{
|
||||
gdisplay_transform_coords (gdisp, bsegs[i].x1, bsegs[i].y1, &x, &y, use_offsets);
|
||||
segs[i].x1 = x; segs[i].y1 = y;
|
||||
gdisplay_transform_coords (gdisp, bsegs[i].x2, bsegs[i].y2, &x, &y, use_offsets);
|
||||
segs[i].x2 = x; segs[i].y2 = y;
|
||||
}
|
||||
|
||||
/* free boundary segments */
|
||||
g_free (bsegs);
|
||||
|
||||
gimp_remove_busy_cursors (NULL);
|
||||
|
||||
return segs;
|
||||
}
|
||||
|
||||
static void
|
||||
fuzzy_select_draw (Tool *tool)
|
||||
{
|
||||
FuzzySelect *fuzzy_sel;
|
||||
|
||||
fuzzy_sel = (FuzzySelect *) tool->private;
|
||||
|
||||
if (segs)
|
||||
gdk_draw_segments (fuzzy_sel->core->win, fuzzy_sel->core->gc, segs, num_segs);
|
||||
}
|
||||
|
||||
static void
|
||||
fuzzy_select_control (Tool *tool,
|
||||
ToolAction action,
|
||||
GDisplay *gdisp)
|
||||
{
|
||||
FuzzySelect *fuzzy_sel;
|
||||
|
||||
fuzzy_sel = (FuzzySelect *) tool->private;
|
||||
|
||||
switch (action)
|
||||
{
|
||||
case PAUSE :
|
||||
draw_core_pause (fuzzy_sel->core, tool);
|
||||
break;
|
||||
|
||||
case RESUME :
|
||||
draw_core_resume (fuzzy_sel->core, tool);
|
||||
break;
|
||||
|
||||
case HALT :
|
||||
draw_core_stop (fuzzy_sel->core, tool);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
fuzzy_select_options_reset (void)
|
||||
{
|
||||
selection_options_reset (fuzzy_options);
|
||||
}
|
||||
|
||||
Tool *
|
||||
tools_new_fuzzy_select (void)
|
||||
{
|
||||
Tool *tool;
|
||||
FuzzySelect *private;
|
||||
|
||||
/* The tool options */
|
||||
if (! fuzzy_options)
|
||||
{
|
||||
fuzzy_options = selection_options_new (FUZZY_SELECT,
|
||||
fuzzy_select_options_reset);
|
||||
tools_register (FUZZY_SELECT, (ToolOptions *) fuzzy_options);
|
||||
}
|
||||
|
||||
tool = tools_new_tool (FUZZY_SELECT);
|
||||
private = g_new0 (FuzzySelect, 1);
|
||||
|
||||
private->core = draw_core_new (fuzzy_select_draw);
|
||||
|
||||
tool->scroll_lock = TRUE; /* Disallow scrolling */
|
||||
|
||||
tool->private = (void *) private;
|
||||
|
||||
tool->button_press_func = fuzzy_select_button_press;
|
||||
tool->button_release_func = fuzzy_select_button_release;
|
||||
tool->motion_func = fuzzy_select_motion;
|
||||
tool->modifier_key_func = rect_select_modifier_update;
|
||||
tool->cursor_update_func = rect_select_cursor_update;
|
||||
tool->oper_update_func = rect_select_oper_update;
|
||||
tool->control_func = fuzzy_select_control;
|
||||
|
||||
return tool;
|
||||
}
|
||||
|
||||
void
|
||||
tools_free_fuzzy_select (Tool *tool)
|
||||
{
|
||||
FuzzySelect *fuzzy_sel;
|
||||
|
||||
fuzzy_sel = (FuzzySelect *) tool->private;
|
||||
draw_core_free (fuzzy_sel->core);
|
||||
g_free (fuzzy_sel);
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
/* 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.
|
||||
*/
|
||||
|
||||
#ifndef __FUZZY_SELECT_H__
|
||||
#define __FUZZY_SELECT_H__
|
||||
|
||||
|
||||
Channel * find_contiguous_region (GimpImage *gimage,
|
||||
GimpDrawable *drawable,
|
||||
gboolean antialias,
|
||||
gint threshold,
|
||||
gint x,
|
||||
gint y,
|
||||
gboolean sample_merged);
|
||||
void fuzzy_select (GimpImage *gimage,
|
||||
GimpDrawable *drawable,
|
||||
gint op,
|
||||
gboolean feather,
|
||||
gdouble feather_radius);
|
||||
|
||||
Tool * tools_new_fuzzy_select (void);
|
||||
void tools_free_fuzzy_select (Tool *tool);
|
||||
|
||||
|
||||
extern Channel *fuzzy_mask;
|
||||
|
||||
|
||||
#endif /* __FUZZY_SELECT_H__ */
|
|
@ -51,7 +51,6 @@
|
|||
#include "scale.h"
|
||||
#include "scroll.h"
|
||||
#include "selection.h"
|
||||
#include "tools.h"
|
||||
#include "undo.h"
|
||||
|
||||
|
||||
|
@ -59,7 +58,8 @@
|
|||
#include "gdisplay_color.h"
|
||||
#endif /* DISPLAY_FILTERS */
|
||||
|
||||
#include "bezier_selectP.h"
|
||||
#include "tools/bezier_selectP.h"
|
||||
#include "tools/tools.h"
|
||||
|
||||
#include "libgimp/gimpmath.h"
|
||||
|
||||
|
|
|
@ -34,9 +34,10 @@
|
|||
#include "gdisplay.h"
|
||||
#include "paint_funcs.h"
|
||||
#include "palette_import.h"
|
||||
#include "tools.h"
|
||||
#include "undo.h"
|
||||
|
||||
#include "tools/tools.h"
|
||||
|
||||
|
||||
/* gimage.c: Junk (ugly dependencies) from gimpimage.c on its way
|
||||
* to proper places. That is, the handlers should be moved to
|
||||
|
|
|
@ -31,14 +31,16 @@
|
|||
#include "gimage_mask.h"
|
||||
#include "gimprc.h"
|
||||
#include "layer.h"
|
||||
#include "paint_core.h"
|
||||
#include "paint_funcs.h"
|
||||
#include "paint_options.h"
|
||||
#include "pixel_region.h"
|
||||
#include "tile_manager.h"
|
||||
#include "tile_manager_pvt.h"
|
||||
#include "undo.h"
|
||||
|
||||
#include "tools/paint_core.h"
|
||||
#include "tools/paint_options.h"
|
||||
#include "tools/tools.h"
|
||||
|
||||
#include "pdb/procedural_db.h"
|
||||
|
||||
#include "libgimp/gimpintl.h"
|
||||
|
|
|
@ -50,9 +50,11 @@
|
|||
#include "gimprc.h"
|
||||
#include "patterns.h"
|
||||
#include "pattern_header.h"
|
||||
#include "paint_core.h"
|
||||
#include "temp_buf.h"
|
||||
|
||||
/* this needs to go away */
|
||||
#include "tools/paint_core.h"
|
||||
|
||||
#include "libgimp/gimpintl.h"
|
||||
|
||||
|
||||
|
|
|
@ -33,11 +33,13 @@
|
|||
|
||||
#include "appenv.h"
|
||||
#include "gimpbrushgenerated.h"
|
||||
#include "paint_core.h"
|
||||
#include "gimprc.h"
|
||||
#include "gimpbrush.h"
|
||||
#include "temp_buf.h"
|
||||
|
||||
/* this needs to go away */
|
||||
#include "tools/paint_core.h"
|
||||
|
||||
#include "libgimp/gimpmath.h"
|
||||
|
||||
|
||||
|
|
|
@ -48,9 +48,11 @@
|
|||
#include "patterns.h"
|
||||
#include "gimpbrush.h"
|
||||
#include "gimpbrushpipe.h"
|
||||
#include "paint_core.h"
|
||||
#include "gimprc.h"
|
||||
|
||||
/* this needs to go away */
|
||||
#include "tools/paint_core.h"
|
||||
|
||||
#include "libgimp/gimpmath.h"
|
||||
#include "libgimp/gimpparasiteio.h"
|
||||
|
||||
|
|
|
@ -38,7 +38,8 @@
|
|||
#include "layer.h"
|
||||
#include "patterns.h"
|
||||
#include "temp_buf.h"
|
||||
#include "tools.h"
|
||||
|
||||
#include "tools/tools.h"
|
||||
|
||||
#include "libgimp/gimplimits.h"
|
||||
#include "libgimp/gimpcolorarea.h"
|
||||
|
|
|
@ -94,30 +94,31 @@
|
|||
#include "apptypes.h"
|
||||
|
||||
#include "appenv.h"
|
||||
#include "brightness_contrast.h"
|
||||
#include "color_balance.h"
|
||||
#include "convert.h"
|
||||
#include "cursorutil.h"
|
||||
#include "curves.h"
|
||||
#include "drawable.h"
|
||||
#include "floating_sel.h"
|
||||
#include "fsdither.h"
|
||||
#include "gdisplay.h"
|
||||
#include "gimpimage.h"
|
||||
#include "gimpui.h"
|
||||
#include "hue_saturation.h"
|
||||
#include "layer.h"
|
||||
#include "levels.h"
|
||||
#include "undo.h"
|
||||
#include "palette.h"
|
||||
#include "gimppalette.h"
|
||||
#include "palette_select.h"
|
||||
#include "pixel_region.h"
|
||||
#include "posterize.h"
|
||||
#include "threshold.h"
|
||||
#include "tile_manager.h"
|
||||
#include "tile_manager_pvt.h" /* ick ick ick. */
|
||||
|
||||
#include "tools/brightness_contrast.h"
|
||||
#include "tools/color_balance.h"
|
||||
#include "tools/curves.h"
|
||||
#include "tools/hue_saturation.h"
|
||||
#include "tools/levels.h"
|
||||
#include "tools/posterize.h"
|
||||
#include "tools/threshold.h"
|
||||
|
||||
#include "libgimp/gimpcolorspace.h"
|
||||
#include "libgimp/gimphelpui.h"
|
||||
#include "libgimp/gimpmath.h"
|
||||
|
|
|
@ -50,7 +50,8 @@
|
|||
#include "plug_in.h"
|
||||
#include "gimage.h"
|
||||
#include "session.h"
|
||||
#include "tools.h"
|
||||
|
||||
#include "tools/tools.h"
|
||||
|
||||
#include "libgimp/gimpenv.h"
|
||||
#include "libgimp/gimputils.h"
|
||||
|
|
|
@ -38,9 +38,10 @@
|
|||
#include "paint_funcs.h"
|
||||
#include "pixel_region.h"
|
||||
#include "tile_manager.h"
|
||||
#include "tools.h"
|
||||
#include "undo.h"
|
||||
|
||||
#include "tools/tools.h"
|
||||
|
||||
#include "libgimp/gimpintl.h"
|
||||
|
||||
#include "tile_manager_pvt.h"
|
||||
|
|
|
@ -37,10 +37,11 @@
|
|||
#include "gimplist.h"
|
||||
#include "gimprc.h"
|
||||
#include "gimpui.h"
|
||||
#include "paint_options.h"
|
||||
#include "session.h"
|
||||
#include "temp_buf.h"
|
||||
|
||||
#include "tools/paint_options.h"
|
||||
|
||||
#include "pdb/procedural_db.h"
|
||||
|
||||
#include "libgimp/gimphelpui.h"
|
||||
|
|
|
@ -68,13 +68,14 @@
|
|||
#include "scale.h"
|
||||
#include "selection.h"
|
||||
#include "tips_dialog.h"
|
||||
#include "tools.h"
|
||||
#include "undo.h"
|
||||
|
||||
#ifdef DISPLAY_FILTERS
|
||||
#include "gdisplay_color_ui.h"
|
||||
#endif /* DISPLAY_FILTERS */
|
||||
|
||||
#include "tools/tools.h"
|
||||
|
||||
#include "libgimp/gimphelpui.h"
|
||||
#include "libgimp/gimpmath.h"
|
||||
|
||||
|
|
|
@ -39,7 +39,8 @@
|
|||
#include "gradient_header.h"
|
||||
#include "patterns.h"
|
||||
#include "session.h"
|
||||
#include "tools.h"
|
||||
|
||||
#include "tools/tools.h"
|
||||
|
||||
#include "libgimp/gimpenv.h"
|
||||
#include "libgimp/gimpcolorarea.h"
|
||||
|
|
|
@ -68,13 +68,14 @@
|
|||
#include "scale.h"
|
||||
#include "selection.h"
|
||||
#include "tips_dialog.h"
|
||||
#include "tools.h"
|
||||
#include "undo.h"
|
||||
|
||||
#ifdef DISPLAY_FILTERS
|
||||
#include "gdisplay_color_ui.h"
|
||||
#endif /* DISPLAY_FILTERS */
|
||||
|
||||
#include "tools/tools.h"
|
||||
|
||||
#include "libgimp/gimphelpui.h"
|
||||
#include "libgimp/gimpmath.h"
|
||||
|
||||
|
|
|
@ -34,7 +34,8 @@
|
|||
#include "info_dialog.h"
|
||||
#include "info_window.h"
|
||||
#include "scroll.h"
|
||||
#include "tools.h"
|
||||
|
||||
#include "tools/tools.h"
|
||||
|
||||
#include "pdb/procedural_db.h"
|
||||
|
||||
|
|
|
@ -39,7 +39,8 @@
|
|||
#include "gradient_header.h"
|
||||
#include "patterns.h"
|
||||
#include "session.h"
|
||||
#include "tools.h"
|
||||
|
||||
#include "tools/tools.h"
|
||||
|
||||
#include "libgimp/gimpenv.h"
|
||||
#include "libgimp/gimpcolorarea.h"
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "commands.h"
|
||||
#include "dialog_handler.h"
|
||||
#include "fileops.h"
|
||||
#include "gdisplay.h"
|
||||
#include "gimphelp.h"
|
||||
#include "gimprc.h"
|
||||
#include "gimpui.h"
|
||||
|
@ -41,8 +42,8 @@
|
|||
#include "paint_funcs.h"
|
||||
#include "preferences_dialog.h"
|
||||
#include "scale.h"
|
||||
#include "tools.h"
|
||||
#include "gdisplay.h"
|
||||
|
||||
#include "tools/tools.h"
|
||||
|
||||
#include "libgimp/gimpenv.h"
|
||||
|
||||
|
|
|
@ -45,8 +45,6 @@
|
|||
#include "lc_dialogP.h"
|
||||
#include "menus.h"
|
||||
#include "ops_buttons.h"
|
||||
#include "bezier_select.h"
|
||||
#include "bezier_selectP.h"
|
||||
#include "path.h"
|
||||
#include "pathP.h"
|
||||
#include "path_transform.h"
|
||||
|
@ -55,6 +53,9 @@
|
|||
#include "plug_in.h"
|
||||
#include "undo.h"
|
||||
|
||||
#include "tools/bezier_select.h"
|
||||
#include "tools/bezier_selectP.h"
|
||||
|
||||
#include "libgimp/gimpmath.h"
|
||||
|
||||
#include "libgimp/gimpintl.h"
|
||||
|
|
|
@ -1,470 +0,0 @@
|
|||
/* 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 <gtk/gtk.h>
|
||||
|
||||
#include "apptypes.h"
|
||||
|
||||
#include "appenv.h"
|
||||
#include "drawable.h"
|
||||
#include "gdisplay.h"
|
||||
#include "gimpimage.h"
|
||||
#include "gimphistogram.h"
|
||||
#include "gimpui.h"
|
||||
#include "histogram_tool.h"
|
||||
#include "histogramwidget.h"
|
||||
#include "pixel_region.h"
|
||||
#include "tool_options.h"
|
||||
#include "tools.h"
|
||||
|
||||
#include "libgimp/gimpmath.h"
|
||||
|
||||
#include "libgimp/gimpintl.h"
|
||||
|
||||
|
||||
#define TEXT_WIDTH 45
|
||||
#define GRADIENT_HEIGHT 15
|
||||
|
||||
/* the histogram structures */
|
||||
|
||||
typedef struct _HistogramTool HistogramTool;
|
||||
|
||||
struct _HistogramTool
|
||||
{
|
||||
gint x, y; /* coords for last mouse click */
|
||||
};
|
||||
|
||||
|
||||
/* histogram_tool action functions */
|
||||
static void histogram_tool_control (Tool *tool,
|
||||
ToolAction tool_action,
|
||||
GDisplay *gdisp);
|
||||
|
||||
static HistogramToolDialog * histogram_tool_dialog_new (void);
|
||||
|
||||
static void histogram_tool_close_callback (GtkWidget *widget,
|
||||
gpointer data);
|
||||
static void histogram_tool_channel_callback (GtkWidget *widget,
|
||||
gpointer data);
|
||||
static void histogram_tool_gradient_draw (GtkWidget *gdisp,
|
||||
gint channel);
|
||||
|
||||
static void histogram_tool_dialog_update (HistogramToolDialog *htd,
|
||||
gint start,
|
||||
gint end);
|
||||
|
||||
|
||||
/* the histogram tool options */
|
||||
static ToolOptions * histogram_tool_options = NULL;
|
||||
|
||||
/* the histogram tool dialog */
|
||||
static HistogramToolDialog * histogram_tool_dialog = NULL;
|
||||
|
||||
|
||||
/* histogram_tool machinery */
|
||||
|
||||
void
|
||||
histogram_tool_histogram_range (HistogramWidget *widget,
|
||||
gint start,
|
||||
gint end,
|
||||
gpointer data)
|
||||
{
|
||||
HistogramToolDialog *htd;
|
||||
gdouble pixels;
|
||||
gdouble count;
|
||||
|
||||
htd = (HistogramToolDialog *) data;
|
||||
|
||||
if (htd == NULL || htd->hist == NULL ||
|
||||
gimp_histogram_nchannels (htd->hist) <= 0)
|
||||
return;
|
||||
|
||||
pixels = gimp_histogram_get_count (htd->hist, 0, 255);
|
||||
count = gimp_histogram_get_count (htd->hist, start, end);
|
||||
|
||||
htd->mean = gimp_histogram_get_mean (htd->hist, htd->channel,
|
||||
start, end);
|
||||
htd->std_dev = gimp_histogram_get_std_dev (htd->hist, htd->channel,
|
||||
start, end);
|
||||
htd->median = gimp_histogram_get_median (htd->hist, htd->channel,
|
||||
start, end);
|
||||
htd->pixels = pixels;
|
||||
htd->count = count;
|
||||
htd->percentile = count / pixels;
|
||||
|
||||
if (htd->shell)
|
||||
histogram_tool_dialog_update (htd, start, end);
|
||||
}
|
||||
|
||||
static void
|
||||
histogram_tool_dialog_update (HistogramToolDialog *htd,
|
||||
gint start,
|
||||
gint end)
|
||||
{
|
||||
gchar text[12];
|
||||
|
||||
/* mean */
|
||||
g_snprintf (text, sizeof (text), "%3.1f", htd->mean);
|
||||
gtk_label_set_text (GTK_LABEL (htd->info_labels[0]), text);
|
||||
|
||||
/* std dev */
|
||||
g_snprintf (text, sizeof (text), "%3.1f", htd->std_dev);
|
||||
gtk_label_set_text (GTK_LABEL (htd->info_labels[1]), text);
|
||||
|
||||
/* median */
|
||||
g_snprintf (text, sizeof (text), "%3.1f", htd->median);
|
||||
gtk_label_set_text (GTK_LABEL (htd->info_labels[2]), text);
|
||||
|
||||
/* pixels */
|
||||
g_snprintf (text, sizeof (text), "%8.1f", htd->pixels);
|
||||
gtk_label_set_text (GTK_LABEL (htd->info_labels[3]), text);
|
||||
|
||||
/* intensity */
|
||||
if (start == end)
|
||||
g_snprintf (text, sizeof (text), "%d", start);
|
||||
else
|
||||
g_snprintf (text, sizeof (text), "%d..%d", start, end);
|
||||
gtk_label_set_text (GTK_LABEL (htd->info_labels[4]), text);
|
||||
|
||||
/* count */
|
||||
g_snprintf (text, sizeof (text), "%8.1f", htd->count);
|
||||
gtk_label_set_text (GTK_LABEL (htd->info_labels[5]), text);
|
||||
|
||||
/* percentile */
|
||||
g_snprintf (text, sizeof (text), "%2.2f", htd->percentile * 100);
|
||||
gtk_label_set_text (GTK_LABEL (htd->info_labels[6]), text);
|
||||
}
|
||||
|
||||
/* histogram_tool action functions */
|
||||
|
||||
static void
|
||||
histogram_tool_control (Tool *tool,
|
||||
ToolAction action,
|
||||
GDisplay *gdisp)
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
case PAUSE:
|
||||
break;
|
||||
|
||||
case RESUME:
|
||||
break;
|
||||
|
||||
case HALT:
|
||||
if (histogram_tool_dialog)
|
||||
histogram_tool_close_callback (NULL, (gpointer) histogram_tool_dialog);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Tool *
|
||||
tools_new_histogram_tool (void)
|
||||
{
|
||||
Tool *tool;
|
||||
HistogramTool *private;
|
||||
|
||||
/* The tool options */
|
||||
if (! histogram_tool_options)
|
||||
{
|
||||
histogram_tool_options = tool_options_new (_("Histogram"));
|
||||
tools_register (HISTOGRAM, histogram_tool_options);
|
||||
}
|
||||
|
||||
tool = tools_new_tool (HISTOGRAM);
|
||||
private = g_new0 (HistogramTool, 1);
|
||||
|
||||
tool->scroll_lock = TRUE; /* Disallow scrolling */
|
||||
tool->preserve = FALSE; /* Don't preserve on drawable change */
|
||||
|
||||
tool->private = (void *) private;
|
||||
|
||||
tool->control_func = histogram_tool_control;
|
||||
|
||||
return tool;
|
||||
}
|
||||
|
||||
void
|
||||
tools_free_histogram_tool (Tool *tool)
|
||||
{
|
||||
HistogramTool * hist;
|
||||
|
||||
hist = (HistogramTool *) tool->private;
|
||||
|
||||
/* Close the histogram dialog */
|
||||
if (histogram_tool_dialog)
|
||||
histogram_tool_close_callback (NULL, (gpointer) histogram_tool_dialog);
|
||||
|
||||
g_free (hist);
|
||||
}
|
||||
|
||||
void
|
||||
histogram_tool_initialize (GDisplay *gdisp)
|
||||
{
|
||||
PixelRegion PR;
|
||||
|
||||
if (gimp_drawable_is_indexed (gimp_image_active_drawable (gdisp->gimage)))
|
||||
{
|
||||
g_message (_("Histogram does not operate on indexed drawables."));
|
||||
return;
|
||||
}
|
||||
|
||||
/* The histogram_tool dialog */
|
||||
if (!histogram_tool_dialog)
|
||||
histogram_tool_dialog = histogram_tool_dialog_new ();
|
||||
else if (!GTK_WIDGET_VISIBLE (histogram_tool_dialog->shell))
|
||||
gtk_widget_show (histogram_tool_dialog->shell);
|
||||
|
||||
histogram_tool_dialog->drawable = gimp_image_active_drawable (gdisp->gimage);
|
||||
histogram_tool_dialog->color = gimp_drawable_is_rgb (histogram_tool_dialog->drawable);
|
||||
|
||||
/* hide or show the channel menu based on image type */
|
||||
if (histogram_tool_dialog->color)
|
||||
gtk_widget_show (histogram_tool_dialog->channel_menu);
|
||||
else
|
||||
gtk_widget_hide (histogram_tool_dialog->channel_menu);
|
||||
|
||||
/* calculate the histogram */
|
||||
pixel_region_init (&PR, gimp_drawable_data (histogram_tool_dialog->drawable),
|
||||
0, 0,
|
||||
gimp_drawable_width (histogram_tool_dialog->drawable),
|
||||
gimp_drawable_height (histogram_tool_dialog->drawable),
|
||||
FALSE);
|
||||
gimp_histogram_calculate (histogram_tool_dialog->hist, &PR, NULL);
|
||||
|
||||
histogram_widget_update (histogram_tool_dialog->histogram,
|
||||
histogram_tool_dialog->hist);
|
||||
histogram_widget_range (histogram_tool_dialog->histogram, 0, 255);
|
||||
}
|
||||
|
||||
/***************************/
|
||||
/* Histogram Tool dialog */
|
||||
/***************************/
|
||||
|
||||
static HistogramToolDialog *
|
||||
histogram_tool_dialog_new (void)
|
||||
{
|
||||
HistogramToolDialog *htd;
|
||||
GtkWidget *main_vbox;
|
||||
GtkWidget *hbox;
|
||||
GtkWidget *vbox;
|
||||
GtkWidget *grad_hbox;
|
||||
GtkWidget *frame;
|
||||
GtkWidget *table;
|
||||
GtkWidget *label;
|
||||
GtkWidget *option_menu;
|
||||
gint i;
|
||||
gint x, y;
|
||||
|
||||
static gchar * histogram_info_names[] =
|
||||
{
|
||||
N_("Mean:"),
|
||||
N_("Std Dev:"),
|
||||
N_("Median:"),
|
||||
N_("Pixels:"),
|
||||
N_("Intensity:"),
|
||||
N_("Count:"),
|
||||
N_("Percentile:")
|
||||
};
|
||||
|
||||
htd = g_new (HistogramToolDialog, 1);
|
||||
htd->channel = GIMP_HISTOGRAM_VALUE;
|
||||
htd->hist = gimp_histogram_new ();
|
||||
|
||||
/* The shell and main vbox */
|
||||
htd->shell = gimp_dialog_new (_("Histogram"), "histogram",
|
||||
tools_help_func,
|
||||
tool_info[HISTOGRAM].private_tip,
|
||||
GTK_WIN_POS_NONE,
|
||||
FALSE, TRUE, FALSE,
|
||||
|
||||
_("Close"), histogram_tool_close_callback,
|
||||
htd, NULL, NULL, TRUE, TRUE,
|
||||
|
||||
NULL);
|
||||
|
||||
main_vbox = gtk_vbox_new (FALSE, 4);
|
||||
gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 4);
|
||||
gtk_container_add (GTK_CONTAINER (GTK_DIALOG (htd->shell)->vbox), main_vbox);
|
||||
|
||||
hbox = gtk_hbox_new (TRUE, 0);
|
||||
gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, FALSE, 0);
|
||||
|
||||
vbox = gtk_vbox_new (FALSE, 4);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
|
||||
|
||||
/* The option menu for selecting channels */
|
||||
htd->channel_menu = gtk_hbox_new (FALSE, 6);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), htd->channel_menu, FALSE, FALSE, 0);
|
||||
|
||||
label = gtk_label_new (_("Information on Channel:"));
|
||||
gtk_box_pack_start (GTK_BOX (htd->channel_menu), label, FALSE, FALSE, 0);
|
||||
gtk_widget_show (label);
|
||||
|
||||
option_menu = gimp_option_menu_new2
|
||||
(FALSE, histogram_tool_channel_callback,
|
||||
htd, (gpointer) htd->channel,
|
||||
|
||||
_("Value"), (gpointer) GIMP_HISTOGRAM_VALUE, NULL,
|
||||
_("Red"), (gpointer) GIMP_HISTOGRAM_RED, NULL,
|
||||
_("Green"), (gpointer) GIMP_HISTOGRAM_GREEN, NULL,
|
||||
_("Blue"), (gpointer) GIMP_HISTOGRAM_BLUE, NULL,
|
||||
|
||||
NULL);
|
||||
gtk_box_pack_start (GTK_BOX (htd->channel_menu), option_menu, FALSE, FALSE, 0);
|
||||
gtk_widget_show (option_menu);
|
||||
|
||||
gtk_widget_show (htd->channel_menu);
|
||||
|
||||
/* The histogram tool histogram */
|
||||
frame = gtk_frame_new (NULL);
|
||||
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
|
||||
|
||||
htd->histogram = histogram_widget_new (HISTOGRAM_WIDTH, HISTOGRAM_HEIGHT);
|
||||
gtk_container_add (GTK_CONTAINER (frame), GTK_WIDGET(htd->histogram));
|
||||
|
||||
gtk_signal_connect (GTK_OBJECT (htd->histogram), "range_changed",
|
||||
GTK_SIGNAL_FUNC (histogram_tool_histogram_range),
|
||||
htd);
|
||||
|
||||
gtk_widget_show (GTK_WIDGET (htd->histogram));
|
||||
gtk_widget_show (frame);
|
||||
|
||||
/* The gradient below the histogram */
|
||||
grad_hbox = gtk_hbox_new (TRUE, 0);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), grad_hbox, FALSE, FALSE, 0);
|
||||
frame = gtk_frame_new (NULL);
|
||||
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
|
||||
gtk_box_pack_start (GTK_BOX (grad_hbox), frame, FALSE, FALSE, 0);
|
||||
|
||||
htd->gradient = gtk_preview_new (GTK_PREVIEW_COLOR);
|
||||
gtk_preview_size (GTK_PREVIEW (htd->gradient),
|
||||
HISTOGRAM_WIDTH, GRADIENT_HEIGHT);
|
||||
gtk_container_add (GTK_CONTAINER (frame), GTK_WIDGET(htd->gradient));
|
||||
gtk_widget_show (htd->gradient);
|
||||
gtk_widget_show (frame);
|
||||
gtk_widget_show (grad_hbox);
|
||||
histogram_tool_gradient_draw (htd->gradient, GIMP_HISTOGRAM_VALUE);
|
||||
|
||||
gtk_widget_show (vbox);
|
||||
gtk_widget_show (hbox);
|
||||
|
||||
/* The table containing histogram information */
|
||||
table = gtk_table_new (4, 4, TRUE);
|
||||
gtk_table_set_col_spacings (GTK_TABLE (table), 6);
|
||||
gtk_box_pack_start (GTK_BOX (main_vbox), table, FALSE, FALSE, 0);
|
||||
|
||||
/* the labels for histogram information */
|
||||
for (i = 0; i < 7; i++)
|
||||
{
|
||||
y = (i % 4);
|
||||
x = (i / 4) * 2;
|
||||
|
||||
label = gtk_label_new (gettext(histogram_info_names[i]));
|
||||
gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
|
||||
gtk_table_attach (GTK_TABLE (table), label, x, x + 1, y, y + 1,
|
||||
GTK_FILL, GTK_FILL, 2, 2);
|
||||
gtk_widget_show (label);
|
||||
|
||||
htd->info_labels[i] = gtk_label_new ("0");
|
||||
gtk_misc_set_alignment (GTK_MISC (htd->info_labels[i]), 0.0, 0.5);
|
||||
gtk_table_attach (GTK_TABLE (table), htd->info_labels[i],
|
||||
x + 1, x + 2, y, y + 1,
|
||||
GTK_FILL, GTK_FILL, 2, 2);
|
||||
gtk_widget_show (htd->info_labels[i]);
|
||||
}
|
||||
|
||||
gtk_widget_show (table);
|
||||
|
||||
gtk_widget_show (main_vbox);
|
||||
gtk_widget_show (htd->shell);
|
||||
|
||||
return htd;
|
||||
}
|
||||
|
||||
static void
|
||||
histogram_tool_close_callback (GtkWidget *widget,
|
||||
gpointer data)
|
||||
{
|
||||
HistogramToolDialog *htd;
|
||||
|
||||
htd = (HistogramToolDialog *) data;
|
||||
|
||||
gimp_dialog_hide (htd->shell);
|
||||
|
||||
active_tool->gdisp = NULL;
|
||||
active_tool->drawable = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
histogram_tool_channel_callback (GtkWidget *widget,
|
||||
gpointer data)
|
||||
{
|
||||
HistogramToolDialog *htd;
|
||||
|
||||
htd = (HistogramToolDialog *) data;
|
||||
|
||||
gimp_menu_item_update (widget, &htd->channel);
|
||||
|
||||
histogram_widget_channel (htd->histogram, htd->channel);
|
||||
histogram_tool_gradient_draw (htd->gradient, htd->channel);
|
||||
}
|
||||
|
||||
static void
|
||||
histogram_tool_gradient_draw (GtkWidget *gradient,
|
||||
gint channel)
|
||||
{
|
||||
guchar buf[HISTOGRAM_WIDTH * 3];
|
||||
guchar r, g, b;
|
||||
gint i;
|
||||
|
||||
r = g = b = 0;
|
||||
switch (channel)
|
||||
{
|
||||
case GIMP_HISTOGRAM_VALUE:
|
||||
case GIMP_HISTOGRAM_ALPHA: r = g = b = 1;
|
||||
break;
|
||||
case GIMP_HISTOGRAM_RED: r = 1;
|
||||
break;
|
||||
case GIMP_HISTOGRAM_GREEN: g = 1;
|
||||
break;
|
||||
case GIMP_HISTOGRAM_BLUE: b = 1;
|
||||
break;
|
||||
default:
|
||||
g_warning ("unknown channel type, can't happen\n");
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; i < HISTOGRAM_WIDTH; i++)
|
||||
{
|
||||
buf[3*i+0] = i*r;
|
||||
buf[3*i+1] = i*g;
|
||||
buf[3*i+2] = i*b;
|
||||
}
|
||||
|
||||
for (i = 0; i < GRADIENT_HEIGHT; i++)
|
||||
gtk_preview_draw_row (GTK_PREVIEW (gradient),
|
||||
buf, 0, i, HISTOGRAM_WIDTH);
|
||||
|
||||
gtk_widget_queue_draw (gradient);
|
||||
}
|
|
@ -1,64 +0,0 @@
|
|||
/* 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.
|
||||
*/
|
||||
|
||||
#ifndef __HISTOGRAM_TOOL_H__
|
||||
#define __HISTOGRAM_TOOL_H__
|
||||
|
||||
|
||||
#define HISTOGRAM_WIDTH 256
|
||||
#define HISTOGRAM_HEIGHT 150
|
||||
|
||||
typedef struct _HistogramToolDialog HistogramToolDialog;
|
||||
|
||||
struct _HistogramToolDialog
|
||||
{
|
||||
GtkWidget *shell;
|
||||
|
||||
GtkWidget *info_labels[7];
|
||||
GtkWidget *channel_menu;
|
||||
HistogramWidget *histogram;
|
||||
GimpHistogram *hist;
|
||||
GtkWidget *gradient;
|
||||
|
||||
gdouble mean;
|
||||
gdouble std_dev;
|
||||
gdouble median;
|
||||
gdouble pixels;
|
||||
gdouble count;
|
||||
gdouble percentile;
|
||||
|
||||
GimpDrawable *drawable;
|
||||
ImageMap image_map;
|
||||
gint channel;
|
||||
gint color;
|
||||
};
|
||||
|
||||
|
||||
/* histogram_tool functions */
|
||||
Tool * tools_new_histogram_tool (void);
|
||||
void tools_free_histogram_tool (Tool *tool);
|
||||
|
||||
void histogram_tool_initialize (GDisplay *gdisp);
|
||||
void histogram_tool_free (void);
|
||||
void histogram_tool_histogram_range (HistogramWidget *hw,
|
||||
gint start,
|
||||
gint end,
|
||||
gpointer data);
|
||||
|
||||
|
||||
#endif /* __HISTOGRAM_TOOL_H__ */
|
|
@ -1,854 +0,0 @@
|
|||
/* 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 <gtk/gtk.h>
|
||||
|
||||
#include "apptypes.h"
|
||||
|
||||
#include "appenv.h"
|
||||
#include "drawable.h"
|
||||
#include "gimage_mask.h"
|
||||
#include "gdisplay.h"
|
||||
#include "gimpimage.h"
|
||||
#include "gimpui.h"
|
||||
#include "hue_saturation.h"
|
||||
#include "image_map.h"
|
||||
#include "pixel_region.h"
|
||||
#include "tools.h"
|
||||
#include "tool_options.h"
|
||||
|
||||
#include "libgimp/gimpcolorspace.h"
|
||||
#include "libgimp/gimpmath.h"
|
||||
|
||||
#include "libgimp/gimpintl.h"
|
||||
|
||||
|
||||
#define HUE_PARTITION_MASK GDK_EXPOSURE_MASK | GDK_ENTER_NOTIFY_MASK
|
||||
|
||||
#define SLIDER_WIDTH 200
|
||||
#define DA_WIDTH 40
|
||||
#define DA_HEIGHT 20
|
||||
|
||||
#define HUE_PARTITION 0x0
|
||||
#define HUE_SLIDER 0x1
|
||||
#define LIGHTNESS_SLIDER 0x2
|
||||
#define SATURATION_SLIDER 0x4
|
||||
#define DRAW 0x40
|
||||
#define ALL 0xFF
|
||||
|
||||
/* the hue-saturation structures */
|
||||
|
||||
typedef struct _HueSaturation HueSaturation;
|
||||
|
||||
struct _HueSaturation
|
||||
{
|
||||
gint x, y; /* coords for last mouse click */
|
||||
};
|
||||
|
||||
|
||||
/* hue saturation action functions */
|
||||
static void hue_saturation_control (Tool *tool,
|
||||
ToolAction tool_action,
|
||||
GDisplay *gdisp);
|
||||
|
||||
static HueSaturationDialog * hue_saturation_dialog_new (void);
|
||||
|
||||
static void hue_saturation_update (HueSaturationDialog *hsd,
|
||||
gint);
|
||||
static void hue_saturation_preview (HueSaturationDialog *hsd);
|
||||
static void hue_saturation_reset_callback (GtkWidget *,
|
||||
gpointer);
|
||||
static void hue_saturation_ok_callback (GtkWidget *,
|
||||
gpointer);
|
||||
static void hue_saturation_cancel_callback (GtkWidget *,
|
||||
gpointer);
|
||||
static void hue_saturation_partition_callback (GtkWidget *,
|
||||
gpointer);
|
||||
static void hue_saturation_preview_update (GtkWidget *,
|
||||
gpointer);
|
||||
static void hue_saturation_hue_adjustment_update (GtkAdjustment *,
|
||||
gpointer);
|
||||
static void hue_saturation_lightness_adjustment_update (GtkAdjustment *,
|
||||
gpointer);
|
||||
static void hue_saturation_saturation_adjustment_update (GtkAdjustment *,
|
||||
gpointer);
|
||||
static gint hue_saturation_hue_partition_events (GtkWidget *,
|
||||
GdkEvent *,
|
||||
HueSaturationDialog *hsd);
|
||||
|
||||
|
||||
/* the hue-saturation tool options */
|
||||
static ToolOptions *hue_saturation_options = NULL;
|
||||
|
||||
/* the hue-saturation tool dialog */
|
||||
static HueSaturationDialog *hue_saturation_dialog = NULL;
|
||||
|
||||
/* Local variables */
|
||||
static gint hue_transfer[6][256];
|
||||
static gint lightness_transfer[6][256];
|
||||
static gint saturation_transfer[6][256];
|
||||
static gint default_colors[6][3] =
|
||||
{
|
||||
{ 255, 0, 0 },
|
||||
{ 255, 255, 0 },
|
||||
{ 0, 255, 0 },
|
||||
{ 0, 255, 255 },
|
||||
{ 0, 0, 255 },
|
||||
{ 255, 0, 255 }
|
||||
};
|
||||
|
||||
|
||||
/* hue saturation machinery */
|
||||
|
||||
void
|
||||
hue_saturation_calculate_transfers (HueSaturationDialog *hsd)
|
||||
{
|
||||
gint value;
|
||||
gint hue;
|
||||
gint i;
|
||||
|
||||
/* Calculate transfers */
|
||||
for (hue = 0; hue < 6; hue++)
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
value = (hsd->hue[0] + hsd->hue[hue + 1]) * 255.0 / 360.0;
|
||||
if ((i + value) < 0)
|
||||
hue_transfer[hue][i] = 255 + (i + value);
|
||||
else if ((i + value) > 255)
|
||||
hue_transfer[hue][i] = i + value - 255;
|
||||
else
|
||||
hue_transfer[hue][i] = i + value;
|
||||
|
||||
/* Lightness */
|
||||
value = (hsd->lightness[0] + hsd->lightness[hue + 1]) * 127.0 / 100.0;
|
||||
value = CLAMP (value, -255, 255);
|
||||
if (value < 0)
|
||||
lightness_transfer[hue][i] = (unsigned char) ((i * (255 + value)) / 255);
|
||||
else
|
||||
lightness_transfer[hue][i] = (unsigned char) (i + ((255 - i) * value) / 255);
|
||||
|
||||
/* Saturation */
|
||||
value = (hsd->saturation[0] + hsd->saturation[hue + 1]) * 255.0 / 100.0;
|
||||
value = CLAMP (value, -255, 255);
|
||||
|
||||
/* This change affects the way saturation is computed. With the
|
||||
old code (different code for value < 0), increasing the
|
||||
saturation affected muted colors very much, and bright colors
|
||||
less. With the new code, it affects muted colors and bright
|
||||
colors more or less evenly. For enhancing the color in photos,
|
||||
the new behavior is exactly what you want. It's hard for me
|
||||
to imagine a case in which the old behavior is better.
|
||||
*/
|
||||
saturation_transfer[hue][i] = CLAMP ((i * (255 + value)) / 255, 0, 255);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
hue_saturation (PixelRegion *srcPR,
|
||||
PixelRegion *destPR,
|
||||
void *user_data)
|
||||
{
|
||||
HueSaturationDialog *hsd;
|
||||
unsigned char *src, *s;
|
||||
unsigned char *dest, *d;
|
||||
int alpha;
|
||||
int w, h;
|
||||
int r, g, b;
|
||||
int hue;
|
||||
|
||||
hsd = (HueSaturationDialog *) user_data;
|
||||
|
||||
/* Set the transfer arrays (for speed) */
|
||||
h = srcPR->h;
|
||||
src = srcPR->data;
|
||||
dest = destPR->data;
|
||||
alpha = (srcPR->bytes == 4) ? TRUE : FALSE;
|
||||
|
||||
while (h--)
|
||||
{
|
||||
w = srcPR->w;
|
||||
s = src;
|
||||
d = dest;
|
||||
while (w--)
|
||||
{
|
||||
r = s[RED_PIX];
|
||||
g = s[GREEN_PIX];
|
||||
b = s[BLUE_PIX];
|
||||
|
||||
gimp_rgb_to_hls_int (&r, &g, &b);
|
||||
|
||||
if (r < 43)
|
||||
hue = 0;
|
||||
else if (r < 85)
|
||||
hue = 1;
|
||||
else if (r < 128)
|
||||
hue = 2;
|
||||
else if (r < 171)
|
||||
hue = 3;
|
||||
else if (r < 213)
|
||||
hue = 4;
|
||||
else
|
||||
hue = 5;
|
||||
|
||||
r = hue_transfer[hue][r];
|
||||
g = lightness_transfer[hue][g];
|
||||
b = saturation_transfer[hue][b];
|
||||
|
||||
gimp_hls_to_rgb_int (&r, &g, &b);
|
||||
|
||||
d[RED_PIX] = r;
|
||||
d[GREEN_PIX] = g;
|
||||
d[BLUE_PIX] = b;
|
||||
|
||||
if (alpha)
|
||||
d[ALPHA_PIX] = s[ALPHA_PIX];
|
||||
|
||||
s += srcPR->bytes;
|
||||
d += destPR->bytes;
|
||||
}
|
||||
|
||||
src += srcPR->rowstride;
|
||||
dest += destPR->rowstride;
|
||||
}
|
||||
}
|
||||
|
||||
/* hue saturation action functions */
|
||||
|
||||
static void
|
||||
hue_saturation_control (Tool *tool,
|
||||
ToolAction action,
|
||||
GDisplay *gdisp)
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
case PAUSE:
|
||||
break;
|
||||
|
||||
case RESUME:
|
||||
break;
|
||||
|
||||
case HALT:
|
||||
hue_saturation_dialog_hide ();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Tool *
|
||||
tools_new_hue_saturation (void)
|
||||
{
|
||||
Tool * tool;
|
||||
HueSaturation * private;
|
||||
|
||||
/* The tool options */
|
||||
if (!hue_saturation_options)
|
||||
{
|
||||
hue_saturation_options = tool_options_new (_("Hue-Saturation"));
|
||||
tools_register (HUE_SATURATION, hue_saturation_options);
|
||||
}
|
||||
|
||||
tool = tools_new_tool (HUE_SATURATION);
|
||||
private = g_new0 (HueSaturation, 1);
|
||||
|
||||
tool->scroll_lock = TRUE; /* Disallow scrolling */
|
||||
tool->preserve = FALSE; /* Don't preserve on drawable change */
|
||||
|
||||
tool->private = (void *) private;
|
||||
|
||||
tool->control_func = hue_saturation_control;
|
||||
|
||||
return tool;
|
||||
}
|
||||
|
||||
void
|
||||
hue_saturation_dialog_hide (void)
|
||||
{
|
||||
if (hue_saturation_dialog)
|
||||
hue_saturation_cancel_callback (NULL, (gpointer) hue_saturation_dialog);
|
||||
}
|
||||
|
||||
void
|
||||
tools_free_hue_saturation (Tool *tool)
|
||||
{
|
||||
HueSaturation * color_bal;
|
||||
|
||||
color_bal = (HueSaturation *) tool->private;
|
||||
|
||||
/* Close the hue saturation dialog */
|
||||
hue_saturation_dialog_hide ();
|
||||
|
||||
g_free (color_bal);
|
||||
}
|
||||
|
||||
void
|
||||
hue_saturation_initialize (GDisplay *gdisp)
|
||||
{
|
||||
gint i;
|
||||
|
||||
if (! gimp_drawable_is_rgb (gimp_image_active_drawable (gdisp->gimage)))
|
||||
{
|
||||
g_message (_("Hue-Saturation operates only on RGB color drawables."));
|
||||
return;
|
||||
}
|
||||
|
||||
/* The "hue-saturation" dialog */
|
||||
if (!hue_saturation_dialog)
|
||||
hue_saturation_dialog = hue_saturation_dialog_new ();
|
||||
else
|
||||
if (!GTK_WIDGET_VISIBLE (hue_saturation_dialog->shell))
|
||||
gtk_widget_show (hue_saturation_dialog->shell);
|
||||
|
||||
for (i = 0; i < 7; i++)
|
||||
{
|
||||
hue_saturation_dialog->hue[i] = 0.0;
|
||||
hue_saturation_dialog->lightness[i] = 0.0;
|
||||
hue_saturation_dialog->saturation[i] = 0.0;
|
||||
}
|
||||
|
||||
hue_saturation_dialog->drawable = gimp_image_active_drawable (gdisp->gimage);
|
||||
hue_saturation_dialog->image_map =
|
||||
image_map_create (gdisp, hue_saturation_dialog->drawable);
|
||||
|
||||
hue_saturation_update (hue_saturation_dialog, ALL);
|
||||
}
|
||||
|
||||
void
|
||||
hue_saturation_free (void)
|
||||
{
|
||||
if (hue_saturation_dialog)
|
||||
{
|
||||
if (hue_saturation_dialog->image_map)
|
||||
{
|
||||
active_tool->preserve = TRUE;
|
||||
image_map_abort (hue_saturation_dialog->image_map);
|
||||
active_tool->preserve = FALSE;
|
||||
|
||||
hue_saturation_dialog->image_map = NULL;
|
||||
}
|
||||
gtk_widget_destroy (hue_saturation_dialog->shell);
|
||||
}
|
||||
}
|
||||
|
||||
/***************************/
|
||||
/* Hue-Saturation dialog */
|
||||
/***************************/
|
||||
|
||||
static HueSaturationDialog *
|
||||
hue_saturation_dialog_new (void)
|
||||
{
|
||||
HueSaturationDialog *hsd;
|
||||
GtkWidget *main_vbox;
|
||||
GtkWidget *main_hbox;
|
||||
GtkWidget *vbox;
|
||||
GtkWidget *hbox;
|
||||
GtkWidget *table;
|
||||
GtkWidget *label;
|
||||
GtkWidget *slider;
|
||||
GtkWidget *abox;
|
||||
GtkWidget *spinbutton;
|
||||
GtkWidget *toggle;
|
||||
GtkWidget *radio_button;
|
||||
GtkWidget *frame;
|
||||
GtkObject *data;
|
||||
GSList *group = NULL;
|
||||
gint i;
|
||||
|
||||
gchar *hue_partition_names[] =
|
||||
{
|
||||
N_("Master"),
|
||||
N_("R"),
|
||||
N_("Y"),
|
||||
N_("G"),
|
||||
N_("C"),
|
||||
N_("B"),
|
||||
N_("M")
|
||||
};
|
||||
|
||||
hsd = g_new (HueSaturationDialog, 1);
|
||||
hsd->hue_partition = ALL_HUES;
|
||||
hsd->preview = TRUE;
|
||||
|
||||
/* The shell and main vbox */
|
||||
hsd->shell = gimp_dialog_new (_("Hue-Saturation"), "hue_saturation",
|
||||
tools_help_func, NULL,
|
||||
GTK_WIN_POS_NONE,
|
||||
FALSE, TRUE, FALSE,
|
||||
|
||||
_("OK"), hue_saturation_ok_callback,
|
||||
hsd, NULL, NULL, TRUE, FALSE,
|
||||
_("Reset"), hue_saturation_reset_callback,
|
||||
hsd, NULL, NULL, FALSE, FALSE,
|
||||
_("Cancel"), hue_saturation_cancel_callback,
|
||||
hsd, NULL, NULL, FALSE, TRUE,
|
||||
|
||||
NULL);
|
||||
|
||||
main_vbox = gtk_vbox_new (FALSE, 4);
|
||||
gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 4);
|
||||
gtk_container_add (GTK_CONTAINER (GTK_DIALOG (hsd->shell)->vbox), main_vbox);
|
||||
|
||||
/* The main hbox containing hue partitions and sliders */
|
||||
main_hbox = gtk_hbox_new (FALSE, 12);
|
||||
gtk_box_pack_start (GTK_BOX (main_vbox), main_hbox, FALSE, FALSE, 0);
|
||||
|
||||
/* The table containing hue partitions */
|
||||
table = gtk_table_new (7, 2, FALSE);
|
||||
gtk_table_set_col_spacings (GTK_TABLE (table), 4);
|
||||
gtk_table_set_row_spacings (GTK_TABLE (table), 2);
|
||||
gtk_box_pack_start (GTK_BOX (main_hbox), table, FALSE, FALSE, 0);
|
||||
|
||||
/* the radio buttons for hue partitions */
|
||||
for (i = 0; i < 7; i++)
|
||||
{
|
||||
radio_button = gtk_radio_button_new_with_label (group, gettext (hue_partition_names[i]));
|
||||
group = gtk_radio_button_group (GTK_RADIO_BUTTON (radio_button));
|
||||
gtk_object_set_data (GTK_OBJECT (radio_button), "hue_partition",
|
||||
(gpointer) i);
|
||||
|
||||
if (!i)
|
||||
{
|
||||
gtk_table_attach (GTK_TABLE (table), radio_button, 0, 2, 0, 1,
|
||||
GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_table_attach (GTK_TABLE (table), radio_button, 0, 1, i, i + 1,
|
||||
GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
|
||||
|
||||
frame = gtk_frame_new (NULL);
|
||||
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
|
||||
gtk_table_attach (GTK_TABLE (table), frame, 1, 2, i, i + 1,
|
||||
GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
|
||||
hsd->hue_partition_da[i - 1] = gtk_preview_new (GTK_PREVIEW_COLOR);
|
||||
gtk_preview_size (GTK_PREVIEW (hsd->hue_partition_da[i - 1]),
|
||||
DA_WIDTH, DA_HEIGHT);
|
||||
gtk_widget_set_events (hsd->hue_partition_da[i - 1],
|
||||
HUE_PARTITION_MASK);
|
||||
gtk_signal_connect (GTK_OBJECT (hsd->hue_partition_da[i - 1]), "event",
|
||||
GTK_SIGNAL_FUNC (hue_saturation_hue_partition_events),
|
||||
hsd);
|
||||
gtk_container_add (GTK_CONTAINER (frame), hsd->hue_partition_da[i - 1]);
|
||||
|
||||
gtk_widget_show (hsd->hue_partition_da[i - 1]);
|
||||
gtk_widget_show (frame);
|
||||
}
|
||||
|
||||
gtk_signal_connect (GTK_OBJECT (radio_button), "toggled",
|
||||
GTK_SIGNAL_FUNC (hue_saturation_partition_callback),
|
||||
hsd);
|
||||
|
||||
gtk_widget_show (radio_button);
|
||||
}
|
||||
|
||||
gtk_widget_show (table);
|
||||
|
||||
/* The vbox for the table and preview toggle */
|
||||
vbox = gtk_vbox_new (FALSE, 4);
|
||||
gtk_box_pack_start (GTK_BOX (main_hbox), vbox, FALSE, FALSE, 0);
|
||||
|
||||
label = gtk_label_new (_("Hue / Lightness / Saturation Adjustments"));
|
||||
gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0.5);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
|
||||
gtk_widget_show (label);
|
||||
|
||||
/* The table containing sliders */
|
||||
table = gtk_table_new (3, 3, FALSE);
|
||||
gtk_table_set_col_spacings (GTK_TABLE (table), 4);
|
||||
gtk_table_set_row_spacings (GTK_TABLE (table), 2);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
|
||||
|
||||
/* Create the hue scale widget */
|
||||
label = gtk_label_new (_("Hue:"));
|
||||
gtk_misc_set_alignment (GTK_MISC (label), 1.0, 1.0);
|
||||
gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,
|
||||
GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
|
||||
|
||||
data = gtk_adjustment_new (0, -180, 180.0, 1.0, 1.0, 0.0);
|
||||
hsd->hue_data = GTK_ADJUSTMENT (data);
|
||||
|
||||
slider = gtk_hscale_new (hsd->hue_data);
|
||||
gtk_widget_set_usize (slider, SLIDER_WIDTH, -1);
|
||||
gtk_scale_set_digits (GTK_SCALE (slider), 0);
|
||||
gtk_scale_set_value_pos (GTK_SCALE (slider), GTK_POS_TOP);
|
||||
gtk_range_set_update_policy (GTK_RANGE (slider), GTK_UPDATE_DELAYED);
|
||||
gtk_table_attach (GTK_TABLE (table), slider, 1, 2, 0, 1,
|
||||
GTK_EXPAND | GTK_SHRINK | GTK_FILL,
|
||||
GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0);
|
||||
|
||||
abox = gtk_vbox_new (FALSE, 0);
|
||||
spinbutton = gtk_spin_button_new (hsd->hue_data, 1.0, 0);
|
||||
gtk_widget_set_usize (spinbutton, 74, -1);
|
||||
gtk_box_pack_end (GTK_BOX (abox), spinbutton, FALSE, FALSE, 0);
|
||||
gtk_table_attach (GTK_TABLE (table), abox, 2, 3, 0, 1,
|
||||
GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
|
||||
|
||||
gtk_signal_connect (GTK_OBJECT (hsd->hue_data), "value_changed",
|
||||
GTK_SIGNAL_FUNC (hue_saturation_hue_adjustment_update),
|
||||
hsd);
|
||||
|
||||
gtk_widget_show (label);
|
||||
gtk_widget_show (slider);
|
||||
gtk_widget_show (spinbutton);
|
||||
gtk_widget_show (abox);
|
||||
|
||||
/* Create the lightness scale widget */
|
||||
label = gtk_label_new (_("Lightness:"));
|
||||
gtk_misc_set_alignment (GTK_MISC (label), 1.0, 1.0);
|
||||
gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2,
|
||||
GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
|
||||
|
||||
data = gtk_adjustment_new (0, -100.0, 100.0, 1.0, 1.0, 0.0);
|
||||
hsd->lightness_data = GTK_ADJUSTMENT (data);
|
||||
|
||||
slider = gtk_hscale_new (hsd->lightness_data);
|
||||
gtk_widget_set_usize (slider, SLIDER_WIDTH, -1);
|
||||
gtk_scale_set_digits (GTK_SCALE (slider), 0);
|
||||
gtk_scale_set_value_pos (GTK_SCALE (slider), GTK_POS_TOP);
|
||||
gtk_range_set_update_policy (GTK_RANGE (slider), GTK_UPDATE_DELAYED);
|
||||
gtk_table_attach (GTK_TABLE (table), slider, 1, 2, 1, 2,
|
||||
GTK_EXPAND | GTK_SHRINK | GTK_FILL,
|
||||
GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0);
|
||||
|
||||
abox = gtk_vbox_new (FALSE, 0);
|
||||
spinbutton = gtk_spin_button_new (hsd->lightness_data, 1.0, 0);
|
||||
gtk_widget_set_usize (spinbutton, 75, -1);
|
||||
gtk_box_pack_end (GTK_BOX (abox), spinbutton, FALSE, FALSE, 0);
|
||||
gtk_table_attach (GTK_TABLE (table), abox, 2, 3, 1, 2,
|
||||
GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
|
||||
|
||||
gtk_signal_connect (GTK_OBJECT (hsd->lightness_data), "value_changed",
|
||||
GTK_SIGNAL_FUNC (hue_saturation_lightness_adjustment_update),
|
||||
hsd);
|
||||
|
||||
gtk_widget_show (label);
|
||||
gtk_widget_show (slider);
|
||||
gtk_widget_show (spinbutton);
|
||||
gtk_widget_show (abox);
|
||||
|
||||
/* Create the saturation scale widget */
|
||||
label = gtk_label_new (_("Saturation:"));
|
||||
gtk_misc_set_alignment (GTK_MISC (label), 1.0, 1.0);
|
||||
gtk_table_attach (GTK_TABLE (table), label, 0, 1, 2, 3,
|
||||
GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
|
||||
|
||||
data = gtk_adjustment_new (0, -100.0, 100.0, 1.0, 1.0, 0.0);
|
||||
hsd->saturation_data = GTK_ADJUSTMENT (data);
|
||||
|
||||
slider = gtk_hscale_new (hsd->saturation_data);
|
||||
gtk_widget_set_usize (slider, SLIDER_WIDTH, -1);
|
||||
gtk_scale_set_digits (GTK_SCALE (slider), 0);
|
||||
gtk_scale_set_value_pos (GTK_SCALE (slider), GTK_POS_TOP);
|
||||
gtk_range_set_update_policy (GTK_RANGE (slider), GTK_UPDATE_DELAYED);
|
||||
gtk_table_attach (GTK_TABLE (table), slider, 1, 2, 2, 3,
|
||||
GTK_EXPAND | GTK_SHRINK | GTK_FILL,
|
||||
GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0);
|
||||
|
||||
abox = gtk_vbox_new (FALSE, 0);
|
||||
spinbutton = gtk_spin_button_new (hsd->saturation_data, 1.0, 0);
|
||||
gtk_widget_set_usize (spinbutton, 75, -1);
|
||||
gtk_box_pack_end (GTK_BOX (abox), spinbutton, FALSE, FALSE, 0);
|
||||
gtk_table_attach (GTK_TABLE (table), abox, 2, 3, 2, 3,
|
||||
GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
|
||||
|
||||
gtk_signal_connect (GTK_OBJECT (hsd->saturation_data), "value_changed",
|
||||
GTK_SIGNAL_FUNC (hue_saturation_saturation_adjustment_update),
|
||||
hsd);
|
||||
|
||||
gtk_widget_show (label);
|
||||
gtk_widget_show (slider);
|
||||
gtk_widget_show (spinbutton);
|
||||
gtk_widget_show (abox);
|
||||
|
||||
gtk_widget_show (table);
|
||||
|
||||
/* Horizontal box for preview toggle button */
|
||||
hbox = gtk_hbox_new (FALSE, 4);
|
||||
gtk_box_pack_end (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
|
||||
|
||||
/* The preview toggle */
|
||||
toggle = gtk_check_button_new_with_label (_("Preview"));
|
||||
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), hsd->preview);
|
||||
gtk_box_pack_end (GTK_BOX (hbox), toggle, FALSE, FALSE, 0);
|
||||
|
||||
gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
|
||||
GTK_SIGNAL_FUNC (hue_saturation_preview_update),
|
||||
hsd);
|
||||
|
||||
gtk_widget_show (toggle);
|
||||
gtk_widget_show (hbox);
|
||||
|
||||
gtk_widget_show (vbox);
|
||||
gtk_widget_show (main_hbox);
|
||||
gtk_widget_show (main_vbox);
|
||||
gtk_widget_show (hsd->shell);
|
||||
|
||||
return hsd;
|
||||
}
|
||||
|
||||
static void
|
||||
hue_saturation_update (HueSaturationDialog *hsd,
|
||||
gint update)
|
||||
{
|
||||
gint i, j, b;
|
||||
gint rgb[3];
|
||||
guchar buf[DA_WIDTH * 3];
|
||||
|
||||
if (update & HUE_SLIDER)
|
||||
{
|
||||
gtk_adjustment_set_value (GTK_ADJUSTMENT (hsd->hue_data),
|
||||
hsd->hue[hsd->hue_partition]);
|
||||
}
|
||||
if (update & LIGHTNESS_SLIDER)
|
||||
{
|
||||
gtk_adjustment_set_value (GTK_ADJUSTMENT (hsd->lightness_data),
|
||||
hsd->lightness[hsd->hue_partition]);
|
||||
}
|
||||
if (update & SATURATION_SLIDER)
|
||||
{
|
||||
gtk_adjustment_set_value (GTK_ADJUSTMENT (hsd->saturation_data),
|
||||
hsd->saturation[hsd->hue_partition]);
|
||||
}
|
||||
|
||||
hue_saturation_calculate_transfers (hsd);
|
||||
|
||||
for (i = 0; i < 6; i++)
|
||||
{
|
||||
rgb[RED_PIX] = default_colors[i][RED_PIX];
|
||||
rgb[GREEN_PIX] = default_colors[i][GREEN_PIX];
|
||||
rgb[BLUE_PIX] = default_colors[i][BLUE_PIX];
|
||||
|
||||
gimp_rgb_to_hls_int (rgb, rgb + 1, rgb + 2);
|
||||
|
||||
rgb[RED_PIX] = hue_transfer[i][rgb[RED_PIX]];
|
||||
rgb[GREEN_PIX] = lightness_transfer[i][rgb[GREEN_PIX]];
|
||||
rgb[BLUE_PIX] = saturation_transfer[i][rgb[BLUE_PIX]];
|
||||
|
||||
gimp_hls_to_rgb_int (rgb, rgb + 1, rgb + 2);
|
||||
|
||||
for (j = 0; j < DA_WIDTH; j++)
|
||||
for (b = 0; b < 3; b++)
|
||||
buf[j * 3 + b] = (guchar) rgb[b];
|
||||
|
||||
for (j = 0; j < DA_HEIGHT; j++)
|
||||
gtk_preview_draw_row (GTK_PREVIEW (hsd->hue_partition_da[i]),
|
||||
buf, 0, j, DA_WIDTH);
|
||||
|
||||
if (update & DRAW)
|
||||
gtk_widget_draw (hsd->hue_partition_da[i], NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
hue_saturation_preview (HueSaturationDialog *hsd)
|
||||
{
|
||||
if (!hsd->image_map)
|
||||
{
|
||||
g_warning ("hue_saturation_preview(): No image map");
|
||||
return;
|
||||
}
|
||||
|
||||
active_tool->preserve = TRUE;
|
||||
image_map_apply (hsd->image_map, hue_saturation, (void *) hsd);
|
||||
active_tool->preserve = FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
hue_saturation_reset_callback (GtkWidget *widget,
|
||||
gpointer data)
|
||||
{
|
||||
HueSaturationDialog *hsd;
|
||||
|
||||
hsd = (HueSaturationDialog *) data;
|
||||
|
||||
hsd->hue[hsd->hue_partition] = 0.0;
|
||||
hsd->lightness[hsd->hue_partition] = 0.0;
|
||||
hsd->saturation[hsd->hue_partition] = 0.0;
|
||||
|
||||
hue_saturation_update (hsd, ALL);
|
||||
|
||||
if (hsd->preview)
|
||||
hue_saturation_preview (hsd);
|
||||
}
|
||||
|
||||
static void
|
||||
hue_saturation_ok_callback (GtkWidget *widget,
|
||||
gpointer data)
|
||||
{
|
||||
HueSaturationDialog *hsd;
|
||||
|
||||
hsd = (HueSaturationDialog *) data;
|
||||
|
||||
gimp_dialog_hide (hsd->shell);
|
||||
|
||||
active_tool->preserve = TRUE;
|
||||
|
||||
if (!hsd->preview)
|
||||
image_map_apply (hsd->image_map, hue_saturation, (gpointer) hsd);
|
||||
|
||||
if (hsd->image_map)
|
||||
image_map_commit (hsd->image_map);
|
||||
|
||||
active_tool->preserve = FALSE;
|
||||
|
||||
hsd->image_map = NULL;
|
||||
|
||||
active_tool->gdisp = NULL;
|
||||
active_tool->drawable = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
hue_saturation_cancel_callback (GtkWidget *widget,
|
||||
gpointer data)
|
||||
{
|
||||
HueSaturationDialog *hsd;
|
||||
|
||||
hsd = (HueSaturationDialog *) data;
|
||||
|
||||
gimp_dialog_hide (hsd->shell);
|
||||
|
||||
if (hsd->image_map)
|
||||
{
|
||||
active_tool->preserve = TRUE;
|
||||
image_map_abort (hsd->image_map);
|
||||
active_tool->preserve = FALSE;
|
||||
|
||||
gdisplays_flush ();
|
||||
hsd->image_map = NULL;
|
||||
}
|
||||
|
||||
active_tool->gdisp = NULL;
|
||||
active_tool->drawable = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
hue_saturation_partition_callback (GtkWidget *widget,
|
||||
gpointer data)
|
||||
{
|
||||
HueSaturationDialog *hsd;
|
||||
HueRange partition;
|
||||
|
||||
hsd = (HueSaturationDialog *) data;
|
||||
|
||||
partition = (HueRange) gtk_object_get_data (GTK_OBJECT (widget),
|
||||
"hue_partition");
|
||||
hsd->hue_partition = partition;
|
||||
|
||||
hue_saturation_update (hsd, ALL);
|
||||
}
|
||||
|
||||
static void
|
||||
hue_saturation_preview_update (GtkWidget *widget,
|
||||
gpointer data)
|
||||
{
|
||||
HueSaturationDialog *hsd;
|
||||
|
||||
hsd = (HueSaturationDialog *) data;
|
||||
|
||||
if (GTK_TOGGLE_BUTTON (widget)->active)
|
||||
{
|
||||
hsd->preview = TRUE;
|
||||
hue_saturation_preview (hsd);
|
||||
}
|
||||
else
|
||||
{
|
||||
hsd->preview = FALSE;
|
||||
if (hsd->image_map)
|
||||
{
|
||||
active_tool->preserve = TRUE;
|
||||
image_map_clear (hsd->image_map);
|
||||
active_tool->preserve = FALSE;
|
||||
gdisplays_flush ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
hue_saturation_hue_adjustment_update (GtkAdjustment *adjustment,
|
||||
gpointer data)
|
||||
{
|
||||
HueSaturationDialog *hsd;
|
||||
|
||||
hsd = (HueSaturationDialog *) data;
|
||||
|
||||
if (hsd->hue[hsd->hue_partition] != adjustment->value)
|
||||
{
|
||||
hsd->hue[hsd->hue_partition] = adjustment->value;
|
||||
hue_saturation_update (hsd, DRAW);
|
||||
|
||||
if (hsd->preview)
|
||||
hue_saturation_preview (hsd);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
hue_saturation_lightness_adjustment_update (GtkAdjustment *adjustment,
|
||||
gpointer data)
|
||||
{
|
||||
HueSaturationDialog *hsd;
|
||||
|
||||
hsd = (HueSaturationDialog *) data;
|
||||
|
||||
if (hsd->lightness[hsd->hue_partition] != adjustment->value)
|
||||
{
|
||||
hsd->lightness[hsd->hue_partition] = adjustment->value;
|
||||
hue_saturation_update (hsd, DRAW);
|
||||
|
||||
if (hsd->preview)
|
||||
hue_saturation_preview (hsd);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
hue_saturation_saturation_adjustment_update (GtkAdjustment *adjustment,
|
||||
gpointer data)
|
||||
{
|
||||
HueSaturationDialog *hsd;
|
||||
|
||||
hsd = (HueSaturationDialog *) data;
|
||||
|
||||
if (hsd->saturation[hsd->hue_partition] != adjustment->value)
|
||||
{
|
||||
hsd->saturation[hsd->hue_partition] = adjustment->value;
|
||||
hue_saturation_update (hsd, DRAW);
|
||||
|
||||
if (hsd->preview)
|
||||
hue_saturation_preview (hsd);
|
||||
}
|
||||
}
|
||||
|
||||
static gint
|
||||
hue_saturation_hue_partition_events (GtkWidget *widget,
|
||||
GdkEvent *event,
|
||||
HueSaturationDialog *hsd)
|
||||
{
|
||||
switch (event->type)
|
||||
{
|
||||
case GDK_EXPOSE:
|
||||
hue_saturation_update (hsd, HUE_PARTITION);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
|
@ -1,71 +0,0 @@
|
|||
/* 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.
|
||||
*/
|
||||
|
||||
#ifndef __HUE_SATURATION_H__
|
||||
#define __HUE_SATURATION_H__
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ALL_HUES,
|
||||
RED_HUES,
|
||||
YELLOW_HUES,
|
||||
GREEN_HUES,
|
||||
CYAN_HUES,
|
||||
BLUE_HUES,
|
||||
MAGENTA_HUES
|
||||
} HueRange;
|
||||
|
||||
typedef struct _HueSaturationDialog HueSaturationDialog;
|
||||
|
||||
struct _HueSaturationDialog
|
||||
{
|
||||
GtkWidget *shell;
|
||||
|
||||
GtkWidget *hue_partition_da[6];
|
||||
|
||||
GtkAdjustment *hue_data;
|
||||
GtkAdjustment *lightness_data;
|
||||
GtkAdjustment *saturation_data;
|
||||
|
||||
GimpDrawable *drawable;
|
||||
ImageMap image_map;
|
||||
|
||||
gdouble hue[7];
|
||||
gdouble lightness[7];
|
||||
gdouble saturation[7];
|
||||
|
||||
HueRange hue_partition;
|
||||
gboolean preview;
|
||||
};
|
||||
|
||||
|
||||
Tool * tools_new_hue_saturation (void);
|
||||
void tools_free_hue_saturation (Tool *tool);
|
||||
|
||||
void hue_saturation_initialize (GDisplay *gdisp);
|
||||
void hue_saturation_free (void);
|
||||
void hue_saturation_dialog_hide (void);
|
||||
void hue_saturation (PixelRegion *srcPR,
|
||||
PixelRegion *destPR,
|
||||
void *data);
|
||||
|
||||
void hue_saturation_calculate_transfers (HueSaturationDialog *hsd);
|
||||
|
||||
|
||||
#endif /* __HUE_SATURATION_H__ */
|
|
@ -34,7 +34,8 @@
|
|||
#include "info_dialog.h"
|
||||
#include "info_window.h"
|
||||
#include "scroll.h"
|
||||
#include "tools.h"
|
||||
|
||||
#include "tools/tools.h"
|
||||
|
||||
#include "pdb/procedural_db.h"
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue