Commit a26f8d3f authored by jaycox's avatar jaycox

new source files that implement pixel Look Up Table functions.


	* app/gimplut.[ch]: new source files that implement pixel Look Up
 	Table functions.

	* app/Makefile.am: build gimplut.[ch]


	* app/brightness_contrast.c
	* app/curves.c
	* app/invert.c
	* app/levels.c
	* app/posterize.c: Use the new lut functions.  Use
 	pixel_region_process_parallel in the PDB versions of these routines.

	* libgimp/parasite.h
	* libgimp/parasite.c: new functions parasite_name and
 	parasite_compare.

	* app/gimpdrawable.c:
	* app/gimpdrawable.h: new function
 	gimp_drawable_get_color_at(...) returns the RGBA[color index]
 	value at a specified position in the drawable.  Don't set the dirty
 	bit on the image if a new parasite is the same as the old.

	* app/gimpimage.c
	* app/gimpimage.h new function
 	gimp_image_get_color_at(...) returns the RGBA[color index]
 	value at a specified position in the drawable.  Don't set the dirty
 	bit on the image if a new parasite is the same as the old.

	* app/by_color_select.c
	* app/color_picker.c: use the new gimp_*_get_color_at
 	functions instead of messing with the tiles.

	* app/layer.c: fixed a minor warning.

	* app/commands.c:
	don't scale the image if the new size == the old size

	* app/channel.c: optimized channel_bounds by only checking the
 	pixels in a tile if it is not already entirely within the
 	currently computed bounds.
