# 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.

# "Perlized" from C source by Manish Singh <yosh@gimp.org>

sub drawable_arg () {{
    name => 'drawable',
    type => 'drawable',
    desc => 'The drawable',
}}

sub channel_arg () {{
    name => 'channel',
    type => 'enum ChannelLutType',
    desc => 'The channel to modify: { %%desc%% }'
}}

sub brightness_contrast {
    $blurb = 'Modify brightness/contrast in the specified drawable.';

    $help = <<'HELP';
This procedures allows the brightness and contrast of the specified drawable to
be modified.  Both 'brightness' and 'contrast' parameters are defined between
-127 and 127.
HELP

    &std_pdb_misc;
    $date = '1997';

    @inargs = ( &drawable_arg );
    foreach (qw( brightness contrast)) {
	push @inargs, { name => $_, type => '-127 <= int32 <= 127',
			desc => "\u$_ adjustment: (%%desc%%)" }
    }

    %invoke = (
	vars => [ 'GimpImage *gimage', 'GimpLut *lut',
		  'PixelRegion srcPR, destPR', 'int x1, y1, x2, y2' ],
	code => <<'CODE'
{
  if (gimp_drawable_is_indexed (drawable))
    success = FALSE;
  else
    {
      gimage = gimp_drawable_gimage (drawable);

      lut = brightness_contrast_lut_new (brightness / 255.0,
					 contrast / 127.0,
					 gimp_drawable_bytes (drawable));

      /* The application should occur only within selection bounds */
      gimp_drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2);

      pixel_region_init (&srcPR, gimp_drawable_data (drawable),
			 x1, y1, (x2 - x1), (y2 - y1), FALSE);
      pixel_region_init (&destPR, gimp_drawable_shadow (drawable),
			 x1, y1, (x2 - x1), (y2 - y1), TRUE);

      pixel_regions_process_parallel ((p_func) gimp_lut_process, lut, 2,
				      &srcPR, &destPR);

      gimp_lut_free (lut);
      gimp_drawable_merge_shadow (drawable, TRUE);
      drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1));
    }
}
CODE
    );
}

sub levels {
    $blurb = 'Modifies intensity levels in the specified drawable.';

    $help = <<'HELP';
This tool allows intensity levels in the specified drawable to be remapped
according to a set of parameters. The low/high input levels specify an initial
mapping from the source intensities. The gamma value determines how intensities
between the low and high input intensities are interpolated. A gamma value of
1.0 results in a linear interpolation. Higher gamma values result in more
high-level intensities. Lower gamma values result in more low-level
intensities. The low/high output levels constrain the final intensity
mapping--that is, no final intensity will be lower than the low output level
and no final intensity will be higher than the high output level. This tool is
only valid on RGB color and grayscale images. It will not operate on indexed
drawables.
HELP

    &std_pdb_misc;

    @inargs = (
	&drawable_arg,
	&channel_arg
    );
    $inargs[1]->{type} .= ' (no ALPHA_LUT)';

    foreach $arg (qw(input output)) {
	foreach (qw(low high)) {
	    push @inargs, { name => "${_}_$arg", type => '0 <= int32 <= 255',
			    desc => "Intensity of ${_}est $arg: (%%desc%%)",
			    alias => "${_}_${arg}v" }
	}
	push @inargs, { name => 'gamma', type => '0.1 <= float <= 10',
			desc => 'Gamma correction factor: (%%desc%%)',
			alias => 'gammav' }
    }
    $#inargs--;

    %invoke = (
	vars => [ 'PixelRegion srcPR, destPR', 'int x1, y1, x2, y2',
		  'GimpLut *lut', 'int i' ],
	code => <<'CODE'
{
  if (gimp_drawable_is_indexed (drawable) ||
      (gimp_drawable_is_gray (drawable) && channel != GRAY_LUT))
    success = FALSE;
  else
    {
      for (i = 0; i < 5; i++)
	{
	  low_input[i] = 0;
	  high_input[i] = 255;
	  low_output[i] = 0;
	  high_output[i] = 255;
	  gamma[i] = 1.0;
	}

      low_input[channel] = low_inputv;
      high_input[channel] = high_inputv;
      gamma[channel] = gammav;
      low_output[channel] = low_outputv;
      high_output[channel] = high_outputv;

      /* setup the lut */
      lut = levels_lut_new (gamma, low_input, high_input,
			    low_output, high_output,
			    gimp_drawable_bytes (drawable));

      /* The application should occur only within selection bounds */
      gimp_drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2);

      pixel_region_init (&srcPR, gimp_drawable_data (drawable),
			 x1, y1, (x2 - x1), (y2 - y1), FALSE);
      pixel_region_init (&destPR, gimp_drawable_shadow (drawable),
			 x1, y1, (x2 - x1), (y2 - y1), TRUE);

      pixel_regions_process_parallel ((p_func) gimp_lut_process, lut, 2,
				      &srcPR, &destPR);

      gimp_lut_free(lut);
      gimp_drawable_merge_shadow (drawable, TRUE);
      drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1));
    }
}
CODE
    );

    foreach (@inargs[2..6]) {
	my $type = $_->{type} =~ /float/ ? 'double' : 'int';
	push @{$invoke{vars}}, "$type $_->{name}\[5]";
    }
}

