gimp/app/core/gimpimage-crop.c

550 lines
14 KiB
C
Raw Normal View History

/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <string.h>
an evil temp_hack which lets GimpContext managing the active display 2001-08-14 Michael Natterer <mitch@gimp.org> * app/gdisplay.h: an evil temp_hack which lets GimpContext managing the active display withoug including "gdisplay.h". Will go away as soon ad context properties are registered dynamically. * app/module_db.c: cleaned up the object code in preparation of moving it to core/. * app/path.c: connect to GimpImage's * app/core/gimpobject.[ch]: derive it from GObject, not from GtkObject any more (yeah :-) * app/core/*.c: #include <glib-object.h> instead of <gtk/gtk.h>, removed some remaining GtkObject-isms. (left in a few #include <gtk/gtk.h> where bigger changes are needed to get rid of the UI dependency). * app/core/core-types.h: #include <gdk-pixbuf/gdk-pixbuf.h> here temporarily. * app/core/gimp.c (gimp_create_display): unref the image after creating it's first display. * app/core/gimpbrush.[ch]: disabled the parts of the code which depend on GimpPaintTool. * app/core/gimpbrushgenerated.c * app/core/gimpbrushpipe.c: changed accordingly. * app/core/gimpcontext.[ch]: evil hack (see above) to manage the active display without including "gdisplay.h" * app/core/gimpimage-mask.[ch]: pass a context to gimage_mask_stroke() and get the current tool's PDB string from there. * app/core/gimpedit.c: changed accordingly. * app/core/gimpimage.c: use gimp_image_update() instead of gdisplays_update_full(). * app/gui/color-area.c * app/gui/colormap-dialog.c * app/gui/dialogs-constructors.c * app/gui/edit-commands.c * app/gui/image-commands.c * app/gui/toolbox.c: changed accordingly (don't use Gtk methods on GObjects). * app/gui/menus.c: fix some const warnings by explicit casting. * app/tools/*.[ch]: ported all tools to GObject, some minor cleanup while i was on it. * app/widgets/gimpdialogfactory.[ch]: ported to GObject. * app/widgets/gimplayerlistview.h: added FOO_GET_CLASS() macro. * tools/pdbgen/app.pl: added a "widgets_eek" hack like "tools_eek" which inserts #include "widgets/widgets-types.h" before ordinary includes. * tools/pdbgen/pdb/brush_select.pdb * tools/pdbgen/pdb/edit.pdb * app/pdb/brush_select_cmds.c * app/pdb/edit_cmds.c: changed according to the stuff above.
2001-08-14 22:53:55 +08:00
#include <glib-object.h>
#include "core-types.h"
#include "base/pixel-region.h"
app/Makefile.am app/gimpunit.c removed... 2001-07-11 Michael Natterer <mitch@gimp.org> * app/Makefile.am * app/gimpunit.c * app/unitrc.h: removed... * app/core/Makefile.am * app/core/gimpunit.[ch]: ...re-added here. * app/core/gimp.[ch]: added the image and drawable hash tables, next_image_ID, next_guide_ID and next_drawable_ID, added a GimpCoreConfig pointer which is now initalized dynamically. * app/core/gimpcoreconfig.[ch]: don't provide a global core_config variable any more (need to access gimp->config now). * app/gdisplay.[ch] * app/core/gimpdrawable.[ch] * app/core/gimpimage.[ch]: removed all global variables from gimpimage.c and gimpdrawable.c, pass a Gimp* to all *_get_by_ID() functions. * tools/pdbgen/app.pl: pass Gimp* to all _get_by_ID() functions. * app/app_procs.c * app/file-open.c * app/file-save.c * app/gimprc.c * app/libgimp_glue.c * app/module_db.c * app/plug_in.c * app/undo.c * app/user_install.c * app/core/core-types.h * app/core/gimpcontext.c * app/core/gimpimage-crop.c * app/core/gimpimage-new.c * app/core/gimpparasite.c * app/gui/file-new-dialog.c * app/gui/file-open-dialog.c * app/gui/info-window.c * app/gui/preferences-dialog.c * app/gui/resize-dialog.c * app/xcf/xcf-load.c * app/xcf/xcf-save.c * app/xcf/xcf.c * app/widgets/gimpdnd.c * app/pdb/channel_cmds.c * app/pdb/color_cmds.c * app/pdb/convert_cmds.c * app/pdb/display_cmds.c * app/pdb/drawable_cmds.c * app/pdb/edit_cmds.c * app/pdb/fileops_cmds.c * app/pdb/floating_sel_cmds.c * app/pdb/guides_cmds.c * app/pdb/image_cmds.c * app/pdb/layer_cmds.c * app/pdb/parasite_cmds.c * app/pdb/paths_cmds.c * app/pdb/selection_cmds.c * app/pdb/text_tool_cmds.c * app/pdb/tools_cmds.c * app/pdb/undo_cmds.c * app/pdb/unit_cmds.c * tools/pdbgen/pdb/image.pdb * tools/pdbgen/pdb/unit.pdb: changed accordingly.
2001-07-11 20:39:49 +08:00
#include "gimp.h"
#include "gimpchannel.h"
#include "gimpdrawable.h"
#include "gimpimage.h"
#include "gimpimage-crop.h"
#include "gimpimage-mask.h"
#include "gimpimage-projection.h"
#include "gimplayer.h"
#include "gimplist.h"
#include "floating_sel.h"
#include "undo.h"
typedef enum
{
AUTO_CROP_NOTHING = 0,
AUTO_CROP_ALPHA = 1,
AUTO_CROP_COLOR = 2
} AutoCropType;
typedef guchar * (* GetColorFunc) (GObject *crop_object,
gint ,
gint );
typedef AutoCropType (* ColorsEqualFunc) (guchar *,
guchar *,
gint );
/* local function prototypes */
static void gimp_image_crop_adjust_guides (GimpImage *gimage,
gint x1,
gint y1,
gint x2,
gint y2);
static AutoCropType gimp_image_crop_guess_bgcolor (GObject *get_color_obj,
GetColorFunc get_color_func,
gint bytes,
gboolean has_alpha,
guchar *color,
gint x1,
gint x2,
gint y1,
gint y2);
static gint gimp_image_crop_colors_equal (guchar *col1,
guchar *col2,
gint bytes);
static gint gimp_image_crop_colors_alpha (guchar *col1,
guchar *col2,
gint bytes);
/* public functions */
void
gimp_image_crop (GimpImage *gimage,
gint x1,
gint y1,
gint x2,
gint y2,
gboolean active_layer_only,
gboolean crop_layers)
{
GimpLayer *layer;
GimpLayer *floating_layer;
GimpChannel *channel;
GList *guide_list_ptr;
GList *list;
gint width, height;
gint lx1, ly1, lx2, ly2;
gint off_x, off_y;
gint doff_x, doff_y;
g_return_if_fail (gimage != NULL);
g_return_if_fail (GIMP_IS_IMAGE (gimage));
width = x2 - x1;
height = y2 - y1;
/* Make sure new width and height are non-zero */
if (width && height)
{
app/Makefile.am app/gimpunit.c removed... 2001-07-11 Michael Natterer <mitch@gimp.org> * app/Makefile.am * app/gimpunit.c * app/unitrc.h: removed... * app/core/Makefile.am * app/core/gimpunit.[ch]: ...re-added here. * app/core/gimp.[ch]: added the image and drawable hash tables, next_image_ID, next_guide_ID and next_drawable_ID, added a GimpCoreConfig pointer which is now initalized dynamically. * app/core/gimpcoreconfig.[ch]: don't provide a global core_config variable any more (need to access gimp->config now). * app/gdisplay.[ch] * app/core/gimpdrawable.[ch] * app/core/gimpimage.[ch]: removed all global variables from gimpimage.c and gimpdrawable.c, pass a Gimp* to all *_get_by_ID() functions. * tools/pdbgen/app.pl: pass Gimp* to all _get_by_ID() functions. * app/app_procs.c * app/file-open.c * app/file-save.c * app/gimprc.c * app/libgimp_glue.c * app/module_db.c * app/plug_in.c * app/undo.c * app/user_install.c * app/core/core-types.h * app/core/gimpcontext.c * app/core/gimpimage-crop.c * app/core/gimpimage-new.c * app/core/gimpparasite.c * app/gui/file-new-dialog.c * app/gui/file-open-dialog.c * app/gui/info-window.c * app/gui/preferences-dialog.c * app/gui/resize-dialog.c * app/xcf/xcf-load.c * app/xcf/xcf-save.c * app/xcf/xcf.c * app/widgets/gimpdnd.c * app/pdb/channel_cmds.c * app/pdb/color_cmds.c * app/pdb/convert_cmds.c * app/pdb/display_cmds.c * app/pdb/drawable_cmds.c * app/pdb/edit_cmds.c * app/pdb/fileops_cmds.c * app/pdb/floating_sel_cmds.c * app/pdb/guides_cmds.c * app/pdb/image_cmds.c * app/pdb/layer_cmds.c * app/pdb/parasite_cmds.c * app/pdb/paths_cmds.c * app/pdb/selection_cmds.c * app/pdb/text_tool_cmds.c * app/pdb/tools_cmds.c * app/pdb/undo_cmds.c * app/pdb/unit_cmds.c * tools/pdbgen/pdb/image.pdb * tools/pdbgen/pdb/unit.pdb: changed accordingly.
2001-07-11 20:39:49 +08:00
gimp_set_busy (gimage->gimp);
if (active_layer_only)
{
undo_push_group_start (gimage, LAYER_RESIZE_UNDO);
layer = gimp_image_get_active_layer (gimage);
if (gimp_layer_is_floating_sel (layer))
floating_sel_relax (layer, TRUE);
gimp_drawable_offsets (GIMP_DRAWABLE (layer), &doff_x, &doff_y);
off_x = (doff_x - x1);
off_y = (doff_y - y1);
gimp_layer_resize (layer, width, height, off_x, off_y);
if (gimp_layer_is_floating_sel (layer))
floating_sel_rigor (layer, TRUE);
undo_push_group_end (gimage);
}
else
{
floating_layer = gimp_image_floating_sel (gimage);
undo_push_group_start (gimage, CROP_UNDO);
/* relax the floating layer */
if (floating_layer)
floating_sel_relax (floating_layer, TRUE);
/* Push the image size to the stack */
undo_push_gimage_mod (gimage);
/* Set the new width and height */
gimage->width = width;
gimage->height = height;
/* Resize all channels */
for (list = GIMP_LIST (gimage->channels)->list;
list;
list = g_list_next (list))
{
channel = (GimpChannel *) list->data;
gimp_channel_resize (channel, width, height, -x1, -y1);
}
/* Don't forget the selection mask! */
gimp_channel_resize (gimage->selection_mask, width, height, -x1, -y1);
gimage_mask_invalidate (gimage);
/* crop all layers */
list = GIMP_LIST (gimage->layers)->list;
while (list)
{
GList *next;
layer = (GimpLayer *) list->data;
next = g_list_next (list);
gimp_layer_translate (layer, -x1, -y1);
gimp_drawable_offsets (GIMP_DRAWABLE (layer), &off_x, &off_y);
if (crop_layers)
{
gimp_drawable_offsets (GIMP_DRAWABLE (layer), &off_x, &off_y);
lx1 = CLAMP (off_x, 0, gimage->width);
ly1 = CLAMP (off_y, 0, gimage->height);
lx2 = CLAMP ((gimp_drawable_width (GIMP_DRAWABLE (layer)) + off_x),
0, gimage->width);
ly2 = CLAMP ((gimp_drawable_height (GIMP_DRAWABLE (layer)) + off_y),
0, gimage->height);
width = lx2 - lx1;
height = ly2 - ly1;
if (width && height)
gimp_layer_resize (layer, width, height,
-(lx1 - off_x),
-(ly1 - off_y));
else
gimp_image_remove_layer (gimage, layer);
}
list = next;
}
/* Make sure the projection matches the gimage size */
gimp_image_projection_allocate (gimage);
/* rigor the floating layer */
if (floating_layer)
floating_sel_rigor (floating_layer, TRUE);
guide_list_ptr = gimage->guides;
while ( guide_list_ptr != NULL)
{
undo_push_guide (gimage, (GimpGuide *) guide_list_ptr->data);
guide_list_ptr = guide_list_ptr->next;
}
undo_push_group_end (gimage);
/* Adjust any guides we might have laying about */
gimp_image_crop_adjust_guides (gimage, x1, y1, x2, y2);
}
Chopped up the display stuff (beware: unfinished)... 2001-10-31 Michael Natterer <mitch@gimp.org> Chopped up the display stuff (beware: unfinished)... The plan is that GimpDisplay is the object which collects updates from the image, compresses them and waits for the GIMP to be idle to actually paint them. It should be a non-GUI object which is the model for the actual widget to connect to. GimpDisplayShell has all the widgets and handles painting and exposing of the result. Nobody should actually be required to update ot look at it as it should be a view on the GimpDisplay object. Much stuff is still in the wrong place and the functions don't follow their files' filename namespace any more. More to come... * app/display/Makefile.am * app/display/gimpdisplay-ops.[ch]: removed. It's functions didn't belong together anyway. * app/display/gimpdisplay-area.[ch]: new files: the GimpArea functions. * app/display/gimpdisplay-handlers.[ch]: new files: signal handlers for GimpImage signals. Mostly from app/gui.c. * app/display/gimpdisplay.[ch]: removed all widgets and other GUI stuff. There is still much undecided here... * app/display/gimpdisplayshell.[ch]: actually use the object and filled it with all the stuff from GimpDisplay. * app/display/gimpdisplay-callbacks.[ch] * app/display/gimpdisplay-foreach.[ch] * app/display/gimpdisplay-render.c * app/display/gimpdisplay-scale.[ch] * app/display/gimpdisplay-scroll.[ch] * app/display/gimpdisplay-selection.c: changed accordingly. * app/core/gimp.[ch]: return a GimpObject from gimp_create_display() so it can be used as single GUI independent point to create displays, require the initial scale as parameter. * app/core/gimpcontext.c: changed the ugly EEKWrapper according to the GimpDisplay structure changes. Bugfix: set the image to NULL in gimp_context_display_destroyed(). * app/core/gimpedit.c * app/core/gimpimage-new.c: changed gimp_create_display() calls accordingly. * app/core/gimpimage-convert.c: invalidate the layer & image previews here, not in the caller. * app/core/gimpimage-crop.c: update the whole image after cropping. * app/core/gimpimage.[ch]: added gimp_image_find_guide(), gimp_image_snap_point() and gimp_image_snap_rectangle(). Added "resolution_changed" and "unit_changed" signals and corresp. public convenience functions to emit them. * app/core/gimplayer.c: emit the image's "alpha_changed" signal when adding alpha to the bottom (and only) layer of the image. * app/gimpprogress.c * app/image_map.c * app/nav_window.c * app/qmask.c * app/undo.c * app/user_install.c: changed accordingly. * app/gui/edit-commands.c * app/gui/file-commands.c * app/gui/file-open-dialog.c * app/gui/image-commands.c * app/gui/info-window.c * app/gui/preferences-dialog.c * app/gui/toolbox.c * app/gui/view-commands.c: ditto. * app/gui/gui.[ch]: removed most gimp->images handlers as the displays connect to them themselves now. chaged gui_display_new() according to the gimp_create_display() changes. Added gui_get_screen_resolution(). * app/tools/gimpbezierselecttool.c * app/tools/gimpblendtool.c * app/tools/gimpbucketfilltool.c * app/tools/gimpbycolorselecttool.c * app/tools/gimpclonetool.c * app/tools/gimpcolorpickertool.c * app/tools/gimpcroptool.c * app/tools/gimpdrawtool.c * app/tools/gimpeditselectiontool.c * app/tools/gimpfliptool.c * app/tools/gimpfreeselecttool.c * app/tools/gimpfuzzyselecttool.c * app/tools/gimpinktool.c * app/tools/gimpiscissorstool.c * app/tools/gimpmagnifytool.c * app/tools/gimpmeasuretool.c * app/tools/gimpmovetool.c * app/tools/gimppainttool.c * app/tools/gimppathtool.c * app/tools/gimprectselecttool.c * app/tools/gimpselectiontool.c * app/tools/gimptexttool.c * app/tools/gimptool.c * app/tools/gimptransformtool.c * app/tools/xinput_airbrush.c: lots of changes because GimpDisplay has become two objects. Lots of gdisp->shell casting uglyness added. This is fine because exactly these parts will have to go away. (GimpDisplay will provide methods for XOR drawing upon the display in image coordinates without the need to transform coordinates all the time. Also the tools shouldn't see GdkEvents but get more useful virtual functions which speak in image coordinates too). * app/widgets/gimpcomponentlistitem.c: removed a now useless image update. * tools/pdbgen/pdb/display.pdb: use gimp_create_display(). * app/pdb/display_cmds.c: regenerated.
2001-11-01 05:18:57 +08:00
gimp_image_update (gimage,
0, 0,
gimage->width,
gimage->height);
gimp_viewable_size_changed (GIMP_VIEWABLE (gimage));
app/Makefile.am app/gimpunit.c removed... 2001-07-11 Michael Natterer <mitch@gimp.org> * app/Makefile.am * app/gimpunit.c * app/unitrc.h: removed... * app/core/Makefile.am * app/core/gimpunit.[ch]: ...re-added here. * app/core/gimp.[ch]: added the image and drawable hash tables, next_image_ID, next_guide_ID and next_drawable_ID, added a GimpCoreConfig pointer which is now initalized dynamically. * app/core/gimpcoreconfig.[ch]: don't provide a global core_config variable any more (need to access gimp->config now). * app/gdisplay.[ch] * app/core/gimpdrawable.[ch] * app/core/gimpimage.[ch]: removed all global variables from gimpimage.c and gimpdrawable.c, pass a Gimp* to all *_get_by_ID() functions. * tools/pdbgen/app.pl: pass Gimp* to all _get_by_ID() functions. * app/app_procs.c * app/file-open.c * app/file-save.c * app/gimprc.c * app/libgimp_glue.c * app/module_db.c * app/plug_in.c * app/undo.c * app/user_install.c * app/core/core-types.h * app/core/gimpcontext.c * app/core/gimpimage-crop.c * app/core/gimpimage-new.c * app/core/gimpparasite.c * app/gui/file-new-dialog.c * app/gui/file-open-dialog.c * app/gui/info-window.c * app/gui/preferences-dialog.c * app/gui/resize-dialog.c * app/xcf/xcf-load.c * app/xcf/xcf-save.c * app/xcf/xcf.c * app/widgets/gimpdnd.c * app/pdb/channel_cmds.c * app/pdb/color_cmds.c * app/pdb/convert_cmds.c * app/pdb/display_cmds.c * app/pdb/drawable_cmds.c * app/pdb/edit_cmds.c * app/pdb/fileops_cmds.c * app/pdb/floating_sel_cmds.c * app/pdb/guides_cmds.c * app/pdb/image_cmds.c * app/pdb/layer_cmds.c * app/pdb/parasite_cmds.c * app/pdb/paths_cmds.c * app/pdb/selection_cmds.c * app/pdb/text_tool_cmds.c * app/pdb/tools_cmds.c * app/pdb/undo_cmds.c * app/pdb/unit_cmds.c * tools/pdbgen/pdb/image.pdb * tools/pdbgen/pdb/unit.pdb: changed accordingly.
2001-07-11 20:39:49 +08:00
gimp_unset_busy (gimage->gimp);
}
}
gboolean
gimp_image_crop_auto_shrink (GimpImage *gimage,
gint x1,
gint y1,
gint x2,
gint y2,
gboolean active_drawable_only,
gint *shrunk_x1,
gint *shrunk_y1,
gint *shrunk_x2,
gint *shrunk_y2)
{
GimpDrawable *active_drawable = NULL;
GetColorFunc get_color_func;
ColorsEqualFunc colors_equal_func;
GObject *get_color_obj;
guchar bgcolor[MAX_CHANNELS] = { 0, 0, 0, 0 };
gboolean has_alpha;
PixelRegion PR;
guchar *buffer = NULL;
gint width, height;
gint bytes;
gint x, y, abort;
gboolean retval = FALSE;
g_return_val_if_fail (gimage != NULL, FALSE);
g_return_val_if_fail (GIMP_IS_IMAGE (gimage), FALSE);
g_return_val_if_fail (shrunk_x1 != NULL, FALSE);
g_return_val_if_fail (shrunk_y1 != NULL, FALSE);
g_return_val_if_fail (shrunk_x2 != NULL, FALSE);
g_return_val_if_fail (shrunk_y2 != NULL, FALSE);
app/Makefile.am app/gimpunit.c removed... 2001-07-11 Michael Natterer <mitch@gimp.org> * app/Makefile.am * app/gimpunit.c * app/unitrc.h: removed... * app/core/Makefile.am * app/core/gimpunit.[ch]: ...re-added here. * app/core/gimp.[ch]: added the image and drawable hash tables, next_image_ID, next_guide_ID and next_drawable_ID, added a GimpCoreConfig pointer which is now initalized dynamically. * app/core/gimpcoreconfig.[ch]: don't provide a global core_config variable any more (need to access gimp->config now). * app/gdisplay.[ch] * app/core/gimpdrawable.[ch] * app/core/gimpimage.[ch]: removed all global variables from gimpimage.c and gimpdrawable.c, pass a Gimp* to all *_get_by_ID() functions. * tools/pdbgen/app.pl: pass Gimp* to all _get_by_ID() functions. * app/app_procs.c * app/file-open.c * app/file-save.c * app/gimprc.c * app/libgimp_glue.c * app/module_db.c * app/plug_in.c * app/undo.c * app/user_install.c * app/core/core-types.h * app/core/gimpcontext.c * app/core/gimpimage-crop.c * app/core/gimpimage-new.c * app/core/gimpparasite.c * app/gui/file-new-dialog.c * app/gui/file-open-dialog.c * app/gui/info-window.c * app/gui/preferences-dialog.c * app/gui/resize-dialog.c * app/xcf/xcf-load.c * app/xcf/xcf-save.c * app/xcf/xcf.c * app/widgets/gimpdnd.c * app/pdb/channel_cmds.c * app/pdb/color_cmds.c * app/pdb/convert_cmds.c * app/pdb/display_cmds.c * app/pdb/drawable_cmds.c * app/pdb/edit_cmds.c * app/pdb/fileops_cmds.c * app/pdb/floating_sel_cmds.c * app/pdb/guides_cmds.c * app/pdb/image_cmds.c * app/pdb/layer_cmds.c * app/pdb/parasite_cmds.c * app/pdb/paths_cmds.c * app/pdb/selection_cmds.c * app/pdb/text_tool_cmds.c * app/pdb/tools_cmds.c * app/pdb/undo_cmds.c * app/pdb/unit_cmds.c * tools/pdbgen/pdb/image.pdb * tools/pdbgen/pdb/unit.pdb: changed accordingly.
2001-07-11 20:39:49 +08:00
gimp_set_busy (gimage->gimp);
/* You should always keep in mind that crop->tx2 and crop->ty2 are the NOT the
coordinates of the bottomright corner of the area to be cropped. They point
at the pixel located one to the right and one to the bottom.
*/
if (active_drawable_only)
{
active_drawable = gimp_image_active_drawable (gimage);
if (! active_drawable)
goto FINISH;
bytes = gimp_drawable_bytes (GIMP_DRAWABLE (active_drawable));
has_alpha = gimp_drawable_has_alpha (GIMP_DRAWABLE (active_drawable));
get_color_obj = G_OBJECT (active_drawable);
get_color_func = (GetColorFunc) gimp_drawable_get_color_at;
}
else
{
has_alpha = TRUE;
bytes = gimp_image_projection_bytes (gimage);
get_color_obj = G_OBJECT (gimage);
get_color_func = (GetColorFunc) gimp_image_projection_get_color_at;
}
switch (gimp_image_crop_guess_bgcolor (get_color_obj, get_color_func,
bytes, has_alpha, bgcolor,
x1, x2-1, y1, y2-1))
{
case AUTO_CROP_ALPHA:
colors_equal_func = (ColorsEqualFunc) gimp_image_crop_colors_alpha;
break;
case AUTO_CROP_COLOR:
colors_equal_func = (ColorsEqualFunc) gimp_image_crop_colors_equal;
break;
default:
goto FINISH;
break;
}
width = x2 - x1;
height = y2 - y1;
if (active_drawable_only)
pixel_region_init (&PR, gimp_drawable_data (active_drawable),
x1, y1, width, height, FALSE);
else
pixel_region_init (&PR, gimp_image_projection (gimage),
x1, y1, width, height, FALSE);
/* The following could be optimized further by processing
* the smaller side first instead of defaulting to width --Sven
*/
buffer = g_malloc ((width > height ? width : height) * bytes);
/* Check how many of the top lines are uniform/transparent. */
abort = FALSE;
for (y = y1; y < y2 && !abort; y++)
{
pixel_region_get_row (&PR, x1, y, width, buffer, 1);
for (x = 0; x < width && !abort; x++)
abort = !(colors_equal_func) (bgcolor, buffer + x * bytes, bytes);
}
if (y == y2 && !abort)
goto FINISH;
y1 = y - 1;
/* Check how many of the bottom lines are uniform/transparent. */
abort = FALSE;
for (y = y2; y > y1 && !abort; y--)
{
pixel_region_get_row (&PR, x1, y-1 , width, buffer, 1);
for (x = 0; x < width && !abort; x++)
abort = !(colors_equal_func) (bgcolor, buffer + x * bytes, bytes);
}
y2 = y + 1;
/* compute a new height for the next operations */
height = y2 - y1;
/* Check how many of the left lines are uniform/transparent. */
abort = FALSE;
for (x = x1; x < x2 && !abort; x++)
{
pixel_region_get_col (&PR, x, y1, height, buffer, 1);
for (y = 0; y < height && !abort; y++)
abort = !(colors_equal_func) (bgcolor, buffer + y * bytes, bytes);
}
x1 = x - 1;
/* Check how many of the right lines are uniform/transparent. */
abort = FALSE;
for (x = x2; x > x1 && !abort; x--)
{
pixel_region_get_col (&PR, x-1, y1, height, buffer, 1);
for (y = 0; y < height && !abort; y++)
abort = !(colors_equal_func) (bgcolor, buffer + y * bytes, bytes);
}
x2 = x + 1;
*shrunk_x1 = x1;
*shrunk_y1 = y1;
*shrunk_x2 = x2;
*shrunk_y2 = y2;
retval = TRUE;
FINISH:
g_free (buffer);
app/Makefile.am app/gimpunit.c removed... 2001-07-11 Michael Natterer <mitch@gimp.org> * app/Makefile.am * app/gimpunit.c * app/unitrc.h: removed... * app/core/Makefile.am * app/core/gimpunit.[ch]: ...re-added here. * app/core/gimp.[ch]: added the image and drawable hash tables, next_image_ID, next_guide_ID and next_drawable_ID, added a GimpCoreConfig pointer which is now initalized dynamically. * app/core/gimpcoreconfig.[ch]: don't provide a global core_config variable any more (need to access gimp->config now). * app/gdisplay.[ch] * app/core/gimpdrawable.[ch] * app/core/gimpimage.[ch]: removed all global variables from gimpimage.c and gimpdrawable.c, pass a Gimp* to all *_get_by_ID() functions. * tools/pdbgen/app.pl: pass Gimp* to all _get_by_ID() functions. * app/app_procs.c * app/file-open.c * app/file-save.c * app/gimprc.c * app/libgimp_glue.c * app/module_db.c * app/plug_in.c * app/undo.c * app/user_install.c * app/core/core-types.h * app/core/gimpcontext.c * app/core/gimpimage-crop.c * app/core/gimpimage-new.c * app/core/gimpparasite.c * app/gui/file-new-dialog.c * app/gui/file-open-dialog.c * app/gui/info-window.c * app/gui/preferences-dialog.c * app/gui/resize-dialog.c * app/xcf/xcf-load.c * app/xcf/xcf-save.c * app/xcf/xcf.c * app/widgets/gimpdnd.c * app/pdb/channel_cmds.c * app/pdb/color_cmds.c * app/pdb/convert_cmds.c * app/pdb/display_cmds.c * app/pdb/drawable_cmds.c * app/pdb/edit_cmds.c * app/pdb/fileops_cmds.c * app/pdb/floating_sel_cmds.c * app/pdb/guides_cmds.c * app/pdb/image_cmds.c * app/pdb/layer_cmds.c * app/pdb/parasite_cmds.c * app/pdb/paths_cmds.c * app/pdb/selection_cmds.c * app/pdb/text_tool_cmds.c * app/pdb/tools_cmds.c * app/pdb/undo_cmds.c * app/pdb/unit_cmds.c * tools/pdbgen/pdb/image.pdb * tools/pdbgen/pdb/unit.pdb: changed accordingly.
2001-07-11 20:39:49 +08:00
gimp_unset_busy (gimage->gimp);
return retval;
}
/* private functions */
static void
gimp_image_crop_adjust_guides (GimpImage *gimage,
gint x1,
gint y1,
gint x2,
gint y2)
{
GList *glist;
GimpGuide *guide;
gboolean remove_guide;
for (glist = gimage->guides; glist; glist = g_list_next (glist))
{
guide = (GimpGuide *) glist->data;
remove_guide = FALSE;
switch (guide->orientation)
{
case ORIENTATION_HORIZONTAL:
if ((guide->position < y1) || (guide->position > y2))
remove_guide = TRUE;
break;
case ORIENTATION_VERTICAL:
if ((guide->position < x1) || (guide->position > x2))
remove_guide = TRUE;
break;
default:
break;
}
if (remove_guide)
{
guide->position = -1;
guide = NULL;
}
else
{
if (guide->orientation == ORIENTATION_HORIZONTAL)
{
guide->position -= y1 ;
}
else
{
guide->position -= x1;
}
}
}
}
static AutoCropType
gimp_image_crop_guess_bgcolor (GObject *get_color_obj,
GetColorFunc get_color_func,
gint bytes,
gboolean has_alpha,
guchar *color,
gint x1,
gint x2,
gint y1,
gint y2)
{
guchar *tl = NULL;
guchar *tr = NULL;
guchar *bl = NULL;
guchar *br = NULL;
gint i, alpha;
for (i = 0; i < bytes; i++)
color[i] = 0;
/* First check if there's transparency to crop. If not, guess the
* background-color to see if at least 2 corners are equal.
*/
if (!(tl = (*get_color_func) (get_color_obj, x1, y1)))
goto ERROR;
if (!(tr = (*get_color_func) (get_color_obj, x1, y2)))
goto ERROR;
if (!(bl = (*get_color_func) (get_color_obj, x2, y1)))
goto ERROR;
if (!(br = (*get_color_func) (get_color_obj, x2, y2)))
goto ERROR;
if (has_alpha)
{
alpha = bytes - 1;
if ((tl[alpha] == 0 && tr[alpha] == 0) ||
(tl[alpha] == 0 && bl[alpha] == 0) ||
(tr[alpha] == 0 && br[alpha] == 0) ||
(bl[alpha] == 0 && br[alpha] == 0))
{
g_free (tl);
g_free (tr);
g_free (bl);
g_free (br);
return AUTO_CROP_ALPHA;
}
}
if (gimp_image_crop_colors_equal (tl, tr, bytes) ||
gimp_image_crop_colors_equal (tl, bl, bytes))
{
memcpy (color, tl, bytes);
}
else if (gimp_image_crop_colors_equal (br, bl, bytes) ||
gimp_image_crop_colors_equal (br, tr, bytes))
{
memcpy (color, br, bytes);
}
else
{
goto ERROR;
}
g_free (tl);
g_free (tr);
g_free (bl);
g_free (br);
return AUTO_CROP_COLOR;
ERROR:
g_free (tl);
g_free (tr);
g_free (bl);
g_free (br);
return AUTO_CROP_NOTHING;
}
static int
gimp_image_crop_colors_equal (guchar *col1,
guchar *col2,
gint bytes)
{
gboolean equal = TRUE;
gint b;
for (b = 0; b < bytes; b++)
{
if (col1[b] != col2[b])
{
equal = FALSE;
break;
}
}
return equal;
}
static gboolean
gimp_image_crop_colors_alpha (guchar *dummy,
guchar *col,
gint bytes)
{
if (col[bytes-1] == 0)
return TRUE;
else
return FALSE;
}