Commit 733d6335 authored by Michael Natterer's avatar Michael Natterer 😴 Committed by Michael Natterer

Made the interpolation type configurable in the scale and transform

2002-02-12  Michael Natterer  <mitch@gimp.org>

	Made the interpolation type configurable in the scale and
	transform options dialogs (#69251):

	* app/base/base-config.[ch]
	* app/config/gimpbaseconfig.[ch]: removed interpolation_type here...

	* app/core/gimpcoreconfig.[ch]
	* app/config/gimpcoreconfig.[ch]: ...and added it here.

	* app/gimprc.c
	* app/gui/preferences-dialog.c: changed accordingly.

	* app/paint-funcs/paint-funcs.[ch]: scale_region: take an
	interpolation_type parameter.

	* app/core/gimpchannel.[ch]
	* app/core/gimpdrawable-transform.[ch]
	* app/core/gimpimage-scale.[ch]
	* app/core/gimplayer.[ch]: pass interpolation_type parameters to all
	scale and transform functions.

	* tools/pdbgen/pdb/image.pdb
	* tools/pdbgen/pdb/layer.pdb
	* tools/pdbgen/pdb/transform_tools.pdb: changed accordingly.

	* app/gui/resize-dialog.[ch]
	* app/tools/transform_options.[ch]: added an interpolation_type menu.

	* app/gui/image-commands.c
	* app/gui/layers-commands.c
	* app/tools/gimptransformtool.c: changed accordingly.

	* app/pdb/image_cmds.c
	* app/pdb/layer_cmds.c
	* app/pdb/transform_tools_cmds.c: regenerated.
parent 912dc07c
2002-02-12 Michael Natterer <mitch@gimp.org>
Made the interpolation type configurable in the scale and
transform options dialogs (#69251):
* app/base/base-config.[ch]
* app/config/gimpbaseconfig.[ch]: removed interpolation_type here...
* app/core/gimpcoreconfig.[ch]
* app/config/gimpcoreconfig.[ch]: ...and added it here.
* app/gimprc.c
* app/gui/preferences-dialog.c: changed accordingly.
* app/paint-funcs/paint-funcs.[ch]: scale_region: take an
interpolation_type parameter.
* app/core/gimpchannel.[ch]
* app/core/gimpdrawable-transform.[ch]
* app/core/gimpimage-scale.[ch]
* app/core/gimplayer.[ch]: pass interpolation_type parameters to all
scale and transform functions.
* tools/pdbgen/pdb/image.pdb
* tools/pdbgen/pdb/layer.pdb
* tools/pdbgen/pdb/transform_tools.pdb: changed accordingly.
* app/gui/resize-dialog.[ch]
* app/tools/transform_options.[ch]: added an interpolation_type menu.
* app/gui/image-commands.c
* app/gui/layers-commands.c
* app/tools/gimptransformtool.c: changed accordingly.
* app/pdb/image_cmds.c
* app/pdb/layer_cmds.c
* app/pdb/transform_tools_cmds.c: regenerated.
2002-02-12 Sven Neumann <sven@gimp.org>
* plug-ins/MapObject/mapobject_preview.c:
......
......@@ -349,6 +349,7 @@ image_scale_implement (ImageResize *image_scale)
gimp_image_scale (gimage,
image_scale->resize->width,
image_scale->resize->height,
image_scale->resize->interpolation,
progress_update_and_flush, progress);
progress_end (progress);
......
......@@ -1021,7 +1021,9 @@ scale_layer_query_ok_callback (GtkWidget *widget,
floating_sel_relax (layer, TRUE);
gimp_layer_scale (layer,
options->resize->width, options->resize->height,
options->resize->width,
options->resize->height,
options->resize->interpolation,
TRUE);
if (gimp_layer_is_floating_sel (layer))
......
......@@ -33,13 +33,12 @@
static GimpBaseConfig static_base_config =
{
INIT_MEMBER(temp_path , NULL),
INIT_MEMBER(swap_path , NULL),
INIT_MEMBER(temp_path , NULL),
INIT_MEMBER(swap_path , NULL),
INIT_MEMBER(tile_cache_size , 33554432),
INIT_MEMBER(stingy_memory_use , FALSE),
INIT_MEMBER(interpolation_type , GIMP_LINEAR_INTERPOLATION),
INIT_MEMBER(num_processors , 1)
INIT_MEMBER(tile_cache_size , 33554432),
INIT_MEMBER(stingy_memory_use, FALSE),
INIT_MEMBER(num_processors , 1)
};
#undef INIT_MEMBER
......
......@@ -24,12 +24,11 @@ typedef struct _GimpBaseConfig GimpBaseConfig;
struct _GimpBaseConfig
{
gchar *temp_path;
gchar *swap_path;
guint tile_cache_size;
gboolean stingy_memory_use;
GimpInterpolationType interpolation_type;
gint num_processors;
gchar *temp_path;
gchar *swap_path;
guint tile_cache_size;
gboolean stingy_memory_use;
gint num_processors;
};
......
......@@ -51,7 +51,6 @@ enum
PROP_STINGY_MEMORY_USE,
PROP_NUM_PROCESSORS,
PROP_TILE_CACHE_SIZE,
PROP_INTERPOLATION_TYPE,
};
static GObjectClass *parent_class = NULL;
......@@ -114,10 +113,6 @@ gimp_base_config_class_init (GimpBaseConfigClass *klass)
GIMP_CONFIG_INSTALL_PROP_MEMSIZE (object_class, PROP_TILE_CACHE_SIZE,
"tile-cache-size",
0, G_MAXUINT, 1 << 25);
GIMP_CONFIG_INSTALL_PROP_ENUM (object_class, PROP_INTERPOLATION_TYPE,
"interpolation-type",
GIMP_TYPE_INTERPOLATION_TYPE,
GIMP_LINEAR_INTERPOLATION);
}
static void
......@@ -162,9 +157,6 @@ gimp_base_config_set_property (GObject *object,
case PROP_TILE_CACHE_SIZE:
base_config->tile_cache_size = g_value_get_uint (value);
break;
case PROP_INTERPOLATION_TYPE:
base_config->interpolation_type = g_value_get_enum (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
......@@ -198,9 +190,6 @@ gimp_base_config_get_property (GObject *object,
case PROP_TILE_CACHE_SIZE:
g_value_set_uint (value, base_config->tile_cache_size);
break;
case PROP_INTERPOLATION_TYPE:
g_value_set_enum (value, base_config->interpolation_type);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
......
......@@ -37,14 +37,13 @@ typedef struct _GimpBaseConfigClass GimpBaseConfigClass;
struct _GimpBaseConfig
{
GObject parent_instance;
gchar *temp_path;
gchar *swap_path;
gboolean stingy_memory_use;
guint num_processors;
guint tile_cache_size;
GimpInterpolationType interpolation_type;
GObject parent_instance;
gchar *temp_path;
gchar *swap_path;
gboolean stingy_memory_use;
guint num_processors;
guint tile_cache_size;
};
struct _GimpBaseConfigClass
......
......@@ -46,6 +46,7 @@ static void gimp_core_config_get_property (GObject *object,
enum
{
PROP_0,
PROP_INTERPOLATION_TYPE,
PROP_PLUG_IN_PATH,
PROP_TOOL_PLUG_IN_PATH,
PROP_MODULE_PATH,
......@@ -119,6 +120,10 @@ gimp_core_config_class_init (GimpCoreConfigClass *klass)
object_class->set_property = gimp_core_config_set_property;
object_class->get_property = gimp_core_config_get_property;
GIMP_CONFIG_INSTALL_PROP_ENUM (object_class, PROP_INTERPOLATION_TYPE,
"interpolation-type",
GIMP_TYPE_INTERPOLATION_TYPE,
GIMP_LINEAR_INTERPOLATION);
GIMP_CONFIG_INSTALL_PROP_PATH (object_class, PROP_PLUG_IN_PATH,
"plug-in-path",
gimp_config_build_plug_in_path ("plug-ins"));
......@@ -240,6 +245,9 @@ gimp_core_config_set_property (GObject *object,
switch (property_id)
{
case PROP_INTERPOLATION_TYPE:
core_config->interpolation_type = g_value_get_enum (value);
break;
case PROP_PLUG_IN_PATH:
g_free (core_config->plug_in_path);
core_config->plug_in_path = g_value_dup_string (value);
......@@ -354,6 +362,9 @@ gimp_core_config_get_property (GObject *object,
switch (property_id)
{
case PROP_INTERPOLATION_TYPE:
g_value_set_enum (value, core_config->interpolation_type);
break;
case PROP_PLUG_IN_PATH:
g_value_set_string (value, core_config->plug_in_path);
break;
......
......@@ -39,35 +39,36 @@ typedef struct _GimpCoreConfigClass GimpCoreConfigClass;
struct _GimpCoreConfig
{
GimpBaseConfig parent_instance;
GimpBaseConfig parent_instance;
gchar *plug_in_path;
gchar *tool_plug_in_path;
gchar *module_path;
gchar *brush_path;
gchar *pattern_path;
gchar *palette_path;
gchar *gradient_path;
gchar *default_brush;
gchar *default_pattern;
gchar *default_palette;
gchar *default_gradient;
gchar *default_comment;
GimpImageBaseType default_image_type;
gint default_image_width;
gint default_image_height;
GimpUnit default_unit;
gdouble default_xresolution;
gdouble default_yresolution;
GimpUnit default_resolution_unit;
gint levels_of_undo;
gchar *plug_in_rc_path;
gchar *module_load_inhibit;
GimpPreviewSize preview_size;
gboolean write_thumbnails;
gdouble gamma_val;
gboolean install_cmap;
gint min_colors;
GimpInterpolationType interpolation_type;
gchar *plug_in_path;
gchar *tool_plug_in_path;
gchar *module_path;
gchar *brush_path;
gchar *pattern_path;
gchar *palette_path;
gchar *gradient_path;
gchar *default_brush;
gchar *default_pattern;
gchar *default_palette;
gchar *default_gradient;
gchar *default_comment;
GimpImageBaseType default_image_type;
gint default_image_width;
gint default_image_height;
GimpUnit default_unit;
gdouble default_xresolution;
gdouble default_yresolution;
GimpUnit default_resolution_unit;
gint levels_of_undo;
gchar *plug_in_rc_path;
gchar *module_load_inhibit;
GimpPreviewSize preview_size;
gboolean write_thumbnails;
gdouble gamma_val;
gboolean install_cmap;
gint min_colors;
};
struct _GimpCoreConfigClass
......
......@@ -79,7 +79,7 @@ static gdouble gimp_drawable_transform_cubic (gdouble dx,
TileManager *
gimp_drawable_transform_tiles_affine (GimpDrawable *drawable,
TileManager *float_tiles,
gboolean interpolation,
GimpInterpolationType interpolation_type,
gboolean clip_result,
GimpMatrix3 matrix,
GimpTransformDirection direction,
......@@ -123,9 +123,10 @@ gimp_drawable_transform_tiles_affine (GimpDrawable *drawable,
alpha = 0;
/* turn interpolation off for simple transformations (e.g. rot90) */
if (gimp_matrix3_is_simple (matrix) ||
base_config->interpolation_type == GIMP_NEAREST_NEIGHBOR_INTERPOLATION)
interpolation = FALSE;
if (gimp_matrix3_is_simple (matrix))
{
interpolation_type = GIMP_NEAREST_NEIGHBOR_INTERPOLATION;
}
/* Get the background color */
gimp_image_get_background (gimage, drawable, bg_col);
......@@ -144,7 +145,7 @@ gimp_drawable_transform_tiles_affine (GimpDrawable *drawable,
bg_col[ALPHA_I_PIX] = TRANSPARENT_OPACITY;
alpha = ALPHA_I_PIX;
/* If the gimage is indexed color, ignore smoothing value */
interpolation = FALSE;
interpolation_type = GIMP_NEAREST_NEIGHBOR_INTERPOLATION;
break;
default:
g_assert_not_reached ();
......@@ -230,21 +231,20 @@ gimp_drawable_transform_tiles_affine (GimpDrawable *drawable,
tile_manager_set_offsets (tiles, tx1, ty1);
/* initialise the pixel_surround accessor */
if (interpolation)
{
if (base_config->interpolation_type == GIMP_CUBIC_INTERPOLATION)
{
pixel_surround_init (&surround, float_tiles, 4, 4, bg_col);
}
else
{
pixel_surround_init (&surround, float_tiles, 2, 2, bg_col);
}
}
else
switch (interpolation_type)
{
case GIMP_CUBIC_INTERPOLATION:
pixel_surround_init (&surround, float_tiles, 4, 4, bg_col);
break;
case GIMP_LINEAR_INTERPOLATION:
pixel_surround_init (&surround, float_tiles, 2, 2, bg_col);
break;
case GIMP_NEAREST_NEIGHBOR_INTERPOLATION:
/* not actually useful, keeps the code cleaner */
pixel_surround_init (&surround, float_tiles, 1, 1, bg_col);
break;
}
width = tile_manager_width (tiles);
......@@ -292,195 +292,192 @@ gimp_drawable_transform_tiles_affine (GimpDrawable *drawable,
/* Set the destination pixels */
if (interpolation)
{
if (base_config->interpolation_type == GIMP_CUBIC_INTERPOLATION)
{
/* ttx & tty are the subpixel coordinates of the point in
* the original selection's floating buffer.
* We need the four integer pixel coords around them:
* itx to itx + 3, ity to ity + 3
*/
itx = floor (ttx);
ity = floor (tty);
switch (interpolation_type)
{
case GIMP_CUBIC_INTERPOLATION:
/* ttx & tty are the subpixel coordinates of the point in
* the original selection's floating buffer.
* We need the four integer pixel coords around them:
* itx to itx + 3, ity to ity + 3
*/
itx = floor (ttx);
ity = floor (tty);
/* check if any part of our region overlaps the buffer */
/* check if any part of our region overlaps the buffer */
if ((itx + 2) >= x1 && (itx - 1) < x2 &&
(ity + 2) >= y1 && (ity - 1) < y2 )
if ((itx + 2) >= x1 && (itx - 1) < x2 &&
(ity + 2) >= y1 && (ity - 1) < y2 )
{
guchar *data;
gint row;
gdouble dx, dy;
guchar *start;
/* lock the pixel surround */
data = pixel_surround_lock (&surround,
itx - 1 - x1, ity - 1 - y1);
row = pixel_surround_rowstride (&surround);
/* the fractional error */
dx = ttx - itx;
dy = tty - ity;
/* calculate alpha of result */
start = &data[alpha];
a_val = gimp_drawable_transform_cubic
(dy,
CUBIC_ROW (dx, start, bytes),
CUBIC_ROW (dx, start + row, bytes),
CUBIC_ROW (dx, start + row + row, bytes),
CUBIC_ROW (dx, start + row + row + row, bytes));
if (a_val <= 0.0)
{
a_recip = 0.0;
d[alpha] = 0;
}
else if (a_val > 255.0)
{
a_recip = 1.0 / a_val;
d[alpha] = 255;
}
else
{
guchar *data;
gint row;
gdouble dx, dy;
guchar *start;
/* lock the pixel surround */
data = pixel_surround_lock (&surround,
itx - 1 - x1, ity - 1 - y1);
row = pixel_surround_rowstride (&surround);
/* the fractional error */
dx = ttx - itx;
dy = tty - ity;
/* calculate alpha of result */
start = &data[alpha];
a_val = gimp_drawable_transform_cubic
(dy,
CUBIC_ROW (dx, start, bytes),
CUBIC_ROW (dx, start + row, bytes),
CUBIC_ROW (dx, start + row + row, bytes),
CUBIC_ROW (dx, start + row + row + row, bytes));
if (a_val <= 0.0)
{
a_recip = 0.0;
d[alpha] = 0;
}
else if (a_val > 255.0)
{
a_recip = 1.0 / a_val;
d[alpha] = 255;
}
else
{
a_recip = 1.0 / a_val;
d[alpha] = RINT(a_val);
}
/* for colour channels c,
* result = bicubic (c * alpha) / bicubic (alpha)
*
* never entered for alpha == 0
*/
for (i = -alpha; i < 0; ++i)
{
start = &data[alpha];
newval =
RINT (a_recip *
gimp_drawable_transform_cubic
(dy,
CUBIC_SCALED_ROW (dx, start, bytes, i),
CUBIC_SCALED_ROW (dx, start + row, bytes, i),
CUBIC_SCALED_ROW (dx, start + row + row, bytes, i),
CUBIC_SCALED_ROW (dx, start + row + row + row, bytes, i)));
if (newval <= 0)
{
*d++ = 0;
}
else if (newval > 255)
{
*d++ = 255;
}
else
{
*d++ = newval;
}
}
/* alpha already done */
d++;
pixel_surround_release (&surround);
}
else /* not in source range */
a_recip = 1.0 / a_val;
d[alpha] = RINT(a_val);
}
/* for colour channels c,
* result = bicubic (c * alpha) / bicubic (alpha)
*
* never entered for alpha == 0
*/
for (i = -alpha; i < 0; ++i)
{
/* increment the destination pointers */
for (b = 0; b < bytes; b++)
*d++ = bg_col[b];
start = &data[alpha];
newval =
RINT (a_recip *
gimp_drawable_transform_cubic
(dy,
CUBIC_SCALED_ROW (dx, start, bytes, i),
CUBIC_SCALED_ROW (dx, start + row, bytes, i),
CUBIC_SCALED_ROW (dx, start + row + row, bytes, i),
CUBIC_SCALED_ROW (dx, start + row + row + row, bytes, i)));
if (newval <= 0)
{
*d++ = 0;
}
else if (newval > 255)
{
*d++ = 255;
}
else
{
*d++ = newval;
}
}
/* alpha already done */
d++;
pixel_surround_release (&surround);
}
else /* not in source range */
{
/* increment the destination pointers */
for (b = 0; b < bytes; b++)
*d++ = bg_col[b];
}
break;
case GIMP_LINEAR_INTERPOLATION:
itx = floor (ttx);
ity = floor (tty);
else /* linear */
/* expand source area to cover interpolation region
* (which runs from itx to itx + 1, same in y)
*/
if ((itx + 1) >= x1 && itx < x2 &&
(ity + 1) >= y1 && ity < y2 )
{
itx = floor (ttx);
ity = floor (tty);
/* expand source area to cover interpolation region
* (which runs from itx to itx + 1, same in y)
*/
if ((itx + 1) >= x1 && itx < x2 &&
(ity + 1) >= y1 && ity < y2 )
guchar *data;
gint row;
double dx, dy;
guchar *chan;
/* lock the pixel surround */
data = pixel_surround_lock (&surround, itx - x1, ity - y1);
row = pixel_surround_rowstride (&surround);
/* the fractional error */
dx = ttx - itx;
dy = tty - ity;
/* calculate alpha value of result pixel */
chan = &data[alpha];
a_val = BILINEAR (chan[0], chan[bytes], chan[row],
chan[row+bytes], dx, dy);
if (a_val <= 0.0)
{
guchar *data;
gint row;
double dx, dy;
guchar *chan;
/* lock the pixel surround */
data = pixel_surround_lock (&surround, itx - x1, ity - y1);
row = pixel_surround_rowstride (&surround);
/* the fractional error */
dx = ttx - itx;
dy = tty - ity;
/* calculate alpha value of result pixel */
chan = &data[alpha];
a_val = BILINEAR (chan[0], chan[bytes], chan[row],
chan[row+bytes], dx, dy);
if (a_val <= 0.0)
{
a_recip = 0.0;
d[alpha] = 0.0;
}
else if (a_val >= 255.0)
{
a_recip = 1.0 / a_val;
d[alpha] = 255;
}
else
{
a_recip = 1.0 / a_val;
d[alpha] = RINT (a_val);
}
/* for colour channels c,
* result = bilinear (c * alpha) / bilinear (alpha)
*
* never entered for alpha == 0
*/
for (i = -alpha; i < 0; ++i)
{
chan = &data[alpha];
newval =
RINT (a_recip *
BILINEAR (chan[0] * chan[i],
chan[bytes] * chan[bytes+i],
chan[row] * chan[row+i],
chan[row+bytes] * chan[row+bytes+i],
dx, dy));
if (newval <= 0)
{
*d++ = 0;
}
else if (newval > 255)
{
*d++ = 255;
}
else
{
*d++ = newval;
}
}
/* alpha already done */
d++;
pixel_surround_release (&surround);
}