sub posterize {
    $blurb = 'Posterize the specified drawable.';

    $help = <<'HELP';
This procedures reduces the number of shades allows in each intensity channel
to the specified 'levels' parameter.
HELP

    &std_pdb_misc;
    $date = '1997';

    @inargs = (
	&drawable_arg,
	{ name => 'levels', type => '2 <= int32 <= 255',
	  desc => 'Levels of posterization: (%%desc%%)' }
    );

    %invoke = (
	vars => [ 'GimpImage *gimage', 'GimpLut *lut',
		  'PixelRegion srcPR, destPR', 'int x1, y1, x2, y2' ],
	code => <<'CODE'
{
  if (gimp_drawable_is_indexed (drawable))
    success = FALSE;
  else
    {
      gimage = gimp_drawable_gimage (drawable);

      lut = posterize_lut_new (levels, gimp_drawable_bytes (drawable)); 

      /* The application should occur only within selection bounds */
      gimp_drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2);

      pixel_region_init (&srcPR, gimp_drawable_data (drawable),
			 x1, y1, (x2 - x1), (y2 - y1), FALSE);
      pixel_region_init (&destPR, gimp_drawable_shadow (drawable),
			 x1, y1, (x2 - x1), (y2 - y1), TRUE);

      pixel_regions_process_parallel ((p_func) gimp_lut_process, lut, 2,
				      &srcPR, &destPR);

      gimp_lut_free (lut);
      gimp_drawable_merge_shadow (drawable, TRUE);
      drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1));
    }
}
CODE
    );
}

sub desaturate {
    $blurb = 'Desaturate the contents of the specified drawable.';

    $help = <<'HELP';
This procedure desaturates the contents of the specified drawable. This
procedure only works on drawables of type RGB color.
HELP

    &std_pdb_misc;

    @inargs = ( &drawable_arg );

    %invoke = (
	headers => [ qw("desaturate.h") ],
	code => <<'CODE'
{
  if (gimp_drawable_is_rgb (drawable))
    desaturate (drawable);
  else
    success = FALSE;
}
CODE
    );
}

sub equalize {
    $blurb = 'Equalize the contents of the specified drawable.';

    $help = <<'HELP';
This procedure equalizes the contents of the specified drawable. Each intensity
channel is equalizeed independently. The equalized intensity is given as inten'
= (255 - inten). Indexed color drawables are not valid for this operation. The
'mask_only' option specifies whether to adjust only the area of the image
within the selection bounds, or the entire image based on the histogram of the
selected area. If there is no selection, the entire image is adjusted based on
the histogram for the entire image.
HELP

    &std_pdb_misc;

    @inargs = (
	&drawable_arg,
	{ name => 'mask_only', type => 'boolean',
	  desc => 'Equalization option' }
    );

    %invoke = (
	headers => [ qw("equalize.h") ],
	code => <<'CODE'
{
  if (! gimp_drawable_is_indexed (drawable))
    equalize (drawable_gimage (drawable), drawable, mask_only);
  else
    success = FALSE;
}
CODE
    );
}

