Commit 5dd23ae1 authored by Michael Natterer's avatar Michael Natterer 😴 Committed by Michael Natterer

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
parent 1edac757
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;
curves_channel_reset (curves, channel);
}
}
void
curves_channel_reset (Curves *curves,
GimpHistogramChannel channel)
{
gint j;
g_return_if_fail (curves != NULL);
gint j;
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 */
......
/* 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;
}
/* 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__ */
/* 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;
}
/* 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__ */
/* 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;
}
}