Commit 163a3f41 authored by Michael Natterer's avatar Michael Natterer 😴 Committed by Michael Natterer

More color correction stuff cleanup:

2002-09-04  Michael Natterer  <mitch@gimp.org>

	More color correction stuff cleanup:

	* app/base/Makefile.am
	* app/base/base-types.h
	* app/base/levels.[ch]: new files containing levels_lut_func(), a
	new "Levels" parameter struct and the "auto levels" stuff.

	* app/base/lut-funcs.[ch]: removed the levels stuff here, added
	lots of g_return_if_fail().

	* app/base/color-balance.[ch]
	* app/base/hue-saturation.[ch]: added init() and reset() functions
	so we don't need to duplicate this code in the tool and the pdb
	wrappers.

	* app/base/curves.[ch]: s/gint/GimpHistogramChannel/g, made
	curves_channel_reset() initialize the curves array.

	* app/tools/gimpcolorbalancetool.[ch]: use the new functions,
	moved the "Range" frame to the top, added a per-range "Reset"
	button, made the global "Reset" button reset all ranges and
	the "Preserve Luminosity" toggle.

	* app/tools/gimpcurvestool.[ch]: don't initialize the curves
	array manually, as curves_channel_reset() does that,
	s/gint/GimpHistogramChannel/g.

	* app/tools/gimphuesaturationtool.c: use the new functions, added
	a per-channel "Reset" button and made the global "Reset" button
	reset all channels, cleaned up the GUI update function.

	* app/tools/gimplevelstool.[ch]: changed to use the new Levels
	parameter struct and it's utility functions. Removed stuff
	which now lives in base/levels.c

	* app/tools/gimpimagemaptool.c: align the "Preview" button
	bottom-left, not bottom-right.

	* tools/pdbgen/pdb/color.pdb: use the new stuff and removed
	uglyness because using the "Levels" struct makes the code more
	straightforward.

	* app/pdb/color_cmds.c: regenerated.