sub invert {
    $blurb = 'Invert the contents of the specified drawable.';

    $help = <<'HELP';
This procedure inverts the contents of the specified drawable. Each intensity
channel is inverted independently. The inverted intensity is given as inten' =
(255 - inten). Indexed color drawables are not valid for this operation.
HELP

    &std_pdb_misc;

    @inargs = ( &drawable_arg );

    %invoke = (
	headers => [ qw("invert.h") ],
	code => <<'CODE'
{
  if (! gimp_drawable_is_indexed (drawable))
    invert (drawable);
  else
    success = FALSE;
}
CODE
    );
}

sub curves_spline {
    $blurb = 'Modifies the intensity curve(s) for specified drawable.';

    $help = <<'HELP';
Modifies the intensity mapping for one channel in the specified drawable. The
drawable must be either grayscale or RGB, and the channel can be either an
intensity component, or the value. The 'control_pts' parameter is an array of
integers which define a set of control points which describe a Catmull Rom
spline which yields the final intensity curve. Use the 'gimp_curves_explicit'
function to explicitly modify intensity levels.
HELP

    &std_pdb_misc;

    @inargs = (
	&drawable_arg,
	&channel_arg,
	{ name => 'control_pts', type => 'int8array',
	  desc => 'The spline control points: { cp1.x, cp1.y, cp2.x, cp2.y,
		   ... }',
	  array => { name => 'num_points', type => '3 < int32 <= 32',
		     desc => 'The number of values in the control point array
			      (%%desc%%)' } }
    );

    %invoke = (
	headers => [ qw("curves.h") ],
	vars => [ 'CurvesDialog cd', 'int x1, y1, x2, y2', 'int i, j',
		  'PixelRegion srcPR, destPR' ],
	code => <<'CODE'
{
  if (gimp_drawable_is_indexed (drawable) || (num_points & 1) ||
      (gimp_drawable_is_gray (drawable) && channel != GRAY_LUT))
    success = FALSE;
  else
    {
      cd.lut = gimp_lut_new ();

      for (i = 0; i < 5; i++)
	for (j = 0; j < 256; j++)
	  cd.curve[i][j] = j;

      for (i = 0; i < 5; i++)
	for (j = 0; j < 17; j++)
	  {
	    cd.points[i][j][0] = -1;
	    cd.points[i][j][1] = -1;
	  }

      for (i = 0; i < 5; i++)
	  cd.curve_type[i] = SMOOTH;

      cd.drawable = drawable;
      cd.channel = channel;
      cd.color = gimp_drawable_is_rgb (drawable);

      for (j = 0; j < num_points / 2; j++)
	{
	  cd.points[cd.channel][j][0] = control_pts[j * 2];
	  cd.points[cd.channel][j][1] = control_pts[j * 2 + 1];
	}
      curves_calculate_curve (&cd);

      /* The application should occur only within selection bounds */
      gimp_drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2);

      pixel_region_init (&srcPR, gimp_drawable_data (drawable),
			 x1, y1, (x2 - x1), (y2 - y1), FALSE);
      pixel_region_init (&destPR, gimp_drawable_shadow (drawable),
			 x1, y1, (x2 - x1), (y2 - y1), TRUE);

      pixel_regions_process_parallel ((p_func) gimp_lut_process, cd.lut, 2,
				      &srcPR, &destPR);

      gimp_lut_free (cd.lut);
      gimp_drawable_merge_shadow (drawable, TRUE);
      drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1));
    }
}
CODE
    );
}

