1997-11-25 06:05:25 +08:00
|
|
|
/* 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
|
1998-04-13 13:44:11 +08:00
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
1997-11-25 06:05:25 +08:00
|
|
|
*/
|
2000-12-15 23:54:17 +08:00
|
|
|
|
app/appenv.h New file. Includes <math.h>. Move G_PI, RINT(), ROUND() etc
1999-09-01 Tor Lillqvist <tml@iki.fi>
* app/appenv.h
* libgimp/gimpmath.h: New file. Includes <math.h>. Move G_PI,
RINT(), ROUND() etc from app/appenv.h here, so plug-ins can
use them, too. Remove some commented-out old stuff in appenv.h.
* libgimp/gimp.h: Include gimpmath.h.
* libgimp/gimp.c (gimp_main): Win32: Don't install signal
handlers, we can't do anything useful in the handler ourselves
anyway (it would be nice to print out a backtrace, but that seems
pretty hard to do, even if not impossible). Let Windows inform the
user about the crash. If the plug-in was compiled with MSVC, and
the user also has it, she is offered a chance to start the
debugger automatically anyway.
* app/*several*.c: Include gimpmath.h for G_PI etc. Don't include
<math.h>, as gimpmath.h includes it.
* plug-ins/*/*many*.c: Include config.h. Don't include <math.h>.
Remove all the duplicated definitions of G_PI and rint(). Use
RINT() instead of rint().
* app/app_procs.[ch]: app_exit() takes a gboolean.
* app/batch.c
* app/commands.c
* app/interface.c: Call app_exit() with FALSE or TRUE.
* app/main.c (on_error): Call gimp_fatal_error. (main): Don't
install any signal handler on Win32 here, either.
* app/errors.c (gimp_fatal_error, gimp_terminate): Win32: Format
the message and call MessageBox with it. g_on_error_query doesn't
do anything useful on Win32, and printf'ing a message to stdout or
stderr doesn't do anything, either, in a windowing application.
1999-09-02 04:30:56 +08:00
|
|
|
#include "config.h"
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
app/appenv.h New file. Includes <math.h>. Move G_PI, RINT(), ROUND() etc
1999-09-01 Tor Lillqvist <tml@iki.fi>
* app/appenv.h
* libgimp/gimpmath.h: New file. Includes <math.h>. Move G_PI,
RINT(), ROUND() etc from app/appenv.h here, so plug-ins can
use them, too. Remove some commented-out old stuff in appenv.h.
* libgimp/gimp.h: Include gimpmath.h.
* libgimp/gimp.c (gimp_main): Win32: Don't install signal
handlers, we can't do anything useful in the handler ourselves
anyway (it would be nice to print out a backtrace, but that seems
pretty hard to do, even if not impossible). Let Windows inform the
user about the crash. If the plug-in was compiled with MSVC, and
the user also has it, she is offered a chance to start the
debugger automatically anyway.
* app/*several*.c: Include gimpmath.h for G_PI etc. Don't include
<math.h>, as gimpmath.h includes it.
* plug-ins/*/*many*.c: Include config.h. Don't include <math.h>.
Remove all the duplicated definitions of G_PI and rint(). Use
RINT() instead of rint().
* app/app_procs.[ch]: app_exit() takes a gboolean.
* app/batch.c
* app/commands.c
* app/interface.c: Call app_exit() with FALSE or TRUE.
* app/main.c (on_error): Call gimp_fatal_error. (main): Don't
install any signal handler on Win32 here, either.
* app/errors.c (gimp_fatal_error, gimp_terminate): Win32: Format
the message and call MessageBox with it. g_on_error_query doesn't
do anything useful on Win32, and printf'ing a message to stdout or
stderr doesn't do anything, either, in a windowing application.
1999-09-02 04:30:56 +08:00
|
|
|
|
2001-08-14 22:53:55 +08:00
|
|
|
#include <glib-object.h>
|
2000-12-17 05:37:03 +08:00
|
|
|
|
2001-01-29 21:51:23 +08:00
|
|
|
#include "libgimpcolor/gimpcolor.h"
|
2001-01-24 07:56:18 +08:00
|
|
|
#include "libgimpmath/gimpmath.h"
|
|
|
|
|
2001-05-10 06:34:59 +08:00
|
|
|
#include "core-types.h"
|
2000-12-17 05:37:03 +08:00
|
|
|
|
2001-05-15 19:25:25 +08:00
|
|
|
#include "base/boundary.h"
|
|
|
|
#include "base/gimplut.h"
|
2001-05-23 07:05:35 +08:00
|
|
|
#include "base/lut-funcs.h"
|
2001-05-15 19:25:25 +08:00
|
|
|
#include "base/pixel-processor.h"
|
|
|
|
#include "base/pixel-region.h"
|
|
|
|
#include "base/tile.h"
|
|
|
|
#include "base/tile-manager.h"
|
|
|
|
|
2001-04-07 23:58:26 +08:00
|
|
|
#include "paint-funcs/paint-funcs.h"
|
|
|
|
|
2000-12-29 23:22:01 +08:00
|
|
|
#include "gimpimage.h"
|
2003-03-12 07:54:49 +08:00
|
|
|
#include "gimpimage-projection.h"
|
2003-02-14 22:14:29 +08:00
|
|
|
#include "gimpimage-undo-push.h"
|
2001-02-02 02:44:22 +08:00
|
|
|
#include "gimpchannel.h"
|
|
|
|
#include "gimplayer.h"
|
2001-07-10 03:48:30 +08:00
|
|
|
#include "gimpparasitelist.h"
|
2001-07-08 06:49:01 +08:00
|
|
|
|
2000-04-28 01:27:28 +08:00
|
|
|
#include "libgimp/gimpintl.h"
|
|
|
|
|
|
|
|
|
2003-02-11 21:52:47 +08:00
|
|
|
static void gimp_channel_class_init (GimpChannelClass *klass);
|
|
|
|
static void gimp_channel_init (GimpChannel *channel);
|
2001-08-11 22:39:19 +08:00
|
|
|
|
2003-02-11 21:52:47 +08:00
|
|
|
static void gimp_channel_finalize (GObject *object);
|
2002-01-31 00:14:26 +08:00
|
|
|
|
2003-02-11 21:52:47 +08:00
|
|
|
static gsize gimp_channel_get_memsize (GimpObject *object);
|
1998-01-22 15:02:57 +08:00
|
|
|
|
2003-02-11 21:52:47 +08:00
|
|
|
static GimpItem * gimp_channel_duplicate (GimpItem *item,
|
|
|
|
GType new_type,
|
|
|
|
gboolean add_alpha);
|
|
|
|
|
2003-02-14 22:14:29 +08:00
|
|
|
static void gimp_channel_push_undo (GimpChannel *mask,
|
|
|
|
const gchar *undo_desc);
|
2003-02-11 21:52:47 +08:00
|
|
|
static void gimp_channel_validate (TileManager *tm,
|
|
|
|
Tile *tile);
|
2002-08-20 18:22:23 +08:00
|
|
|
|
2000-12-17 06:02:10 +08:00
|
|
|
|
2001-01-29 21:51:23 +08:00
|
|
|
static GimpDrawableClass * parent_class = NULL;
|
1998-01-22 15:02:57 +08:00
|
|
|
|
2001-01-15 01:11:14 +08:00
|
|
|
|
2001-08-11 22:39:19 +08:00
|
|
|
GType
|
2000-12-29 00:19:55 +08:00
|
|
|
gimp_channel_get_type (void)
|
1998-01-22 15:02:57 +08:00
|
|
|
{
|
2001-08-11 22:39:19 +08:00
|
|
|
static GType channel_type = 0;
|
1998-01-22 15:02:57 +08:00
|
|
|
|
2001-08-11 22:39:19 +08:00
|
|
|
if (! channel_type)
|
1998-01-22 15:02:57 +08:00
|
|
|
{
|
2001-08-11 22:39:19 +08:00
|
|
|
static const GTypeInfo channel_info =
|
1998-01-22 15:02:57 +08:00
|
|
|
{
|
2001-08-11 22:39:19 +08:00
|
|
|
sizeof (GimpChannelClass),
|
|
|
|
(GBaseInitFunc) NULL,
|
|
|
|
(GBaseFinalizeFunc) NULL,
|
|
|
|
(GClassInitFunc) gimp_channel_class_init,
|
|
|
|
NULL, /* class_finalize */
|
|
|
|
NULL, /* class_data */
|
1998-01-22 15:02:57 +08:00
|
|
|
sizeof (GimpChannel),
|
2001-08-11 22:39:19 +08:00
|
|
|
0, /* n_preallocs */
|
|
|
|
(GInstanceInitFunc) gimp_channel_init,
|
1998-01-22 15:02:57 +08:00
|
|
|
};
|
|
|
|
|
2001-08-11 22:39:19 +08:00
|
|
|
channel_type = g_type_register_static (GIMP_TYPE_DRAWABLE,
|
|
|
|
"GimpChannel",
|
|
|
|
&channel_info, 0);
|
1998-01-22 15:02:57 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return channel_type;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2001-01-10 08:36:54 +08:00
|
|
|
gimp_channel_class_init (GimpChannelClass *klass)
|
1998-01-22 15:02:57 +08:00
|
|
|
{
|
2003-03-22 08:48:09 +08:00
|
|
|
GObjectClass *object_class;
|
|
|
|
GimpObjectClass *gimp_object_class;
|
|
|
|
GimpViewableClass *viewable_class;
|
|
|
|
GimpItemClass *item_class;
|
1998-01-22 15:02:57 +08:00
|
|
|
|
2002-01-31 00:14:26 +08:00
|
|
|
object_class = G_OBJECT_CLASS (klass);
|
|
|
|
gimp_object_class = GIMP_OBJECT_CLASS (klass);
|
2003-03-22 08:48:09 +08:00
|
|
|
viewable_class = GIMP_VIEWABLE_CLASS (klass);
|
2003-02-11 21:52:47 +08:00
|
|
|
item_class = GIMP_ITEM_CLASS (klass);
|
2001-01-10 08:36:54 +08:00
|
|
|
|
Port to glib/gtk+ 2.0 episode I (every segfault has it's beginning)
2001-07-24 Michael Natterer <mitch@gimp.org>
Port to glib/gtk+ 2.0 episode I (every segfault has it's beginning)
* configure.in: require glib/gtk+ >= 1.3.7, commented out the
gtkxmhtml stuff.
From now on, you will need glib, pango, atk and gtk+ HEAD from CVS
to hack or use GIMP HEAD.
Beware, it crashes randomly :)
* app/core/Makefile.am
* app/core/gimpmarshal.list: new file plus rules to generate
gimpmarshal.[ch] from it.
* app/core/*
* app/tools/*
* app/widgets/*
* libgimpwidgets/*: started to use the glib object system. All
core/ objects are still gtk objects however. All signals are
created using g_signal_new(). There are many gtk+ artefacts left.
Finally, we will _not_ use the gtk_signal_foo() wrappers and
friends any more.
* app/colormaps.c
* app/devices.[ch]
* app/disp_callbacks.c
* app/errorconsole.c
* app/file-save.[ch]
* app/interface.c
* app/module_db.c
* app/nav_window.c
* app/ops_buttons.c
* app/scroll.c
* app/user_install.c
* app/gui/about-dialog.c
* app/gui/brush-editor.c
* app/gui/brushes-commands.c
* app/gui/color-notebook.c
* app/gui/colormap-dialog.c
* app/gui/dialogs-commands.c
* app/gui/dialogs-constructors.c
* app/gui/file-commands.c
* app/gui/file-dialog-utils.c
* app/gui/file-new-dialog.c
* app/gui/file-open-dialog.[ch]
* app/gui/file-save-dialog.c
* app/gui/gradient-editor.c
* app/gui/gradients-commands.c
* app/gui/image-commands.c
* app/gui/info-dialog.[ch]
* app/gui/layer-select.c
* app/gui/layers-commands.c
* app/gui/menus.c
* app/gui/offset-dialog.c
* app/gui/palette-editor.c
* app/gui/palettes-commands.c
* app/gui/patterns-commands.c
* app/gui/preferences-dialog.c
* app/gui/resize-dialog.[ch]
* app/gui/splash.c
* app/gui/tips-dialog.c
* app/gui/tool-options-dialog.c
* app/gui/toolbox.c
* app/gui/tools-commands.c
* libgimp/gimpbrushmenu.c
* libgimp/gimpmenu.c
* libgimp/gimppatternmenu.c
* libgimp/gimpui.c
* libgimpbase/gimpenv.c: tons and tons of changes like "const
gchar*", switch from GdkDeviceInfo to GdkDevice (very incomplete
and currently disables), lots of s/gtk_signal/g_signal/,
removal/replacement of deprecated stuff,
s/GtkSignalFunc/GCallback/ and lots of small changes and fixes
while I was on it, zillions of warnings left...
* modules/Makefile.am: disabled the water color selector
temporarily (XInput issues).
* plug-ins/Makefile.am
* plug-ins/common/.cvsignore
* plug-ins/common/Makefile.am
* plug-ins/common/plugin-defs.pl: simply excluded all plug-ins
which did not build (including Script-Fu). They are trivial to
fix.
2001-07-25 05:27:11 +08:00
|
|
|
parent_class = g_type_class_peek_parent (klass);
|
1998-01-22 15:02:57 +08:00
|
|
|
|
2003-03-22 08:48:09 +08:00
|
|
|
object_class->finalize = gimp_channel_finalize;
|
2002-01-31 00:14:26 +08:00
|
|
|
|
2003-03-22 08:48:09 +08:00
|
|
|
gimp_object_class->get_memsize = gimp_channel_get_memsize;
|
2003-02-11 21:52:47 +08:00
|
|
|
|
2003-03-22 08:48:09 +08:00
|
|
|
viewable_class->default_stock_id = "gimp-channel";
|
|
|
|
|
|
|
|
item_class->duplicate = gimp_channel_duplicate;
|
|
|
|
item_class->default_name = _("Channel");
|
|
|
|
item_class->rename_desc = _("Rename Channel");
|
1998-01-22 15:02:57 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_channel_init (GimpChannel *channel)
|
|
|
|
{
|
2002-03-04 01:38:12 +08:00
|
|
|
gimp_rgba_set (&channel->color, 0.0, 0.0, 0.0, GIMP_OPACITY_OPAQUE);
|
2001-01-29 21:51:23 +08:00
|
|
|
|
|
|
|
channel->show_masked = FALSE;
|
|
|
|
|
|
|
|
/* Selection mask variables */
|
2003-01-11 01:55:53 +08:00
|
|
|
channel->boundary_known = FALSE;
|
2001-01-29 21:51:23 +08:00
|
|
|
channel->segs_in = NULL;
|
|
|
|
channel->segs_out = NULL;
|
|
|
|
channel->num_segs_in = 0;
|
|
|
|
channel->num_segs_out = 0;
|
2003-01-11 01:55:53 +08:00
|
|
|
channel->empty = FALSE;
|
|
|
|
channel->bounds_known = FALSE;
|
2001-01-29 21:51:23 +08:00
|
|
|
channel->x1 = 0;
|
|
|
|
channel->y1 = 0;
|
|
|
|
channel->x2 = 0;
|
|
|
|
channel->y2 = 0;
|
1998-01-22 15:02:57 +08:00
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2001-01-29 21:51:23 +08:00
|
|
|
static void
|
2001-08-11 22:39:19 +08:00
|
|
|
gimp_channel_finalize (GObject *object)
|
2001-01-29 21:51:23 +08:00
|
|
|
{
|
|
|
|
GimpChannel *channel;
|
|
|
|
|
|
|
|
channel = GIMP_CHANNEL (object);
|
|
|
|
|
|
|
|
if (channel->segs_in)
|
2001-08-11 22:39:19 +08:00
|
|
|
{
|
|
|
|
g_free (channel->segs_in);
|
|
|
|
channel->segs_in = NULL;
|
|
|
|
}
|
|
|
|
|
2001-01-29 21:51:23 +08:00
|
|
|
if (channel->segs_out)
|
2001-08-11 22:39:19 +08:00
|
|
|
{
|
|
|
|
g_free (channel->segs_out);
|
|
|
|
channel->segs_out = NULL;
|
|
|
|
}
|
2001-01-29 21:51:23 +08:00
|
|
|
|
2001-08-11 22:39:19 +08:00
|
|
|
G_OBJECT_CLASS (parent_class)->finalize (object);
|
2001-01-29 21:51:23 +08:00
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2002-01-31 00:14:26 +08:00
|
|
|
static gsize
|
|
|
|
gimp_channel_get_memsize (GimpObject *object)
|
|
|
|
{
|
|
|
|
GimpChannel *channel;
|
|
|
|
gsize memsize = 0;
|
|
|
|
|
|
|
|
channel = GIMP_CHANNEL (object);
|
|
|
|
|
|
|
|
memsize += channel->num_segs_in * sizeof (BoundSeg);
|
|
|
|
memsize += channel->num_segs_out * sizeof (BoundSeg);
|
|
|
|
|
|
|
|
return memsize + GIMP_OBJECT_CLASS (parent_class)->get_memsize (object);
|
|
|
|
}
|
|
|
|
|
2003-02-11 21:52:47 +08:00
|
|
|
static GimpItem *
|
|
|
|
gimp_channel_duplicate (GimpItem *item,
|
|
|
|
GType new_type,
|
|
|
|
gboolean add_alpha)
|
|
|
|
{
|
|
|
|
GimpChannel *channel;
|
|
|
|
GimpItem *new_item;
|
|
|
|
GimpChannel *new_channel;
|
|
|
|
|
|
|
|
g_return_val_if_fail (g_type_is_a (new_type, GIMP_TYPE_DRAWABLE), NULL);
|
|
|
|
|
|
|
|
if (g_type_is_a (new_type, GIMP_TYPE_CHANNEL))
|
|
|
|
add_alpha = FALSE;
|
|
|
|
|
|
|
|
new_item = GIMP_ITEM_CLASS (parent_class)->duplicate (item, new_type,
|
|
|
|
add_alpha);
|
|
|
|
|
|
|
|
if (! GIMP_IS_CHANNEL (new_item))
|
|
|
|
return new_item;
|
|
|
|
|
|
|
|
channel = GIMP_CHANNEL (item);
|
|
|
|
new_channel = GIMP_CHANNEL (new_item);
|
|
|
|
|
|
|
|
/* set the channel color and opacity */
|
|
|
|
new_channel->color = channel->color;
|
|
|
|
|
|
|
|
new_channel->show_masked = channel->show_masked;
|
|
|
|
|
|
|
|
/* selection mask variables */
|
|
|
|
new_channel->bounds_known = channel->bounds_known;
|
|
|
|
new_channel->empty = channel->empty;
|
|
|
|
new_channel->x1 = channel->x1;
|
|
|
|
new_channel->y1 = channel->y1;
|
|
|
|
new_channel->x2 = channel->x2;
|
|
|
|
new_channel->y2 = channel->y2;
|
|
|
|
|
|
|
|
return new_item;
|
|
|
|
}
|
|
|
|
|
2002-08-20 18:22:23 +08:00
|
|
|
static void
|
2003-02-14 22:14:29 +08:00
|
|
|
gimp_channel_push_undo (GimpChannel *mask,
|
|
|
|
const gchar *undo_desc)
|
2002-08-20 18:22:23 +08:00
|
|
|
{
|
|
|
|
GimpImage *gimage;
|
|
|
|
|
|
|
|
gimage = gimp_item_get_image (GIMP_ITEM (mask));
|
|
|
|
|
2002-08-30 00:48:17 +08:00
|
|
|
g_return_if_fail (gimage != NULL);
|
|
|
|
|
2003-02-14 22:14:29 +08:00
|
|
|
gimp_image_undo_push_mask (gimage, undo_desc, mask);
|
2002-08-20 18:22:23 +08:00
|
|
|
|
|
|
|
mask->boundary_known = FALSE;
|
|
|
|
|
|
|
|
/* invalidate the preview */
|
|
|
|
GIMP_DRAWABLE (mask)->preview_valid = FALSE;
|
|
|
|
}
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
static void
|
2001-01-29 10:45:02 +08:00
|
|
|
gimp_channel_validate (TileManager *tm,
|
|
|
|
Tile *tile)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
|
|
|
/* Set the contents of the tile to empty */
|
1998-08-12 01:35:34 +08:00
|
|
|
memset (tile_data_pointer (tile, 0, 0),
|
1999-08-22 19:45:31 +08:00
|
|
|
TRANSPARENT_OPACITY, tile_size (tile));
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
2002-08-20 18:22:23 +08:00
|
|
|
|
|
|
|
/* public functions */
|
|
|
|
|
2001-01-29 10:45:02 +08:00
|
|
|
GimpChannel *
|
|
|
|
gimp_channel_new (GimpImage *gimage,
|
2001-12-03 21:44:59 +08:00
|
|
|
gint width,
|
|
|
|
gint height,
|
2001-01-29 10:45:02 +08:00
|
|
|
const gchar *name,
|
|
|
|
const GimpRGB *color)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2001-01-29 10:45:02 +08:00
|
|
|
GimpChannel *channel;
|
2001-01-15 12:37:01 +08:00
|
|
|
|
2002-08-30 00:48:17 +08:00
|
|
|
g_return_val_if_fail (GIMP_IS_IMAGE (gimage), NULL);
|
2001-01-15 12:37:01 +08:00
|
|
|
g_return_val_if_fail (color != NULL, NULL);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2001-08-10 22:41:39 +08:00
|
|
|
channel = g_object_new (GIMP_TYPE_CHANNEL, NULL);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2001-01-29 10:45:02 +08:00
|
|
|
gimp_drawable_configure (GIMP_DRAWABLE (channel),
|
2003-02-01 00:37:03 +08:00
|
|
|
gimage,
|
|
|
|
0, 0, width, height,
|
|
|
|
GIMP_GRAY_IMAGE, name);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/* set the channel color and opacity */
|
2001-12-13 07:48:18 +08:00
|
|
|
channel->color = *color;
|
2001-12-03 21:44:59 +08:00
|
|
|
|
1999-08-22 19:45:31 +08:00
|
|
|
channel->show_masked = TRUE;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/* selection mask variables */
|
2001-12-13 07:48:18 +08:00
|
|
|
channel->x2 = width;
|
|
|
|
channel->y2 = height;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
return channel;
|
|
|
|
}
|
|
|
|
|
2003-03-12 07:54:49 +08:00
|
|
|
GimpChannel *
|
|
|
|
gimp_channel_new_from_component (GimpImage *gimage,
|
|
|
|
GimpChannelType type,
|
|
|
|
const gchar *name,
|
|
|
|
const GimpRGB *color)
|
|
|
|
{
|
|
|
|
GimpChannel *channel;
|
|
|
|
TileManager *projection;
|
|
|
|
PixelRegion src;
|
|
|
|
PixelRegion dest;
|
|
|
|
gint width;
|
|
|
|
gint height;
|
|
|
|
gint pixel = -1;
|
|
|
|
|
|
|
|
g_return_val_if_fail (GIMP_IS_IMAGE (gimage), NULL);
|
|
|
|
g_return_val_if_fail (color != NULL, NULL);
|
|
|
|
|
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
case GIMP_RED_CHANNEL: pixel = RED_PIX; break;
|
|
|
|
case GIMP_GREEN_CHANNEL: pixel = GREEN_PIX; break;
|
|
|
|
case GIMP_BLUE_CHANNEL: pixel = BLUE_PIX; break;
|
|
|
|
case GIMP_GRAY_CHANNEL: pixel = GRAY_PIX; break;
|
|
|
|
case GIMP_INDEXED_CHANNEL: pixel = INDEXED_PIX; break;
|
|
|
|
case GIMP_ALPHA_CHANNEL:
|
|
|
|
switch (gimp_image_base_type (gimage))
|
|
|
|
{
|
|
|
|
case GIMP_RGB: pixel = ALPHA_PIX; break;
|
|
|
|
case GIMP_GRAY: pixel = ALPHA_G_PIX; break;
|
|
|
|
case GIMP_INDEXED: pixel = ALPHA_I_PIX; break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_return_val_if_fail (pixel != -1, NULL);
|
|
|
|
|
|
|
|
projection = gimp_image_projection (gimage);
|
|
|
|
width = tile_manager_width (projection);
|
|
|
|
height = tile_manager_height (projection);
|
|
|
|
|
|
|
|
channel = gimp_channel_new (gimage, width, height, name, color);
|
|
|
|
|
|
|
|
pixel_region_init (&src, projection,
|
|
|
|
0, 0, width, height, FALSE);
|
|
|
|
pixel_region_init (&dest, GIMP_DRAWABLE (channel)->tiles,
|
|
|
|
0, 0, width, height, TRUE);
|
|
|
|
|
|
|
|
copy_component (&src, &dest, pixel);
|
|
|
|
|
|
|
|
return channel;
|
|
|
|
}
|
|
|
|
|
1999-07-07 11:18:54 +08:00
|
|
|
void
|
2001-01-29 10:45:02 +08:00
|
|
|
gimp_channel_set_color (GimpChannel *channel,
|
2003-03-17 10:25:39 +08:00
|
|
|
const GimpRGB *color,
|
|
|
|
gboolean push_undo)
|
1999-07-07 11:18:54 +08:00
|
|
|
{
|
2001-01-15 12:37:01 +08:00
|
|
|
g_return_if_fail (GIMP_IS_CHANNEL (channel));
|
|
|
|
g_return_if_fail (color != NULL);
|
1999-08-22 19:45:31 +08:00
|
|
|
|
2001-07-08 06:49:01 +08:00
|
|
|
if (gimp_rgba_distance (&channel->color, color) > 0.0001)
|
|
|
|
{
|
2003-03-17 10:25:39 +08:00
|
|
|
if (push_undo)
|
|
|
|
{
|
|
|
|
GimpImage *gimage;
|
|
|
|
|
|
|
|
gimage = gimp_item_get_image (GIMP_ITEM (channel));
|
|
|
|
|
|
|
|
if (gimage)
|
|
|
|
gimp_image_undo_push_channel_color (gimage, _("Set Channel Color"),
|
|
|
|
channel);
|
|
|
|
}
|
|
|
|
|
2001-07-08 06:49:01 +08:00
|
|
|
channel->color = *color;
|
|
|
|
|
|
|
|
gimp_drawable_update (GIMP_DRAWABLE (channel),
|
|
|
|
0, 0,
|
|
|
|
GIMP_DRAWABLE (channel)->width,
|
|
|
|
GIMP_DRAWABLE (channel)->height);
|
|
|
|
}
|
1999-08-22 19:45:31 +08:00
|
|
|
}
|
1999-07-07 11:18:54 +08:00
|
|
|
|
2002-03-09 00:34:42 +08:00
|
|
|
void
|
|
|
|
gimp_channel_get_color (const GimpChannel *channel,
|
|
|
|
GimpRGB *color)
|
1999-08-08 04:55:26 +08:00
|
|
|
{
|
2002-03-09 00:34:42 +08:00
|
|
|
g_return_if_fail (GIMP_IS_CHANNEL (channel));
|
|
|
|
g_return_if_fail (color != NULL);
|
2001-01-15 12:37:01 +08:00
|
|
|
|
2002-03-09 00:34:42 +08:00
|
|
|
*color = channel->color;
|
1999-08-08 04:55:26 +08:00
|
|
|
}
|
2001-01-29 21:51:23 +08:00
|
|
|
|
2002-03-04 01:38:12 +08:00
|
|
|
gdouble
|
2001-01-29 10:45:02 +08:00
|
|
|
gimp_channel_get_opacity (const GimpChannel *channel)
|
2001-01-15 12:37:01 +08:00
|
|
|
{
|
2002-08-30 00:48:17 +08:00
|
|
|
g_return_val_if_fail (GIMP_IS_CHANNEL (channel), GIMP_OPACITY_TRANSPARENT);
|
2001-01-15 12:37:01 +08:00
|
|
|
|
2002-03-04 01:38:12 +08:00
|
|
|
return channel->color.a;
|
1999-08-08 04:55:26 +08:00
|
|
|
}
|
|
|
|
|
2002-08-20 18:22:23 +08:00
|
|
|
void
|
2001-01-29 10:45:02 +08:00
|
|
|
gimp_channel_set_opacity (GimpChannel *channel,
|
Made drawable/layer properties (visibility, opacity etc.) undoable (fixes
2003-03-17 Michael Natterer <mitch@gimp.org>
Made drawable/layer properties (visibility, opacity etc.)
undoable (fixes bug #73893).
* app/core/core-enums.[ch]: added undo types/groups for
visibility, mode, opacity, linked and preserve_trans.
* app/core/Makefile.am
* app/core/core-types.h
* app/core/gimpitemundo.[ch]: new GimpUndo subclass which holds a
ref'ed GimpItem pointer so (1) this doesn't need to be done by all
undo steps related to an item and (2) the item the undo step is
for can be determined from outside the undo system.
* app/core/gimpimage-undo.[ch]: added gimp_image_undo_push_item()
which returns a new GimpItemUndo.
* app/core/gimpimage-undo-push.[ch]: use it for all item related
undo steps. Removed lots of GimpItem, GimpLayer, GimpDrawable
and GimpVectors pointers from the private undo structs. Added
undo push functions for the new undo types added above.
* app/core/gimpdrawable.[ch] (gimp_drawable_set_visible): added
"gboolean push_undo" parameter.
* app/core/gimplayer.[ch] (gimp_layer_set_opacity, _mode,
_preserve_trans, _linked): added "gboolean push_undo" parameters.
* app/core/gimpimage-mask.c
* app/core/gimpimage-merge.c
* app/core/gimplayer-floating-sel.c
* app/tools/gimpmovetool.c
* app/xcf/xcf-load.c
* app/widgets/gimpdrawablelistitem.c
* app/widgets/gimplayerlistitem.c
* app/widgets/gimplayerlistview.c: changed accordingly.
* tools/pdbgen/pdb/channel.pdb
* tools/pdbgen/pdb/layer.pdb: ditto. Added '$undo' paramaters to
the foo_accessors() functions. Removed $func from foo_accesors()
because we don't manipulate items without using getters/setters
any longer.
* app/pdb/channel_cmds.c
* app/pdb/layer_cmds.c: regenerated.
* app/widgets/gimpcellrenderertoggle.[ch]: added "clicked" signal
which carries an additional "GdkModifierType state" parameter as
in GimpCellRendererViewable .
* app/widgets/gimpcontainertreeview.c: emit "clicked" from
the toggle renderer, not "toggled" so the callbacks get the
modifier state.
* app/widgets/gimpdrawabletreeview.c: resurrected the "exclusive
visible by <shift>+click" feature as in 1.2.
* app/widgets/gimplayertreeview.c: compress layer opacity undos by
looking at the top of the undo stack and not pushing an undo if
there already is a GIMP_UNDO_DRAWABLE_OPACITY for the active
layer.
2003-03-18 02:02:41 +08:00
|
|
|
gdouble opacity,
|
|
|
|
gboolean push_undo)
|
1999-07-07 11:18:54 +08:00
|
|
|
{
|
2001-01-15 12:37:01 +08:00
|
|
|
g_return_if_fail (GIMP_IS_CHANNEL (channel));
|
|
|
|
|
2002-03-04 01:38:12 +08:00
|
|
|
opacity = CLAMP (opacity, GIMP_OPACITY_TRANSPARENT, GIMP_OPACITY_OPAQUE);
|
2001-01-15 12:37:01 +08:00
|
|
|
|
Made drawable/layer properties (visibility, opacity etc.) undoable (fixes
2003-03-17 Michael Natterer <mitch@gimp.org>
Made drawable/layer properties (visibility, opacity etc.)
undoable (fixes bug #73893).
* app/core/core-enums.[ch]: added undo types/groups for
visibility, mode, opacity, linked and preserve_trans.
* app/core/Makefile.am
* app/core/core-types.h
* app/core/gimpitemundo.[ch]: new GimpUndo subclass which holds a
ref'ed GimpItem pointer so (1) this doesn't need to be done by all
undo steps related to an item and (2) the item the undo step is
for can be determined from outside the undo system.
* app/core/gimpimage-undo.[ch]: added gimp_image_undo_push_item()
which returns a new GimpItemUndo.
* app/core/gimpimage-undo-push.[ch]: use it for all item related
undo steps. Removed lots of GimpItem, GimpLayer, GimpDrawable
and GimpVectors pointers from the private undo structs. Added
undo push functions for the new undo types added above.
* app/core/gimpdrawable.[ch] (gimp_drawable_set_visible): added
"gboolean push_undo" parameter.
* app/core/gimplayer.[ch] (gimp_layer_set_opacity, _mode,
_preserve_trans, _linked): added "gboolean push_undo" parameters.
* app/core/gimpimage-mask.c
* app/core/gimpimage-merge.c
* app/core/gimplayer-floating-sel.c
* app/tools/gimpmovetool.c
* app/xcf/xcf-load.c
* app/widgets/gimpdrawablelistitem.c
* app/widgets/gimplayerlistitem.c
* app/widgets/gimplayerlistview.c: changed accordingly.
* tools/pdbgen/pdb/channel.pdb
* tools/pdbgen/pdb/layer.pdb: ditto. Added '$undo' paramaters to
the foo_accessors() functions. Removed $func from foo_accesors()
because we don't manipulate items without using getters/setters
any longer.
* app/pdb/channel_cmds.c
* app/pdb/layer_cmds.c: regenerated.
* app/widgets/gimpcellrenderertoggle.[ch]: added "clicked" signal
which carries an additional "GdkModifierType state" parameter as
in GimpCellRendererViewable .
* app/widgets/gimpcontainertreeview.c: emit "clicked" from
the toggle renderer, not "toggled" so the callbacks get the
modifier state.
* app/widgets/gimpdrawabletreeview.c: resurrected the "exclusive
visible by <shift>+click" feature as in 1.2.
* app/widgets/gimplayertreeview.c: compress layer opacity undos by
looking at the top of the undo stack and not pushing an undo if
there already is a GIMP_UNDO_DRAWABLE_OPACITY for the active
layer.
2003-03-18 02:02:41 +08:00
|
|
|
if (channel->color.a != opacity)
|
|
|
|
{
|
|
|
|
if (push_undo)
|
|
|
|
{
|
|
|
|
GimpImage *gimage;
|
|
|
|
|
|
|
|
gimage = gimp_item_get_image (GIMP_ITEM (channel));
|
|
|
|
|
|
|
|
if (gimage)
|
|
|
|
gimp_image_undo_push_channel_color (gimage, _("Set Channel Opacity"),
|
|
|
|
channel);
|
|
|
|
}
|
|
|
|
|
|
|
|
channel->color.a = opacity;
|
|
|
|
|
|
|
|
gimp_drawable_update (GIMP_DRAWABLE (channel),
|
|
|
|
0, 0,
|
|
|
|
GIMP_DRAWABLE (channel)->width,
|
|
|
|
GIMP_DRAWABLE (channel)->height);
|
|
|
|
}
|
1999-07-07 11:18:54 +08:00
|
|
|
}
|
|
|
|
|
2002-08-20 18:22:23 +08:00
|
|
|
gboolean
|
|
|
|
gimp_channel_get_show_masked (GimpChannel *channel)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail (GIMP_IS_CHANNEL (channel), FALSE);
|
|
|
|
|
|
|
|
return channel->show_masked;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gimp_channel_set_show_masked (GimpChannel *channel,
|
|
|
|
gboolean show_masked)
|
|
|
|
{
|
|
|
|
g_return_if_fail (GIMP_IS_CHANNEL (channel));
|
|
|
|
|
|
|
|
if (show_masked != channel->show_masked)
|
|
|
|
{
|
|
|
|
channel->show_masked = show_masked ? TRUE : FALSE;
|
|
|
|
|
|
|
|
gimp_drawable_update (GIMP_DRAWABLE (channel),
|
|
|
|
0, 0,
|
|
|
|
GIMP_DRAWABLE (channel)->width,
|
|
|
|
GIMP_DRAWABLE (channel)->height);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
void
|
2002-02-12 10:31:45 +08:00
|
|
|
gimp_channel_scale (GimpChannel *channel,
|
|
|
|
gint new_width,
|
|
|
|
gint new_height,
|
|
|
|
GimpInterpolationType interpolation_type)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2000-12-29 00:19:55 +08:00
|
|
|
PixelRegion srcPR, destPR;
|
1997-11-25 06:05:25 +08:00
|
|
|
TileManager *new_tiles;
|
|
|
|
|
2001-08-11 22:39:19 +08:00
|
|
|
g_return_if_fail (GIMP_IS_CHANNEL (channel));
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
if (new_width == 0 || new_height == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* Update the old channel position */
|
2001-07-08 06:49:01 +08:00
|
|
|
gimp_drawable_update (GIMP_DRAWABLE (channel),
|
|
|
|
0, 0,
|
|
|
|
GIMP_DRAWABLE (channel)->width,
|
|
|
|
GIMP_DRAWABLE (channel)->height);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2001-12-18 07:41:01 +08:00
|
|
|
/* Allocate the new channel */
|
|
|
|
new_tiles = tile_manager_new (new_width, new_height, 1);
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
/* Configure the pixel regions */
|
1999-08-22 19:45:31 +08:00
|
|
|
pixel_region_init (&srcPR, GIMP_DRAWABLE (channel)->tiles,
|
|
|
|
0, 0,
|
|
|
|
GIMP_DRAWABLE (channel)->width,
|
2001-12-18 07:41:01 +08:00
|
|
|
GIMP_DRAWABLE (channel)->height,
|
|
|
|
FALSE);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2001-12-18 07:41:01 +08:00
|
|
|
pixel_region_init (&destPR, new_tiles,
|
|
|
|
0, 0,
|
|
|
|
new_width, new_height,
|
|
|
|
TRUE);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2001-12-18 07:41:01 +08:00
|
|
|
/* Sclae the channel */
|
2002-02-12 10:31:45 +08:00
|
|
|
scale_region (&srcPR, &destPR, interpolation_type);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/* Push the channel on the undo stack */
|
2003-02-14 22:14:29 +08:00
|
|
|
gimp_image_undo_push_channel_mod (gimp_item_get_image (GIMP_ITEM (channel)),
|
|
|
|
_("Scale Channel"),
|
|
|
|
channel);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/* Configure the new channel */
|
2001-12-18 07:41:01 +08:00
|
|
|
GIMP_DRAWABLE (channel)->tiles = new_tiles;
|
|
|
|
GIMP_DRAWABLE (channel)->width = new_width;
|
1999-08-22 19:45:31 +08:00
|
|
|
GIMP_DRAWABLE (channel)->height = new_height;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/* bounds are now unknown */
|
|
|
|
channel->bounds_known = FALSE;
|
|
|
|
|
|
|
|
/* Update the new channel position */
|
2001-07-08 06:49:01 +08:00
|
|
|
gimp_drawable_update (GIMP_DRAWABLE (channel),
|
|
|
|
0, 0,
|
|
|
|
GIMP_DRAWABLE (channel)->width,
|
|
|
|
GIMP_DRAWABLE (channel)->height);
|
2003-01-30 01:27:34 +08:00
|
|
|
|
|
|
|
gimp_viewable_size_changed (GIMP_VIEWABLE (channel));
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2001-01-29 10:45:02 +08:00
|
|
|
gimp_channel_resize (GimpChannel *channel,
|
2001-12-03 21:44:59 +08:00
|
|
|
gint new_width,
|
|
|
|
gint new_height,
|
2001-01-29 10:45:02 +08:00
|
|
|
gint offx,
|
|
|
|
gint offy)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2000-12-29 00:19:55 +08:00
|
|
|
PixelRegion srcPR, destPR;
|
1997-11-25 06:05:25 +08:00
|
|
|
TileManager *new_tiles;
|
2000-12-29 00:19:55 +08:00
|
|
|
guchar bg = 0;
|
|
|
|
gint clear;
|
|
|
|
gint w, h;
|
|
|
|
gint x1, y1, x2, y2;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2001-08-11 22:39:19 +08:00
|
|
|
g_return_if_fail (GIMP_IS_CHANNEL (channel));
|
|
|
|
|
2001-12-18 07:41:01 +08:00
|
|
|
if (new_width == 0 || new_height == 0)
|
1997-11-25 06:05:25 +08:00
|
|
|
return;
|
|
|
|
|
2000-01-26 07:06:12 +08:00
|
|
|
x1 = CLAMP (offx, 0, new_width);
|
|
|
|
y1 = CLAMP (offy, 0, new_height);
|
|
|
|
x2 = CLAMP ((offx + GIMP_DRAWABLE (channel)->width), 0, new_width);
|
|
|
|
y2 = CLAMP ((offy + GIMP_DRAWABLE (channel)->height), 0, new_height);
|
2002-08-30 00:48:17 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
w = x2 - x1;
|
|
|
|
h = y2 - y1;
|
|
|
|
|
|
|
|
if (offx > 0)
|
|
|
|
{
|
|
|
|
x1 = 0;
|
|
|
|
x2 = offx;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
x1 = -offx;
|
|
|
|
x2 = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (offy > 0)
|
|
|
|
{
|
|
|
|
y1 = 0;
|
|
|
|
y2 = offy;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
y1 = -offy;
|
|
|
|
y2 = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Update the old channel position */
|
2001-07-08 06:49:01 +08:00
|
|
|
gimp_drawable_update (GIMP_DRAWABLE (channel),
|
|
|
|
0, 0,
|
|
|
|
GIMP_DRAWABLE (channel)->width,
|
|
|
|
GIMP_DRAWABLE (channel)->height);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/* Configure the pixel regions */
|
1999-08-22 19:45:31 +08:00
|
|
|
pixel_region_init (&srcPR, GIMP_DRAWABLE (channel)->tiles,
|
|
|
|
x1, y1, w, h, FALSE);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/* Determine whether the new channel needs to be initially cleared */
|
1999-08-22 19:45:31 +08:00
|
|
|
if ((new_width > GIMP_DRAWABLE (channel)->width) ||
|
|
|
|
(new_height > GIMP_DRAWABLE (channel)->height) ||
|
1997-11-25 06:05:25 +08:00
|
|
|
(x2 || y2))
|
|
|
|
clear = TRUE;
|
|
|
|
else
|
|
|
|
clear = FALSE;
|
|
|
|
|
|
|
|
/* Allocate the new channel, configure dest region */
|
|
|
|
new_tiles = tile_manager_new (new_width, new_height, 1);
|
|
|
|
|
|
|
|
/* Set to black (empty--for selections) */
|
|
|
|
if (clear)
|
|
|
|
{
|
2001-12-18 07:41:01 +08:00
|
|
|
pixel_region_init (&destPR, new_tiles,
|
|
|
|
0, 0,
|
|
|
|
new_width, new_height,
|
|
|
|
TRUE);
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
color_region (&destPR, &bg);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* copy from the old to the new */
|
|
|
|
pixel_region_init (&destPR, new_tiles, x2, y2, w, h, TRUE);
|
|
|
|
if (w && h)
|
|
|
|
copy_region (&srcPR, &destPR);
|
|
|
|
|
|
|
|
/* Push the channel on the undo stack */
|
2003-02-14 22:14:29 +08:00
|
|
|
gimp_image_undo_push_channel_mod (gimp_item_get_image (GIMP_ITEM (channel)),
|
|
|
|
_("Resize Channel"),
|
|
|
|
channel);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/* Configure the new channel */
|
1999-08-22 19:45:31 +08:00
|
|
|
GIMP_DRAWABLE (channel)->tiles = new_tiles;
|
|
|
|
GIMP_DRAWABLE (channel)->width = new_width;
|
|
|
|
GIMP_DRAWABLE (channel)->height = new_height;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/* bounds are now unknown */
|
|
|
|
channel->bounds_known = FALSE;
|
|
|
|
|
|
|
|
/* update the new channel area */
|
2001-07-08 06:49:01 +08:00
|
|
|
gimp_drawable_update (GIMP_DRAWABLE (channel),
|
|
|
|
0, 0,
|
|
|
|
GIMP_DRAWABLE (channel)->width,
|
|
|
|
GIMP_DRAWABLE (channel)->height);
|
2003-01-30 01:27:34 +08:00
|
|
|
|
|
|
|
gimp_viewable_size_changed (GIMP_VIEWABLE (channel));
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
2001-01-30 01:54:02 +08:00
|
|
|
|
1999-08-22 19:45:31 +08:00
|
|
|
/******************************/
|
|
|
|
/* selection mask functions */
|
|
|
|
/******************************/
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2001-01-29 10:45:02 +08:00
|
|
|
GimpChannel *
|
|
|
|
gimp_channel_new_mask (GimpImage *gimage,
|
2001-12-03 21:44:59 +08:00
|
|
|
gint width,
|
|
|
|
gint height)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2001-01-29 10:45:02 +08:00
|
|
|
GimpRGB black = { 0.0, 0.0, 0.0, 0.5 };
|
|
|
|
GimpChannel *new_channel;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2001-08-11 22:39:19 +08:00
|
|
|
g_return_val_if_fail (GIMP_IS_IMAGE (gimage), NULL);
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
/* Create the new channel */
|
2001-01-29 10:45:02 +08:00
|
|
|
new_channel = gimp_channel_new (gimage, width, height,
|
|
|
|
_("Selection Mask"), &black);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/* Set the validate procedure */
|
1999-08-22 19:45:31 +08:00
|
|
|
tile_manager_set_validate_proc (GIMP_DRAWABLE (new_channel)->tiles,
|
2001-01-29 10:45:02 +08:00
|
|
|
gimp_channel_validate);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
return new_channel;
|
|
|
|
}
|
|
|
|
|
1999-08-22 19:45:31 +08:00
|
|
|
gboolean
|
2001-01-29 10:45:02 +08:00
|
|
|
gimp_channel_boundary (GimpChannel *mask,
|
|
|
|
BoundSeg **segs_in,
|
|
|
|
BoundSeg **segs_out,
|
|
|
|
gint *num_segs_in,
|
|
|
|
gint *num_segs_out,
|
|
|
|
gint x1,
|
|
|
|
gint y1,
|
|
|
|
gint x2,
|
|
|
|
gint y2)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2000-12-29 00:19:55 +08:00
|
|
|
gint x3, y3, x4, y4;
|
1997-11-25 06:05:25 +08:00
|
|
|
PixelRegion bPR;
|
|
|
|
|
2001-08-11 22:39:19 +08:00
|
|
|
g_return_val_if_fail (GIMP_IS_CHANNEL (mask), FALSE);
|
2002-08-30 00:48:17 +08:00
|
|
|
g_return_val_if_fail (segs_in != NULL, FALSE);
|
|
|
|
g_return_val_if_fail (segs_out != NULL, FALSE);
|
|
|
|
g_return_val_if_fail (num_segs_in != NULL, FALSE);
|
|
|
|
g_return_val_if_fail (num_segs_out != NULL, FALSE);
|
2001-08-11 22:39:19 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
if (! mask->boundary_known)
|
|
|
|
{
|
|
|
|
/* free the out of date boundary segments */
|
|
|
|
if (mask->segs_in)
|
|
|
|
g_free (mask->segs_in);
|
|
|
|
if (mask->segs_out)
|
|
|
|
g_free (mask->segs_out);
|
|
|
|
|
2001-01-29 10:45:02 +08:00
|
|
|
if (gimp_channel_bounds (mask, &x3, &y3, &x4, &y4))
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
1999-08-22 19:45:31 +08:00
|
|
|
pixel_region_init (&bPR, GIMP_DRAWABLE (mask)->tiles,
|
|
|
|
x3, y3, (x4 - x3), (y4 - y3), FALSE);
|
1997-11-25 06:05:25 +08:00
|
|
|
mask->segs_out = find_mask_boundary (&bPR, &mask->num_segs_out,
|
|
|
|
IgnoreBounds,
|
|
|
|
x1, y1,
|
|
|
|
x2, y2);
|
2000-01-26 07:06:12 +08:00
|
|
|
x1 = MAX (x1, x3);
|
|
|
|
y1 = MAX (y1, y3);
|
|
|
|
x2 = MIN (x2, x4);
|
|
|
|
y2 = MIN (y2, y4);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
if (x2 > x1 && y2 > y1)
|
|
|
|
{
|
1999-08-22 19:45:31 +08:00
|
|
|
pixel_region_init (&bPR, GIMP_DRAWABLE (mask)->tiles,
|
|
|
|
0, 0,
|
|
|
|
GIMP_DRAWABLE (mask)->width,
|
|
|
|
GIMP_DRAWABLE (mask)->height, FALSE);
|
1997-11-25 06:05:25 +08:00
|
|
|
mask->segs_in = find_mask_boundary (&bPR, &mask->num_segs_in,
|
|
|
|
WithinBounds,
|
|
|
|
x1, y1,
|
|
|
|
x2, y2);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
1999-08-22 19:45:31 +08:00
|
|
|
mask->segs_in = NULL;
|
1997-11-25 06:05:25 +08:00
|
|
|
mask->num_segs_in = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
1999-08-22 19:45:31 +08:00
|
|
|
mask->segs_in = NULL;
|
|
|
|
mask->segs_out = NULL;
|
|
|
|
mask->num_segs_in = 0;
|
1997-11-25 06:05:25 +08:00
|
|
|
mask->num_segs_out = 0;
|
|
|
|
}
|
2002-08-20 18:22:23 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
mask->boundary_known = TRUE;
|
|
|
|
}
|
|
|
|
|
1999-08-22 19:45:31 +08:00
|
|
|
*segs_in = mask->segs_in;
|
|
|
|
*segs_out = mask->segs_out;
|
|
|
|
*num_segs_in = mask->num_segs_in;
|
1997-11-25 06:05:25 +08:00
|
|
|
*num_segs_out = mask->num_segs_out;
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2001-12-03 21:44:59 +08:00
|
|
|
gint
|
2001-01-29 10:45:02 +08:00
|
|
|
gimp_channel_value (GimpChannel *mask,
|
|
|
|
gint x,
|
|
|
|
gint y)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
|
|
|
Tile *tile;
|
2001-12-03 21:44:59 +08:00
|
|
|
gint val;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2001-08-11 22:39:19 +08:00
|
|
|
g_return_val_if_fail (GIMP_IS_CHANNEL (mask), 0);
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
/* Some checks to cut back on unnecessary work */
|
|
|
|
if (mask->bounds_known)
|
|
|
|
{
|
|
|
|
if (mask->empty)
|
|
|
|
return 0;
|
|
|
|
else if (x < mask->x1 || x >= mask->x2 || y < mask->y1 || y >= mask->y2)
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
1999-08-22 19:45:31 +08:00
|
|
|
if (x < 0 || x >= GIMP_DRAWABLE (mask)->width ||
|
|
|
|
y < 0 || y >= GIMP_DRAWABLE (mask)->height)
|
1997-11-25 06:05:25 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
1999-08-22 19:45:31 +08:00
|
|
|
tile = tile_manager_get_tile (GIMP_DRAWABLE (mask)->tiles, x, y, TRUE, FALSE);
|
|
|
|
val = *(guchar *) (tile_data_pointer (tile, x % TILE_WIDTH, y % TILE_HEIGHT));
|
1998-07-10 10:43:12 +08:00
|
|
|
tile_release (tile, FALSE);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
return val;
|
|
|
|
}
|
|
|
|
|
1999-08-22 19:45:31 +08:00
|
|
|
gboolean
|
2001-01-29 10:45:02 +08:00
|
|
|
gimp_channel_bounds (GimpChannel *mask,
|
|
|
|
gint *x1,
|
|
|
|
gint *y1,
|
|
|
|
gint *x2,
|
|
|
|
gint *y2)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2000-12-29 00:19:55 +08:00
|
|
|
PixelRegion maskPR;
|
|
|
|
guchar *data, *data1;
|
|
|
|
gint x, y;
|
|
|
|
gint ex, ey;
|
|
|
|
gint tx1, tx2, ty1, ty2;
|
|
|
|
gint minx, maxx;
|
|
|
|
gpointer pr;
|
1999-08-22 19:45:31 +08:00
|
|
|
|
2001-08-11 22:39:19 +08:00
|
|
|
g_return_val_if_fail (GIMP_IS_CHANNEL (mask), FALSE);
|
2002-08-30 00:48:17 +08:00
|
|
|
g_return_val_if_fail (x1 != NULL, FALSE);
|
|
|
|
g_return_val_if_fail (y1 != NULL, FALSE);
|
|
|
|
g_return_val_if_fail (x2 != NULL, FALSE);
|
|
|
|
g_return_val_if_fail (y2 != NULL, FALSE);
|
2001-08-11 22:39:19 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
/* if the mask's bounds have already been reliably calculated... */
|
|
|
|
if (mask->bounds_known)
|
|
|
|
{
|
|
|
|
*x1 = mask->x1;
|
|
|
|
*y1 = mask->y1;
|
|
|
|
*x2 = mask->x2;
|
|
|
|
*y2 = mask->y2;
|
|
|
|
|
2002-08-30 00:48:17 +08:00
|
|
|
return ! mask->empty;
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* go through and calculate the bounds */
|
1999-08-22 19:45:31 +08:00
|
|
|
tx1 = GIMP_DRAWABLE (mask)->width;
|
|
|
|
ty1 = GIMP_DRAWABLE (mask)->height;
|
1999-04-09 14:00:11 +08:00
|
|
|
tx2 = 0;
|
|
|
|
ty2 = 0;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
1999-08-22 19:45:31 +08:00
|
|
|
pixel_region_init (&maskPR, GIMP_DRAWABLE (mask)->tiles,
|
|
|
|
0, 0,
|
|
|
|
GIMP_DRAWABLE (mask)->width,
|
|
|
|
GIMP_DRAWABLE (mask)->height, FALSE);
|
2002-08-30 00:48:17 +08:00
|
|
|
|
1999-08-22 19:45:31 +08:00
|
|
|
for (pr = pixel_regions_register (1, &maskPR);
|
|
|
|
pr != NULL;
|
|
|
|
pr = pixel_regions_process (pr))
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
1999-05-28 13:08:10 +08:00
|
|
|
data1 = data = maskPR.data;
|
1997-11-25 06:05:25 +08:00
|
|
|
ex = maskPR.x + maskPR.w;
|
|
|
|
ey = maskPR.y + maskPR.h;
|
1999-02-16 16:53:54 +08:00
|
|
|
/* only check the pixels if this tile is not fully within the currently
|
|
|
|
computed bounds */
|
1999-04-09 14:00:11 +08:00
|
|
|
if (maskPR.x < tx1 || ex > tx2 ||
|
|
|
|
maskPR.y < ty1 || ey > ty2)
|
1999-02-16 16:53:54 +08:00
|
|
|
{
|
1999-04-09 14:00:11 +08:00
|
|
|
/* Check upper left and lower right corners to see if we can
|
|
|
|
avoid checking the rest of the pixels in this tile */
|
|
|
|
if (data[0] && data[maskPR.rowstride*(maskPR.h - 1) + maskPR.w - 1])
|
2002-08-30 00:48:17 +08:00
|
|
|
{
|
|
|
|
if (maskPR.x < tx1)
|
|
|
|
tx1 = maskPR.x;
|
|
|
|
if (ex > tx2)
|
|
|
|
tx2 = ex;
|
|
|
|
if (maskPR.y < ty1)
|
|
|
|
ty1 = maskPR.y;
|
|
|
|
if (ey > ty2)
|
|
|
|
ty2 = ey;
|
|
|
|
}
|
1999-04-09 14:00:11 +08:00
|
|
|
else
|
2002-08-30 00:48:17 +08:00
|
|
|
{
|
|
|
|
for (y = maskPR.y; y < ey; y++, data1 += maskPR.rowstride)
|
|
|
|
{
|
|
|
|
for (x = maskPR.x, data = data1; x < ex; x++, data++)
|
|
|
|
{
|
|
|
|
if (*data)
|
|
|
|
{
|
|
|
|
minx = x;
|
|
|
|
maxx = x;
|
|
|
|
|
|
|
|
for (; x < ex; x++, data++)
|
|
|
|
if (*data)
|
|
|
|
maxx = x;
|
|
|
|
|
|
|
|
if (minx < tx1)
|
|
|
|
tx1 = minx;
|
|
|
|
if (maxx > tx2)
|
|
|
|
tx2 = maxx;
|
|
|
|
if (y < ty1)
|
|
|
|
ty1 = y;
|
|
|
|
if (y > ty2)
|
|
|
|
ty2 = y;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
2000-01-26 07:06:12 +08:00
|
|
|
tx2 = CLAMP (tx2 + 1, 0, GIMP_DRAWABLE (mask)->width);
|
|
|
|
ty2 = CLAMP (ty2 + 1, 0, GIMP_DRAWABLE (mask)->height);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
1999-08-22 19:45:31 +08:00
|
|
|
if (tx1 == GIMP_DRAWABLE (mask)->width && ty1 == GIMP_DRAWABLE (mask)->height)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
|
|
|
mask->empty = TRUE;
|
1999-08-22 19:45:31 +08:00
|
|
|
mask->x1 = 0;
|
|
|
|
mask->y1 = 0;
|
|
|
|
mask->x2 = GIMP_DRAWABLE (mask)->width;
|
|
|
|
mask->y2 = GIMP_DRAWABLE (mask)->height;
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
mask->empty = FALSE;
|
1999-08-22 19:45:31 +08:00
|
|
|
mask->x1 = tx1;
|
|
|
|
mask->y1 = ty1;
|
|
|
|
mask->x2 = tx2;
|
|
|
|
mask->y2 = ty2;
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
2002-08-20 18:22:23 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
mask->bounds_known = TRUE;
|
|
|
|
|
1999-04-09 14:00:11 +08:00
|
|
|
*x1 = tx1;
|
|
|
|
*x2 = tx2;
|
|
|
|
*y1 = ty1;
|
|
|
|
*y2 = ty2;
|
|
|
|
|
1999-08-22 19:45:31 +08:00
|
|
|
return !mask->empty;
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
1999-08-22 19:45:31 +08:00
|
|
|
gboolean
|
2001-01-29 10:45:02 +08:00
|
|
|
gimp_channel_is_empty (GimpChannel *mask)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2000-12-29 00:19:55 +08:00
|
|
|
PixelRegion maskPR;
|
|
|
|
guchar *data;
|
|
|
|
gint x, y;
|
|
|
|
gpointer pr;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2001-08-11 22:39:19 +08:00
|
|
|
g_return_val_if_fail (GIMP_IS_CHANNEL (mask), FALSE);
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
if (mask->bounds_known)
|
|
|
|
return mask->empty;
|
|
|
|
|
1999-08-22 19:45:31 +08:00
|
|
|
pixel_region_init (&maskPR, GIMP_DRAWABLE (mask)->tiles,
|
|
|
|
0, 0,
|
|
|
|
GIMP_DRAWABLE (mask)->width,
|
|
|
|
GIMP_DRAWABLE (mask)->height, FALSE);
|
2002-08-20 18:22:23 +08:00
|
|
|
|
1999-08-22 19:45:31 +08:00
|
|
|
for (pr = pixel_regions_register (1, &maskPR);
|
|
|
|
pr != NULL;
|
|
|
|
pr = pixel_regions_process (pr))
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
|
|
|
/* check if any pixel in the mask is non-zero */
|
|
|
|
data = maskPR.data;
|
2002-08-30 00:48:17 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
for (y = 0; y < maskPR.h; y++)
|
|
|
|
for (x = 0; x < maskPR.w; x++)
|
|
|
|
if (*data++)
|
|
|
|
{
|
|
|
|
pixel_regions_process_stop (pr);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* The mask is empty, meaning we can set the bounds as known */
|
|
|
|
if (mask->segs_in)
|
|
|
|
g_free (mask->segs_in);
|
|
|
|
if (mask->segs_out)
|
|
|
|
g_free (mask->segs_out);
|
|
|
|
|
1999-08-22 19:45:31 +08:00
|
|
|
mask->empty = TRUE;
|
|
|
|
mask->segs_in = NULL;
|
|
|
|
mask->segs_out = NULL;
|
|
|
|
mask->num_segs_in = 0;
|
|
|
|
mask->num_segs_out = 0;
|
|
|
|
mask->bounds_known = TRUE;
|
1997-11-25 06:05:25 +08:00
|
|
|
mask->boundary_known = TRUE;
|
1999-08-22 19:45:31 +08:00
|
|
|
mask->x1 = 0;
|
|
|
|
mask->y1 = 0;
|
|
|
|
mask->x2 = GIMP_DRAWABLE (mask)->width;
|
|
|
|
mask->y2 = GIMP_DRAWABLE (mask)->height;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2001-01-29 10:45:02 +08:00
|
|
|
gimp_channel_add_segment (GimpChannel *mask,
|
|
|
|
gint x,
|
|
|
|
gint y,
|
2001-12-03 21:44:59 +08:00
|
|
|
gint width,
|
|
|
|
gint value)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2000-12-29 00:19:55 +08:00
|
|
|
PixelRegion maskPR;
|
|
|
|
guchar *data;
|
|
|
|
gint val;
|
|
|
|
gint x2;
|
|
|
|
gpointer pr;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2001-08-11 22:39:19 +08:00
|
|
|
g_return_if_fail (GIMP_IS_CHANNEL (mask));
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
/* check horizontal extents... */
|
|
|
|
x2 = x + width;
|
2002-08-30 00:48:17 +08:00
|
|
|
x2 = CLAMP (x2, 0, GIMP_DRAWABLE (mask)->width);
|
|
|
|
x = CLAMP (x, 0, GIMP_DRAWABLE (mask)->width);
|
1997-11-25 06:05:25 +08:00
|
|
|
width = x2 - x;
|
2002-08-30 00:48:17 +08:00
|
|
|
if (!width)
|
|
|
|
return;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
1999-08-22 19:45:31 +08:00
|
|
|
if (y < 0 || y > GIMP_DRAWABLE (mask)->height)
|
1997-11-25 06:05:25 +08:00
|
|
|
return;
|
|
|
|
|
1999-08-22 19:45:31 +08:00
|
|
|
pixel_region_init (&maskPR, GIMP_DRAWABLE (mask)->tiles,
|
|
|
|
x, y, width, 1, TRUE);
|
2002-08-30 00:48:17 +08:00
|
|
|
|
1999-08-22 19:45:31 +08:00
|
|
|
for (pr = pixel_regions_register (1, &maskPR);
|
|
|
|
pr != NULL;
|
|
|
|
pr = pixel_regions_process (pr))
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
|
|
|
data = maskPR.data;
|
|
|
|
width = maskPR.w;
|
|
|
|
while (width--)
|
|
|
|
{
|
|
|
|
val = *data + value;
|
|
|
|
if (val > 255)
|
|
|
|
val = 255;
|
|
|
|
*data++ = val;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2001-01-29 10:45:02 +08:00
|
|
|
gimp_channel_sub_segment (GimpChannel *mask,
|
|
|
|
gint x,
|
|
|
|
gint y,
|
2001-12-03 21:44:59 +08:00
|
|
|
gint width,
|
|
|
|
gint value)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2000-12-29 00:19:55 +08:00
|
|
|
PixelRegion maskPR;
|
|
|
|
guchar *data;
|
|
|
|
gint val;
|
|
|
|
gint x2;
|
|
|
|
gpointer pr;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2001-08-11 22:39:19 +08:00
|
|
|
g_return_if_fail (GIMP_IS_CHANNEL (mask));
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
/* check horizontal extents... */
|
|
|
|
x2 = x + width;
|
2002-08-30 00:48:17 +08:00
|
|
|
x2 = CLAMP (x2, 0, GIMP_DRAWABLE (mask)->width);
|
|
|
|
x = CLAMP (x, 0, GIMP_DRAWABLE (mask)->width);
|
1997-11-25 06:05:25 +08:00
|
|
|
width = x2 - x;
|
2002-08-30 00:48:17 +08:00
|
|
|
|
|
|
|
if (! width)
|
|
|
|
return;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
1999-08-22 19:45:31 +08:00
|
|
|
if (y < 0 || y > GIMP_DRAWABLE (mask)->height)
|
1997-11-25 06:05:25 +08:00
|
|
|
return;
|
|
|
|
|
2002-08-30 00:48:17 +08:00
|
|
|
pixel_region_init (&maskPR, GIMP_DRAWABLE (mask)->tiles,
|
|
|
|
x, y, width, 1, TRUE);
|
|
|
|
|
1999-08-22 19:45:31 +08:00
|
|
|
for (pr = pixel_regions_register (1, &maskPR);
|
|
|
|
pr != NULL;
|
|
|
|
pr = pixel_regions_process (pr))
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
|
|
|
data = maskPR.data;
|
|
|
|
width = maskPR.w;
|
|
|
|
while (width--)
|
|
|
|
{
|
|
|
|
val = *data - value;
|
|
|
|
if (val < 0)
|
|
|
|
val = 0;
|
|
|
|
*data++ = val;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2002-03-19 00:22:14 +08:00
|
|
|
gimp_channel_combine_rect (GimpChannel *mask,
|
|
|
|
GimpChannelOps op,
|
|
|
|
gint x,
|
|
|
|
gint y,
|
|
|
|
gint w,
|
|
|
|
gint h)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2000-12-29 00:19:55 +08:00
|
|
|
gint x2, y2;
|
1997-11-25 06:05:25 +08:00
|
|
|
PixelRegion maskPR;
|
2000-12-29 00:19:55 +08:00
|
|
|
guchar color;
|
1999-08-22 19:45:31 +08:00
|
|
|
|
2001-08-11 22:39:19 +08:00
|
|
|
g_return_if_fail (GIMP_IS_CHANNEL (mask));
|
|
|
|
|
1999-04-09 14:00:11 +08:00
|
|
|
y2 = y + h;
|
|
|
|
x2 = x + w;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2000-01-26 07:06:12 +08:00
|
|
|
x = CLAMP (x, 0, GIMP_DRAWABLE (mask)->width);
|
|
|
|
y = CLAMP (y, 0, GIMP_DRAWABLE (mask)->height);
|
|
|
|
x2 = CLAMP (x2, 0, GIMP_DRAWABLE (mask)->width);
|
|
|
|
y2 = CLAMP (y2, 0, GIMP_DRAWABLE (mask)->height);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
1999-04-09 14:00:11 +08:00
|
|
|
if (x2 - x <= 0 || y2 - y <= 0)
|
1997-11-25 06:05:25 +08:00
|
|
|
return;
|
|
|
|
|
1999-08-22 19:45:31 +08:00
|
|
|
pixel_region_init (&maskPR, GIMP_DRAWABLE (mask)->tiles,
|
|
|
|
x, y, x2 - x, y2 - y, TRUE);
|
2002-03-19 00:22:14 +08:00
|
|
|
|
|
|
|
if (op == GIMP_CHANNEL_OP_ADD || op == GIMP_CHANNEL_OP_REPLACE)
|
2002-08-30 00:48:17 +08:00
|
|
|
color = OPAQUE_OPACITY;
|
1999-04-09 14:00:11 +08:00
|
|
|
else
|
2002-08-30 00:48:17 +08:00
|
|
|
color = TRANSPARENT_OPACITY;
|
2002-03-19 00:22:14 +08:00
|
|
|
|
1999-08-22 19:45:31 +08:00
|
|
|
color_region (&maskPR, &color);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/* Determine new boundary */
|
2002-03-19 00:22:14 +08:00
|
|
|
if (mask->bounds_known && (op == GIMP_CHANNEL_OP_ADD) && !mask->empty)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
|
|
|
if (x < mask->x1)
|
|
|
|
mask->x1 = x;
|
|
|
|
if (y < mask->y1)
|
|
|
|
mask->y1 = y;
|
|
|
|
if ((x + w) > mask->x2)
|
|
|
|
mask->x2 = (x + w);
|
|
|
|
if ((y + h) > mask->y2)
|
|
|
|
mask->y2 = (y + h);
|
|
|
|
}
|
2002-03-19 00:22:14 +08:00
|
|
|
else if (op == GIMP_CHANNEL_OP_REPLACE || mask->empty)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
|
|
|
mask->empty = FALSE;
|
2002-08-30 00:48:17 +08:00
|
|
|
mask->x1 = x;
|
|
|
|
mask->y1 = y;
|
|
|
|
mask->x2 = x + w;
|
|
|
|
mask->y2 = y + h;
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
mask->bounds_known = FALSE;
|
|
|
|
|
2000-01-26 07:06:12 +08:00
|
|
|
mask->x1 = CLAMP (mask->x1, 0, GIMP_DRAWABLE (mask)->width);
|
|
|
|
mask->y1 = CLAMP (mask->y1, 0, GIMP_DRAWABLE (mask)->height);
|
|
|
|
mask->x2 = CLAMP (mask->x2, 0, GIMP_DRAWABLE (mask)->width);
|
|
|
|
mask->y2 = CLAMP (mask->y2, 0, GIMP_DRAWABLE (mask)->height);
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2002-03-19 00:22:14 +08:00
|
|
|
gimp_channel_combine_ellipse (GimpChannel *mask,
|
|
|
|
GimpChannelOps op,
|
|
|
|
gint x,
|
|
|
|
gint y,
|
|
|
|
gint w,
|
|
|
|
gint h,
|
|
|
|
gboolean antialias)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2000-12-29 00:19:55 +08:00
|
|
|
gint i, j;
|
|
|
|
gint x0, x1, x2;
|
|
|
|
gint val, last;
|
1999-08-22 19:45:31 +08:00
|
|
|
gfloat a_sqr, b_sqr, aob_sqr;
|
|
|
|
gfloat w_sqr, h_sqr;
|
|
|
|
gfloat y_sqr;
|
|
|
|
gfloat t0, t1;
|
|
|
|
gfloat r;
|
|
|
|
gfloat cx, cy;
|
|
|
|
gfloat rad;
|
|
|
|
gfloat dist;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2001-08-11 22:39:19 +08:00
|
|
|
g_return_if_fail (GIMP_IS_CHANNEL (mask));
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
if (!w || !h)
|
|
|
|
return;
|
|
|
|
|
|
|
|
a_sqr = (w * w / 4.0);
|
|
|
|
b_sqr = (h * h / 4.0);
|
|
|
|
aob_sqr = a_sqr / b_sqr;
|
|
|
|
|
|
|
|
cx = x + w / 2.0;
|
|
|
|
cy = y + h / 2.0;
|
|
|
|
|
|
|
|
for (i = y; i < (y + h); i++)
|
|
|
|
{
|
1999-08-22 19:45:31 +08:00
|
|
|
if (i >= 0 && i < GIMP_DRAWABLE (mask)->height)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
|
|
|
/* Non-antialiased code */
|
2000-05-13 01:07:54 +08:00
|
|
|
if (!antialias)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
|
|
|
y_sqr = (i + 0.5 - cy) * (i + 0.5 - cy);
|
|
|
|
rad = sqrt (a_sqr - a_sqr * y_sqr / (double) b_sqr);
|
|
|
|
x1 = ROUND (cx - rad);
|
|
|
|
x2 = ROUND (cx + rad);
|
|
|
|
|
|
|
|
switch (op)
|
|
|
|
{
|
2002-03-19 00:22:14 +08:00
|
|
|
case GIMP_CHANNEL_OP_ADD:
|
|
|
|
case GIMP_CHANNEL_OP_REPLACE:
|
2001-01-29 10:45:02 +08:00
|
|
|
gimp_channel_add_segment (mask, x1, i, (x2 - x1), 255);
|
1997-11-25 06:05:25 +08:00
|
|
|
break;
|
2002-08-30 00:48:17 +08:00
|
|
|
|
2002-03-19 00:22:14 +08:00
|
|
|
case GIMP_CHANNEL_OP_SUBTRACT:
|
2001-01-29 10:45:02 +08:00
|
|
|
gimp_channel_sub_segment (mask, x1, i, (x2 - x1), 255);
|
1997-11-25 06:05:25 +08:00
|
|
|
break;
|
2002-08-30 00:48:17 +08:00
|
|
|
|
1999-11-05 03:50:14 +08:00
|
|
|
default:
|
2002-03-18 06:54:26 +08:00
|
|
|
g_warning ("Only ADD, REPLACE, and SUBTRACT are valid for channel_combine!");
|
1999-11-05 03:50:14 +08:00
|
|
|
break;
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
/* antialiasing */
|
|
|
|
else
|
|
|
|
{
|
|
|
|
x0 = x;
|
|
|
|
last = 0;
|
|
|
|
h_sqr = (i + 0.5 - cy) * (i + 0.5 - cy);
|
|
|
|
for (j = x; j < (x + w); j++)
|
|
|
|
{
|
|
|
|
w_sqr = (j + 0.5 - cx) * (j + 0.5 - cx);
|
|
|
|
|
|
|
|
if (h_sqr != 0)
|
|
|
|
{
|
|
|
|
t0 = w_sqr / h_sqr;
|
|
|
|
t1 = a_sqr / (t0 + aob_sqr);
|
|
|
|
r = sqrt (t1 + t0 * t1);
|
|
|
|
rad = sqrt (w_sqr + h_sqr);
|
|
|
|
dist = rad - r;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
dist = -1.0;
|
|
|
|
|
|
|
|
if (dist < -0.5)
|
|
|
|
val = 255;
|
|
|
|
else if (dist < 0.5)
|
|
|
|
val = (int) (255 * (1 - (dist + 0.5)));
|
|
|
|
else
|
|
|
|
val = 0;
|
1999-04-09 14:00:11 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
if (last != val && last)
|
|
|
|
{
|
|
|
|
switch (op)
|
|
|
|
{
|
2002-03-19 00:22:14 +08:00
|
|
|
case GIMP_CHANNEL_OP_ADD:
|
|
|
|
case GIMP_CHANNEL_OP_REPLACE:
|
2001-01-29 10:45:02 +08:00
|
|
|
gimp_channel_add_segment (mask, x0, i, j - x0, last);
|
1997-11-25 06:05:25 +08:00
|
|
|
break;
|
2002-08-30 00:48:17 +08:00
|
|
|
|
2002-03-19 00:22:14 +08:00
|
|
|
case GIMP_CHANNEL_OP_SUBTRACT:
|
2001-01-29 10:45:02 +08:00
|
|
|
gimp_channel_sub_segment (mask, x0, i, j - x0, last);
|
1997-11-25 06:05:25 +08:00
|
|
|
break;
|
2002-08-30 00:48:17 +08:00
|
|
|
|
1999-11-05 03:50:14 +08:00
|
|
|
default:
|
2002-03-18 06:54:26 +08:00
|
|
|
g_warning ("Only ADD, REPLACE, and SUBTRACT are valid for channel_combine!");
|
1999-11-05 03:50:14 +08:00
|
|
|
break;
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (last != val)
|
|
|
|
{
|
|
|
|
x0 = j;
|
|
|
|
last = val;
|
1999-04-09 14:00:11 +08:00
|
|
|
/* because we are symetric accross the y axis we can
|
|
|
|
skip ahead a bit if we are inside the ellipse*/
|
|
|
|
if (val == 255 && j < cx)
|
|
|
|
j = cx + (cx - j) - 1;
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (last)
|
|
|
|
{
|
2002-03-19 00:22:14 +08:00
|
|
|
switch (op)
|
|
|
|
{
|
|
|
|
case GIMP_CHANNEL_OP_ADD:
|
|
|
|
case GIMP_CHANNEL_OP_REPLACE:
|
|
|
|
gimp_channel_add_segment (mask, x0, i, j - x0, last);
|
|
|
|
break;
|
2002-08-30 00:48:17 +08:00
|
|
|
|
2002-03-19 00:22:14 +08:00
|
|
|
case GIMP_CHANNEL_OP_SUBTRACT:
|
|
|
|
gimp_channel_sub_segment (mask, x0, i, j - x0, last);
|
|
|
|
break;
|
2002-08-30 00:48:17 +08:00
|
|
|
|
2002-03-19 00:22:14 +08:00
|
|
|
default:
|
|
|
|
g_warning ("Only ADD, REPLACE, and SUBTRACT are valid for channel_combine!");
|
|
|
|
break;
|
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Determine new boundary */
|
2002-03-19 00:22:14 +08:00
|
|
|
if (mask->bounds_known && (op == GIMP_CHANNEL_OP_ADD) && !mask->empty)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
|
|
|
if (x < mask->x1)
|
|
|
|
mask->x1 = x;
|
|
|
|
if (y < mask->y1)
|
|
|
|
mask->y1 = y;
|
|
|
|
if ((x + w) > mask->x2)
|
|
|
|
mask->x2 = (x + w);
|
|
|
|
if ((y + h) > mask->y2)
|
|
|
|
mask->y2 = (y + h);
|
|
|
|
}
|
2002-03-19 00:22:14 +08:00
|
|
|
else if (op == GIMP_CHANNEL_OP_REPLACE || mask->empty)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
|
|
|
mask->empty = FALSE;
|
2002-08-30 00:48:17 +08:00
|
|
|
mask->x1 = x;
|
|
|
|
mask->y1 = y;
|
|
|
|
mask->x2 = x + w;
|
|
|
|
mask->y2 = y + h;
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
mask->bounds_known = FALSE;
|
|
|
|
|
2000-01-26 07:06:12 +08:00
|
|
|
mask->x1 = CLAMP (mask->x1, 0, GIMP_DRAWABLE (mask)->width);
|
|
|
|
mask->y1 = CLAMP (mask->y1, 0, GIMP_DRAWABLE (mask)->height);
|
|
|
|
mask->x2 = CLAMP (mask->x2, 0, GIMP_DRAWABLE (mask)->width);
|
|
|
|
mask->y2 = CLAMP (mask->y2, 0, GIMP_DRAWABLE (mask)->height);
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
1999-04-09 14:00:11 +08:00
|
|
|
static void
|
2001-08-11 22:39:19 +08:00
|
|
|
gimp_channel_combine_sub_region_add (gpointer unused,
|
2001-01-29 10:45:02 +08:00
|
|
|
PixelRegion *srcPR,
|
|
|
|
PixelRegion *destPR)
|
1999-04-09 14:00:11 +08:00
|
|
|
{
|
1999-08-22 19:45:31 +08:00
|
|
|
guchar *src, *dest;
|
2000-12-29 00:19:55 +08:00
|
|
|
gint x, y, val;
|
1999-08-22 19:45:31 +08:00
|
|
|
|
|
|
|
src = srcPR->data;
|
1999-04-09 14:00:11 +08:00
|
|
|
dest = destPR->data;
|
1999-08-22 19:45:31 +08:00
|
|
|
|
1999-04-09 14:00:11 +08:00
|
|
|
for (y = 0; y < srcPR->h; y++)
|
|
|
|
{
|
1999-08-22 19:45:31 +08:00
|
|
|
for (x = 0; x < srcPR->w; x++)
|
|
|
|
{
|
|
|
|
val = dest[x] + src[x];
|
|
|
|
if (val > 255)
|
|
|
|
dest[x] = 255;
|
|
|
|
else
|
|
|
|
dest[x] = val;
|
|
|
|
}
|
|
|
|
src += srcPR->rowstride;
|
|
|
|
dest += destPR->rowstride;
|
1999-04-09 14:00:11 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2001-08-11 22:39:19 +08:00
|
|
|
gimp_channel_combine_sub_region_sub (gpointer unused,
|
2001-01-29 10:45:02 +08:00
|
|
|
PixelRegion *srcPR,
|
|
|
|
PixelRegion *destPR)
|
1999-04-09 14:00:11 +08:00
|
|
|
{
|
1999-08-22 19:45:31 +08:00
|
|
|
guchar *src, *dest;
|
2000-12-29 00:19:55 +08:00
|
|
|
gint x, y;
|
1999-08-22 19:45:31 +08:00
|
|
|
|
|
|
|
src = srcPR->data;
|
1999-04-09 14:00:11 +08:00
|
|
|
dest = destPR->data;
|
1999-08-22 19:45:31 +08:00
|
|
|
|
1999-04-09 14:00:11 +08:00
|
|
|
for (y = 0; y < srcPR->h; y++)
|
|
|
|
{
|
1999-08-22 19:45:31 +08:00
|
|
|
for (x = 0; x < srcPR->w; x++)
|
|
|
|
{
|
|
|
|
if (src[x] > dest[x])
|
|
|
|
dest[x] = 0;
|
|
|
|
else
|
|
|
|
dest[x]-= src[x];
|
|
|
|
}
|
|
|
|
src += srcPR->rowstride;
|
|
|
|
dest += destPR->rowstride;
|
1999-04-09 14:00:11 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2001-08-11 22:39:19 +08:00
|
|
|
gimp_channel_combine_sub_region_intersect (gpointer unused,
|
2001-01-29 10:45:02 +08:00
|
|
|
PixelRegion *srcPR,
|
|
|
|
PixelRegion *destPR)
|
1999-04-09 14:00:11 +08:00
|
|
|
{
|
1999-08-22 19:45:31 +08:00
|
|
|
guchar *src, *dest;
|
2000-12-29 00:19:55 +08:00
|
|
|
gint x, y;
|
1999-08-22 19:45:31 +08:00
|
|
|
|
|
|
|
src = srcPR->data;
|
1999-04-09 14:00:11 +08:00
|
|
|
dest = destPR->data;
|
1999-08-22 19:45:31 +08:00
|
|
|
|
1999-04-09 14:00:11 +08:00
|
|
|
for (y = 0; y < srcPR->h; y++)
|
|
|
|
{
|
1999-08-22 19:45:31 +08:00
|
|
|
for (x = 0; x < srcPR->w; x++)
|
|
|
|
{
|
2000-01-26 07:06:12 +08:00
|
|
|
dest[x] = MIN (dest[x], src[x]);
|
1999-08-22 19:45:31 +08:00
|
|
|
}
|
|
|
|
src += srcPR->rowstride;
|
|
|
|
dest += destPR->rowstride;
|
1999-04-09 14:00:11 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
void
|
2002-03-19 00:22:14 +08:00
|
|
|
gimp_channel_combine_mask (GimpChannel *mask,
|
|
|
|
GimpChannel *add_on,
|
|
|
|
GimpChannelOps op,
|
|
|
|
gint off_x,
|
|
|
|
gint off_y)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
|
|
|
PixelRegion srcPR, destPR;
|
2000-12-29 00:19:55 +08:00
|
|
|
gint x1, y1, x2, y2;
|
|
|
|
gint w, h;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2001-08-11 22:39:19 +08:00
|
|
|
g_return_if_fail (GIMP_IS_CHANNEL (mask));
|
|
|
|
g_return_if_fail (GIMP_IS_CHANNEL (add_on));
|
|
|
|
|
2000-01-26 07:06:12 +08:00
|
|
|
x1 = CLAMP (off_x, 0, GIMP_DRAWABLE (mask)->width);
|
|
|
|
y1 = CLAMP (off_y, 0, GIMP_DRAWABLE (mask)->height);
|
|
|
|
x2 = CLAMP (off_x + GIMP_DRAWABLE (add_on)->width, 0,
|
|
|
|
GIMP_DRAWABLE (mask)->width);
|
|
|
|
y2 = CLAMP (off_y + GIMP_DRAWABLE (add_on)->height, 0,
|
|
|
|
GIMP_DRAWABLE (mask)->height);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
w = (x2 - x1);
|
|
|
|
h = (y2 - y1);
|
|
|
|
|
1999-08-22 19:45:31 +08:00
|
|
|
pixel_region_init (&srcPR, GIMP_DRAWABLE (add_on)->tiles,
|
|
|
|
(x1 - off_x), (y1 - off_y), w, h, FALSE);
|
2002-08-30 00:48:17 +08:00
|
|
|
pixel_region_init (&destPR, GIMP_DRAWABLE (mask)->tiles,
|
|
|
|
x1, y1, w, h, TRUE);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
1999-04-09 14:00:11 +08:00
|
|
|
switch (op)
|
1999-08-22 19:45:31 +08:00
|
|
|
{
|
2002-03-19 00:22:14 +08:00
|
|
|
case GIMP_CHANNEL_OP_ADD:
|
|
|
|
case GIMP_CHANNEL_OP_REPLACE:
|
2001-01-29 10:45:02 +08:00
|
|
|
pixel_regions_process_parallel ((p_func)
|
|
|
|
gimp_channel_combine_sub_region_add,
|
1999-08-22 19:45:31 +08:00
|
|
|
NULL, 2, &srcPR, &destPR);
|
|
|
|
break;
|
2002-08-30 00:48:17 +08:00
|
|
|
|
2002-03-19 00:22:14 +08:00
|
|
|
case GIMP_CHANNEL_OP_SUBTRACT:
|
2001-01-29 10:45:02 +08:00
|
|
|
pixel_regions_process_parallel ((p_func)
|
|
|
|
gimp_channel_combine_sub_region_sub,
|
1999-08-22 19:45:31 +08:00
|
|
|
NULL, 2, &srcPR, &destPR);
|
|
|
|
break;
|
2002-08-30 00:48:17 +08:00
|
|
|
|
2002-03-19 00:22:14 +08:00
|
|
|
case GIMP_CHANNEL_OP_INTERSECT:
|
1999-08-22 19:45:31 +08:00
|
|
|
pixel_regions_process_parallel ((p_func)
|
2001-01-29 10:45:02 +08:00
|
|
|
gimp_channel_combine_sub_region_intersect,
|
1999-08-22 19:45:31 +08:00
|
|
|
NULL, 2, &srcPR, &destPR);
|
|
|
|
break;
|
2002-08-30 00:48:17 +08:00
|
|
|
|
1999-08-22 19:45:31 +08:00
|
|
|
default:
|
2001-11-15 19:31:18 +08:00
|
|
|
g_warning ("%s: unknown operation type\n", G_GNUC_PRETTY_FUNCTION);
|
1999-08-22 19:45:31 +08:00
|
|
|
break;
|
|
|
|
}
|
2001-01-29 10:45:02 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
mask->bounds_known = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2001-10-22 20:13:44 +08:00
|
|
|
gimp_channel_feather (GimpChannel *mask,
|
2001-01-29 10:45:02 +08:00
|
|
|
gdouble radius_x,
|
|
|
|
gdouble radius_y,
|
2001-10-22 20:13:44 +08:00
|
|
|
gboolean push_undo)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
|
|
|
PixelRegion srcPR;
|
|
|
|
|
2001-10-22 20:13:44 +08:00
|
|
|
g_return_if_fail (GIMP_IS_CHANNEL (mask));
|
2001-08-11 22:39:19 +08:00
|
|
|
|
2001-10-22 20:13:44 +08:00
|
|
|
if (push_undo)
|
2003-02-14 22:14:29 +08:00
|
|
|
gimp_channel_push_undo (mask, _("Feather Channel"));
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2001-10-22 20:13:44 +08:00
|
|
|
pixel_region_init (&srcPR, GIMP_DRAWABLE (mask)->tiles,
|
|
|
|
0, 0,
|
|
|
|
gimp_drawable_width (GIMP_DRAWABLE (mask)),
|
|
|
|
gimp_drawable_height (GIMP_DRAWABLE (mask)),
|
|
|
|
FALSE);
|
1999-05-07 07:10:29 +08:00
|
|
|
gaussian_blur_region (&srcPR, radius_x, radius_y);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2001-10-22 20:13:44 +08:00
|
|
|
mask->bounds_known = FALSE;
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
2002-03-09 00:34:42 +08:00
|
|
|
void
|
2002-08-20 18:22:23 +08:00
|
|
|
gimp_channel_sharpen (GimpChannel *mask,
|
|
|
|
gboolean push_undo)
|
2002-03-09 00:34:42 +08:00
|
|
|
{
|
|
|
|
PixelRegion maskPR;
|
|
|
|
GimpLut *lut;
|
|
|
|
|
|
|
|
g_return_if_fail (GIMP_IS_CHANNEL (mask));
|
|
|
|
|
2002-08-20 18:22:23 +08:00
|
|
|
if (push_undo)
|
2003-02-14 22:14:29 +08:00
|
|
|
gimp_channel_push_undo (mask, _("Sharpen Channel"));
|
2002-03-09 00:34:42 +08:00
|
|
|
|
|
|
|
pixel_region_init (&maskPR, GIMP_DRAWABLE (mask)->tiles,
|
|
|
|
0, 0,
|
|
|
|
GIMP_DRAWABLE (mask)->width,
|
|
|
|
GIMP_DRAWABLE (mask)->height, TRUE);
|
|
|
|
lut = threshold_lut_new (0.5, 1);
|
|
|
|
|
|
|
|
pixel_regions_process_parallel ((p_func) gimp_lut_process_inline,
|
|
|
|
lut, 1, &maskPR);
|
|
|
|
gimp_lut_free (lut);
|
2002-09-24 23:57:27 +08:00
|
|
|
|
|
|
|
mask->bounds_known = FALSE;
|
2002-03-09 00:34:42 +08:00
|
|
|
}
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
void
|
2002-08-20 18:22:23 +08:00
|
|
|
gimp_channel_clear (GimpChannel *mask,
|
|
|
|
gboolean push_undo)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
|
|
|
PixelRegion maskPR;
|
2002-08-27 22:17:46 +08:00
|
|
|
guchar bg = TRANSPARENT_OPACITY;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2001-08-11 22:39:19 +08:00
|
|
|
g_return_if_fail (GIMP_IS_CHANNEL (mask));
|
|
|
|
|
2002-08-20 18:22:23 +08:00
|
|
|
if (push_undo)
|
2003-02-14 22:14:29 +08:00
|
|
|
gimp_channel_push_undo (mask, _("Clear Channel"));
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
if (mask->bounds_known && !mask->empty)
|
|
|
|
{
|
1999-08-22 19:45:31 +08:00
|
|
|
pixel_region_init (&maskPR, GIMP_DRAWABLE (mask)->tiles,
|
|
|
|
mask->x1, mask->y1,
|
1997-11-25 06:05:25 +08:00
|
|
|
(mask->x2 - mask->x1), (mask->y2 - mask->y1), TRUE);
|
|
|
|
color_region (&maskPR, &bg);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* clear the mask */
|
1999-08-22 19:45:31 +08:00
|
|
|
pixel_region_init (&maskPR, GIMP_DRAWABLE (mask)->tiles,
|
|
|
|
0, 0,
|
|
|
|
GIMP_DRAWABLE (mask)->width,
|
|
|
|
GIMP_DRAWABLE (mask)->height, TRUE);
|
1997-11-25 06:05:25 +08:00
|
|
|
color_region (&maskPR, &bg);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* we know the bounds */
|
|
|
|
mask->bounds_known = TRUE;
|
1999-08-22 19:45:31 +08:00
|
|
|
mask->empty = TRUE;
|
|
|
|
mask->x1 = 0;
|
|
|
|
mask->y1 = 0;
|
|
|
|
mask->x2 = GIMP_DRAWABLE (mask)->width;
|
|
|
|
mask->y2 = GIMP_DRAWABLE (mask)->height;
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2002-08-20 18:22:23 +08:00
|
|
|
gimp_channel_all (GimpChannel *mask,
|
|
|
|
gboolean push_undo)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2002-03-09 00:34:42 +08:00
|
|
|
PixelRegion maskPR;
|
2002-08-27 22:17:46 +08:00
|
|
|
guchar bg = OPAQUE_OPACITY;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2001-08-11 22:39:19 +08:00
|
|
|
g_return_if_fail (GIMP_IS_CHANNEL (mask));
|
|
|
|
|
2002-08-20 18:22:23 +08:00
|
|
|
if (push_undo)
|
2003-02-14 22:14:29 +08:00
|
|
|
gimp_channel_push_undo (mask, _("Fill Channel"));
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2002-03-09 00:34:42 +08:00
|
|
|
/* clear the mask */
|
1999-08-22 19:45:31 +08:00
|
|
|
pixel_region_init (&maskPR, GIMP_DRAWABLE (mask)->tiles,
|
|
|
|
0, 0,
|
|
|
|
GIMP_DRAWABLE (mask)->width,
|
|
|
|
GIMP_DRAWABLE (mask)->height, TRUE);
|
2002-03-09 00:34:42 +08:00
|
|
|
color_region (&maskPR, &bg);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2002-03-09 00:34:42 +08:00
|
|
|
/* we know the bounds */
|
|
|
|
mask->bounds_known = TRUE;
|
|
|
|
mask->empty = FALSE;
|
|
|
|
mask->x1 = 0;
|
|
|
|
mask->y1 = 0;
|
|
|
|
mask->x2 = GIMP_DRAWABLE (mask)->width;
|
|
|
|
mask->y2 = GIMP_DRAWABLE (mask)->height;
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2002-06-07 03:07:59 +08:00
|
|
|
gimp_channel_invert (GimpChannel *mask,
|
|
|
|
gboolean push_undo)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2001-08-11 22:39:19 +08:00
|
|
|
g_return_if_fail (GIMP_IS_CHANNEL (mask));
|
|
|
|
|
2002-06-07 03:07:59 +08:00
|
|
|
if (push_undo)
|
2003-02-14 22:14:29 +08:00
|
|
|
gimp_channel_push_undo (mask, _("Invert Channel"));
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2002-08-20 18:22:23 +08:00
|
|
|
if (mask->bounds_known && mask->empty)
|
|
|
|
{
|
|
|
|
gimp_channel_all (mask, FALSE);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
PixelRegion maskPR;
|
|
|
|
GimpLut *lut;
|
|
|
|
|
|
|
|
pixel_region_init (&maskPR, GIMP_DRAWABLE (mask)->tiles,
|
|
|
|
0, 0,
|
|
|
|
GIMP_DRAWABLE (mask)->width,
|
|
|
|
GIMP_DRAWABLE (mask)->height, TRUE);
|
2002-03-09 00:34:42 +08:00
|
|
|
|
2002-08-20 18:22:23 +08:00
|
|
|
lut = invert_lut_new (1);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2002-08-20 18:22:23 +08:00
|
|
|
pixel_regions_process_parallel ((p_func) gimp_lut_process_inline, lut,
|
|
|
|
1, &maskPR);
|
2002-06-07 03:07:59 +08:00
|
|
|
|
2002-08-20 18:22:23 +08:00
|
|
|
gimp_lut_free (lut);
|
|
|
|
|
|
|
|
mask->bounds_known = FALSE;
|
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2001-01-29 10:45:02 +08:00
|
|
|
gimp_channel_border (GimpChannel *mask,
|
2001-12-03 21:44:59 +08:00
|
|
|
gint radius_x,
|
2002-08-20 18:22:23 +08:00
|
|
|
gint radius_y,
|
|
|
|
gboolean push_undo)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
|
|
|
PixelRegion bPR;
|
2000-12-29 00:19:55 +08:00
|
|
|
gint x1, y1, x2, y2;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2001-08-11 22:39:19 +08:00
|
|
|
g_return_if_fail (GIMP_IS_CHANNEL (mask));
|
|
|
|
|
2001-12-03 21:44:59 +08:00
|
|
|
if (radius_x < 0 || radius_y < 0)
|
|
|
|
return;
|
|
|
|
|
2001-01-29 10:45:02 +08:00
|
|
|
if (! gimp_channel_bounds (mask, &x1, &y1, &x2, &y2))
|
1997-11-25 06:05:25 +08:00
|
|
|
return;
|
2002-08-20 18:22:23 +08:00
|
|
|
|
2001-01-29 10:45:02 +08:00
|
|
|
if (gimp_channel_is_empty (mask))
|
1999-05-07 07:10:29 +08:00
|
|
|
return;
|
|
|
|
|
|
|
|
if (x1 - radius_x < 0)
|
1998-06-18 03:17:00 +08:00
|
|
|
x1 = 0;
|
|
|
|
else
|
1999-05-07 07:10:29 +08:00
|
|
|
x1 -= radius_x;
|
1999-08-22 19:45:31 +08:00
|
|
|
if (x2 + radius_x > GIMP_DRAWABLE (mask)->width)
|
|
|
|
x2 = GIMP_DRAWABLE (mask)->width;
|
1998-06-18 03:17:00 +08:00
|
|
|
else
|
1999-05-07 07:10:29 +08:00
|
|
|
x2 += radius_x;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
1999-05-07 07:10:29 +08:00
|
|
|
if (y1 - radius_y < 0)
|
1998-06-18 03:17:00 +08:00
|
|
|
y1 = 0;
|
|
|
|
else
|
1999-05-07 07:10:29 +08:00
|
|
|
y1 -= radius_y;
|
1999-08-22 19:45:31 +08:00
|
|
|
if (y2 + radius_y > GIMP_DRAWABLE (mask)->height)
|
|
|
|
y2 = GIMP_DRAWABLE (mask)->height;
|
1998-06-18 03:17:00 +08:00
|
|
|
else
|
1999-05-07 07:10:29 +08:00
|
|
|
y2 += radius_y;
|
2001-01-29 10:45:02 +08:00
|
|
|
|
2002-08-20 18:22:23 +08:00
|
|
|
if (push_undo)
|
2003-02-14 22:14:29 +08:00
|
|
|
gimp_channel_push_undo (mask, _("Border Channel"));
|
1997-11-25 06:05:25 +08:00
|
|
|
|
1999-08-22 19:45:31 +08:00
|
|
|
pixel_region_init (&bPR, GIMP_DRAWABLE (mask)->tiles, x1, y1,
|
1998-06-18 03:17:00 +08:00
|
|
|
(x2-x1), (y2-y1), TRUE);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
1999-08-22 19:45:31 +08:00
|
|
|
border_region (&bPR, radius_x, radius_y);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
mask->bounds_known = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2001-01-29 10:45:02 +08:00
|
|
|
gimp_channel_grow (GimpChannel *mask,
|
2001-12-03 21:44:59 +08:00
|
|
|
gint radius_x,
|
2002-08-20 18:22:23 +08:00
|
|
|
gint radius_y,
|
|
|
|
gboolean push_undo)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
|
|
|
PixelRegion bPR;
|
2000-12-29 00:19:55 +08:00
|
|
|
gint x1, y1, x2, y2;
|
1998-06-18 03:17:00 +08:00
|
|
|
|
2001-08-11 22:39:19 +08:00
|
|
|
g_return_if_fail (GIMP_IS_CHANNEL (mask));
|
|
|
|
|
1999-05-07 07:10:29 +08:00
|
|
|
if (radius_x == 0 && radius_y == 0)
|
1998-06-18 03:17:00 +08:00
|
|
|
return;
|
|
|
|
|
2001-12-03 21:44:59 +08:00
|
|
|
if (radius_x <= 0 && radius_y <= 0)
|
1999-05-07 07:10:29 +08:00
|
|
|
{
|
2002-08-20 18:22:23 +08:00
|
|
|
gimp_channel_shrink (mask, -radius_x, -radius_y, FALSE, push_undo);
|
1999-05-07 07:10:29 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2001-12-03 21:44:59 +08:00
|
|
|
if (radius_x < 0 || radius_y < 0)
|
1998-06-18 03:17:00 +08:00
|
|
|
return;
|
2001-12-02 22:59:30 +08:00
|
|
|
|
2001-12-03 21:44:59 +08:00
|
|
|
if (! gimp_channel_bounds (mask, &x1, &y1, &x2, &y2))
|
|
|
|
return;
|
2002-08-20 18:22:23 +08:00
|
|
|
|
2001-01-29 10:45:02 +08:00
|
|
|
if (gimp_channel_is_empty (mask))
|
1997-11-25 06:05:25 +08:00
|
|
|
return;
|
|
|
|
|
1999-05-07 07:10:29 +08:00
|
|
|
if (x1 - radius_x > 0)
|
|
|
|
x1 = x1 - radius_x;
|
1998-06-18 03:17:00 +08:00
|
|
|
else
|
|
|
|
x1 = 0;
|
1999-05-07 07:10:29 +08:00
|
|
|
if (y1 - radius_y > 0)
|
|
|
|
y1 = y1 - radius_y;
|
1998-06-18 03:17:00 +08:00
|
|
|
else
|
|
|
|
y1 = 0;
|
1999-08-22 19:45:31 +08:00
|
|
|
if (x2 + radius_x < GIMP_DRAWABLE (mask)->width)
|
1999-05-07 07:10:29 +08:00
|
|
|
x2 = x2 + radius_x;
|
1998-06-18 03:17:00 +08:00
|
|
|
else
|
1999-08-22 19:45:31 +08:00
|
|
|
x2 = GIMP_DRAWABLE (mask)->width;
|
|
|
|
if (y2 + radius_y < GIMP_DRAWABLE (mask)->height)
|
1999-05-07 07:10:29 +08:00
|
|
|
y2 = y2 + radius_y;
|
1998-06-18 03:17:00 +08:00
|
|
|
else
|
1999-08-22 19:45:31 +08:00
|
|
|
y2 = GIMP_DRAWABLE (mask)->height;
|
1998-06-18 03:17:00 +08:00
|
|
|
|
2002-08-20 18:22:23 +08:00
|
|
|
if (push_undo)
|
2003-02-14 22:14:29 +08:00
|
|
|
gimp_channel_push_undo (mask, _("Grow Channel"));
|
1997-11-25 06:05:25 +08:00
|
|
|
|
1998-06-18 03:17:00 +08:00
|
|
|
/* need full extents for grow, not! */
|
1999-08-22 19:45:31 +08:00
|
|
|
pixel_region_init (&bPR, GIMP_DRAWABLE (mask)->tiles, x1, y1, (x2 - x1),
|
1998-06-18 03:17:00 +08:00
|
|
|
(y2 - y1), TRUE);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
1999-05-07 07:10:29 +08:00
|
|
|
fatten_region (&bPR, radius_x, radius_y);
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
mask->bounds_known = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2001-01-29 10:45:02 +08:00
|
|
|
gimp_channel_shrink (GimpChannel *mask,
|
|
|
|
gint radius_x,
|
|
|
|
gint radius_y,
|
2002-08-20 18:22:23 +08:00
|
|
|
gboolean edge_lock,
|
|
|
|
gboolean push_undo)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
|
|
|
PixelRegion bPR;
|
2000-12-29 00:19:55 +08:00
|
|
|
gint x1, y1, x2, y2;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2001-08-11 22:39:19 +08:00
|
|
|
g_return_if_fail (GIMP_IS_CHANNEL (mask));
|
|
|
|
|
1999-05-07 07:10:29 +08:00
|
|
|
if (radius_x == 0 && radius_y == 0)
|
1998-06-18 03:17:00 +08:00
|
|
|
return;
|
1999-05-07 07:10:29 +08:00
|
|
|
|
2001-12-03 21:44:59 +08:00
|
|
|
if (radius_x <= 0 && radius_y <= 0)
|
1999-05-07 07:10:29 +08:00
|
|
|
{
|
2002-08-20 18:22:23 +08:00
|
|
|
gimp_channel_grow (mask, -radius_x, -radius_y, push_undo);
|
1999-05-07 07:10:29 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2001-12-03 21:44:59 +08:00
|
|
|
if (radius_x < 0 || radius_y < 0)
|
|
|
|
return;
|
|
|
|
|
2001-01-29 10:45:02 +08:00
|
|
|
if (! gimp_channel_bounds (mask, &x1, &y1, &x2, &y2))
|
1997-11-25 06:05:25 +08:00
|
|
|
return;
|
2002-08-20 18:22:23 +08:00
|
|
|
|
2001-01-29 10:45:02 +08:00
|
|
|
if (gimp_channel_is_empty (mask))
|
1998-06-18 03:17:00 +08:00
|
|
|
return;
|
|
|
|
|
|
|
|
if (x1 > 0)
|
|
|
|
x1--;
|
|
|
|
if (y1 > 0)
|
|
|
|
y1--;
|
1999-08-22 19:45:31 +08:00
|
|
|
if (x2 < GIMP_DRAWABLE (mask)->width)
|
1998-06-18 03:17:00 +08:00
|
|
|
x2++;
|
1999-08-22 19:45:31 +08:00
|
|
|
if (y2 < GIMP_DRAWABLE (mask)->height)
|
1998-06-18 03:17:00 +08:00
|
|
|
y2++;
|
1999-05-07 07:10:29 +08:00
|
|
|
|
2002-08-20 18:22:23 +08:00
|
|
|
if (push_undo)
|
2003-02-14 22:14:29 +08:00
|
|
|
gimp_channel_push_undo (mask, _("Shrink Channel"));
|
1999-05-07 07:10:29 +08:00
|
|
|
|
1999-08-22 19:45:31 +08:00
|
|
|
pixel_region_init (&bPR, GIMP_DRAWABLE (mask)->tiles, x1, y1, (x2 - x1),
|
1998-06-18 03:17:00 +08:00
|
|
|
(y2 - y1), TRUE);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
1999-05-07 07:10:29 +08:00
|
|
|
thin_region (&bPR, radius_x, radius_y, edge_lock);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
mask->bounds_known = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2001-01-29 10:45:02 +08:00
|
|
|
gimp_channel_translate (GimpChannel *mask,
|
|
|
|
gint off_x,
|
2002-08-20 18:22:23 +08:00
|
|
|
gint off_y,
|
|
|
|
gboolean push_undo)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2002-08-30 00:48:17 +08:00
|
|
|
GimpChannel *tmp_mask = NULL;
|
2000-12-29 00:19:55 +08:00
|
|
|
gint width, height;
|
|
|
|
PixelRegion srcPR, destPR;
|
2002-08-30 00:48:17 +08:00
|
|
|
guchar empty = TRANSPARENT_OPACITY;
|
2000-12-29 00:19:55 +08:00
|
|
|
gint x1, y1, x2, y2;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2001-08-11 22:39:19 +08:00
|
|
|
g_return_if_fail (GIMP_IS_CHANNEL (mask));
|
|
|
|
|
2002-08-20 18:22:23 +08:00
|
|
|
if (push_undo)
|
2003-02-14 22:14:29 +08:00
|
|
|
gimp_channel_push_undo (mask, _("Translate Channel"));
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2001-01-29 10:45:02 +08:00
|
|
|
gimp_channel_bounds (mask, &x1, &y1, &x2, &y2);
|
2000-01-26 07:06:12 +08:00
|
|
|
x1 = CLAMP ((x1 + off_x), 0, GIMP_DRAWABLE (mask)->width);
|
|
|
|
y1 = CLAMP ((y1 + off_y), 0, GIMP_DRAWABLE (mask)->height);
|
|
|
|
x2 = CLAMP ((x2 + off_x), 0, GIMP_DRAWABLE (mask)->width);
|
|
|
|
y2 = CLAMP ((y2 + off_y), 0, GIMP_DRAWABLE (mask)->height);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2002-08-30 00:48:17 +08:00
|
|
|
width = x2 - x1;
|
1997-11-25 06:05:25 +08:00
|
|
|
height = y2 - y1;
|
|
|
|
|
|
|
|
/* make sure width and height are non-zero */
|
|
|
|
if (width != 0 && height != 0)
|
|
|
|
{
|
|
|
|
/* copy the portion of the mask we will keep to a
|
|
|
|
* temporary buffer
|
|
|
|
*/
|
2002-02-26 01:58:50 +08:00
|
|
|
tmp_mask = gimp_channel_new_mask (gimp_item_get_image (GIMP_ITEM (mask)),
|
2001-01-29 10:45:02 +08:00
|
|
|
width, height);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
1999-08-22 19:45:31 +08:00
|
|
|
pixel_region_init (&srcPR, GIMP_DRAWABLE (mask)->tiles,
|
|
|
|
x1 - off_x, y1 - off_y, width, height, FALSE);
|
|
|
|
pixel_region_init (&destPR, GIMP_DRAWABLE (tmp_mask)->tiles,
|
|
|
|
0, 0, width, height, TRUE);
|
1997-11-25 06:05:25 +08:00
|
|
|
copy_region (&srcPR, &destPR);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* clear the mask */
|
1999-08-22 19:45:31 +08:00
|
|
|
pixel_region_init (&srcPR, GIMP_DRAWABLE (mask)->tiles,
|
|
|
|
0, 0,
|
|
|
|
GIMP_DRAWABLE (mask)->width,
|
|
|
|
GIMP_DRAWABLE (mask)->height, TRUE);
|
1997-11-25 06:05:25 +08:00
|
|
|
color_region (&srcPR, &empty);
|
|
|
|
|
|
|
|
if (width != 0 && height != 0)
|
|
|
|
{
|
|
|
|
/* copy the temp mask back to the mask */
|
1999-08-22 19:45:31 +08:00
|
|
|
pixel_region_init (&srcPR, GIMP_DRAWABLE (tmp_mask)->tiles,
|
|
|
|
0, 0, width, height, FALSE);
|
|
|
|
pixel_region_init (&destPR, GIMP_DRAWABLE (mask)->tiles,
|
|
|
|
x1, y1, width, height, TRUE);
|
1997-11-25 06:05:25 +08:00
|
|
|
copy_region (&srcPR, &destPR);
|
|
|
|
|
|
|
|
/* free the temporary mask */
|
2003-01-06 06:07:10 +08:00
|
|
|
g_object_unref (tmp_mask);
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* calculate new bounds */
|
|
|
|
if (width == 0 || height == 0)
|
|
|
|
{
|
|
|
|
mask->empty = TRUE;
|
2002-08-30 00:48:17 +08:00
|
|
|
mask->x1 = 0;
|
|
|
|
mask->y1 = 0;
|
|
|
|
mask->x2 = GIMP_DRAWABLE (mask)->width;
|
|
|
|
mask->y2 = GIMP_DRAWABLE (mask)->height;
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
mask->x1 = x1;
|
|
|
|
mask->y1 = y1;
|
|
|
|
mask->x2 = x2;
|
|
|
|
mask->y2 = y2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2001-01-29 10:45:02 +08:00
|
|
|
gimp_channel_load (GimpChannel *mask,
|
2002-08-20 18:22:23 +08:00
|
|
|
GimpChannel *channel,
|
|
|
|
gboolean push_undo)
|
2001-01-29 00:44:22 +08:00
|
|
|
{
|
|
|
|
PixelRegion srcPR, destPR;
|
|
|
|
|
2001-08-11 22:39:19 +08:00
|
|
|
g_return_if_fail (GIMP_IS_CHANNEL (mask));
|
|
|
|
g_return_if_fail (GIMP_IS_CHANNEL (channel));
|
|
|
|
|
2002-08-20 18:22:23 +08:00
|
|
|
if (push_undo)
|
2003-02-14 22:14:29 +08:00
|
|
|
gimp_channel_push_undo (mask, _("Channel Load"));
|
2001-01-29 00:44:22 +08:00
|
|
|
|
|
|
|
/* copy the channel to the mask */
|
|
|
|
pixel_region_init (&srcPR, GIMP_DRAWABLE (channel)->tiles,
|
|
|
|
0, 0,
|
|
|
|
GIMP_DRAWABLE (channel)->width,
|
|
|
|
GIMP_DRAWABLE (channel)->height, FALSE);
|
|
|
|
pixel_region_init (&destPR, GIMP_DRAWABLE (mask)->tiles,
|
|
|
|
0, 0,
|
|
|
|
GIMP_DRAWABLE (channel)->width,
|
|
|
|
GIMP_DRAWABLE (channel)->height, TRUE);
|
|
|
|
copy_region (&srcPR, &destPR);
|
|
|
|
|
|
|
|
mask->bounds_known = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2001-01-29 10:45:02 +08:00
|
|
|
gimp_channel_layer_alpha (GimpChannel *mask,
|
2002-08-20 18:22:23 +08:00
|
|
|
GimpLayer *layer,
|
|
|
|
gboolean push_undo)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
|
|
|
PixelRegion srcPR, destPR;
|
2000-12-29 00:19:55 +08:00
|
|
|
gint x1, y1, x2, y2;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2001-08-11 22:39:19 +08:00
|
|
|
g_return_if_fail (GIMP_IS_CHANNEL (mask));
|
|
|
|
g_return_if_fail (GIMP_IS_LAYER (layer));
|
2002-03-09 00:34:42 +08:00
|
|
|
g_return_if_fail (gimp_drawable_has_alpha (GIMP_DRAWABLE (layer)));
|
2001-08-11 22:39:19 +08:00
|
|
|
|
2002-08-20 18:22:23 +08:00
|
|
|
if (push_undo)
|
2003-02-14 22:14:29 +08:00
|
|
|
gimp_channel_push_undo (mask, _("Channel from Alpha"));
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2002-08-20 18:22:23 +08:00
|
|
|
/* clear the mask if it is not already known to be empty */
|
|
|
|
if (! (mask->bounds_known && mask->empty))
|
|
|
|
gimp_channel_clear (mask, FALSE);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2000-01-26 07:06:12 +08:00
|
|
|
x1 = CLAMP (GIMP_DRAWABLE (layer)->offset_x, 0, GIMP_DRAWABLE (mask)->width);
|
|
|
|
y1 = CLAMP (GIMP_DRAWABLE (layer)->offset_y, 0, GIMP_DRAWABLE (mask)->height);
|
|
|
|
x2 = CLAMP (GIMP_DRAWABLE (layer)->offset_x + GIMP_DRAWABLE (layer)->width,
|
|
|
|
0, GIMP_DRAWABLE (mask)->width);
|
|
|
|
y2 = CLAMP (GIMP_DRAWABLE( layer)->offset_y + GIMP_DRAWABLE (layer)->height,
|
|
|
|
0, GIMP_DRAWABLE (mask)->height);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
1999-08-22 19:45:31 +08:00
|
|
|
pixel_region_init (&srcPR, GIMP_DRAWABLE (layer)->tiles,
|
|
|
|
(x1 - GIMP_DRAWABLE (layer)->offset_x),
|
|
|
|
(y1 - GIMP_DRAWABLE (layer)->offset_y),
|
1997-11-25 06:05:25 +08:00
|
|
|
(x2 - x1), (y2 - y1), FALSE);
|
1999-08-22 19:45:31 +08:00
|
|
|
pixel_region_init (&destPR, GIMP_DRAWABLE (mask)->tiles,
|
|
|
|
x1, y1, (x2 - x1), (y2 - y1), TRUE);
|
1997-11-25 06:05:25 +08:00
|
|
|
extract_alpha_region (&srcPR, NULL, &destPR);
|
|
|
|
|
|
|
|
mask->bounds_known = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2001-01-29 10:45:02 +08:00
|
|
|
gimp_channel_layer_mask (GimpChannel *mask,
|
2002-08-20 18:22:23 +08:00
|
|
|
GimpLayer *layer,
|
|
|
|
gboolean push_undo)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
|
|
|
PixelRegion srcPR, destPR;
|
2001-01-29 00:44:22 +08:00
|
|
|
gint x1, y1, x2, y2;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2001-08-11 22:39:19 +08:00
|
|
|
g_return_if_fail (GIMP_IS_CHANNEL (mask));
|
|
|
|
g_return_if_fail (GIMP_IS_LAYER (layer));
|
2002-03-09 00:34:42 +08:00
|
|
|
g_return_if_fail (gimp_layer_get_mask (layer));
|
2001-08-11 22:39:19 +08:00
|
|
|
|
2002-08-20 18:22:23 +08:00
|
|
|
if (push_undo)
|
2003-02-14 22:14:29 +08:00
|
|
|
gimp_channel_push_undo (mask, _("Channel from Mask"));
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2002-08-20 18:22:23 +08:00
|
|
|
/* clear the mask if it is not already known to be empty */
|
|
|
|
if (! (mask->bounds_known && mask->empty))
|
|
|
|
gimp_channel_clear (mask, FALSE);
|
2001-01-29 00:44:22 +08:00
|
|
|
|
2001-02-02 02:44:22 +08:00
|
|
|
x1 = CLAMP (GIMP_DRAWABLE (layer)->offset_x, 0, GIMP_DRAWABLE (mask)->width);
|
|
|
|
y1 = CLAMP (GIMP_DRAWABLE (layer)->offset_y, 0, GIMP_DRAWABLE (mask)->height);
|
|
|
|
x2 = CLAMP (GIMP_DRAWABLE (layer)->offset_x + GIMP_DRAWABLE (layer)->width,
|
|
|
|
0, GIMP_DRAWABLE (mask)->width);
|
|
|
|
y2 = CLAMP (GIMP_DRAWABLE (layer)->offset_y + GIMP_DRAWABLE (layer)->height,
|
|
|
|
0, GIMP_DRAWABLE (mask)->height);
|
2001-01-29 00:44:22 +08:00
|
|
|
|
2001-02-02 02:44:22 +08:00
|
|
|
pixel_region_init (&srcPR, GIMP_DRAWABLE (layer->mask)->tiles,
|
|
|
|
(x1 - GIMP_DRAWABLE (layer)->offset_x),
|
|
|
|
(y1 - GIMP_DRAWABLE (layer)->offset_y),
|
2001-01-29 00:44:22 +08:00
|
|
|
(x2 - x1), (y2 - y1),
|
|
|
|
FALSE);
|
2001-02-02 02:44:22 +08:00
|
|
|
pixel_region_init (&destPR, GIMP_DRAWABLE (mask)->tiles,
|
2001-01-29 00:44:22 +08:00
|
|
|
x1, y1,
|
|
|
|
(x2 - x1), (y2 - y1),
|
|
|
|
TRUE);
|
1997-11-25 06:05:25 +08:00
|
|
|
copy_region (&srcPR, &destPR);
|
|
|
|
|
|
|
|
mask->bounds_known = FALSE;
|
|
|
|
}
|
1998-01-22 15:02:57 +08:00
|
|
|
|
|
|
|
void
|
2001-01-29 10:45:02 +08:00
|
|
|
gimp_channel_invalidate_bounds (GimpChannel *channel)
|
1998-01-22 15:02:57 +08:00
|
|
|
{
|
2001-08-11 22:39:19 +08:00
|
|
|
g_return_if_fail (GIMP_IS_CHANNEL (channel));
|
|
|
|
|
1998-01-22 15:02:57 +08:00
|
|
|
channel->bounds_known = FALSE;
|
|
|
|
}
|