parent ed92f218
......@@ -186,6 +186,8 @@ gimp_SOURCES = \
gimplist.h \
gimplistF.h \
gimplistP.h \
gimplut.c \
gimplut.h \
gimpparasite.c \
gimpparasite.h \
gimpprogress.c \
......
......@@ -1133,7 +1133,9 @@ image_scale_callback (GtkWidget *w,
image_scale = (ImageResize *) client_data;
if ((gimage = image_scale->gimage) != NULL)
if ((gimage = image_scale->gimage) != NULL &&
(image_scale->resize->width != gimage->width ||
image_scale->resize->height != gimage->height))
{
if (image_scale->resize->width > 0 &&
image_scale->resize->height > 0)
......
......@@ -30,6 +30,7 @@
#include "image_map.h"
#include "interface.h"
#include "curves.h"
#include "gimplut.h"
#include "libgimp/gimpintl.h"
......@@ -96,6 +97,8 @@ struct _CurvesDialog
int curve_type;
int points[5][17][2];
unsigned char curve[5][256];
GimpLut *lut;
};
typedef double CRMatrix[4][4];
......@@ -141,65 +144,49 @@ static CRMatrix CR_basis =
};
static void curves (PixelRegion *, PixelRegion *, void *);
static Argument * curves_spline_invoker (Argument *);
static Argument * curves_explicit_invoker (Argument *);
/* curves machinery */
static void
curves (PixelRegion *srcPR,
PixelRegion *destPR,
void *user_data)
static float
curves_lut_func(CurvesDialog *cd,
int nchannels, int channel, float value)
{
CurvesDialog *cd;
unsigned char *src, *s;
unsigned char *dest, *d;
int has_alpha, alpha;
int w, h;
cd = (CurvesDialog *) user_data;
h = srcPR->h;
src = srcPR->data;
dest = destPR->data;
has_alpha = (srcPR->bytes == 2 || srcPR->bytes == 4);
alpha = has_alpha ? srcPR->bytes - 1 : srcPR->bytes;
float f;
int index;
double inten;
int j;
while (h--)
if (nchannels == 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 && (nchannels == 2 || nchannels == 4)
&& channel == nchannels -1)
return inten;
if (inten < 0.0)
inten = cd->curve[j][0]/255.0;
else if (inten >= 1.0)
inten = cd->curve[j][255]/255.0;
else /* interpolate the curve */
{
w = srcPR->w;
s = src;
d = dest;
while (w--)
{
if (cd->color)
{
/* The contributions from the individual channel level settings */
d[RED_PIX] = cd->curve[HISTOGRAM_RED][s[RED_PIX]];
d[GREEN_PIX] = cd->curve[HISTOGRAM_GREEN][s[GREEN_PIX]];
d[BLUE_PIX] = cd->curve[HISTOGRAM_BLUE][s[BLUE_PIX]];
/* The overall changes */
d[RED_PIX] = cd->curve[HISTOGRAM_VALUE][d[RED_PIX]];
d[GREEN_PIX] = cd->curve[HISTOGRAM_VALUE][d[GREEN_PIX]];
d[BLUE_PIX] = cd->curve[HISTOGRAM_VALUE][d[BLUE_PIX]];
}
else
d[GRAY_PIX] = cd->curve[HISTOGRAM_VALUE][s[GRAY_PIX]];
if (has_alpha) {
d[alpha] = cd->curve[HISTOGRAM_ALPHA][s[alpha]];
/* d[alpha] = s[alpha]; */
}
s += srcPR->bytes;
d += destPR->bytes;
}
src += srcPR->rowstride;
dest += destPR->rowstride;
index = floor(inten * 255.0);
f = inten*255.0 - index;
inten = ((1.0 - f) * cd->curve[j][index ] +
( f) * cd->curve[j][index + 1] ) / 255.0;
}
}
return inten;
}
/* curves action functions */
......@@ -446,6 +433,7 @@ curves_new_dialog ()
for (i = 0; i < 5; i++)
for (j = 0; j < 256; j++)
cd->curve[i][j] = j;
cd->lut = gimp_lut_new();
for (i = 0; i < 5; i++)
channel_items [i].user_data = (gpointer) cd;
......@@ -810,6 +798,9 @@ curves_calculate_curve (CurvesDialog *cd)
}
break;
}
gimp_lut_setup(cd->lut, (GimpLutFunc) curves_lut_func,
(void *) cd, gimp_drawable_bytes(cd->drawable));
}
static void
......@@ -820,7 +811,8 @@ curves_preview (CurvesDialog *cd)
active_tool->preserve = TRUE; /* Going to dirty the display... */
image_map_apply (cd->image_map, curves, (void *) cd);
image_map_apply (cd->image_map, (ImageMapApplyFunc)gimp_lut_process_2,
(void *) cd->lut);
active_tool->preserve = FALSE; /* All done */
}
......@@ -988,7 +980,8 @@ curves_ok_callback (GtkWidget *widget,
active_tool->preserve = TRUE; /* We're about to dirty... */
if (!cd->preview)
image_map_apply (cd->image_map, curves, (void *) cd);
image_map_apply (cd->image_map, (ImageMapApplyFunc)gimp_lut_process_2,
(void *) cd->lut);
if (cd->image_map)
image_map_commit (cd->image_map);
......@@ -1361,6 +1354,7 @@ curves_spline_invoker (Argument *args)
{
int_value = args[0].value.pdb_int;
drawable = drawable_get_ID (int_value);
cd.drawable = drawable;
if (drawable == NULL)
success = FALSE;
else
......@@ -1407,6 +1401,7 @@ curves_spline_invoker (Argument *args)
/* arrange to modify the curves */
if (success)
{
cd.lut = gimp_lut_new();
for (i = 0; i < 5; i++)
for (j = 0; j < 256; j++)
cd.curve[i][j] = j;
......@@ -1435,9 +1430,10 @@ curves_spline_invoker (Argument *args)
pixel_region_init (&srcPR, drawable_data (drawable), x1, y1, (x2 - x1), (y2 - y1), FALSE);
pixel_region_init (&destPR, drawable_shadow (drawable), x1, y1, (x2 - x1), (y2 - y1), TRUE);
for (pr = pixel_regions_register (2, &srcPR, &destPR); pr != NULL; pr = pixel_regions_process (pr))
curves (&srcPR, &destPR, (void *) &cd);
pixel_regions_process_parallel((p_func)gimp_lut_process, cd.lut,
2, &srcPR, &destPR);
gimp_lut_free(cd.lut);
drawable_merge_shadow (drawable, TRUE);
drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1));
}
......@@ -1509,6 +1505,7 @@ curves_explicit_invoker (Argument *args)
{
int_value = args[0].value.pdb_int;
drawable = drawable_get_ID (int_value);
cd.drawable = drawable;
if (drawable == NULL)
success = FALSE;
else
......@@ -1564,15 +1561,18 @@ curves_explicit_invoker (Argument *args)
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 */
drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2);
pixel_region_init (&srcPR, drawable_data (drawable), x1, y1, (x2 - x1), (y2 - y1), FALSE);
pixel_region_init (&destPR, drawable_shadow (drawable), x1, y1, (x2 - x1), (y2 - y1), TRUE);
for (pr = pixel_regions_register (2, &srcPR, &destPR); pr != NULL; pr = pixel_regions_process (pr))
curves (&srcPR, &destPR, (void *) &cd);
pixel_regions_process_parallel((p_func)gimp_lut_process, cd.lut,
2, &srcPR, &destPR);
drawable_merge_shadow (drawable, TRUE);
drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1));
......
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* gimplut.c: Copyright (C) 1999 Jay Cox <jaycox@earthlink.net>
*
* 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 "gimplutP.h"
#include "gimplut.h"
#include <stdio.h>
GimpLut *
gimp_lut_new()
{
GimpLut *lut;
lut = g_new(GimpLut, 1);
lut->luts = NULL;
lut->nchannels = 0;
return lut;
}
void
gimp_lut_free(GimpLut *lut)
{
int i;
for (i = 0; i < lut->nchannels; i++)
g_free(lut->luts[i]);
if (lut->luts)
g_free(lut->luts);
}
void
gimp_lut_setup (GimpLut *lut, GimpLutFunc func,
void *user_data, int nchannels)
{
int i, v;
double val;
if (lut->luts)
{
for (i = 0; i < lut->nchannels; i++)
g_free(lut->luts[i]);
g_free(lut->luts);
}
lut->nchannels = nchannels;
lut->luts = g_new(unsigned char*, lut->nchannels);
for (i = 0; i < lut->nchannels; i++)
{
lut->luts[i] = g_new(unsigned char, 256);
for (v = 0; v < 256; v++)
{ /* to add gamma correction use func(v ^ g) ^ 1/g instead. */
val = 255.0 * func(user_data, lut->nchannels, i, v/255.0) + 0.5;
if (val < 0.0)
lut->luts[i][v] = 0;
else if (val >= 255.0)
lut->luts[i][v] = 255;
else
lut->luts[i][v] = val;
}
}
}
void
gimp_lut_setup_exact (GimpLut *lut, GimpLutFunc func,
void *user_data, int nchannels)
{
gimp_lut_setup(lut, func, user_data, nchannels);
}
void
gimp_lut_process (GimpLut *lut,
PixelRegion *srcPR,
PixelRegion *destPR)
{
int h, width, src_r_i, dest_r_i;
unsigned char *src, *dest;
unsigned char *lut0, *lut1, *lut2, *lut3;
if (lut->nchannels > 0)
lut0 = lut->luts[0];
if (lut->nchannels > 1)
lut1 = lut->luts[1];
if (lut->nchannels > 2)
lut2 = lut->luts[2];
if (lut->nchannels > 3)
lut3 = lut->luts[3];
h = srcPR->h;
src = srcPR->data;
dest = destPR->data;
width = srcPR->w;
src_r_i = srcPR->rowstride - (srcPR->bytes * srcPR->w);
dest_r_i = destPR->rowstride - (destPR->bytes * srcPR->w);
if (src_r_i == 0 && dest_r_i == 0)
{
width *= h;
h = 1;
}
while (h--)
{
switch (lut->nchannels)
{
case 1:
while (width--)
{
*dest = lut0[*src];
src++;
dest++;
}
break;
case 2:
while (width--)
{
dest[0] = lut0[src[0]];
dest[1] = lut1[src[1]];
src += 2;
dest += 2;
}
break;
case 3:
while (width--)
{
dest[0] = lut0[src[0]];
dest[1] = lut1[src[1]];
dest[2] = lut2[src[2]];
src += 3;
dest += 3;
}
break;
case 4:
while (width--)
{
dest[0] = lut0[src[0]];
dest[1] = lut1[src[1]];
dest[2] = lut2[src[2]];
dest[3] = lut3[src[3]];
src += 4;
dest += 4;
}
break;
default:
fprintf(stderr, "gimplut: Error: nchannels = %d\n", lut->nchannels);
}
width = srcPR->w;
src += src_r_i;
dest += dest_r_i;
}
}
void
gimp_lut_process_2 (PixelRegion *srcPR,
PixelRegion *destPR,
GimpLut *lut)
{
gimp_lut_process(lut, srcPR, destPR);
}
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* gimplut.h: Copyright (C) 1999 Jay Cox <jaycox@earthlink.net>
*
* 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_LUT_H__
#define __GIMP_LUT_H__
#include "gimplutF.h"
#include "pixel_region.h"
/* TODO: the GimpLutFunc should really be passed the ColorModel of the region,
not just the number of channels */
/* GimpLutFuncs should assume that the input and output gamma are 1.0
and do no correction as this will be handled by gimp_lut_setup */
typedef float (*GimpLutFunc)(void *user_data, int nchannels,
int channel, float value);
GimpLut * gimp_lut_new ();
void gimp_lut_free (GimpLut *lut);
void gimp_lut_setup (GimpLut *, GimpLutFunc,
void *user_data,
int nchannels);
/* gimp_lut_setup_exact is currently identical to gimp_lut_setup. It
however is guaranteed to never perform any interpolation or gamma
correction on the lut */
void gimp_lut_setup_exact (GimpLut *, GimpLutFunc,
void *user_data,
int nchannels);
void gimp_lut_process (GimpLut *lut,
PixelRegion *srcPR,
PixelRegion *destPR);
/* gimp_lut_process_2 is the same as gimp_lut_process but the lut
perameter is last instead of first. this is necesary because
pixel_region_process_paralell sends the user_data as the 1st
parameter, and the image_map functions send user_data as the last
parameter */
void gimp_lut_process_2 (PixelRegion *srcPR,
PixelRegion *destPR,
GimpLut *lut);
#endif /* __GIMP_LUT_H__ */
......@@ -27,6 +27,7 @@
#include "gdisplay.h"
#include "image_map.h"
#include "interface.h"
#include "gimplut.h"
#include "libgimp/gimpintl.h"
......@@ -66,6 +67,8 @@ struct _BrightnessContrastDialog
double contrast;
gint preview;
GimpLut *lut;
};
/* brightness contrast action functions */
......@@ -91,83 +94,58 @@ static void brightness_contrast_contrast_text_update (GtkWidget *, gpointer
static void *brightness_contrast_options = NULL;
static BrightnessContrastDialog *brightness_contrast_dialog = NULL;
static void brightness_contrast (PixelRegion *, PixelRegion *, void *);
static Argument * brightness_contrast_invoker (Argument *);
/* brightness contrast machinery */
static void
brightness_contrast (PixelRegion *srcPR,
PixelRegion *destPR,
void *user_data)
static float
brightness_contrast_lut_func(BrightnessContrastDialog *bcd,
int nchannels, int channel, float value)
{
BrightnessContrastDialog *bcd;
unsigned char *src, *s;
unsigned char *dest, *d;
unsigned char brightness[256];
unsigned char contrast[256];
float nvalue;
double power;
int has_alpha;
int alpha;
int w, h, b;
gint32 value;
int i;
bcd = (BrightnessContrastDialog *) user_data;
/* Set the transfer arrays (for speed) */
h = srcPR->h;
src = srcPR->data;
dest = destPR->data;
has_alpha = (srcPR->bytes == 2 || srcPR->bytes == 4);
alpha = has_alpha ? srcPR->bytes - 1 : srcPR->bytes;
/* return the original value for the alpha channel */
if ((nchannels == 2 || nchannels == 4) && channel == nchannels -1)
return value;
/* apply brightness */
if (bcd->brightness < 0)
for (i = 0; i < 256; i++)
brightness[i] = (unsigned char) ((i * (255 + bcd->brightness)) / 255);
value = value * (1.0 + bcd->brightness/255.0);
else
for (i = 0; i < 256; i++)
brightness[i] = (unsigned char) (i + ((255 - i) * bcd->brightness) / 255);
value = value + ((1.0 - value) * bcd->brightness/255.0);
/* apply contrast */
if (bcd->contrast < 0)
for (i = 0; i < 256; i++)
{
value = (i > 127) ? (255 - i) : i;
value = (int) (127.0 * pow ((double) (value ? value : 1) / 127.0,
(double) (127 + bcd->contrast) / 127.0));
value = CLAMP0255 (value);
contrast[i] = (i > 127) ? (255 - value) : value;
}
{
if (value > 0.5)
nvalue = 1.0 - value;
else
nvalue = value;
if (nvalue < 0.0)
nvalue = 0.0;
nvalue = 0.5 * pow (nvalue * 2.0 , (double) (127 + bcd->contrast) / 127.0);
if (value > 0.5)
value = 1.0 - nvalue;
else
value = nvalue;
}
else
for (i = 0; i < 256; i++)
{
value = (i > 127) ? (255 - i) : i;
power = (bcd->contrast == 127) ? 127 : 127.0 / (127 - bcd->contrast);
value = (int) (127.0 * pow ((double) value / 127.0, power));
value = CLAMP0255 (value);
contrast[i] = (i > 127) ? (255 - value) : value;
}
while (h--)
{
w = srcPR->w;
s = src;
d = dest;
while (w--)
{
for (b = 0; b < alpha; b++)
d[b] = contrast[brightness[s[b]]];
if (has_alpha)
d[alpha] = s[alpha];
s += srcPR->bytes;
d += destPR->bytes;
}
src += srcPR->rowstride;
dest += destPR->rowstride;
}
{
if (value > 0.5)
nvalue = 1.0 - value;
else
nvalue = value;
if (nvalue < 0.0)
nvalue = 0.0;
power = (bcd->contrast == 127) ? 127 : 127.0 / (127 - bcd->contrast);
nvalue = 0.5 * pow (2.0 * nvalue, power);
if (value > 0.5)
value = 1.0 - nvalue;
else
value = nvalue;
}
return value;
}
......@@ -334,6 +312,8 @@ brightness_contrast_new_dialog ()
bcd = g_malloc (sizeof (BrightnessContrastDialog));
bcd->preview = TRUE;
bcd->lut = gimp_lut_new();
/* The shell and main vbox */
bcd->shell = gtk_dialog_new ();
gtk_window_set_wmclass (GTK_WINDOW (bcd->shell), "brightness_contrast", "Gimp");
......@@ -483,7 +463,10 @@ brightness_contrast_preview (BrightnessContrastDialog *bcd)
if (!bcd->image_map)
g_message (_("brightness_contrast_preview(): No image map"));
active_tool->preserve = TRUE;
image_map_apply (bcd->image_map, brightness_contrast, (void *) bcd);
gimp_lut_setup(bcd->lut, (GimpLutFunc) brightness_contrast_lut_func,
(void *) bcd, gimp_drawable_bytes(bcd->drawable));
image_map_apply (bcd->image_map, (ImageMapApplyFunc)gimp_lut_process_2,
(void *) bcd->lut);
active_tool->preserve = FALSE;
}
......@@ -501,7 +484,12 @@ brightness_contrast_ok_callback (GtkWidget *widget,
active_tool->preserve = TRUE;
if (!bcd->preview)
image_map_apply (bcd->image_map, brightness_contrast, (void *) bcd);
{
gimp_lut_setup(bcd->lut, (GimpLutFunc) brightness_contrast_lut_func,
(void *) bcd, gimp_drawable_bytes(bcd->drawable));
image_map_apply (bcd->image_map, (ImageMapApplyFunc)gimp_lut_process_2,
(void *) bcd->lut);
}
if (bcd->image_map)
image_map_commit (bcd->image_map);
......@@ -736,6 +724,7 @@ brightness_contrast_invoker (Argument *args)
{
bcd.brightness = brightness;
bcd.contrast = contrast;
bcd.lut = gimp_lut_new();
/* The application should occur only within selection bounds */
drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2);
......@@ -743,9 +732,13 @@ brightness_contrast_invoker (Argument *args)
pixel_region_init (&srcPR, drawable_data (drawable), x1, y1, (x2 - x1), (y2 - y1), FALSE);
pixel_region_init (&destPR, drawable_shadow (drawable), x1, y1, (x2 - x1), (y2 - y1), TRUE);
for (pr = pixel_regions_register (2, &srcPR, &destPR); pr != NULL; pr = pixel_regions_process (pr))
brightness_contrast (&srcPR, &destPR, (void *) &bcd);
gimp_lut_setup(bcd.lut, (GimpLutFunc) brightness_contrast_lut_func,
(void *) &bcd, gimp_drawable_bytes(drawable));
pixel_regions_process_parallel((p_func)gimp_lut_process, bcd.lut,
2, &srcPR, &destPR);
gimp_lut_free(bcd.lut);
drawable_merge_shadow (drawable, TRUE);
drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1));
}
......
......@@ -340,9 +340,7 @@ by_color_select_button_release (Tool *tool,
GDisplay * gdisp;
int x, y;
GimpDrawable *drawable;
Tile *tile;
unsigned char col[MAX_CHANNELS];
unsigned char *data;
unsigned char *color;
int use_offsets;
gdisp = (GDisplay *) gdisp_ptr;
......@@ -360,25 +358,17 @@ by_color_select_button_release (Tool *tool,
/* Get the start color */
if (by_color_options->sample_merged)
{
if (x < 0 || y < 0 || x >= gdisp->gimage->width || y >= gdisp->gimage->height)
if (!(color = gimp_image_get_color_at(gdisp->gimage, x, y)))
return;
tile = tile_manager_get_tile (gimage_composite (gdisp->gimage), x, y, TRUE, FALSE);
data = tile_data_pointer (tile, x % TILE_WIDTH, y % TILE_HEIGHT);
gimage_get_color (gdisp->gimage, gimage_composite_type(gdisp->gimage), col, data);
tile_release (tile, FALSE);
}
else
{
if (x < 0 || y < 0 || x >= drawable_width (drawable) || y >= drawable_height (drawable))
if (!(color = gimp_drawable_get_color_at(drawable, x, y)))
return;
tile = tile_manager_get_tile (drawable_data (drawable), x, y, TRUE, FALSE);
data = tile_data_pointer (tile, x % TILE_WIDTH, y % TILE_HEIGHT);
gimage_get_color (gdisp->gimage, drawable_type(drawable), col, data);
tile_release (tile, FALSE);
}
/* select the area */
by_color_select (gdisp->gimage, drawable, col,
by_color_select (gdisp->gimage, drawable, color,
by_color_dialog->threshold,
by_color_sel->operation,
by_color_options->antialias,
......@@ -386,6 +376,8 @@ by_color_select_button_release (Tool *tool,
by_color_options->feather_radius,
by_color_options->sample_merged);