sub curves_explicit {
    $blurb = 'Modifies the intensity curve(s) for specified drawable.';

    $help = <<'HELP';
Modifies the intensity mapping for one channel in the specified drawable. The
drawable must be either grayscale or RGB, and the channel can be either an
intensity component, or the value. The 'curve' parameter is an array of bytes
which explicitly defines how each pixel value in the drawable will be modified.
Use the 'gimp_curves_spline' function to modify intensity levels with Catmull
Rom splines.
HELP

    &std_pdb_misc;

    @inargs = (
	&drawable_arg,
	&channel_arg,
	{ name => 'curve', type => 'int8array',
	  desc => 'The explicit curve',
	  array => { name => 'num_bytes',
		     desc => 'The number of bytes in the new curve (always
			      256)' } }
    );

    %invoke = (
	headers => [ qw("curves.h") ],
	vars => [ 'CurvesDialog cd', 'int x1, y1, x2, y2', 'int i, j',
		  'PixelRegion srcPR, destPR' ],
	code => <<'CODE'
{
  if (gimp_drawable_is_indexed (drawable) || (num_bytes != 256) ||
      (gimp_drawable_is_gray (drawable) && channel != GRAY_LUT))
    success = FALSE;
  else 
    {
      for (i = 0; i < 5; i++)
	for (j = 0; j < 256; j++)
	  cd.curve[i][j] = j;

      cd.drawable = drawable;
      cd.channel = channel;
      cd.color = gimp_drawable_is_rgb (drawable);

      for (j = 0; j < 256; j++)
	cd.curve[cd.channel][j] = curve[j];

      cd.lut = gimp_lut_new ();
      gimp_lut_setup (cd.lut, (GimpLutFunc) curves_lut_func,
		      (void *) &cd, gimp_drawable_bytes(drawable));
      
      /* The application should occur only within selection bounds */
      gimp_drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2);
      pixel_region_init (&srcPR, gimp_drawable_data (drawable),
			 x1, y1, (x2 - x1), (y2 - y1), FALSE);
      pixel_region_init (&destPR, gimp_drawable_shadow (drawable),
			 x1, y1, (x2 - x1), (y2 - y1), TRUE);

      pixel_regions_process_parallel ((p_func) gimp_lut_process, cd.lut, 2,
				      &srcPR, &destPR);

      gimp_lut_free (cd.lut);
      gimp_drawable_merge_shadow (drawable, TRUE);
      drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1));
    }
}
CODE
    );
}

sub color_balance {
    $blurb = 'Modify the color balance of the specified drawable.';

    $help = <<'HELP';
Modify the color balance of the specified drawable. There are three axis which
can be modified: cyan-red, magenta-green, and yellow-blue. Negative values
increase the amount of the former, positive values increase the amount of the
latter. Color balance can be controlled with the 'transfer_mode' setting, which
allows shadows, midtones, and highlights in an image to be affected
differently. The 'preserve_lum' parameter, if non-zero, ensures that the
luminosity of each pixel remains fixed.
HELP

    &std_pdb_misc;
    $date = '1997';

    @inargs = (
	&drawable_arg,
	{ name => 'transfer_mode', type => 'enum TransferMode',
	  desc => 'Transfer mode: { %%desc%% }' },
	{ name => 'preserve_lum', type => 'boolean',
	  desc => 'Preserve luminosity values at each pixel' }
    );

    foreach (qw(cyan_red magenta_green yellow_blue)) {
	my $arg = { name => $_, type => '-100 <= float <= 100' };
        ($arg->{desc} = ucfirst $_) =~ s/_(.)/-\U$1\E/;
	 $arg->{desc} .= ' color balance: (%%desc%%)';
	push @inargs, $arg;
    }

    %invoke = (
	headers => [ qw("color_balance.h") ],
	vars => [ 'ColorBalanceDialog cbd', 'int i', 'void *pr',
		  'PixelRegion srcPR, destPR', 'int x1, y1, x2, y2' ],
	code => <<'CODE'
{
  if (gimp_drawable_is_indexed (drawable))
    success = FALSE;
  else
    {
      for (i = 0; i < 3; i++)
	{
	  cbd.cyan_red[i] = 0.0;
	  cbd.magenta_green[i] = 0.0;
	  cbd.yellow_blue[i] = 0.0;
	}

      cbd.preserve_luminosity = preserve_lum;
      cbd.cyan_red[transfer_mode] = cyan_red;
      cbd.magenta_green[transfer_mode] = magenta_green;
      cbd.yellow_blue[transfer_mode] = yellow_blue;

      color_balance_create_lookup_tables (&cbd);

      /* The application should occur only within selection bounds */
      gimp_drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2);

      pixel_region_init (&srcPR, gimp_drawable_data (drawable),
			 x1, y1, (x2 - x1), (y2 - y1), FALSE);
      pixel_region_init (&destPR, gimp_drawable_shadow (drawable),
			 x1, y1, (x2 - x1), (y2 - y1), TRUE);

      for (pr = pixel_regions_register (2, &srcPR, &destPR); pr;
	   pr = pixel_regions_process (pr))
        color_balance (&srcPR, &destPR, (void *) &cbd);

      gimp_drawable_merge_shadow (drawable, TRUE);
      drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1));
    }
}
CODE
    );
}

