mirror of https://github.com/GNOME/gimp.git
app/core/Makefile.am app/core/core-types.h app/core/gimpcurve-save.[ch]
2007-11-02 Michael Natterer <mitch@gimp.org> * app/core/Makefile.am * app/core/core-types.h * app/core/gimpcurve-save.[ch] * app/core/gimpcurve-load.[ch] * app/core/gimpcurve.[ch]: new GimpData subclass which keeps a curve as known from the curves tool. Pretty much unfinished, but can do everything that used to be done by base/curves.c and more. * app/base/curves.[ch]: stripped down to plain arrays of uchar (the actual curve) and the LUT setup function. All the rest is done by GimpCurve now. * app/tools/gimpcurvestool.[ch]: use an array of GimpCurves instead of the old Curves cruft. Use Curves only for the last step of creating the LUT. Pretty much unfinished migration here too. * tools/pdbgen/pdb/color.pdb: use a GimpCurve here too. * app/pdb/color_cmds.c: regenerated. svn path=/trunk/; revision=24041
This commit is contained in:
parent
1edac75743
commit
5dd23ae18b
22
ChangeLog
22
ChangeLog
|
@ -1,3 +1,25 @@
|
|||
2007-11-02 Michael Natterer <mitch@gimp.org>
|
||||
|
||||
* app/core/Makefile.am
|
||||
* app/core/core-types.h
|
||||
* app/core/gimpcurve-save.[ch]
|
||||
* app/core/gimpcurve-load.[ch]
|
||||
* app/core/gimpcurve.[ch]: new GimpData subclass which keeps a
|
||||
curve as known from the curves tool. Pretty much unfinished, but
|
||||
can do everything that used to be done by base/curves.c and more.
|
||||
|
||||
* app/base/curves.[ch]: stripped down to plain arrays of
|
||||
uchar (the actual curve) and the LUT setup function. All the rest
|
||||
is done by GimpCurve now.
|
||||
|
||||
* app/tools/gimpcurvestool.[ch]: use an array of GimpCurves
|
||||
instead of the old Curves cruft. Use Curves only for the last step
|
||||
of creating the LUT. Pretty much unfinished migration here too.
|
||||
|
||||
* tools/pdbgen/pdb/color.pdb: use a GimpCurve here too.
|
||||
|
||||
* app/pdb/color_cmds.c: regenerated.
|
||||
|
||||
2007-11-02 Sven Neumann <sven@gimp.org>
|
||||
|
||||
* app/widgets/gimpcairo-utils.c (gimp_cairo_set_source_color):
|
||||
|
|
|
@ -29,17 +29,6 @@
|
|||
#include "gimplut.h"
|
||||
|
||||
|
||||
|
||||
/* local function prototypes */
|
||||
|
||||
static void curves_plot_curve (Curves *curves,
|
||||
gint channel,
|
||||
gint p1,
|
||||
gint p2,
|
||||
gint p3,
|
||||
gint p4);
|
||||
|
||||
|
||||
/* public functions */
|
||||
|
||||
void
|
||||
|
@ -53,91 +42,10 @@ curves_init (Curves *curves)
|
|||
channel <= GIMP_HISTOGRAM_ALPHA;
|
||||
channel++)
|
||||
{
|
||||
curves->curve_type[channel] = GIMP_CURVE_SMOOTH;
|
||||
gint j;
|
||||
|
||||
curves_channel_reset (curves, channel);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
curves_channel_reset (Curves *curves,
|
||||
GimpHistogramChannel channel)
|
||||
{
|
||||
gint j;
|
||||
|
||||
g_return_if_fail (curves != NULL);
|
||||
|
||||
for (j = 0; j < 256; j++)
|
||||
curves->curve[channel][j] = j;
|
||||
|
||||
for (j = 0; j < CURVES_NUM_POINTS; j++)
|
||||
{
|
||||
curves->points[channel][j][0] = -1;
|
||||
curves->points[channel][j][1] = -1;
|
||||
}
|
||||
|
||||
curves->points[channel][0][0] = 0;
|
||||
curves->points[channel][0][1] = 0;
|
||||
curves->points[channel][CURVES_NUM_POINTS - 1][0] = 255;
|
||||
curves->points[channel][CURVES_NUM_POINTS - 1][1] = 255;
|
||||
}
|
||||
|
||||
void
|
||||
curves_calculate_curve (Curves *curves,
|
||||
GimpHistogramChannel channel)
|
||||
{
|
||||
gint i;
|
||||
gint points[CURVES_NUM_POINTS];
|
||||
gint num_pts;
|
||||
gint p1, p2, p3, p4;
|
||||
|
||||
g_return_if_fail (curves != NULL);
|
||||
|
||||
switch (curves->curve_type[channel])
|
||||
{
|
||||
case GIMP_CURVE_FREE:
|
||||
break;
|
||||
|
||||
case GIMP_CURVE_SMOOTH:
|
||||
/* cycle through the curves */
|
||||
num_pts = 0;
|
||||
for (i = 0; i < CURVES_NUM_POINTS; i++)
|
||||
if (curves->points[channel][i][0] != -1)
|
||||
points[num_pts++] = i;
|
||||
|
||||
/* Initialize boundary curve points */
|
||||
if (num_pts != 0)
|
||||
{
|
||||
for (i = 0; i < curves->points[channel][points[0]][0]; i++)
|
||||
curves->curve[channel][i] = curves->points[channel][points[0]][1];
|
||||
|
||||
for (i = curves->points[channel][points[num_pts - 1]][0];
|
||||
i < 256;
|
||||
i++)
|
||||
curves->curve[channel][i] =
|
||||
curves->points[channel][points[num_pts - 1]][1];
|
||||
}
|
||||
|
||||
for (i = 0; i < num_pts - 1; i++)
|
||||
{
|
||||
p1 = points[MAX (i - 1, 0)];
|
||||
p2 = points[i];
|
||||
p3 = points[i + 1];
|
||||
p4 = points[MIN (i + 2, num_pts - 1)];
|
||||
|
||||
curves_plot_curve (curves, channel, p1, p2, p3, p4);
|
||||
}
|
||||
|
||||
/* ensure that the control points are used exactly */
|
||||
for (i = 0; i < num_pts; i++)
|
||||
{
|
||||
gint x = curves->points[channel][points[i]][0];
|
||||
gint y = curves->points[channel][points[i]][1];
|
||||
|
||||
curves->curve[channel][x] = y;
|
||||
}
|
||||
|
||||
break;
|
||||
for (j = 0; j < 256; j++)
|
||||
curves->curve[channel][j] = j;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -191,115 +99,3 @@ curves_lut_func (Curves *curves,
|
|||
|
||||
return inten;
|
||||
}
|
||||
|
||||
|
||||
/* private functions */
|
||||
|
||||
/*
|
||||
* This function calculates the curve values between the control points
|
||||
* p2 and p3, taking the potentially existing neighbors p1 and p4 into
|
||||
* account.
|
||||
*
|
||||
* This function uses a cubic bezier curve for the individual segments and
|
||||
* calculates the necessary intermediate control points depending on the
|
||||
* neighbor curve control points.
|
||||
*/
|
||||
|
||||
static void
|
||||
curves_plot_curve (Curves *curves,
|
||||
gint channel,
|
||||
gint p1,
|
||||
gint p2,
|
||||
gint p3,
|
||||
gint p4)
|
||||
{
|
||||
gint i;
|
||||
gdouble x0, x3;
|
||||
gdouble y0, y1, y2, y3;
|
||||
gdouble dx, dy;
|
||||
gdouble y, t;
|
||||
gdouble slope;
|
||||
|
||||
/* the outer control points for the bezier curve. */
|
||||
x0 = curves->points[channel][p2][0];
|
||||
y0 = curves->points[channel][p2][1];
|
||||
x3 = curves->points[channel][p3][0];
|
||||
y3 = curves->points[channel][p3][1];
|
||||
|
||||
/*
|
||||
* the x values of the inner control points are fixed at
|
||||
* x1 = 1/3*x0 + 2/3*x3 and x2 = 2/3*x0 + 1/3*x3
|
||||
* this ensures that the x values increase linearily with the
|
||||
* parameter t and enables us to skip the calculation of the x
|
||||
* values altogehter - just calculate y(t) evenly spaced.
|
||||
*/
|
||||
|
||||
dx = x3 - x0;
|
||||
dy = y3 - y0;
|
||||
|
||||
g_return_if_fail (dx > 0);
|
||||
|
||||
if (p1 == p2 && p3 == p4)
|
||||
{
|
||||
/* No information about the neighbors,
|
||||
* calculate y1 and y2 to get a straight line
|
||||
*/
|
||||
y1 = y0 + dy / 3.0;
|
||||
y2 = y0 + dy * 2.0 / 3.0;
|
||||
}
|
||||
else if (p1 == p2 && p3 != p4)
|
||||
{
|
||||
/* only the right neighbor is available. Make the tangent at the
|
||||
* right endpoint parallel to the line between the left endpoint
|
||||
* and the right neighbor. Then point the tangent at the left towards
|
||||
* the control handle of the right tangent, to ensure that the curve
|
||||
* does not have an inflection point.
|
||||
*/
|
||||
slope = (curves->points[channel][p4][1] - y0) /
|
||||
(curves->points[channel][p4][0] - x0);
|
||||
|
||||
y2 = y3 - slope * dx / 3.0;
|
||||
y1 = y0 + (y2 - y0) / 2.0;
|
||||
}
|
||||
else if (p1 != p2 && p3 == p4)
|
||||
{
|
||||
/* see previous case */
|
||||
slope = (y3 - curves->points[channel][p1][1]) /
|
||||
(x3 - curves->points[channel][p1][0]);
|
||||
|
||||
y1 = y0 + slope * dx / 3.0;
|
||||
y2 = y3 + (y1 - y3) / 2.0;
|
||||
}
|
||||
else /* (p1 != p2 && p3 != p4) */
|
||||
{
|
||||
/* Both neighbors are available. Make the tangents at the endpoints
|
||||
* parallel to the line between the opposite endpoint and the adjacent
|
||||
* neighbor.
|
||||
*/
|
||||
slope = (y3 - curves->points[channel][p1][1]) /
|
||||
(x3 - curves->points[channel][p1][0]);
|
||||
|
||||
y1 = y0 + slope * dx / 3.0;
|
||||
|
||||
slope = (curves->points[channel][p4][1] - y0) /
|
||||
(curves->points[channel][p4][0] - x0);
|
||||
|
||||
y2 = y3 - slope * dx / 3.0;
|
||||
}
|
||||
|
||||
/*
|
||||
* finally calculate the y(t) values for the given bezier values. We can
|
||||
* use homogenously distributed values for t, since x(t) increases linearily.
|
||||
*/
|
||||
for (i = 0; i <= dx; i++)
|
||||
{
|
||||
t = i / dx;
|
||||
y = y0 * (1-t) * (1-t) * (1-t) +
|
||||
3 * y1 * (1-t) * (1-t) * t +
|
||||
3 * y2 * (1-t) * t * t +
|
||||
y3 * t * t * t;
|
||||
|
||||
curves->curve[channel][ROUND(x0) + i] = CLAMP0255 (ROUND (y));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,25 +19,18 @@
|
|||
#ifndef __CURVES_H__
|
||||
#define __CURVES_H__
|
||||
|
||||
#define CURVES_NUM_POINTS 17
|
||||
|
||||
struct _Curves
|
||||
{
|
||||
GimpCurveType curve_type[5];
|
||||
gint points[5][CURVES_NUM_POINTS][2];
|
||||
guchar curve[5][256];
|
||||
guchar curve[5][256];
|
||||
};
|
||||
|
||||
|
||||
void curves_init (Curves *curves);
|
||||
void curves_channel_reset (Curves *curves,
|
||||
GimpHistogramChannel channel);
|
||||
void curves_calculate_curve (Curves *curves,
|
||||
GimpHistogramChannel channel);
|
||||
gfloat curves_lut_func (Curves *curves,
|
||||
gint nchannels,
|
||||
gint channel,
|
||||
gfloat value);
|
||||
void curves_init (Curves *curves);
|
||||
gfloat curves_lut_func (Curves *curves,
|
||||
gint nchannels,
|
||||
gint channel,
|
||||
gfloat value);
|
||||
|
||||
|
||||
#endif /* __CURVES_H__ */
|
||||
|
|
|
@ -90,6 +90,12 @@ libappcore_a_sources = \
|
|||
gimpcontext.h \
|
||||
gimpcoords.c \
|
||||
gimpcoords.h \
|
||||
gimpcurve.c \
|
||||
gimpcurve.h \
|
||||
gimpcurve-load.c \
|
||||
gimpcurve-load.h \
|
||||
gimpcurve-save.c \
|
||||
gimpcurve-save.h \
|
||||
gimpdashpattern.c \
|
||||
gimpdashpattern.h \
|
||||
gimpdata.c \
|
||||
|
|
|
@ -95,6 +95,7 @@ typedef struct _GimpGradient GimpGradient;
|
|||
typedef struct _GimpPattern GimpPattern;
|
||||
typedef struct _GimpPatternClipboard GimpPatternClipboard;
|
||||
typedef struct _GimpPalette GimpPalette;
|
||||
typedef struct _GimpCurve GimpCurve;
|
||||
|
||||
|
||||
/* drawable objects */
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
/* GIMP - The GNU 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 <errno.h>
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <glib/gstdio.h>
|
||||
|
||||
#include "libgimpbase/gimpbase.h"
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
#include "libgimpbase/gimpwin32-io.h"
|
||||
#endif
|
||||
|
||||
#include "core-types.h"
|
||||
|
||||
#include "gimpcurve.h"
|
||||
#include "gimpcurve-load.h"
|
||||
|
||||
#include "gimp-intl.h"
|
||||
|
||||
|
||||
GList *
|
||||
gimp_curve_load (const gchar *filename,
|
||||
GError **error)
|
||||
{
|
||||
GimpCurve *curve;
|
||||
FILE *file;
|
||||
|
||||
g_return_val_if_fail (filename != NULL, NULL);
|
||||
g_return_val_if_fail (g_path_is_absolute (filename), NULL);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||
|
||||
file = g_fopen (filename, "rb");
|
||||
|
||||
if (! file)
|
||||
{
|
||||
g_set_error (error, GIMP_DATA_ERROR, GIMP_DATA_ERROR_OPEN,
|
||||
_("Could not open '%s' for reading: %s"),
|
||||
gimp_filename_to_utf8 (filename), g_strerror (errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* load curves */
|
||||
|
||||
fclose (file);
|
||||
|
||||
return NULL;
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/* GIMP - The GNU 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 __GIMP_CURVE_LOAD_H__
|
||||
#define __GIMP_CURVE_LOAD_H__
|
||||
|
||||
|
||||
#define GIMP_CURVE_FILE_EXTENSION ".curve"
|
||||
|
||||
|
||||
GList * gimp_curve_load (const gchar *filename,
|
||||
GError **error);
|
||||
|
||||
|
||||
#endif /* __GIMP_CURVE_LOAD_H__ */
|
|
@ -0,0 +1,59 @@
|
|||
/* GIMP - The GNU 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 <errno.h>
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <glib/gstdio.h>
|
||||
|
||||
#include "libgimpbase/gimpbase.h"
|
||||
|
||||
#include "core-types.h"
|
||||
|
||||
#include "gimpcurve.h"
|
||||
#include "gimpcurve-save.h"
|
||||
|
||||
#include "gimp-intl.h"
|
||||
|
||||
|
||||
gboolean
|
||||
gimp_curve_save (GimpData *data,
|
||||
GError **error)
|
||||
{
|
||||
GimpCurve *curve = GIMP_CURVE (data);
|
||||
FILE *file;
|
||||
|
||||
file = g_fopen (data->filename, "wb");
|
||||
|
||||
if (! file)
|
||||
{
|
||||
g_set_error (error, GIMP_DATA_ERROR, GIMP_DATA_ERROR_OPEN,
|
||||
_("Could not open '%s' for writing: %s"),
|
||||
gimp_filename_to_utf8 (data->filename),
|
||||
g_strerror (errno));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* write curve */
|
||||
|
||||
fclose (file);
|
||||
|
||||
return TRUE;
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
/* GIMP - The GNU 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 __GIMP_CURVE_SAVE_H__
|
||||
#define __GIMP_CURVE_SAVE_H__
|
||||
|
||||
|
||||
/* don't call this function directly, use gimp_data_save() instead */
|
||||
gboolean gimp_curve_save (GimpData *data,
|
||||
GError **error);
|
||||
|
||||
|
||||
#endif /* __GIMP_CURVE_SAVE_H__ */
|
|
@ -0,0 +1,594 @@
|
|||
/* GIMP - The GNU 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 <glib-object.h>
|
||||
|
||||
#include "libgimpmath/gimpmath.h"
|
||||
|
||||
#include "core-types.h"
|
||||
|
||||
#include "gimpcurve.h"
|
||||
#include "gimpcurve-load.h"
|
||||
#include "gimpcurve-save.h"
|
||||
|
||||
#include "gimp-intl.h"
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_CURVE_TYPE
|
||||
};
|
||||
|
||||
|
||||
/* local function prototypes */
|
||||
|
||||
static void gimp_curve_finalize (GObject *object);
|
||||
static void gimp_curve_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec);
|
||||
static void gimp_curve_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec);
|
||||
|
||||
static gint64 gimp_curve_get_memsize (GimpObject *object,
|
||||
gint64 *gui_size);
|
||||
|
||||
static void gimp_curve_get_preview_size (GimpViewable *viewable,
|
||||
gint size,
|
||||
gboolean popup,
|
||||
gboolean dot_for_dot,
|
||||
gint *width,
|
||||
gint *height);
|
||||
static gboolean gimp_curve_get_popup_size (GimpViewable *viewable,
|
||||
gint width,
|
||||
gint height,
|
||||
gboolean dot_for_dot,
|
||||
gint *popup_width,
|
||||
gint *popup_height);
|
||||
static TempBuf * gimp_curve_get_new_preview (GimpViewable *viewable,
|
||||
GimpContext *context,
|
||||
gint width,
|
||||
gint height);
|
||||
static gchar * gimp_curve_get_description (GimpViewable *viewable,
|
||||
gchar **tooltip);
|
||||
static gchar * gimp_curve_get_extension (GimpData *data);
|
||||
static GimpData * gimp_curve_duplicate (GimpData *data);
|
||||
|
||||
static void gimp_curve_plot (GimpCurve *curve,
|
||||
gint p1,
|
||||
gint p2,
|
||||
gint p3,
|
||||
gint p4);
|
||||
|
||||
|
||||
G_DEFINE_TYPE (GimpCurve, gimp_curve, GIMP_TYPE_DATA)
|
||||
|
||||
#define parent_class gimp_curve_parent_class
|
||||
|
||||
|
||||
static void
|
||||
gimp_curve_class_init (GimpCurveClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GimpObjectClass *gimp_object_class = GIMP_OBJECT_CLASS (klass);
|
||||
GimpViewableClass *viewable_class = GIMP_VIEWABLE_CLASS (klass);
|
||||
GimpDataClass *data_class = GIMP_DATA_CLASS (klass);
|
||||
|
||||
object_class->finalize = gimp_curve_finalize;
|
||||
object_class->set_property = gimp_curve_set_property;
|
||||
object_class->get_property = gimp_curve_get_property;
|
||||
|
||||
gimp_object_class->get_memsize = gimp_curve_get_memsize;
|
||||
|
||||
viewable_class->default_stock_id = "FIXME";
|
||||
viewable_class->get_preview_size = gimp_curve_get_preview_size;
|
||||
viewable_class->get_popup_size = gimp_curve_get_popup_size;
|
||||
viewable_class->get_new_preview = gimp_curve_get_new_preview;
|
||||
viewable_class->get_description = gimp_curve_get_description;
|
||||
|
||||
data_class->save = gimp_curve_save;
|
||||
data_class->get_extension = gimp_curve_get_extension;
|
||||
data_class->duplicate = gimp_curve_duplicate;
|
||||
|
||||
g_object_class_install_property (object_class, PROP_CURVE_TYPE,
|
||||
g_param_spec_enum ("curve-type", NULL, NULL,
|
||||
GIMP_TYPE_CURVE_TYPE,
|
||||
GIMP_CURVE_SMOOTH,
|
||||
GIMP_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT));
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_curve_init (GimpCurve *curve)
|
||||
{
|
||||
gimp_curve_reset (curve, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_curve_finalize (GObject *object)
|
||||
{
|
||||
GimpCurve *curve = GIMP_CURVE (object);
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_curve_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GimpCurve *curve = GIMP_CURVE (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_CURVE_TYPE:
|
||||
gimp_curve_set_curve_type (curve, g_value_get_enum (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_curve_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GimpCurve *curve = GIMP_CURVE (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_CURVE_TYPE:
|
||||
g_value_set_enum (value, curve->curve_type);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static gint64
|
||||
gimp_curve_get_memsize (GimpObject *object,
|
||||
gint64 *gui_size)
|
||||
{
|
||||
GimpCurve *curve = GIMP_CURVE (object);
|
||||
gint64 memsize = 0;
|
||||
|
||||
return memsize + GIMP_OBJECT_CLASS (parent_class)->get_memsize (object,
|
||||
gui_size);
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_curve_get_preview_size (GimpViewable *viewable,
|
||||
gint size,
|
||||
gboolean popup,
|
||||
gboolean dot_for_dot,
|
||||
gint *width,
|
||||
gint *height)
|
||||
{
|
||||
*width = size;
|
||||
*height = size;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gimp_curve_get_popup_size (GimpViewable *viewable,
|
||||
gint width,
|
||||
gint height,
|
||||
gboolean dot_for_dot,
|
||||
gint *popup_width,
|
||||
gint *popup_height)
|
||||
{
|
||||
GimpCurve *curve = GIMP_CURVE (viewable);
|
||||
|
||||
*popup_width = width * 2;
|
||||
*popup_height = height * 2;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static TempBuf *
|
||||
gimp_curve_get_new_preview (GimpViewable *viewable,
|
||||
GimpContext *context,
|
||||
gint width,
|
||||
gint height)
|
||||
{
|
||||
GimpCurve *curve = GIMP_CURVE (viewable);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static gchar *
|
||||
gimp_curve_get_description (GimpViewable *viewable,
|
||||
gchar **tooltip)
|
||||
{
|
||||
GimpCurve *curve = GIMP_CURVE (viewable);
|
||||
|
||||
return g_strdup_printf ("%s", GIMP_OBJECT (curve)->name);
|
||||
}
|
||||
|
||||
|
||||
static gchar *
|
||||
gimp_curve_get_extension (GimpData *data)
|
||||
{
|
||||
return GIMP_CURVE_FILE_EXTENSION;
|
||||
}
|
||||
|
||||
static GimpData *
|
||||
gimp_curve_duplicate (GimpData *data)
|
||||
{
|
||||
GimpCurve *curve = GIMP_CURVE (data);
|
||||
GimpCurve *new;
|
||||
|
||||
new = g_object_new (GIMP_TYPE_CURVE,
|
||||
"curve-type", curve->curve_type,
|
||||
NULL);
|
||||
|
||||
return GIMP_DATA (new);
|
||||
}
|
||||
|
||||
|
||||
/* public functions */
|
||||
|
||||
GimpData *
|
||||
gimp_curve_new (const gchar *name)
|
||||
{
|
||||
g_return_val_if_fail (name != NULL, NULL);
|
||||
g_return_val_if_fail (*name != '\0', NULL);
|
||||
|
||||
return g_object_new (GIMP_TYPE_CURVE,
|
||||
"name", name,
|
||||
NULL);
|
||||
}
|
||||
|
||||
GimpData *
|
||||
gimp_curve_get_standard (void)
|
||||
{
|
||||
static GimpData *standard_curve = NULL;
|
||||
|
||||
if (! standard_curve)
|
||||
{
|
||||
standard_curve = gimp_curve_new ("Standard");
|
||||
|
||||
standard_curve->dirty = FALSE;
|
||||
gimp_data_make_internal (standard_curve);
|
||||
|
||||
g_object_ref (standard_curve);
|
||||
}
|
||||
|
||||
return standard_curve;
|
||||
}
|
||||
|
||||
void
|
||||
gimp_curve_reset (GimpCurve *curve,
|
||||
gboolean reset_type)
|
||||
{
|
||||
gint i;
|
||||
|
||||
g_return_if_fail (GIMP_IS_CURVE (curve));
|
||||
|
||||
if (reset_type)
|
||||
curve->curve_type = GIMP_CURVE_SMOOTH;
|
||||
|
||||
for (i = 0; i < 256; i++)
|
||||
curve->curve[i] = i;
|
||||
|
||||
for (i = 0; i < GIMP_CURVE_NUM_POINTS; i++)
|
||||
{
|
||||
curve->points[i][0] = -1;
|
||||
curve->points[i][1] = -1;
|
||||
}
|
||||
|
||||
curve->points[0][0] = 0;
|
||||
curve->points[0][1] = 0;
|
||||
curve->points[GIMP_CURVE_NUM_POINTS - 1][0] = 255;
|
||||
curve->points[GIMP_CURVE_NUM_POINTS - 1][1] = 255;
|
||||
|
||||
g_object_freeze_notify (G_OBJECT (curve));
|
||||
|
||||
/* g_object_notify (G_OBJECT (curve), "points"); */
|
||||
/* g_object_notify (G_OBJECT (curve), "curve"); */
|
||||
g_object_notify (G_OBJECT (curve), "curve-type");
|
||||
|
||||
g_object_thaw_notify (G_OBJECT (curve));
|
||||
}
|
||||
|
||||
void
|
||||
gimp_curve_set_curve_type (GimpCurve *curve,
|
||||
GimpCurveType curve_type)
|
||||
{
|
||||
g_return_if_fail (GIMP_IS_CURVE (curve));
|
||||
|
||||
if (curve->curve_type != curve_type)
|
||||
{
|
||||
curve->curve_type = curve_type;
|
||||
|
||||
if (curve_type == GIMP_CURVE_SMOOTH)
|
||||
{
|
||||
gint i;
|
||||
gint32 index;
|
||||
|
||||
/* pick representative points from the curve and make them
|
||||
* control points
|
||||
*/
|
||||
for (i = 0; i <= 8; i++)
|
||||
{
|
||||
index = CLAMP0255 (i * 32);
|
||||
|
||||
curve->points[i * 2][0] = index;
|
||||
curve->points[i * 2][1] = curve->curve[index];
|
||||
}
|
||||
}
|
||||
|
||||
gimp_curve_calculate (curve);
|
||||
|
||||
g_object_notify (G_OBJECT (curve), "curve-type");
|
||||
gimp_data_dirty (GIMP_DATA (curve));
|
||||
}
|
||||
}
|
||||
|
||||
GimpCurveType
|
||||
gimp_curve_get_curve_type (GimpCurve *curve)
|
||||
{
|
||||
g_return_val_if_fail (GIMP_IS_CURVE (curve), GIMP_CURVE_SMOOTH);
|
||||
|
||||
return curve->curve_type;
|
||||
}
|
||||
|
||||
#define MIN_DISTANCE 8
|
||||
|
||||
gint
|
||||
gimp_curve_get_closest_point (GimpCurve *curve,
|
||||
gint x)
|
||||
{
|
||||
gint closest_point = 0;
|
||||
gint distance = G_MAXINT;
|
||||
gint i;
|
||||
|
||||
g_return_val_if_fail (GIMP_IS_CURVE (curve), 0);
|
||||
|
||||
for (i = 0; i < GIMP_CURVE_NUM_POINTS; i++)
|
||||
{
|
||||
if (curve->points[i][0] != -1)
|
||||
if (abs (x - curve->points[i][0]) < distance)
|
||||
{
|
||||
distance = abs (x - curve->points[i][0]);
|
||||
closest_point = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (distance > MIN_DISTANCE)
|
||||
closest_point = (x + 8) / 16;
|
||||
|
||||
return closest_point;
|
||||
}
|
||||
|
||||
void
|
||||
gimp_curve_set_point (GimpCurve *curve,
|
||||
gint point,
|
||||
gint x,
|
||||
gint y)
|
||||
{
|
||||
g_return_if_fail (GIMP_IS_CURVE (curve));
|
||||
|
||||
if (curve->curve_type == GIMP_CURVE_FREE)
|
||||
return;
|
||||
|
||||
curve->points[point][0] = x;
|
||||
curve->points[point][1] = y;
|
||||
|
||||
gimp_curve_calculate (curve);
|
||||
}
|
||||
|
||||
void
|
||||
gimp_curve_move_point (GimpCurve *curve,
|
||||
gint point,
|
||||
gint y)
|
||||
{
|
||||
g_return_if_fail (GIMP_IS_CURVE (curve));
|
||||
|
||||
if (curve->curve_type == GIMP_CURVE_FREE)
|
||||
return;
|
||||
|
||||
curve->points[point][1] = y;
|
||||
|
||||
gimp_curve_calculate (curve);
|
||||
}
|
||||
|
||||
void
|
||||
gimp_curve_get_uchar (GimpCurve *curve,
|
||||
guchar *dest_array)
|
||||
{
|
||||
g_return_if_fail (GIMP_IS_CURVE (curve));
|
||||
g_return_if_fail (dest_array != NULL);
|
||||
|
||||
memcpy (dest_array, curve->curve, 256);
|
||||
}
|
||||
|
||||
|
||||
/* private functions */
|
||||
|
||||
void
|
||||
gimp_curve_calculate (GimpCurve *curve)
|
||||
{
|
||||
gint i;
|
||||
gint points[GIMP_CURVE_NUM_POINTS];
|
||||
gint num_pts;
|
||||
gint p1, p2, p3, p4;
|
||||
|
||||
switch (curve->curve_type)
|
||||
{
|
||||
case GIMP_CURVE_SMOOTH:
|
||||
/* cycle through the curves */
|
||||
num_pts = 0;
|
||||
for (i = 0; i < GIMP_CURVE_NUM_POINTS; i++)
|
||||
if (curve->points[i][0] != -1)
|
||||
points[num_pts++] = i;
|
||||
|
||||
/* Initialize boundary curve points */
|
||||
if (num_pts != 0)
|
||||
{
|
||||
for (i = 0; i < curve->points[points[0]][0]; i++)
|
||||
curve->curve[i] = curve->points[points[0]][1];
|
||||
|
||||
for (i = curve->points[points[num_pts - 1]][0]; i < 256; i++)
|
||||
curve->curve[i] = curve->points[points[num_pts - 1]][1];
|
||||
}
|
||||
|
||||
for (i = 0; i < num_pts - 1; i++)
|
||||
{
|
||||
p1 = points[MAX (i - 1, 0)];
|
||||
p2 = points[i];
|
||||
p3 = points[i + 1];
|
||||
p4 = points[MIN (i + 2, num_pts - 1)];
|
||||
|
||||
gimp_curve_plot (curve, p1, p2, p3, p4);
|
||||
}
|
||||
|
||||
/* ensure that the control points are used exactly */
|
||||
for (i = 0; i < num_pts; i++)
|
||||
{
|
||||
gint x = curve->points[points[i]][0];
|
||||
gint y = curve->points[points[i]][1];
|
||||
|
||||
curve->curve[x] = y;
|
||||
}
|
||||
break;
|
||||
|
||||
case GIMP_CURVE_FREE:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This function calculates the curve values between the control points
|
||||
* p2 and p3, taking the potentially existing neighbors p1 and p4 into
|
||||
* account.
|
||||
*
|
||||
* This function uses a cubic bezier curve for the individual segments and
|
||||
* calculates the necessary intermediate control points depending on the
|
||||
* neighbor curve control points.
|
||||
*/
|
||||
static void
|
||||
gimp_curve_plot (GimpCurve *curve,
|
||||
gint p1,
|
||||
gint p2,
|
||||
gint p3,
|
||||
gint p4)
|
||||
{
|
||||
gint i;
|
||||
gdouble x0, x3;
|
||||
gdouble y0, y1, y2, y3;
|
||||
gdouble dx, dy;
|
||||
gdouble y, t;
|
||||
gdouble slope;
|
||||
|
||||
/* the outer control points for the bezier curve. */
|
||||
x0 = curve->points[p2][0];
|
||||
y0 = curve->points[p2][1];
|
||||
x3 = curve->points[p3][0];
|
||||
y3 = curve->points[p3][1];
|
||||
|
||||
/*
|
||||
* the x values of the inner control points are fixed at
|
||||
* x1 = 1/3*x0 + 2/3*x3 and x2 = 2/3*x0 + 1/3*x3
|
||||
* this ensures that the x values increase linearily with the
|
||||
* parameter t and enables us to skip the calculation of the x
|
||||
* values altogehter - just calculate y(t) evenly spaced.
|
||||
*/
|
||||
|
||||
dx = x3 - x0;
|
||||
dy = y3 - y0;
|
||||
|
||||
g_return_if_fail (dx > 0);
|
||||
|
||||
if (p1 == p2 && p3 == p4)
|
||||
{
|
||||
/* No information about the neighbors,
|
||||
* calculate y1 and y2 to get a straight line
|
||||
*/
|
||||
y1 = y0 + dy / 3.0;
|
||||
y2 = y0 + dy * 2.0 / 3.0;
|
||||
}
|
||||
else if (p1 == p2 && p3 != p4)
|
||||
{
|
||||
/* only the right neighbor is available. Make the tangent at the
|
||||
* right endpoint parallel to the line between the left endpoint
|
||||
* and the right neighbor. Then point the tangent at the left towards
|
||||
* the control handle of the right tangent, to ensure that the curve
|
||||
* does not have an inflection point.
|
||||
*/
|
||||
slope = (curve->points[p4][1] - y0) /
|
||||
(curve->points[p4][0] - x0);
|
||||
|
||||
y2 = y3 - slope * dx / 3.0;
|
||||
y1 = y0 + (y2 - y0) / 2.0;
|
||||
}
|
||||
else if (p1 != p2 && p3 == p4)
|
||||
{
|
||||
/* see previous case */
|
||||
slope = (y3 - curve->points[p1][1]) /
|
||||
(x3 - curve->points[p1][0]);
|
||||
|
||||
y1 = y0 + slope * dx / 3.0;
|
||||
y2 = y3 + (y1 - y3) / 2.0;
|
||||
}
|
||||
else /* (p1 != p2 && p3 != p4) */
|
||||
{
|
||||
/* Both neighbors are available. Make the tangents at the endpoints
|
||||
* parallel to the line between the opposite endpoint and the adjacent
|
||||
* neighbor.
|
||||
*/
|
||||
slope = (y3 - curve->points[p1][1]) /
|
||||
(x3 - curve->points[p1][0]);
|
||||
|
||||
y1 = y0 + slope * dx / 3.0;
|
||||
|
||||
slope = (curve->points[p4][1] - y0) /
|
||||
(curve->points[p4][0] - x0);
|
||||
|
||||
y2 = y3 - slope * dx / 3.0;
|
||||
}
|
||||
|
||||
/*
|
||||
* finally calculate the y(t) values for the given bezier values. We can
|
||||
* use homogenously distributed values for t, since x(t) increases linearily.
|
||||
*/
|
||||
for (i = 0; i <= dx; i++)
|
||||
{
|
||||
t = i / dx;
|
||||
y = y0 * (1-t) * (1-t) * (1-t) +
|
||||
3 * y1 * (1-t) * (1-t) * t +
|
||||
3 * y2 * (1-t) * t * t +
|
||||
y3 * t * t * t;
|
||||
|
||||
curve->curve[ROUND(x0) + i] = CLAMP0255 (ROUND (y));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
/* GIMP - The GNU 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 __GIMP_CURVE_H__
|
||||
#define __GIMP_CURVE_H__
|
||||
|
||||
|
||||
#include "gimpdata.h"
|
||||
|
||||
|
||||
#define GIMP_CURVE_NUM_POINTS 17 /* TODO: get rid of this limit */
|
||||
|
||||
|
||||
#define GIMP_TYPE_CURVE (gimp_curve_get_type ())
|
||||
#define GIMP_CURVE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_CURVE, GimpCurve))
|
||||
#define GIMP_CURVE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_CURVE, GimpCurveClass))
|
||||
#define GIMP_IS_CURVE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_CURVE))
|
||||
#define GIMP_IS_CURVE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_CURVE))
|
||||
#define GIMP_CURVE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_CURVE, GimpCurveClass))
|
||||
|
||||
|
||||
typedef struct _GimpCurveClass GimpCurveClass;
|
||||
|
||||
struct _GimpCurve
|
||||
{
|
||||
GimpData parent_instance;
|
||||
|
||||
GimpCurveType curve_type;
|
||||
|
||||
gint points[GIMP_CURVE_NUM_POINTS][2];
|
||||
guchar curve[256];
|
||||
|
||||
};
|
||||
|
||||
struct _GimpCurveClass
|
||||
{
|
||||
GimpDataClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
GType gimp_curve_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GimpData * gimp_curve_new (const gchar *name);
|
||||
GimpData * gimp_curve_get_standard (void);
|
||||
|
||||
void gimp_curve_reset (GimpCurve *curve,
|
||||
gboolean reset_type);
|
||||
|
||||
void gimp_curve_set_curve_type (GimpCurve *curve,
|
||||
GimpCurveType curve_type);
|
||||
GimpCurveType gimp_curve_get_curve_type (GimpCurve *curve);
|
||||
|
||||
gint gimp_curve_get_closest_point (GimpCurve *curve,
|
||||
gint x);
|
||||
void gimp_curve_set_point (GimpCurve *curve,
|
||||
gint point,
|
||||
gint x,
|
||||
gint y);
|
||||
void gimp_curve_move_point (GimpCurve *curve,
|
||||
gint point,
|
||||
gint y);
|
||||
|
||||
void gimp_curve_get_uchar (GimpCurve *curve,
|
||||
guchar *dest_array);
|
||||
|
||||
void gimp_curve_calculate (GimpCurve *curve);
|
||||
|
||||
|
||||
#endif /* __GIMP_CURVE_H__ */
|
|
@ -40,6 +40,7 @@
|
|||
#include "base/pixel-region.h"
|
||||
#include "base/threshold.h"
|
||||
#include "core/gimp.h"
|
||||
#include "core/gimpcurve.h"
|
||||
#include "core/gimpdrawable-desaturate.h"
|
||||
#include "core/gimpdrawable-equalize.h"
|
||||
#include "core/gimpdrawable-histogram.h"
|
||||
|
@ -394,6 +395,7 @@ curves_spline_invoker (GimpProcedure *procedure,
|
|||
/* The application should occur only within selection bounds */
|
||||
if (gimp_drawable_mask_intersect (drawable, &x, &y, &width, &height))
|
||||
{
|
||||
GimpCurve *curve;
|
||||
Curves c;
|
||||
gint j;
|
||||
PixelRegion srcPR, destPR;
|
||||
|
@ -408,17 +410,23 @@ curves_spline_invoker (GimpProcedure *procedure,
|
|||
|
||||
curves_init (&c);
|
||||
|
||||
curve = GIMP_CURVE (gimp_curve_new ("curves_spline"));
|
||||
|
||||
/* unset the last point */
|
||||
c.points[channel][CURVES_NUM_POINTS - 1][0] = -1;
|
||||
c.points[channel][CURVES_NUM_POINTS - 1][1] = -1;
|
||||
curve->points[GIMP_CURVE_NUM_POINTS - 1][0] = -1;
|
||||
curve->points[GIMP_CURVE_NUM_POINTS - 1][1] = -1;
|
||||
|
||||
for (j = 0; j < num_points / 2; j++)
|
||||
{
|
||||
c.points[channel][j][0] = control_pts[j * 2];
|
||||
c.points[channel][j][1] = control_pts[j * 2 + 1];
|
||||
curve->points[j][0] = control_pts[j * 2];
|
||||
curve->points[j][1] = control_pts[j * 2 + 1];
|
||||
}
|
||||
|
||||
curves_calculate_curve (&c, channel);
|
||||
gimp_curve_calculate (curve);
|
||||
|
||||
gimp_curve_get_uchar (curve, c.curve[channel]);
|
||||
|
||||
g_object_unref (curve);
|
||||
|
||||
gimp_lut_setup (lut,
|
||||
(GimpLutFunc) curves_lut_func,
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include "base/gimplut.h"
|
||||
|
||||
#include "core/gimp.h"
|
||||
#include "core/gimpcurve.h"
|
||||
#include "core/gimpdrawable.h"
|
||||
#include "core/gimpdrawable-histogram.h"
|
||||
#include "core/gimpimage.h"
|
||||
|
@ -67,7 +68,6 @@
|
|||
#define GRAPH_SIZE 256
|
||||
#define BAR_SIZE 12
|
||||
#define RADIUS 4
|
||||
#define MIN_DISTANCE 8
|
||||
|
||||
|
||||
/* local function prototypes */
|
||||
|
@ -106,8 +106,6 @@ static gboolean gimp_curves_tool_settings_load (GimpImageMapTool *image_map
|
|||
static gboolean gimp_curves_tool_settings_save (GimpImageMapTool *image_map_tool,
|
||||
gpointer fp);
|
||||
|
||||
static void curves_add_point (GimpCurvesTool *tool,
|
||||
gint channel);
|
||||
static gboolean curves_key_press (GimpCurvesTool *tool,
|
||||
GdkEventKey *kevent);
|
||||
static void curves_update (GimpCurvesTool *tool,
|
||||
|
@ -194,12 +192,12 @@ gimp_curves_tool_init (GimpCurvesTool *tool)
|
|||
{
|
||||
gint i;
|
||||
|
||||
tool->curves = g_slice_new0 (Curves);
|
||||
for (i = 0; i < G_N_ELEMENTS (tool->curve); i++)
|
||||
tool->curve[i] = GIMP_CURVE (gimp_curve_new ("curves tool"));
|
||||
|
||||
tool->lut = gimp_lut_new ();
|
||||
tool->channel = GIMP_HISTOGRAM_VALUE;
|
||||
|
||||
curves_init (tool->curves);
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (tool->col_value); i++)
|
||||
tool->col_value[i] = -1;
|
||||
|
||||
|
@ -211,8 +209,11 @@ static void
|
|||
gimp_curves_tool_finalize (GObject *object)
|
||||
{
|
||||
GimpCurvesTool *tool = GIMP_CURVES_TOOL (object);
|
||||
gint i;
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (tool->curve); i++)
|
||||
g_object_unref (tool->curve[i]);
|
||||
|
||||
g_slice_free (Curves, tool->curves);
|
||||
gimp_lut_free (tool->lut);
|
||||
|
||||
if (tool->hist)
|
||||
|
@ -243,6 +244,7 @@ gimp_curves_tool_initialize (GimpTool *tool,
|
|||
{
|
||||
GimpCurvesTool *c_tool = GIMP_CURVES_TOOL (tool);
|
||||
GimpDrawable *drawable = gimp_image_get_active_drawable (display->image);
|
||||
gint i;
|
||||
|
||||
if (! drawable)
|
||||
return FALSE;
|
||||
|
@ -254,11 +256,12 @@ gimp_curves_tool_initialize (GimpTool *tool,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (c_tool->curve); i++)
|
||||
gimp_curve_reset (c_tool->curve[i], TRUE);
|
||||
|
||||
if (! c_tool->hist)
|
||||
c_tool->hist = gimp_histogram_new ();
|
||||
|
||||
curves_init (c_tool->curves);
|
||||
|
||||
c_tool->channel = GIMP_HISTOGRAM_VALUE;
|
||||
c_tool->color = gimp_drawable_is_rgb (drawable);
|
||||
c_tool->alpha = gimp_drawable_has_alpha (drawable);
|
||||
|
@ -304,8 +307,17 @@ gimp_curves_tool_button_release (GimpTool *tool,
|
|||
|
||||
if (state & GDK_SHIFT_MASK)
|
||||
{
|
||||
curves_add_point (c_tool, c_tool->channel);
|
||||
curves_calculate_curve (c_tool->curves, c_tool->channel);
|
||||
GimpCurve *curve = c_tool->curve[c_tool->channel];
|
||||
|
||||
c_tool->selected =
|
||||
gimp_curve_get_closest_point (curve,
|
||||
c_tool->col_value[c_tool->channel]);
|
||||
|
||||
gimp_curve_set_point (curve,
|
||||
c_tool->selected,
|
||||
c_tool->col_value[c_tool->channel],
|
||||
curve->curve[c_tool->col_value[c_tool->channel]]);
|
||||
|
||||
curves_update (c_tool, GRAPH | XRANGE);
|
||||
}
|
||||
else if (state & GDK_CONTROL_MASK)
|
||||
|
@ -314,8 +326,16 @@ gimp_curves_tool_button_release (GimpTool *tool,
|
|||
|
||||
for (i = 0; i < 5; i++)
|
||||
{
|
||||
curves_add_point (c_tool, i);
|
||||
curves_calculate_curve (c_tool->curves, c_tool->channel);
|
||||
GimpCurve *curve = c_tool->curve[i];
|
||||
|
||||
c_tool->selected =
|
||||
gimp_curve_get_closest_point (curve,
|
||||
c_tool->col_value[i]);
|
||||
|
||||
gimp_curve_set_point (curve,
|
||||
c_tool->selected,
|
||||
c_tool->col_value[i],
|
||||
curve->curve[c_tool->col_value[i]]);
|
||||
}
|
||||
|
||||
curves_update (c_tool, GRAPH | XRANGE);
|
||||
|
@ -396,57 +416,16 @@ gimp_curves_tool_color_picked (GimpColorTool *color_tool,
|
|||
curves_update (tool, GRAPH);
|
||||
}
|
||||
|
||||
static void
|
||||
curves_add_point (GimpCurvesTool *tool,
|
||||
gint channel)
|
||||
{
|
||||
Curves *curves = tool->curves;
|
||||
gint closest_point = 0;
|
||||
gint distance;
|
||||
gint curvex;
|
||||
gint i;
|
||||
|
||||
switch (curves->curve_type[channel])
|
||||
{
|
||||
case GIMP_CURVE_SMOOTH:
|
||||
curvex = tool->col_value[channel];
|
||||
distance = G_MAXINT;
|
||||
|
||||
for (i = 0; i < CURVES_NUM_POINTS; i++)
|
||||
{
|
||||
if (curves->points[channel][i][0] != -1)
|
||||
if (abs (curvex -curves->points[channel][i][0]) < distance)
|
||||
{
|
||||
distance = abs (curvex - curves->points[channel][i][0]);
|
||||
closest_point = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (distance > MIN_DISTANCE)
|
||||
closest_point = (curvex + 8) / 16;
|
||||
|
||||
curves->points[channel][closest_point][0] = curvex;
|
||||
curves->points[channel][closest_point][1] = curves->curve[channel][curvex];
|
||||
|
||||
tool->selected = closest_point;
|
||||
break;
|
||||
|
||||
case GIMP_CURVE_FREE:
|
||||
/* do nothing for free form curves */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
curves_key_press (GimpCurvesTool *tool,
|
||||
GdkEventKey *kevent)
|
||||
{
|
||||
Curves *curves = tool->curves;
|
||||
gint i = tool->selected;
|
||||
gint y = curves->points[tool->channel][i][1];
|
||||
gboolean update = FALSE;
|
||||
GimpCurve *curve = tool->curve[tool->channel];
|
||||
gint i = tool->selected;
|
||||
gint y = curve->points[i][1];
|
||||
gboolean update = FALSE;
|
||||
|
||||
if (tool->grabbed || curves->curve_type[tool->channel] == GIMP_CURVE_FREE)
|
||||
if (tool->grabbed || curve->curve_type == GIMP_CURVE_FREE)
|
||||
return FALSE;
|
||||
|
||||
switch (kevent->keyval)
|
||||
|
@ -454,7 +433,7 @@ curves_key_press (GimpCurvesTool *tool,
|
|||
case GDK_Left:
|
||||
for (i = i - 1; i >= 0 && !update; i--)
|
||||
{
|
||||
if (curves->points[tool->channel][i][0] != -1)
|
||||
if (curve->points[i][0] != -1)
|
||||
{
|
||||
tool->selected = i;
|
||||
update = TRUE;
|
||||
|
@ -463,9 +442,9 @@ curves_key_press (GimpCurvesTool *tool,
|
|||
break;
|
||||
|
||||
case GDK_Right:
|
||||
for (i = i + 1; i < CURVES_NUM_POINTS && !update; i++)
|
||||
for (i = i + 1; i < GIMP_CURVE_NUM_POINTS && !update; i++)
|
||||
{
|
||||
if (curves->points[tool->channel][i][0] != -1)
|
||||
if (curve->points[i][0] != -1)
|
||||
{
|
||||
tool->selected = i;
|
||||
update = TRUE;
|
||||
|
@ -477,8 +456,8 @@ curves_key_press (GimpCurvesTool *tool,
|
|||
if (y < 255)
|
||||
{
|
||||
y = y + (kevent->state & GDK_SHIFT_MASK ? 16 : 1);
|
||||
curves->points[tool->channel][i][1] = MIN (y, 255);
|
||||
curves_calculate_curve (curves, tool->channel);
|
||||
|
||||
gimp_curve_move_point (curve, i, CLAMP0255 (y));
|
||||
update = TRUE;
|
||||
}
|
||||
break;
|
||||
|
@ -487,8 +466,8 @@ curves_key_press (GimpCurvesTool *tool,
|
|||
if (y > 0)
|
||||
{
|
||||
y = y - (kevent->state & GDK_SHIFT_MASK ? 16 : 1);
|
||||
curves->points[tool->channel][i][1] = MAX (y, 0);
|
||||
curves_calculate_curve (curves, tool->channel);
|
||||
|
||||
gimp_curve_move_point (curve, i, CLAMP0255 (y));
|
||||
update = TRUE;
|
||||
}
|
||||
break;
|
||||
|
@ -510,10 +489,15 @@ static void
|
|||
gimp_curves_tool_map (GimpImageMapTool *image_map_tool)
|
||||
{
|
||||
GimpCurvesTool *tool = GIMP_CURVES_TOOL (image_map_tool);
|
||||
Curves curves;
|
||||
gint i;
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (tool->curve); i++)
|
||||
gimp_curve_get_uchar (tool->curve[i], curves.curve[i]);
|
||||
|
||||
gimp_lut_setup (tool->lut,
|
||||
(GimpLutFunc) curves_lut_func,
|
||||
tool->curves,
|
||||
&curves,
|
||||
gimp_drawable_bytes (image_map_tool->drawable));
|
||||
|
||||
gimp_image_map_apply (image_map_tool->image_map,
|
||||
|
@ -727,7 +711,9 @@ gimp_curves_tool_reset (GimpImageMapTool *image_map_tool)
|
|||
for (channel = GIMP_HISTOGRAM_VALUE;
|
||||
channel <= GIMP_HISTOGRAM_ALPHA;
|
||||
channel++)
|
||||
curves_channel_reset (tool->curves, channel);
|
||||
{
|
||||
gimp_curve_reset (tool->curve[channel], FALSE);
|
||||
}
|
||||
|
||||
curves_update (tool, XRANGE | GRAPH);
|
||||
}
|
||||
|
@ -737,26 +723,25 @@ gimp_curves_tool_settings_load (GimpImageMapTool *image_map_tool,
|
|||
gpointer fp,
|
||||
GError **error)
|
||||
{
|
||||
GimpCurvesTool *tool = GIMP_CURVES_TOOL (image_map_tool);
|
||||
Curves *curves = tool->curves;
|
||||
FILE *file = fp;
|
||||
GimpCurvesTool *tool = GIMP_CURVES_TOOL (image_map_tool);
|
||||
FILE *file = fp;
|
||||
gint i, j;
|
||||
gint fields;
|
||||
gchar buf[50];
|
||||
gint index[5][CURVES_NUM_POINTS];
|
||||
gint value[5][CURVES_NUM_POINTS];
|
||||
gint index[5][GIMP_CURVE_NUM_POINTS];
|
||||
gint value[5][GIMP_CURVE_NUM_POINTS];
|
||||
|
||||
if (! fgets (buf, sizeof (buf), file) ||
|
||||
strcmp (buf, "# GIMP Curves File\n") != 0)
|
||||
{
|
||||
g_set_error (error, GIMP_CONFIG_ERROR, GIMP_CONFIG_ERROR_PARSE,
|
||||
_("not a GIMP Levels file"));
|
||||
_("not a GIMP Curves file"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
for (i = 0; i < 5; i++)
|
||||
{
|
||||
for (j = 0; j < CURVES_NUM_POINTS; j++)
|
||||
for (j = 0; j < GIMP_CURVE_NUM_POINTS; j++)
|
||||
{
|
||||
fields = fscanf (file, "%d %d ", &index[i][j], &value[i][j]);
|
||||
if (fields != 2)
|
||||
|
@ -772,17 +757,18 @@ gimp_curves_tool_settings_load (GimpImageMapTool *image_map_tool,
|
|||
|
||||
for (i = 0; i < 5; i++)
|
||||
{
|
||||
curves->curve_type[i] = GIMP_CURVE_SMOOTH;
|
||||
GimpCurve *curve = tool->curve[i];
|
||||
|
||||
for (j = 0; j < CURVES_NUM_POINTS; j++)
|
||||
curve->curve_type = GIMP_CURVE_SMOOTH;
|
||||
|
||||
for (j = 0; j < GIMP_CURVE_NUM_POINTS; j++)
|
||||
{
|
||||
curves->points[i][j][0] = index[i][j];
|
||||
curves->points[i][j][1] = value[i][j];
|
||||
curve->points[j][0] = index[i][j];
|
||||
curve->points[j][1] = value[i][j];
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < 5; i++)
|
||||
curves_calculate_curve (curves, i);
|
||||
gimp_curve_calculate (curve);
|
||||
}
|
||||
|
||||
curves_update (tool, ALL);
|
||||
|
||||
|
@ -796,33 +782,35 @@ static gboolean
|
|||
gimp_curves_tool_settings_save (GimpImageMapTool *image_map_tool,
|
||||
gpointer fp)
|
||||
{
|
||||
GimpCurvesTool *tool = GIMP_CURVES_TOOL (image_map_tool);
|
||||
Curves *curves = tool->curves;
|
||||
FILE *file = fp;
|
||||
GimpCurvesTool *tool = GIMP_CURVES_TOOL (image_map_tool);
|
||||
FILE *file = fp;
|
||||
gint i, j;
|
||||
gint32 index;
|
||||
|
||||
for (i = 0; i < 5; i++)
|
||||
if (curves->curve_type[i] == GIMP_CURVE_FREE)
|
||||
{
|
||||
/* pick representative points from the curve
|
||||
and make them control points */
|
||||
for (j = 0; j <= 8; j++)
|
||||
{
|
||||
index = CLAMP0255 (j * 32);
|
||||
curves->points[i][j * 2][0] = index;
|
||||
curves->points[i][j * 2][1] = curves->curve[i][index];
|
||||
}
|
||||
}
|
||||
|
||||
fprintf (file, "# GIMP Curves File\n");
|
||||
|
||||
for (i = 0; i < 5; i++)
|
||||
{
|
||||
for (j = 0; j < CURVES_NUM_POINTS; j++)
|
||||
GimpCurve *curve = tool->curve[i];
|
||||
|
||||
if (curve->curve_type == GIMP_CURVE_FREE)
|
||||
{
|
||||
/* pick representative points from the curve and make them
|
||||
* control points
|
||||
*/
|
||||
for (j = 0; j <= 8; j++)
|
||||
{
|
||||
index = CLAMP0255 (j * 32);
|
||||
|
||||
curve->points[j * 2][0] = index;
|
||||
curve->points[j * 2][1] = curve->curve[index];
|
||||
}
|
||||
}
|
||||
|
||||
for (j = 0; j < GIMP_CURVE_NUM_POINTS; j++)
|
||||
fprintf (file, "%d %d ",
|
||||
curves->points[i][j][0],
|
||||
curves->points[i][j][1]);
|
||||
curve->points[j][0],
|
||||
curve->points[j][1]);
|
||||
|
||||
fprintf (file, "\n");
|
||||
}
|
||||
|
@ -835,8 +823,7 @@ static void
|
|||
curves_update (GimpCurvesTool *tool,
|
||||
gint update)
|
||||
{
|
||||
GimpHistogramChannel channel;
|
||||
Curves *curves = tool->curves;
|
||||
GimpHistogramChannel channel;
|
||||
|
||||
if (tool->color)
|
||||
{
|
||||
|
@ -862,18 +849,18 @@ curves_update (GimpCurvesTool *tool,
|
|||
case GIMP_HISTOGRAM_ALPHA:
|
||||
case GIMP_HISTOGRAM_RGB:
|
||||
gimp_color_bar_set_buffers (GIMP_COLOR_BAR (tool->xrange),
|
||||
curves->curve[tool->channel],
|
||||
curves->curve[tool->channel],
|
||||
curves->curve[tool->channel]);
|
||||
tool->curve[tool->channel]->curve,
|
||||
tool->curve[tool->channel]->curve,
|
||||
tool->curve[tool->channel]->curve);
|
||||
break;
|
||||
|
||||
case GIMP_HISTOGRAM_RED:
|
||||
case GIMP_HISTOGRAM_GREEN:
|
||||
case GIMP_HISTOGRAM_BLUE:
|
||||
gimp_color_bar_set_buffers (GIMP_COLOR_BAR (tool->xrange),
|
||||
curves->curve[GIMP_HISTOGRAM_RED],
|
||||
curves->curve[GIMP_HISTOGRAM_GREEN],
|
||||
curves->curve[GIMP_HISTOGRAM_BLUE]);
|
||||
tool->curve[GIMP_HISTOGRAM_RED]->curve,
|
||||
tool->curve[GIMP_HISTOGRAM_GREEN]->curve,
|
||||
tool->curve[GIMP_HISTOGRAM_BLUE]->curve);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -901,7 +888,7 @@ curves_channel_callback (GtkWidget *widget,
|
|||
tool->channel = (tool->channel == GIMP_HISTOGRAM_ALPHA) ? 1 : 0;
|
||||
|
||||
gimp_int_radio_group_set_active (GTK_RADIO_BUTTON (tool->curve_type),
|
||||
tool->curves->curve_type[tool->channel]);
|
||||
tool->curve[tool->channel]->curve_type);
|
||||
|
||||
curves_update (tool, ALL);
|
||||
}
|
||||
|
@ -913,7 +900,7 @@ curves_channel_reset_callback (GtkWidget *widget,
|
|||
{
|
||||
tool->grabbed = FALSE;
|
||||
|
||||
curves_channel_reset (tool->curves, tool->channel);
|
||||
gimp_curve_reset (tool->curve[tool->channel], FALSE);
|
||||
|
||||
curves_update (tool, XRANGE | GRAPH);
|
||||
|
||||
|
@ -951,32 +938,13 @@ static void
|
|||
curves_curve_type_callback (GtkWidget *widget,
|
||||
GimpCurvesTool *tool)
|
||||
{
|
||||
GimpCurveType curve_type;
|
||||
Curves *curves = tool->curves;
|
||||
GimpCurveType curve_type;
|
||||
|
||||
gimp_radio_button_update (widget, &curve_type);
|
||||
|
||||
if (curves->curve_type[tool->channel] != curve_type)
|
||||
if (tool->curve[tool->channel]->curve_type != curve_type)
|
||||
{
|
||||
curves->curve_type[tool->channel] = curve_type;
|
||||
|
||||
if (curve_type == GIMP_CURVE_SMOOTH)
|
||||
{
|
||||
gint i;
|
||||
gint32 index;
|
||||
|
||||
/* pick representative points from the curve
|
||||
* and make them control points
|
||||
*/
|
||||
for (i = 0; i <= 8; i++)
|
||||
{
|
||||
index = CLAMP0255 (i * 32);
|
||||
curves->points[tool->channel][i * 2][0] = index;
|
||||
curves->points[tool->channel][i * 2][1] = curves->curve[tool->channel][index];
|
||||
}
|
||||
}
|
||||
|
||||
curves_calculate_curve (curves, tool->channel);
|
||||
gimp_curve_set_curve_type (tool->curve[tool->channel], curve_type);
|
||||
|
||||
curves_update (tool, XRANGE | GRAPH);
|
||||
|
||||
|
@ -1009,16 +977,13 @@ curves_graph_events (GtkWidget *widget,
|
|||
GdkEvent *event,
|
||||
GimpCurvesTool *tool)
|
||||
{
|
||||
Curves *curves = tool->curves;
|
||||
GdkEventButton *bevent;
|
||||
GdkEventMotion *mevent;
|
||||
GimpCurve *curve = tool->curve[tool->channel];
|
||||
GimpCursorType new_cursor = GDK_X_CURSOR;
|
||||
gint i;
|
||||
gint tx, ty;
|
||||
gint x, y;
|
||||
gint width, height;
|
||||
gint closest_point;
|
||||
gint distance;
|
||||
gint x1, x2, y1, y2;
|
||||
|
||||
width = widget->allocation.width - 2 * RADIUS;
|
||||
|
@ -1033,173 +998,163 @@ curves_graph_events (GtkWidget *widget,
|
|||
x = CLAMP0255 (x);
|
||||
y = CLAMP0255 (y);
|
||||
|
||||
distance = G_MAXINT;
|
||||
for (i = 0, closest_point = 0; i < CURVES_NUM_POINTS; i++)
|
||||
{
|
||||
if (curves->points[tool->channel][i][0] != -1)
|
||||
if (abs (x - curves->points[tool->channel][i][0]) < distance)
|
||||
{
|
||||
distance = abs (x - curves->points[tool->channel][i][0]);
|
||||
closest_point = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (distance > MIN_DISTANCE)
|
||||
closest_point = (x + 8) / 16;
|
||||
closest_point = gimp_curve_get_closest_point (curve, x);
|
||||
|
||||
switch (event->type)
|
||||
{
|
||||
case GDK_BUTTON_PRESS:
|
||||
bevent = (GdkEventButton *) event;
|
||||
{
|
||||
GdkEventButton *bevent = (GdkEventButton *) event;
|
||||
|
||||
if (bevent->button != 1)
|
||||
return TRUE;
|
||||
if (bevent->button != 1)
|
||||
return TRUE;
|
||||
|
||||
tool->grabbed = TRUE;
|
||||
tool->grabbed = TRUE;
|
||||
|
||||
curves_set_cursor (tool, GDK_TCROSS);
|
||||
curves_set_cursor (tool, GDK_TCROSS);
|
||||
|
||||
switch (curves->curve_type[tool->channel])
|
||||
{
|
||||
case GIMP_CURVE_SMOOTH:
|
||||
/* determine the leftmost and rightmost points */
|
||||
tool->leftmost = -1;
|
||||
for (i = closest_point - 1; i >= 0; i--)
|
||||
if (curves->points[tool->channel][i][0] != -1)
|
||||
{
|
||||
tool->leftmost = curves->points[tool->channel][i][0];
|
||||
break;
|
||||
}
|
||||
switch (curve->curve_type)
|
||||
{
|
||||
case GIMP_CURVE_SMOOTH:
|
||||
/* determine the leftmost and rightmost points */
|
||||
tool->leftmost = -1;
|
||||
for (i = closest_point - 1; i >= 0; i--)
|
||||
if (curve->points[i][0] != -1)
|
||||
{
|
||||
tool->leftmost = curve->points[i][0];
|
||||
break;
|
||||
}
|
||||
|
||||
tool->rightmost = 256;
|
||||
for (i = closest_point + 1; i < CURVES_NUM_POINTS; i++)
|
||||
if (curves->points[tool->channel][i][0] != -1)
|
||||
{
|
||||
tool->rightmost = curves->points[tool->channel][i][0];
|
||||
break;
|
||||
}
|
||||
tool->rightmost = 256;
|
||||
for (i = closest_point + 1; i < GIMP_CURVE_NUM_POINTS; i++)
|
||||
if (curve->points[i][0] != -1)
|
||||
{
|
||||
tool->rightmost = curve->points[i][0];
|
||||
break;
|
||||
}
|
||||
|
||||
tool->selected = closest_point;
|
||||
curves->points[tool->channel][tool->selected][0] = x;
|
||||
curves->points[tool->channel][tool->selected][1] = 255 - y;
|
||||
tool->selected = closest_point;
|
||||
|
||||
gimp_image_map_tool_preview (GIMP_IMAGE_MAP_TOOL (tool));
|
||||
break;
|
||||
gimp_curve_set_point (curve, tool->selected, x, 255 - y);
|
||||
|
||||
case GIMP_CURVE_FREE:
|
||||
curves->curve[tool->channel][x] = 255 - y;
|
||||
tool->selected = x;
|
||||
tool->last = y;
|
||||
break;
|
||||
}
|
||||
gimp_image_map_tool_preview (GIMP_IMAGE_MAP_TOOL (tool));
|
||||
break;
|
||||
|
||||
curves_calculate_curve (curves, tool->channel);
|
||||
curves_update (tool, XRANGE | GRAPH);
|
||||
case GIMP_CURVE_FREE:
|
||||
curve->curve[x] = 255 - y;
|
||||
tool->selected = x;
|
||||
tool->last = y;
|
||||
break;
|
||||
}
|
||||
|
||||
if (! GTK_WIDGET_HAS_FOCUS (widget))
|
||||
gtk_widget_grab_focus (widget);
|
||||
curves_update (tool, XRANGE | GRAPH);
|
||||
|
||||
if (! GTK_WIDGET_HAS_FOCUS (widget))
|
||||
gtk_widget_grab_focus (widget);
|
||||
|
||||
}
|
||||
return TRUE;
|
||||
|
||||
case GDK_BUTTON_RELEASE:
|
||||
bevent = (GdkEventButton *) event;
|
||||
{
|
||||
GdkEventButton *bevent = (GdkEventButton *) event;
|
||||
|
||||
if (bevent->button != 1)
|
||||
return TRUE;
|
||||
if (bevent->button != 1)
|
||||
return TRUE;
|
||||
|
||||
tool->grabbed = FALSE;
|
||||
tool->grabbed = FALSE;
|
||||
|
||||
curves_set_cursor (tool, GDK_FLEUR);
|
||||
curves_set_cursor (tool, GDK_FLEUR);
|
||||
|
||||
if (curves->curve_type[tool->channel] == GIMP_CURVE_FREE)
|
||||
gimp_image_map_tool_preview (GIMP_IMAGE_MAP_TOOL (tool));
|
||||
if (curve->curve_type == GIMP_CURVE_FREE)
|
||||
gimp_image_map_tool_preview (GIMP_IMAGE_MAP_TOOL (tool));
|
||||
|
||||
}
|
||||
return TRUE;
|
||||
|
||||
case GDK_MOTION_NOTIFY:
|
||||
mevent = (GdkEventMotion *) event;
|
||||
{
|
||||
GdkEventMotion *mevent = (GdkEventMotion *) event;
|
||||
|
||||
switch (curves->curve_type[tool->channel])
|
||||
{
|
||||
case GIMP_CURVE_SMOOTH:
|
||||
/* If no point is grabbed... */
|
||||
if (! tool->grabbed)
|
||||
{
|
||||
if (curves->points[tool->channel][closest_point][0] != -1)
|
||||
new_cursor = GDK_FLEUR;
|
||||
else
|
||||
switch (curve->curve_type)
|
||||
{
|
||||
case GIMP_CURVE_SMOOTH:
|
||||
/* If no point is grabbed... */
|
||||
if (! tool->grabbed)
|
||||
{
|
||||
if (curve->points[closest_point][0] != -1)
|
||||
new_cursor = GDK_FLEUR;
|
||||
else
|
||||
new_cursor = GDK_TCROSS;
|
||||
}
|
||||
/* Else, drag the grabbed point */
|
||||
else
|
||||
{
|
||||
new_cursor = GDK_TCROSS;
|
||||
}
|
||||
/* Else, drag the grabbed point */
|
||||
else
|
||||
{
|
||||
|
||||
gimp_curve_set_point (curve, tool->selected, -1, -1);
|
||||
|
||||
if (x > tool->leftmost && x < tool->rightmost)
|
||||
{
|
||||
closest_point = (x + 8) / 16;
|
||||
if (curve->points[closest_point][0] == -1)
|
||||
tool->selected = closest_point;
|
||||
|
||||
gimp_curve_set_point (curve, tool->selected, x, 255 - y);
|
||||
}
|
||||
|
||||
gimp_image_map_tool_preview (GIMP_IMAGE_MAP_TOOL (tool));
|
||||
}
|
||||
break;
|
||||
|
||||
case GIMP_CURVE_FREE:
|
||||
if (tool->grabbed)
|
||||
{
|
||||
if (tool->selected > x)
|
||||
{
|
||||
x1 = x;
|
||||
x2 = tool->selected;
|
||||
y1 = y;
|
||||
y2 = tool->last;
|
||||
}
|
||||
else
|
||||
{
|
||||
x1 = tool->selected;
|
||||
x2 = x;
|
||||
y1 = tool->last;
|
||||
y2 = y;
|
||||
}
|
||||
|
||||
if (x2 != x1)
|
||||
{
|
||||
for (i = x1; i <= x2; i++)
|
||||
curve->curve[i] =
|
||||
255 - (y1 + ((y2 - y1) * (i - x1)) / (x2 - x1));
|
||||
}
|
||||
else
|
||||
{
|
||||
curve->curve[x] = 255 - y;
|
||||
}
|
||||
|
||||
tool->selected = x;
|
||||
tool->last = y;
|
||||
}
|
||||
|
||||
if (mevent->state & GDK_BUTTON1_MASK)
|
||||
new_cursor = GDK_TCROSS;
|
||||
else
|
||||
new_cursor = GDK_PENCIL;
|
||||
|
||||
curves->points[tool->channel][tool->selected][0] = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (x > tool->leftmost && x < tool->rightmost)
|
||||
{
|
||||
closest_point = (x + 8) / 16;
|
||||
if (curves->points[tool->channel][closest_point][0] == -1)
|
||||
tool->selected = closest_point;
|
||||
curves_set_cursor (tool, new_cursor);
|
||||
|
||||
curves->points[tool->channel][tool->selected][0] = x;
|
||||
curves->points[tool->channel][tool->selected][1] = 255 - y;
|
||||
}
|
||||
tool->cursor_x = x;
|
||||
tool->cursor_y = y;
|
||||
|
||||
curves_calculate_curve (curves, tool->channel);
|
||||
|
||||
gimp_image_map_tool_preview (GIMP_IMAGE_MAP_TOOL (tool));
|
||||
}
|
||||
break;
|
||||
|
||||
case GIMP_CURVE_FREE:
|
||||
if (tool->grabbed)
|
||||
{
|
||||
if (tool->selected > x)
|
||||
{
|
||||
x1 = x;
|
||||
x2 = tool->selected;
|
||||
y1 = y;
|
||||
y2 = tool->last;
|
||||
}
|
||||
else
|
||||
{
|
||||
x1 = tool->selected;
|
||||
x2 = x;
|
||||
y1 = tool->last;
|
||||
y2 = y;
|
||||
}
|
||||
|
||||
if (x2 != x1)
|
||||
{
|
||||
for (i = x1; i <= x2; i++)
|
||||
curves->curve[tool->channel][i] =
|
||||
255 - (y1 + ((y2 - y1) * (i - x1)) / (x2 - x1));
|
||||
}
|
||||
else
|
||||
{
|
||||
curves->curve[tool->channel][x] = 255 - y;
|
||||
}
|
||||
|
||||
tool->selected = x;
|
||||
tool->last = y;
|
||||
}
|
||||
|
||||
if (mevent->state & GDK_BUTTON1_MASK)
|
||||
new_cursor = GDK_TCROSS;
|
||||
else
|
||||
new_cursor = GDK_PENCIL;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
curves_set_cursor (tool, new_cursor);
|
||||
|
||||
tool->cursor_x = x;
|
||||
tool->cursor_y = y;
|
||||
|
||||
curves_update (tool, XRANGE | GRAPH);
|
||||
curves_update (tool, XRANGE | GRAPH);
|
||||
}
|
||||
return TRUE;
|
||||
|
||||
case GDK_KEY_PRESS:
|
||||
|
@ -1272,7 +1227,7 @@ curves_graph_expose (GtkWidget *widget,
|
|||
GdkEventExpose *eevent,
|
||||
GimpCurvesTool *tool)
|
||||
{
|
||||
Curves *curves = tool->curves;
|
||||
GimpCurve *curve = tool->curve[tool->channel];
|
||||
GimpHistogramChannel channel;
|
||||
gint width;
|
||||
gint height;
|
||||
|
@ -1322,7 +1277,7 @@ curves_graph_expose (GtkWidget *widget,
|
|||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
x = i;
|
||||
y = 255 - curves->curve[tool->channel][x];
|
||||
y = 255 - curve->curve[x];
|
||||
|
||||
points[i].x = RADIUS + ROUND ((gdouble) width * x / 256.0);
|
||||
points[i].y = RADIUS + ROUND ((gdouble) height * y / 256.0);
|
||||
|
@ -1330,16 +1285,16 @@ curves_graph_expose (GtkWidget *widget,
|
|||
|
||||
gdk_draw_lines (widget->window, graph_gc, points, 256);
|
||||
|
||||
if (curves->curve_type[tool->channel] == GIMP_CURVE_SMOOTH)
|
||||
if (curve->curve_type == GIMP_CURVE_SMOOTH)
|
||||
{
|
||||
/* Draw the points */
|
||||
for (i = 0; i < CURVES_NUM_POINTS; i++)
|
||||
for (i = 0; i < GIMP_CURVE_NUM_POINTS; i++)
|
||||
{
|
||||
x = curves->points[tool->channel][i][0];
|
||||
x = curve->points[i][0];
|
||||
if (x < 0)
|
||||
continue;
|
||||
|
||||
y = 255 - curves->points[tool->channel][i][1];
|
||||
y = 255 - curve->points[i][1];
|
||||
|
||||
gdk_draw_arc (widget->window, graph_gc,
|
||||
TRUE,
|
||||
|
|
|
@ -37,7 +37,7 @@ struct _GimpCurvesTool
|
|||
{
|
||||
GimpImageMapTool parent_instance;
|
||||
|
||||
Curves *curves;
|
||||
GimpCurve *curve[5];
|
||||
GimpLut *lut;
|
||||
|
||||
/* dialog */
|
||||
|
|
|
@ -422,7 +422,7 @@ HELP
|
|||
);
|
||||
|
||||
%invoke = (
|
||||
headers => [ qw("base/curves.h") ],
|
||||
headers => [ qw("base/curves.h" "core/gimpcurve.h") ],
|
||||
code => <<'CODE'
|
||||
{
|
||||
if (! gimp_item_is_attached (GIMP_ITEM (drawable)) ||
|
||||
|
@ -440,6 +440,7 @@ HELP
|
|||
/* The application should occur only within selection bounds */
|
||||
if (gimp_drawable_mask_intersect (drawable, &x, &y, &width, &height))
|
||||
{
|
||||
GimpCurve *curve;
|
||||
Curves c;
|
||||
gint j;
|
||||
PixelRegion srcPR, destPR;
|
||||
|
@ -454,17 +455,23 @@ HELP
|
|||
|
||||
curves_init (&c);
|
||||
|
||||
curve = GIMP_CURVE (gimp_curve_new ("curves_spline"));
|
||||
|
||||
/* unset the last point */
|
||||
c.points[channel][CURVES_NUM_POINTS - 1][0] = -1;
|
||||
c.points[channel][CURVES_NUM_POINTS - 1][1] = -1;
|
||||
curve->points[GIMP_CURVE_NUM_POINTS - 1][0] = -1;
|
||||
curve->points[GIMP_CURVE_NUM_POINTS - 1][1] = -1;
|
||||
|
||||
for (j = 0; j < num_points / 2; j++)
|
||||
{
|
||||
c.points[channel][j][0] = control_pts[j * 2];
|
||||
c.points[channel][j][1] = control_pts[j * 2 + 1];
|
||||
curve->points[j][0] = control_pts[j * 2];
|
||||
curve->points[j][1] = control_pts[j * 2 + 1];
|
||||
}
|
||||
|
||||
curves_calculate_curve (&c, channel);
|
||||
gimp_curve_calculate (curve);
|
||||
|
||||
gimp_curve_get_uchar (curve, c.curve[channel]);
|
||||
|
||||
g_object_unref (curve);
|
||||
|
||||
gimp_lut_setup (lut,
|
||||
(GimpLutFunc) curves_lut_func,
|
||||
|
|
Loading…
Reference in New Issue