parent 53930815
2002-09-04 Michael Natterer <mitch@gimp.org>
More color correction stuff cleanup:
* app/base/Makefile.am
* app/base/base-types.h
* app/base/levels.[ch]: new files containing levels_lut_func(), a
new "Levels" parameter struct and the "auto levels" stuff.
* app/base/lut-funcs.[ch]: removed the levels stuff here, added
lots of g_return_if_fail().
* app/base/color-balance.[ch]
* app/base/hue-saturation.[ch]: added init() and reset() functions
so we don't need to duplicate this code in the tool and the pdb
wrappers.
* app/base/curves.[ch]: s/gint/GimpHistogramChannel/g, made
curves_channel_reset() initialize the curves array.
* app/tools/gimpcolorbalancetool.[ch]: use the new functions,
moved the "Range" frame to the top, added a per-range "Reset"
button, made the global "Reset" button reset all ranges and
the "Preserve Luminosity" toggle.
* app/tools/gimpcurvestool.[ch]: don't initialize the curves
array manually, as curves_channel_reset() does that,
s/gint/GimpHistogramChannel/g.
* app/tools/gimphuesaturationtool.c: use the new functions, added
a per-channel "Reset" button and made the global "Reset" button
reset all channels, cleaned up the GUI update function.
* app/tools/gimplevelstool.[ch]: changed to use the new Levels
parameter struct and it's utility functions. Removed stuff
which now lives in base/levels.c
* app/tools/gimpimagemaptool.c: align the "Preview" button
bottom-left, not bottom-right.
* tools/pdbgen/pdb/color.pdb: use the new stuff and removed
uglyness because using the "Levels" struct makes the code more
straightforward.
* app/pdb/color_cmds.c: regenerated.
2002-09-04 Michael Natterer <mitch@gimp.org>
* app/gui/color-select.c
......
......@@ -32,6 +32,8 @@ libappbase_a_SOURCES = \
gimplut.h \
hue-saturation.c \
hue-saturation.h \
levels.c \
levels.h \
lut-funcs.c \
lut-funcs.h \
pixel-processor.c \
......
......@@ -51,6 +51,7 @@ typedef struct _GimpLut GimpLut;
typedef struct _ColorBalance ColorBalance;
typedef struct _Curves Curves;
typedef struct _HueSaturation HueSaturation;
typedef struct _Levels Levels;
typedef struct _Threshold Threshold;
typedef struct _PixelRegionIterator PixelRegionIterator;
......
......@@ -51,6 +51,30 @@ static gdouble shadows_sub[256] = { 0 };
/* public functions */
void
color_balance_init (ColorBalance *cb)
{
GimpTransferMode range;
g_return_if_fail (cb != NULL);
for (range = GIMP_SHADOWS; range <= GIMP_HIGHLIGHTS; range++)
color_balance_range_reset (cb, range);
cb->preserve_luminosity = TRUE;
}
void
color_balance_range_reset (ColorBalance *cb,
GimpTransferMode range)
{
g_return_if_fail (cb != NULL);
cb->cyan_red[range] = 0.0;
cb->magenta_green[range] = 0.0;
cb->yellow_blue[range] = 0.0;
}
void
color_balance_create_lookup_tables (ColorBalance *cb)
{
......@@ -60,6 +84,8 @@ color_balance_create_lookup_tables (ColorBalance *cb)
gint i;
gint32 r_n, g_n, b_n;
g_return_if_fail (cb != NULL);
if (! transfer_initialized)
{
color_balance_transfer_init ();
......
......@@ -34,10 +34,13 @@ struct _ColorBalance
};
void color_balance_create_lookup_tables (ColorBalance *cb);
void color_balance (PixelRegion *srcPR,
PixelRegion *destPR,
gpointer data);
void color_balance_init (ColorBalance *cb);
void color_balance_range_reset (ColorBalance *cb,
GimpTransferMode range);
void color_balance_create_lookup_tables (ColorBalance *cb);
void color_balance (PixelRegion *srcPR,
PixelRegion *destPR,
gpointer data);
#endif /* __COLOR_BALANCE_H__ */
......@@ -61,25 +61,31 @@ static CRMatrix CR_basis =
void
curves_init (Curves *curves)
{
gint i, j;
GimpHistogramChannel channel;
for (i = 0; i < 5; i++)
{
curves->curve_type[i] = CURVES_SMOOTH;
g_return_if_fail (curves != NULL);
for (j = 0; j < 256; j++)
curves->curve[i][j] = j;
for (channel = GIMP_HISTOGRAM_VALUE;
channel <= GIMP_HISTOGRAM_ALPHA;
channel++)
{
curves->curve_type[channel] = CURVES_SMOOTH;
curves_channel_reset (curves, i);
curves_channel_reset (curves, channel);
}
}
void
curves_channel_reset (Curves *curves,
gint channel)
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 < 17; j++)
{
curves->points[channel][j][0] = -1;
......@@ -93,14 +99,16 @@ curves_channel_reset (Curves *curves,
}
void
curves_calculate_curve (Curves *curves,
gint channel)
curves_calculate_curve (Curves *curves,
GimpHistogramChannel channel)
{
gint i;
gint points[17];
gint num_pts;
gint p1, p2, p3, p4;
g_return_if_fail (curves != NULL);
switch (curves->curve_type[channel])
{
case CURVES_FREE:
......
......@@ -35,11 +35,11 @@ struct _Curves
};
void curves_init (Curves *curves);
void curves_channel_reset (Curves *curves,
gint channel);
void curves_calculate_curve (Curves *curves,
gint channel);
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,
......
......@@ -29,6 +29,28 @@
#include "pixel-region.h"
void
hue_saturation_init (HueSaturation *hs)
{
GimpHueRange partition;
g_return_if_fail (hs != NULL);
for (partition = GIMP_ALL_HUES; partition <= GIMP_MAGENTA_HUES; partition++)
hue_saturation_partition_reset (hs, partition);
}
void
hue_saturation_partition_reset (HueSaturation *hs,
GimpHueRange partition)
{
g_return_if_fail (hs != NULL);
hs->hue[partition] = 0.0;
hs->lightness[partition] = 0.0;
hs->saturation[partition] = 0.0;
}
void
hue_saturation_calculate_transfers (HueSaturation *hs)
{
......@@ -36,6 +58,8 @@ hue_saturation_calculate_transfers (HueSaturation *hs)
gint hue;
gint i;
g_return_if_fail (hs != NULL);
/* Calculate transfers */
for (hue = 0; hue < 6; hue++)
for (i = 0; i < 256; i++)
......
......@@ -32,6 +32,9 @@ struct _HueSaturation
};
void hue_saturation_init (HueSaturation *hs);
void hue_saturation_partition_reset (HueSaturation *hs,
GimpHueRange partition);
void hue_saturation_calculate_transfers (HueSaturation *hs);
void hue_saturation (PixelRegion *srcPR,
PixelRegion *destPR,
......
/* 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 <glib-object.h>
#include "libgimpmath/gimpmath.h"
#include "base-types.h"
#include "gimphistogram.h"
#include "levels.h"
/* public functions */
void
levels_init (Levels *levels)
{
GimpHistogramChannel channel;
g_return_if_fail (levels != NULL);
for (channel = GIMP_HISTOGRAM_VALUE;
channel <= GIMP_HISTOGRAM_ALPHA;
channel++)
{
levels_channel_reset (levels, channel);
}
}
void
levels_channel_reset (Levels *levels,
GimpHistogramChannel channel)
{
g_return_if_fail (levels != NULL);
levels->gamma[channel] = 1.0;
levels->low_input[channel] = 0;
levels->high_input[channel] = 255;
levels->low_output[channel] = 0;
levels->high_output[channel] = 255;
}
void
levels_auto (Levels *levels,
GimpHistogram *hist,
gboolean color)
{
GimpHistogramChannel channel;
g_return_if_fail (levels != NULL);
g_return_if_fail (hist != NULL);
if (color)
{
/* Set the overall value to defaults */
levels_channel_reset (levels, GIMP_HISTOGRAM_VALUE);
for (channel = GIMP_HISTOGRAM_RED;
channel <= GIMP_HISTOGRAM_BLUE;
channel++)
levels_channel_auto (levels, hist, channel);
}
else
{
levels_channel_auto (levels, hist, GIMP_HISTOGRAM_VALUE);
}
}
void
levels_channel_auto (Levels *levels,
GimpHistogram *hist,
GimpHistogramChannel channel)
{
gint i;
gdouble count, new_count, percentage, next_percentage;
g_return_if_fail (levels != NULL);
g_return_if_fail (hist != NULL);
levels->gamma[channel] = 1.0;
levels->low_output[channel] = 0;
levels->high_output[channel] = 255;
count = gimp_histogram_get_count (hist, 0, 255);
if (count == 0.0)
{
levels->low_input[channel] = 0;
levels->high_input[channel] = 0;
}
else
{
/* Set the low input */
new_count = 0.0;
for (i = 0; i < 255; i++)
{
new_count += gimp_histogram_get_value (hist, channel, i);
percentage = new_count / count;
next_percentage =
(new_count + gimp_histogram_get_value (hist,
channel,
i + 1)) / count;
if (fabs (percentage - 0.006) < fabs (next_percentage - 0.006))
{
levels->low_input[channel] = i + 1;
break;
}
}
/* Set the high input */
new_count = 0.0;
for (i = 255; i > 0; i--)
{
new_count += gimp_histogram_get_value (hist, channel, i);
percentage = new_count / count;
next_percentage =
(new_count + gimp_histogram_get_value (hist,
channel,
i - 1)) / count;
if (fabs (percentage - 0.006) < fabs (next_percentage - 0.006))
{
levels->high_input[channel] = i - 1;
break;
}
}
}
}
void
levels_calculate_transfers (Levels *levels)
{
gdouble inten;
gint i, j;
g_return_if_fail (levels != NULL);
/* Recalculate the levels arrays */
for (j = 0; j < 5; j++)
{
for (i = 0; i < 256; i++)
{
/* determine input intensity */
if (levels->high_input[j] != levels->low_input[j])
{
inten = ((gdouble) (i - levels->low_input[j]) /
(double) (levels->high_input[j] - levels->low_input[j]));
}
else
{
inten = (gdouble) (i - levels->low_input[j]);
}
inten = CLAMP (inten, 0.0, 1.0);
if (levels->gamma[j] != 0.0)
inten = pow (inten, (1.0 / levels->gamma[j]));
levels->input[j][i] = (guchar) (inten * 255.0 + 0.5);
}
}
}
gfloat
levels_lut_func (Levels *levels,
gint n_channels,
gint channel,
gfloat value)
{
gdouble inten;
gint j;
if (n_channels == 1)
j = 0;
else
j = channel + 1;
inten = value;
/* For color images this runs through the loop with j = channel +1
* the first time and j = 0 the second time
*
* For bw images this runs through the loop with j = 0 the first and
* only time
*/
for (; j >= 0; j -= (channel + 1))
{
/* don't apply the overall curve to the alpha channel */
if (j == 0 && (n_channels == 2 || n_channels == 4)
&& channel == n_channels -1)
return inten;
/* determine input intensity */
if (levels->high_input[j] != levels->low_input[j])
inten = ((gdouble) (255.0 * inten - levels->low_input[j]) /
(gdouble) (levels->high_input[j] - levels->low_input[j]));
else
inten = (gdouble) (255.0 * inten - levels->low_input[j]);
if (levels->gamma[j] != 0.0)
{
if (inten >= 0.0)
inten = pow ( inten, (1.0 / levels->gamma[j]));
else
inten = -pow (-inten, (1.0 / levels->gamma[j]));
}
/* determine the output intensity */
if (levels->high_output[j] >= levels->low_output[j])
inten = (gdouble) (inten * (levels->high_output[j] -
levels->low_output[j]) +
levels->low_output[j]);
else if (levels->high_output[j] < levels->low_output[j])
inten = (gdouble) (levels->low_output[j] - inten *
(levels->low_output[j] - levels->high_output[j]));
inten /= 255.0;
}
return inten;
}
/* 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 __LEVELS_H__
#define __LEVELS_H__
struct _Levels
{
gdouble gamma[5];
gint low_input[5];
gint high_input[5];
gint low_output[5];
gint high_output[5];
guchar input[5][256]; /* this is used only by the gui */
};
void levels_init (Levels *levels);
void levels_channel_reset (Levels *levels,
GimpHistogramChannel channel);
void levels_auto (Levels *levels,
GimpHistogram *hist,
gboolean color);
void levels_channel_auto (Levels *levels,
GimpHistogram *hist,
GimpHistogramChannel channel);
void levels_calculate_transfers (Levels *levels);
gfloat levels_lut_func (Levels *levels,
gint n_channels,
gint channel,
gfloat value);
#endif /* __LEVELS_H__ */
......@@ -120,6 +120,8 @@ brightness_contrast_lut_setup (GimpLut *lut,
{
B_C_struct data;
g_return_if_fail (lut != NULL);
data.brightness = brightness;
data.contrast = contrast;
......@@ -158,6 +160,8 @@ void
invert_lut_setup (GimpLut *lut,
gint n_channels)
{
g_return_if_fail (lut != NULL);
gimp_lut_setup_exact (lut, (GimpLutFunc) invert_lut_func,
NULL , n_channels);
}
......@@ -195,6 +199,8 @@ add_lut_setup (GimpLut *lut,
gdouble amount,
gint n_channels)
{
g_return_if_fail (lut != NULL);
gimp_lut_setup (lut, (GimpLutFunc) add_lut_func,
(gpointer) &amount, n_channels);
}
......@@ -232,6 +238,8 @@ intersect_lut_setup (GimpLut *lut,
gdouble value,
gint n_channels)
{
g_return_if_fail (lut != NULL);
gimp_lut_setup_exact (lut, (GimpLutFunc) intersect_lut_func,
(gpointer) &value , n_channels);
}
......@@ -272,120 +280,12 @@ threshold_lut_setup (GimpLut *lut,
gdouble value,
gint n_channels)
{
g_return_if_fail (lut != NULL);
gimp_lut_setup_exact (lut, (GimpLutFunc) threshold_lut_func,
(gpointer) &value , n_channels);
}
/* ------------- levels ------------ */
typedef struct
{
gdouble *gamma;
gint *low_input;
gint *high_input;
gint *low_output;
gint *high_output;
} levels_struct;
static gfloat
levels_lut_func (levels_struct *data,
gint n_channels,
gint channel,
gfloat value)
{
gdouble inten;
gint j;
if (n_channels == 1)
j = 0;
else
j = channel + 1;
inten = value;
/* For color images this runs through the loop with j = channel +1
* the first time and j = 0 the second time
*
* For bw images this runs through the loop with j = 0 the first and
* only time
*/
for (; j >= 0; j -= (channel + 1))
{
/* don't apply the overall curve to the alpha channel */
if (j == 0 && (n_channels == 2 || n_channels == 4)
&& channel == n_channels -1)
return inten;
/* determine input intensity */
if (data->high_input[j] != data->low_input[j])
inten = ((gdouble) (255.0 * inten - data->low_input[j]) /
(gdouble) (data->high_input[j] - data->low_input[j]));
else
inten = (gdouble) (255.0 * inten - data->low_input[j]);
if (data->gamma[j] != 0.0)
{
if (inten >= 0.0)
inten = pow ( inten, (1.0 / data->gamma[j]));
else
inten = -pow (-inten, (1.0 / data->gamma[j]));
}
/* determine the output intensity */
if (data->high_output[j] >= data->low_output[j])
inten = (gdouble) (inten * (data->high_output[j] - data->low_output[j]) +