sub histogram {
    $blurb = <<'BLURB';
Returns information on the intensity histogram for the specified drawable.
BLURB

    $help = <<'HELP';
This tool makes it possible to gather information about the intensity histogram
of a drawable. A channel to examine is first specified. This can be either
value, red, green, or blue, depending on whether the drawable is of type color
or grayscale. The drawable may not be indexed. Second, a range of intensities
are specified. The gimp_histogram function returns statistics based on the
pixels in the drawable that fall under this range of values. Mean, standard
deviation, median, number of pixels, and percentile are all returned.
Additionally, the total count of pixels in the image is returned. Counts of
pixels are weighted by any associated alpha values and by the current selection
mask. That is, pixels that lie outside an active selection mask will not be
counted. Similarly, pixels with transparent alpha values will not be counted.
HELP

    &std_pdb_misc;

    @inargs = (
	&drawable_arg,
	&channel_arg,
    );

    foreach (qw(start end)) {
	push @inargs, { name => "${_}_range", type => '0 <= int32 < 256',
			desc => "\u$_ of the intensity measurement range" }
    }

    @outargs = (
	{ name => 'mean',
	  desc => 'Mean itensity value' },
	{ name => 'std_dev',
	  desc => 'Standard deviation of intensity values' },
	{ name => 'median',
	  desc => 'Median itensity value' },
	{ name => 'pixels',
	  desc => 'Alpha-weighted pixel count for entire image' },
	{ name => 'count',
	  desc => 'Alpha-weighted pixel count for range' },
	{ name => 'percentile',
	  desc => 'Percentile that range falls under' }
    );

    foreach (@outargs) {
	@$_{qw(type alias no_declare)} = ('float', "htd.$_->{name}", 1)
    }

    %invoke = (
	headers => [ qw("histogram_tool.h" "gimage.h") ],
	vars => [ 'PixelRegion srcPR, maskPR', 'int x1, y1, x2, y2',
		  'HistogramToolDialog htd', 'int off_x, off_y',
		  'gboolean no_mask', 'Channel *mask' ],
	code => <<'CODE'
{
  if (gimp_drawable_is_indexed (drawable) ||
      (gimp_drawable_is_gray (drawable) && channel != GRAY_LUT))
    success = FALSE;
  else
    {
      htd.shell = NULL;
      htd.channel = channel;
      htd.drawable = drawable;
      htd.color = gimp_drawable_is_rgb (drawable);
      htd.histogram = histogram_widget_new (HISTOGRAM_WIDTH,
					    HISTOGRAM_HEIGHT);

      gtk_signal_connect (GTK_OBJECT (htd.histogram), "rangechanged",
                          (GtkSignalFunc) histogram_tool_histogram_range,
                          (void*) &htd);

      /* The information collection should occur only within selection bounds */
      no_mask = (gimp_drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2) == FALSE);
      gimp_drawable_offsets (drawable, &off_x, &off_y);

      /* Configure the src from the drawable data */
      pixel_region_init (&srcPR, gimp_drawable_data (drawable),
			 x1, y1, (x2 - x1), (y2 - y1), FALSE);

      /*  Configure the mask from the gimage's selection mask */
      mask = gimage_get_mask (drawable_gimage (GIMP_DRAWABLE (drawable)));
      pixel_region_init (&maskPR, gimp_drawable_data (GIMP_DRAWABLE(mask)),
			 x1 + off_x, y1 + off_y, (x2 - x1), (y2 - y1), FALSE);

      /* Apply the image transformation to the pixels */
      htd.hist = gimp_histogram_new ();
      if (no_mask)
	gimp_histogram_calculate (htd.hist, &srcPR, NULL);
      else
	gimp_histogram_calculate (htd.hist, &srcPR, &maskPR);

      /* Calculate the statistics */
      histogram_tool_histogram_range (htd.histogram, start_range, end_range,
				      &htd);
    }
}
CODE
    );
}

sub hue_saturation {
    $blurb = <<'BLURB';
Modify hue, lightness, and saturation in the specified drawable.
BLURB

    $help = <<'HELP';
This procedures allows the hue, lightness, and saturation in the specified
drawable to be modified. The 'hue_range' parameter provides the capability to
limit range of affected hues.
HELP

    &std_pdb_misc;
    $date = '1997';

    @inargs = (
	&drawable_arg,
	{ name => 'hue_range', type => 'enum HueRange',
	  desc => 'Range of affected hues: { %%desc%% }' },
	{ name => 'hue_offset', type => '-180 <= float <= 180',
	  desc => 'Hue offset in degrees: (%%desc%%)' }
    );

    foreach (qw(lightness saturation)) {
	push @inargs, { name => $_, type => '-100 <= float <= 100',
			desc => "$_ modification: (%%desc%%)" }
    }

    %invoke = (
	headers => [ qw("hue_saturation.h") ],
	vars => [ 'HueSaturationDialog hsd', 'int i', 'void *pr',
		  'PixelRegion srcPR, destPR', 'int x1, y1, x2, y2' ],
	code => <<'CODE'
{
  if (gimp_drawable_is_indexed (drawable))
    success = FALSE;
  else
    {
      for (i = 0; i < 7; i++)
	{
	  hsd.hue[i] = 0.0;
	  hsd.lightness[i] = 0.0;
	  hsd.saturation[i] = 0.0;
	}

      hsd.hue[hue_range] = hue_offset;
      hsd.lightness[hue_range] = lightness;
      hsd.saturation[hue_range] = saturation;

      /* Calculate the transfer arrays */
      hue_saturation_calculate_transfers (&hsd);

      /* The application should occur only within selection bounds */
      gimp_drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2);

      pixel_region_init (&srcPR, gimp_drawable_data (drawable),
			 x1, y1, (x2 - x1), (y2 - y1), FALSE);
      pixel_region_init (&destPR, gimp_drawable_shadow (drawable),
			 x1, y1, (x2 - x1), (y2 - y1), TRUE);

      for (pr = pixel_regions_register (2, &srcPR, &destPR); pr;
	   pr = pixel_regions_process (pr))
        hue_saturation (&srcPR, &destPR, (void *) &hsd);

      gimp_drawable_merge_shadow (drawable, TRUE);
      drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1));
    }
}
CODE
    );
}

sub threshold {
    $blurb = 'Threshold the specified drawable.';

    $help = <<'HELP';
This procedures generates a threshold map of the specified drawable. All pixels
between the values of 'low_threshold' and 'high_threshold' are replaced with
white, and all other pixels with black.
HELP

    &std_pdb_misc;
    $date = '1997';

    @inargs = ( &drawable_arg );
    foreach (qw(low high)) {
	push @inargs, { name => "${_}_threshold", type => '0 <= int32 <= 255',
			desc => "The $_ threshold value: %%desc%%" }
    }

    %invoke = (
	headers => [ qw("threshold.h") ],
	vars => [ 'ThresholdDialog td', 'int x1, y1, x2, y2',
		  'PixelRegion srcPR, destPR' ],
	code => <<'CODE'
{
  if (gimp_drawable_is_indexed (drawable) || (low_threshold >= high_threshold))
    success = FALSE;
  else
    {
      td.color = gimp_drawable_is_rgb (drawable);
      td.low_threshold = low_threshold;
      td.high_threshold = high_threshold;

      /* The application should occur only within selection bounds */
      gimp_drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2);

      pixel_region_init (&srcPR, gimp_drawable_data (drawable),
			 x1, y1, (x2 - x1), (y2 - y1), FALSE);
      pixel_region_init (&destPR, gimp_drawable_shadow (drawable),
			 x1, y1, (x2 - x1), (y2 - y1), TRUE);

      pixel_regions_process_parallel ((p_func) threshold_2, (void*) &td, 2,
				      &srcPR, &destPR);

      gimp_drawable_merge_shadow (drawable, TRUE);
      drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1));
    }
}
CODE
    );
}

@headers = qw("gimpimage.h" "gimpdrawable.h" "gimplut.h" "lut_funcs.h");

@procs = qw(brightness_contrast levels posterize desaturate equalize invert
	    curves_spline curves_explicit color_balance histogram
	    hue_saturation threshold);
%exports = (app => [@procs]);

$desc = 'Color';

1;
