gimpimage-resize.c 99.6 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/* 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.
 */
18

19 20
#include "config.h"

21
#include <string.h>
22

23
#include "gimpimageP.h"
24
#include "cursorutil.h"
25 26
#include "drawable.h"
#include "floating_sel.h"
27
#include "gdisplay.h"
28
#include "gimage_mask.h"
29
#include "gimpcontext.h"
30
#include "paint_funcs.h"
31
#include "parasitelist.h"
32 33
#include "undo.h"
#include "gimpsignal.h"
Manish Singh's avatar
Manish Singh committed
34
#include "gimpparasite.h"
35
#include "path.h"
36
#include "gimprc.h"
37

scott's avatar
scott committed
38 39
#include "tile_manager.h"
#include "tile.h"
40 41 42
#include "layer_pvt.h"
#include "drawable_pvt.h"		/* ick ick. */

43 44
#include "libgimp/gimpcolorspace.h"
#include "libgimp/gimplimits.h"
45
#include "libgimp/gimpmath.h"
46
#include "libgimp/gimpparasite.h"
47 48 49

#include "libgimp/gimpintl.h"

50

51 52 53 54 55 56 57
#ifdef DEBUG
#define TRC(x) printf x
#else
#define TRC(x)
#endif


58
/*  Local function declarations  */
59
static void     gimp_image_destroy               (GtkObject *object);
60
static void     gimp_image_free_projection       (GimpImage *);
61
static void     gimp_image_allocate_shadow       (GimpImage *, gint, gint, gint);
62 63 64
static void     gimp_image_allocate_projection   (GimpImage *);
static void     gimp_image_free_layers           (GimpImage *);
static void     gimp_image_free_channels         (GimpImage *);
65 66 67 68
static void     gimp_image_construct_layers      (GimpImage *, gint, gint, gint, gint);
static void     gimp_image_construct_channels    (GimpImage *, gint, gint, gint, gint);
static void     gimp_image_initialize_projection (GimpImage *, gint, gint, gint, gint);
static void     gimp_image_get_active_channels   (GimpImage *, GimpDrawable *, gint *);
69 70

/*  projection functions  */
71 72
static void     project_intensity            (GimpImage *, Layer *,
					      PixelRegion *, PixelRegion *,
73
					      PixelRegion *);
74 75
static void     project_intensity_alpha      (GimpImage *, Layer *,
					      PixelRegion *, PixelRegion *,
76
					      PixelRegion *);
77 78 79 80
static void     project_indexed              (GimpImage *, Layer *,
					      PixelRegion *, PixelRegion *);
static void     project_channel              (GimpImage *, Channel *,
					      PixelRegion *, PixelRegion *);
81 82 83 84

/*
 *  Global variables
 */
85
gint valid_combinations[][MAX_CHANNELS + 1] =
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
{
  /* RGB GIMAGE */
  { -1, -1, -1, COMBINE_INTEN_INTEN, COMBINE_INTEN_INTEN_A },
  /* RGBA GIMAGE */
  { -1, -1, -1, COMBINE_INTEN_A_INTEN, COMBINE_INTEN_A_INTEN_A },
  /* GRAY GIMAGE */
  { -1, COMBINE_INTEN_INTEN, COMBINE_INTEN_INTEN_A, -1, -1 },
  /* GRAYA GIMAGE */
  { -1, COMBINE_INTEN_A_INTEN, COMBINE_INTEN_A_INTEN_A, -1, -1 },
  /* INDEXED GIMAGE */
  { -1, COMBINE_INDEXED_INDEXED, COMBINE_INDEXED_INDEXED_A, -1, -1 },
  /* INDEXEDA GIMAGE */
  { -1, -1, COMBINE_INDEXED_A_INDEXED_A, -1, -1 },
};

101
guint32 next_guide_id = 1;  /* For generating guide_ID handles for PDB stuff */
102

103 104 105 106 107

/*
 *  Static variables
 */

108
enum {
109
  CLEAN,
110 111 112 113 114
  DIRTY,
  REPAINT,
  RENAME,
  RESIZE,
  RESTRUCTURE,
115
  COLORMAP_CHANGED,
116
  UNDO_EVENT,
117 118
  LAST_SIGNAL
};
119

120
static guint            gimp_image_signals[LAST_SIGNAL];
121
static GimpObjectClass *parent_class;
122

123

124 125 126 127
static void
gimp_image_class_init (GimpImageClass *klass)
{
  GtkObjectClass *object_class;
128
  GtkType         type;
129 130 131 132 133 134 135 136
  
  object_class = GTK_OBJECT_CLASS(klass);
  parent_class = gtk_type_class (gimp_object_get_type ());
  
  type=object_class->type;

  object_class->destroy =  gimp_image_destroy;

137 138 139
  gimp_image_signals[CLEAN] =
	  gimp_signal_new ("clean", GTK_RUN_FIRST, type, 0,
			   gimp_sigtype_void);
140
  gimp_image_signals[DIRTY] =
141 142
	  gimp_signal_new ("dirty", GTK_RUN_FIRST, type, 0,
			   gimp_sigtype_void);
143
  gimp_image_signals[REPAINT] =
144 145
	  gimp_signal_new ("repaint", GTK_RUN_FIRST, type, 0,
			   gimp_sigtype_int_int_int_int);
146
  gimp_image_signals[RENAME] =
147 148
	  gimp_signal_new ("rename", GTK_RUN_FIRST, type, 0,
			   gimp_sigtype_void);
149
  gimp_image_signals[RESIZE] =
150 151
	  gimp_signal_new ("resize", GTK_RUN_FIRST, type, 0,
			   gimp_sigtype_void);
152
  gimp_image_signals[RESTRUCTURE] =
153 154
	  gimp_signal_new ("restructure", GTK_RUN_FIRST, type, 0,
			   gimp_sigtype_void);
155
  gimp_image_signals[COLORMAP_CHANGED] =
156 157
	  gimp_signal_new ("colormap_changed", GTK_RUN_FIRST, type, 0,
			   gimp_sigtype_int);
158 159 160
  gimp_image_signals[UNDO_EVENT] = 
	  gimp_signal_new ("undo_event", GTK_RUN_FIRST, type, 0,
			   gimp_sigtype_int);
161 162 163 164 165 166 167
  
  gtk_object_class_add_signals (object_class, gimp_image_signals, LAST_SIGNAL);
}


/* static functions */

Sven Neumann's avatar
Sven Neumann committed
168 169
static void 
gimp_image_init (GimpImage *gimage)
170
{
171 172 173
  gimage->has_filename          = FALSE;
  gimage->num_cols              = 0;
  gimage->cmap                  = NULL;
174
  gimage->disp_count            = 0;
175 176
  gimage->instance_count        = 0;
  gimage->shadow                = NULL;
177
  gimage->dirty                 = 1;
178 179 180 181 182 183 184 185 186 187 188 189
  gimage->undo_on               = TRUE;
  gimage->construct_flag        = -1;
  gimage->tattoo_state          = 0;
  gimage->projection            = NULL;
  gimage->guides                = NULL;
  gimage->layers                = NULL;
  gimage->channels              = NULL;
  gimage->layer_stack           = NULL;
  gimage->undo_stack            = NULL;
  gimage->redo_stack            = NULL;
  gimage->undo_bytes            = 0;
  gimage->undo_levels           = 0;
190
  gimage->group_count           = 0;
191
  gimage->pushing_undo_group    = UNDO_NULL;
192 193 194
  gimage->comp_preview_valid[0] = FALSE;
  gimage->comp_preview_valid[1] = FALSE;
  gimage->comp_preview_valid[2] = FALSE;
195
  gimage->comp_preview          = NULL;
196
  gimage->parasites             = parasite_list_new ();
197 198 199 200 201
  gimage->xresolution           = default_xresolution;
  gimage->yresolution           = default_yresolution;
  gimage->unit                  = default_units;
  gimage->save_proc             = NULL;
  gimage->paths                 = NULL;
202 203
}

Sven Neumann's avatar
Sven Neumann committed
204 205 206 207 208
GtkType 
gimp_image_get_type (void) 
{
  static GtkType type;

209 210 211 212 213 214
  GIMP_TYPE_INIT (type,
		  GimpImage,
		  GimpImageClass,
		  gimp_image_init,
		  gimp_image_class_init,
		  GIMP_TYPE_OBJECT);
Sven Neumann's avatar
Sven Neumann committed
215
  return type;
216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239
}

static void
gimp_image_allocate_projection (GimpImage *gimage)
{
  if (gimage->projection)
    gimp_image_free_projection (gimage);

  /*  Find the number of bytes required for the projection.
   *  This includes the intensity channels and an alpha channel
   *  if one doesn't exist.
   */
  switch (gimp_image_base_type (gimage))
    {
    case RGB:
    case INDEXED:
      gimage->proj_bytes = 4;
      gimage->proj_type = RGBA_GIMAGE;
      break;
    case GRAY:
      gimage->proj_bytes = 2;
      gimage->proj_type = GRAYA_GIMAGE;
      break;
    default:
240
      g_assert_not_reached ();
241 242 243 244
    }

  /*  allocate the new projection  */
  gimage->projection = tile_manager_new (gimage->width, gimage->height, gimage->proj_bytes);
245
  tile_manager_set_user_data (gimage->projection, (void *) gimage);
246 247 248 249 250 251 252 253 254 255 256 257 258
  tile_manager_set_validate_proc (gimage->projection, gimp_image_validate);
}

static void
gimp_image_free_projection (GimpImage *gimage)
{
  if (gimage->projection)
    tile_manager_destroy (gimage->projection);

  gimage->projection = NULL;
}

static void
Sven Neumann's avatar
Sven Neumann committed
259
gimp_image_allocate_shadow (GimpImage *gimage, 
260 261 262
			    gint       width, 
			    gint       height, 
			    gint       bpp)
263 264 265 266 267 268 269 270 271
{
  /*  allocate the new projection  */
  gimage->shadow = tile_manager_new (width, height, bpp);
}


/* function definitions */

GimpImage *
272 273 274
gimp_image_new (gint               width,
		gint               height,
		GimpImageBaseType  base_type)
275
{
276 277
  GimpImage *gimage = GIMP_IMAGE (gtk_type_new (gimp_image_get_type ()));
  gint i;
278

279 280 281
  gimage->filename  = NULL;
  gimage->width     = width;
  gimage->height    = height;
282 283 284 285 286 287 288 289 290 291
  gimage->base_type = base_type;

  switch (base_type)
    {
    case RGB:
    case GRAY:
      break;
    case INDEXED:
      /* always allocate 256 colors for the colormap */
      gimage->num_cols = 0;
292
      gimage->cmap     = (guchar *) g_malloc0 (COLORMAP_SIZE);
293 294 295 296 297 298
      break;
    default:
      break;
    }

  /*  configure the active pointers  */
299
  gimage->active_layer   = NULL;
300
  gimage->active_channel = NULL;  /* no default active channel */
301
  gimage->floating_sel   = NULL;
302 303 304 305

  /*  set all color channels visible and active  */
  for (i = 0; i < MAX_CHANNELS; i++)
    {
306 307
      gimage->visible[i] = TRUE;
      gimage->active[i]  = TRUE;
308 309 310
    }

  /* create the selection mask */
311 312
  gimage->selection_mask = channel_new_mask (gimage,
					     gimage->width, gimage->height);
313

314
  /* set the qmask properties */
315 316
  gimage->qmask_state    = FALSE;
  gimage->qmask_opacity  = 50;
317 318 319
  gimage->qmask_color[0] = 255; 
  gimage->qmask_color[1] = 0; 
  gimage->qmask_color[2] = 0; 
320 321 322 323 324

  return gimage;
}

void
325
gimp_image_set_filename (GimpImage *gimage, 
326
			 gchar     *filename)
327
{
328 329 330
  gchar    *new_filename;
  gchar    *old_filename;
  gboolean  free_old;
331

332 333 334 335 336 337
  /* 
   * WARNING: this function will free the current filename even if you are 
   * setting it to itself so any pointer you hold to the filename will be
   * invalid after this call.  So please use with care.
   */

338
  new_filename = g_strdup (filename);
339 340
  old_filename = gimage->filename;
  free_old = gimage->has_filename;
341 342 343 344 345 346 347 348 349 350 351 352

  if (filename && filename[0])
    {
      gimage->filename = new_filename;
      gimage->has_filename = TRUE;
    }
  else
    {
      gimage->filename = NULL;
      gimage->has_filename = FALSE;
    }

353 354 355
  if (free_old)
    g_free (old_filename);

356 357 358
  gtk_signal_emit (GTK_OBJECT (gimage), gimp_image_signals[RENAME]);
}

359
void
360
gimp_image_set_resolution (GimpImage *gimage,
361 362
			   gdouble    xresolution,
			   gdouble    yresolution)
363
{
364 365 366 367 368
  /* nothing to do if setting res to the same as before */
  if ((ABS (gimage->xresolution - xresolution) < 1e-5) &&
      (ABS (gimage->yresolution - yresolution) < 1e-5))
      return;

369 370 371
  /* don't allow to set the resolution out of bounds */
  if (xresolution < GIMP_MIN_RESOLUTION || xresolution > GIMP_MAX_RESOLUTION ||
      yresolution < GIMP_MIN_RESOLUTION || yresolution > GIMP_MAX_RESOLUTION)
372 373
    return;

374
  undo_push_resolution (gimage);
375

376 377
  gimage->xresolution = xresolution;
  gimage->yresolution = yresolution;
378 379 380

  /* really just want to recalc size and repaint */
  gdisplays_shrink_wrap (gimage);
381 382
}

383 384
void
gimp_image_get_resolution (GimpImage *gimage,
385 386
			   gdouble   *xresolution,
			   gdouble   *yresolution)
387
{
388 389
  g_return_if_fail (xresolution && yresolution);

390 391
  *xresolution = gimage->xresolution;
  *yresolution = gimage->yresolution;
392 393
}

394 395
void
gimp_image_set_unit (GimpImage *gimage,
396
		     GimpUnit   unit)
397
{
398 399
  undo_push_resolution (gimage);

400 401 402
  gimage->unit = unit;
}

403
GimpUnit
404 405 406 407 408
gimp_image_get_unit (GimpImage *gimage)
{
  return gimage->unit;
}

409
void
Sven Neumann's avatar
Sven Neumann committed
410 411
gimp_image_set_save_proc (GimpImage     *gimage, 
			  PlugInProcDef *proc)
412 413 414 415 416 417 418 419 420
{
  gimage->save_proc = proc;
}

PlugInProcDef *
gimp_image_get_save_proc (GimpImage *gimage)
{
  return gimage->save_proc;
}
421

422
void
423
gimp_image_resize (GimpImage *gimage, 
424 425 426 427
		   gint       new_width, 
		   gint       new_height,
		   gint       offset_x, 
		   gint       offset_y)
428 429
{
  Channel *channel;
430 431 432 433
  Layer   *layer;
  Layer   *floating_layer;
  GSList  *list;
  GList   *guide_list;
434

435 436
  gimp_add_busy_cursors();

437
  g_assert (new_width > 0 && new_height > 0);
438 439 440 441

  /*  Get the floating layer if one exists  */
  floating_layer = gimp_image_floating_sel (gimage);

Sven Neumann's avatar
Sven Neumann committed
442
  undo_push_group_start (gimage, IMAGE_RESIZE_UNDO);
443 444 445 446 447 448 449 450 451

  /*  Relax the floating selection  */
  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  */
452
  gimage->width  = new_width;
453 454 455 456 457 458 459 460 461
  gimage->height = new_height;

  /*  Resize all channels  */
  list = gimage->channels;
  while (list)
    {
      channel = (Channel *) list->data;
      channel_resize (channel, new_width, new_height, offset_x, offset_y);
      list = g_slist_next (list);
462 463 464 465 466 467 468 469 470 471

    }

  /*  Reposition or remove any guides  */
  guide_list = gimage->guides;
  while (guide_list)
    {
      Guide *guide;

      guide = (Guide*) guide_list->data;
Sven Neumann's avatar
Sven Neumann committed
472
      guide_list = g_list_next (guide_list);
473 474 475

      switch (guide->orientation)
	{
476
	case ORIENTATION_HORIZONTAL:
Sven Neumann's avatar
Sven Neumann committed
477
	  undo_push_guide (gimage, guide);
478 479 480 481
	  guide->position += offset_y;
	  if (guide->position < 0 || guide->position > new_height)
	    gimp_image_delete_guide (gimage, guide);
	  break;
482
	case ORIENTATION_VERTICAL:
Sven Neumann's avatar
Sven Neumann committed
483
	  undo_push_guide (gimage, guide);
484 485 486 487 488 489 490
	  guide->position += offset_x;
	  if (guide->position < 0 || guide->position > new_width)
	    gimp_image_delete_guide (gimage, guide);
	  break;
	default:
	  g_error("Unknown guide orientation I.\n");
	}
491 492 493
    }

  /*  Don't forget the selection mask!  */
494 495
  channel_resize (gimage->selection_mask,
		  new_width, new_height, offset_x, offset_y);
496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514
  gimage_mask_invalidate (gimage);

  /*  Reposition all layers  */
  list = gimage->layers;
  while (list)
    {
      layer = (Layer *) list->data;
      layer_translate (layer, offset_x, offset_y);
      list = g_slist_next (list);
    }

  /*  Make sure the projection matches the gimage size  */
  gimp_image_projection_realloc (gimage);

  /*  Rigor the floating selection  */
  if (floating_layer)
    floating_sel_rigor (floating_layer, TRUE);

  gtk_signal_emit (GTK_OBJECT (gimage), gimp_image_signals[RESIZE]);
515

516
  gimp_remove_busy_cursors (NULL);
517 518
}

519 520 521 522 523 524 525 526 527 528 529 530
gint
gimp_image_get_width (const GimpImage *gimage)
{
  return gimage->width;
}

gint
gimp_image_get_height (const GimpImage *gimage)
{
  return gimage->height;
}

531
void
532
gimp_image_scale (GimpImage *gimage, 
533 534
		  gint       new_width, 
		  gint       new_height)
535 536
{
  Channel *channel;
Sven Neumann's avatar
Sven Neumann committed
537 538 539
  Layer   *layer;
  Layer   *floating_layer;
  GSList  *list;
540
  GSList  *remove = NULL;
Sven Neumann's avatar
Sven Neumann committed
541 542
  GList   *glist;
  Guide   *guide;
543 544 545 546
  gint     old_width;
  gint     old_height;
  gdouble  img_scale_w = 1.0;
  gdouble  img_scale_h = 1.0;
547

548
  if ((new_width == 0) || (new_height == 0))
549
    {
550
      g_message (("gimp_image_scale: Scaling to zero width or height has been rejected."));
551 552
      return;
    }
553

554
  gimp_add_busy_cursors ();
555

556 557 558
  /*  Get the floating layer if one exists  */
  floating_layer = gimp_image_floating_sel (gimage);

Sven Neumann's avatar
Sven Neumann committed
559
  undo_push_group_start (gimage, IMAGE_SCALE_UNDO);
560 561 562 563 564 565 566 567 568

  /*  Relax the floating selection  */
  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  */
569 570 571

  old_width      = gimage->width;
  old_height     = gimage->height;
572
  gimage->width  = new_width;
573
  gimage->height = new_height;
574 575
  img_scale_w    = (gdouble)new_width / (gdouble)old_width;
  img_scale_h    = (gdouble)new_height / (gdouble)old_height;
576
 
577
  /*  Scale all channels  */
578
  for (list = gimage->channels; list; list = g_slist_next (list))
579 580 581 582 583 584
    {
      channel = (Channel *) list->data;
      channel_scale (channel, new_width, new_height);
    }

  /*  Don't forget the selection mask!  */
585 586 587 588 589
  /*  if (channel_is_empty(gimage->selection_mask))
        channel_resize(gimage->selection_mask, new_width, new_height, 0, 0)
      else
  */
        
590 591 592 593 594
  channel_scale (gimage->selection_mask, new_width, new_height);
  gimage_mask_invalidate (gimage);

  /*  Scale all layers  */
  list = gimage->layers;
595
  for (list = gimage->layers; list; list = g_slist_next (list))
596
    {
597 598
      layer = (Layer *) list->data;
      if (layer_scale_by_factors (layer, img_scale_w, img_scale_h) == FALSE)
599 600 601 602 603 604
	{
	  /* Since 0 < img_scale_w, img_scale_h, failure due to one or more     */
	  /* vanishing scaled layer dimensions. Implicit delete implemented     */
	  /* here. Upstream warning implemented in resize_check_layer_scaling() */
          /* [resize.c line 1295], which offers the user the chance to bail out.*/

605
          remove = g_slist_append (remove, layer);
606 607 608 609 610
        }
    }
  /* We defer removing layers lost to scaling until now            */
  /* so as not to mix the operations of iterating over and removal */
  /* from gimage->layers.                                          */  
611

612
  for (list = remove; list; list = g_slist_next (list))
613
    {
614
      layer = list->data;
615
      gimage_remove_layer (gimage, layer);
616
    }
617
  g_slist_free (remove);
618

619
  /*  Scale any Guides  */
620
  for (glist = gimage->guides; glist; glist = g_list_next (glist))
621 622 623 624 625
    {
      guide = (Guide*) glist->data;

      switch (guide->orientation)
	{
626
	case ORIENTATION_HORIZONTAL:
Sven Neumann's avatar
Sven Neumann committed
627
	  undo_push_guide (gimage, guide);
628 629
	  guide->position = (guide->position * new_height) / old_height;
	  break;
630
	case ORIENTATION_VERTICAL:
Sven Neumann's avatar
Sven Neumann committed
631
	  undo_push_guide (gimage, guide);
632 633 634 635 636 637
	  guide->position = (guide->position * new_width) / old_width;
	  break;
	default:
	  g_error("Unknown guide orientation II.\n");
	}
    }
638

639 640 641 642 643 644 645 646
  /*  Make sure the projection matches the gimage size  */
  gimp_image_projection_realloc (gimage);

  /*  Rigor the floating selection  */
  if (floating_layer)
    floating_sel_rigor (floating_layer, TRUE);

  gtk_signal_emit (GTK_OBJECT (gimage), gimp_image_signals[RESIZE]);
647

648
  gimp_remove_busy_cursors (NULL);
649 650 651
}

TileManager *
652
gimp_image_shadow (GimpImage *gimage, 
653 654 655
		   gint       width, 
		   gint       height, 
		   gint       bpp)
656 657
{
  if (gimage->shadow &&
658 659 660
      ((width != tile_manager_level_width (gimage->shadow)) ||
       (height != tile_manager_level_height (gimage->shadow)) ||
       (bpp != tile_manager_level_bpp (gimage->shadow))))
661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682
    gimp_image_free_shadow (gimage);
  else if (gimage->shadow)
    return gimage->shadow;

  gimp_image_allocate_shadow (gimage, width, height, bpp);

  return gimage->shadow;
}

void
gimp_image_free_shadow (GimpImage *gimage)
{
  /*  Free the shadow buffer from the specified gimage if it exists  */
  if (gimage->shadow)
    tile_manager_destroy (gimage->shadow);

  gimage->shadow = NULL;
}

static void
gimp_image_destroy (GtkObject *object)
{
683
  GimpImage* gimage = GIMP_IMAGE (object);
Sven Neumann's avatar
Sven Neumann committed
684 685 686 687 688 689 690 691 692 693 694 695 696

  gimp_image_free_projection (gimage);
  gimp_image_free_shadow (gimage);
  
  if (gimage->cmap)
    g_free (gimage->cmap);
  
  if (gimage->has_filename)
    g_free (gimage->filename);
  
  gimp_image_free_layers (gimage);
  gimp_image_free_channels (gimage);
  channel_delete (gimage->selection_mask);
697

BST 1999 Andy Thomas's avatar
BST 1999 Andy Thomas committed
698 699 700
  if (gimage->comp_preview)
    temp_buf_free (gimage->comp_preview);

Sven Neumann's avatar
Sven Neumann committed
701
  if (gimage->parasites)
702
    gtk_object_unref (GTK_OBJECT (gimage->parasites));
703 704 705
}

void
706 707 708 709 710 711
gimp_image_apply_image (GimpImage	 *gimage,
			GimpDrawable	 *drawable,
			PixelRegion	 *src2PR,
			gint              undo,
			gint              opacity,
			LayerModeEffects  mode,
712
			/*  alternative to using drawable tiles as src1: */
713 714 715
			TileManager	 *src1_tiles,
			gint              x,
			gint              y)
716
{
717 718 719 720 721 722
  Channel     *mask;
  gint         x1, y1, x2, y2;
  gint         offset_x, offset_y;
  PixelRegion  src1PR, destPR, maskPR;
  gint         operation;
  gint         active [MAX_CHANNELS];
723 724

  /*  get the selection mask if one exists  */
725
  mask = (gimage_mask_is_empty (gimage)) ? NULL : gimp_image_get_mask (gimage);
726 727 728 729 730 731 732 733 734 735

  /*  configure the active channel array  */
  gimp_image_get_active_channels (gimage, drawable, active);

  /*  determine what sort of operation is being attempted and
   *  if it's actually legal...
   */
  operation = valid_combinations [drawable_type (drawable)][src2PR->bytes];
  if (operation == -1)
    {
Sven Neumann's avatar
Sven Neumann committed
736
      g_message ("gimp_image_apply_image sent illegal parameters");
737 738 739 740 741 742 743
      return;
    }

  /*  get the layer offsets  */
  drawable_offsets (drawable, &offset_x, &offset_y);

  /*  make sure the image application coordinates are within gimage bounds  */
744
  x1 = CLAMP (x, 0, drawable_width  (drawable));
745
  y1 = CLAMP (y, 0, drawable_height (drawable));
746
  x2 = CLAMP (x + src2PR->w, 0, drawable_width  (drawable));
747 748 749 750 751 752 753 754
  y2 = CLAMP (y + src2PR->h, 0, drawable_height (drawable));

  if (mask)
    {
      /*  make sure coordinates are in mask bounds ...
       *  we need to add the layer offset to transform coords
       *  into the mask coordinate system
       */
755 756 757 758
      x1 = CLAMP (x1, -offset_x, drawable_width (GIMP_DRAWABLE(mask))-offset_x);
      y1 = CLAMP (y1, -offset_y, drawable_height(GIMP_DRAWABLE(mask))-offset_y);
      x2 = CLAMP (x2, -offset_x, drawable_width (GIMP_DRAWABLE(mask))-offset_x);
      y2 = CLAMP (y2, -offset_y, drawable_height(GIMP_DRAWABLE(mask))-offset_y);
759 760 761 762
    }

  /*  If the calling procedure specified an undo step...  */
  if (undo)
763
    undo_push_image (gimp_drawable_gimage (drawable), drawable, x1, y1, x2, y2);
764 765 766 767 768

  /* configure the pixel regions
   *  If an alternative to using the drawable's data as src1 was provided...
   */
  if (src1_tiles)
769 770
    pixel_region_init (&src1PR, src1_tiles, 
		       x1, y1, (x2 - x1), (y2 - y1), FALSE);
771
  else
772 773 774 775 776 777 778
    pixel_region_init (&src1PR, drawable_data (drawable), 
		       x1, y1, (x2 - x1), (y2 - y1), FALSE);
  pixel_region_init (&destPR, drawable_data (drawable), 
		     x1, y1, (x2 - x1), (y2 - y1), TRUE);
  pixel_region_resize (src2PR, 
		       src2PR->x + (x1 - x), src2PR->y + (y1 - y), 
		       (x2 - x1), (y2 - y1));
779 780 781

  if (mask)
    {
782
      gint mx, my;
783 784 785 786 787 788 789 790

      /*  configure the mask pixel region
       *  don't use x1 and y1 because they are in layer
       *  coordinate system.  Need mask coordinate system
       */
      mx = x1 + offset_x;
      my = y1 + offset_y;

791 792 793 794 795
      pixel_region_init (&maskPR, 
			 drawable_data (GIMP_DRAWABLE(mask)), 
			 mx, my, 
			 (x2 - x1), (y2 - y1), 
			 FALSE);
796 797 798 799 800 801 802 803 804 805 806 807 808 809 810
      combine_regions (&src1PR, src2PR, &destPR, &maskPR, NULL,
		       opacity, mode, active, operation);
    }
  else
    combine_regions (&src1PR, src2PR, &destPR, NULL, NULL,
		     opacity, mode, active, operation);
}

/* Similar to gimp_image_apply_image but works in "replace" mode (i.e.
   transparent pixels in src2 make the result transparent rather
   than opaque.

   Takes an additional mask pixel region as well.
*/
void
811 812 813
gimp_image_replace_image (GimpImage    *gimage, 
			  GimpDrawable *drawable, 
			  PixelRegion  *src2PR,
814 815
			  gint          undo, 
			  gint          opacity,
816
			  PixelRegion  *maskPR,
817 818
			  gint          x, 
			  gint          y)
819
{
820 821 822 823 824 825 826 827
  Channel     *mask;
  gint         x1, y1, x2, y2;
  gint         offset_x, offset_y;
  PixelRegion  src1PR, destPR;
  PixelRegion  mask2PR, tempPR;
  guchar      *temp_data;
  gint         operation;
  gint         active [MAX_CHANNELS];
828 829

  /*  get the selection mask if one exists  */
830
  mask = (gimage_mask_is_empty (gimage)) ? NULL : gimp_image_get_mask (gimage);
831 832 833 834 835 836 837 838 839 840

  /*  configure the active channel array  */
  gimp_image_get_active_channels (gimage, drawable, active);

  /*  determine what sort of operation is being attempted and
   *  if it's actually legal...
   */
  operation = valid_combinations [drawable_type (drawable)][src2PR->bytes];
  if (operation == -1)
    {
Sven Neumann's avatar
Sven Neumann committed
841
      g_message ("gimp_image_apply_image sent illegal parameters");
842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859
      return;
    }

  /*  get the layer offsets  */
  drawable_offsets (drawable, &offset_x, &offset_y);

  /*  make sure the image application coordinates are within gimage bounds  */
  x1 = CLAMP (x, 0, drawable_width (drawable));
  y1 = CLAMP (y, 0, drawable_height (drawable));
  x2 = CLAMP (x + src2PR->w, 0, drawable_width (drawable));
  y2 = CLAMP (y + src2PR->h, 0, drawable_height (drawable));

  if (mask)
    {
      /*  make sure coordinates are in mask bounds ...
       *  we need to add the layer offset to transform coords
       *  into the mask coordinate system
       */
860 861 862 863
      x1 = CLAMP (x1, -offset_x, drawable_width (GIMP_DRAWABLE(mask))-offset_x);
      y1 = CLAMP (y1, -offset_y, drawable_height(GIMP_DRAWABLE(mask))-offset_y);
      x2 = CLAMP (x2, -offset_x, drawable_width (GIMP_DRAWABLE(mask))-offset_x);
      y2 = CLAMP (y2, -offset_y, drawable_height(GIMP_DRAWABLE(mask))-offset_y);
864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887
    }

  /*  If the calling procedure specified an undo step...  */
  if (undo)
    drawable_apply_image (drawable, x1, y1, x2, y2, NULL, FALSE);

  /* configure the pixel regions
   *  If an alternative to using the drawable's data as src1 was provided...
   */
  pixel_region_init (&src1PR, drawable_data (drawable), x1, y1, (x2 - x1), (y2 - y1), FALSE);
  pixel_region_init (&destPR, drawable_data (drawable), x1, y1, (x2 - x1), (y2 - y1), TRUE);
  pixel_region_resize (src2PR, src2PR->x + (x1 - x), src2PR->y + (y1 - y), (x2 - x1), (y2 - y1));

  if (mask)
    {
      int mx, my;

      /*  configure the mask pixel region
       *  don't use x1 and y1 because they are in layer
       *  coordinate system.  Need mask coordinate system
       */
      mx = x1 + offset_x;
      my = y1 + offset_y;

888 889 890 891 892
      pixel_region_init (&mask2PR, 
			 drawable_data (GIMP_DRAWABLE(mask)), 
			 mx, my, 
			 (x2 - x1), (y2 - y1), 
			 FALSE);
893 894 895 896 897 898

      tempPR.bytes = 1;
      tempPR.x = 0;
      tempPR.y = 0;
      tempPR.w = x2 - x1;
      tempPR.h = y2 - y1;
899
      tempPR.rowstride = tempPR.w * tempPR.bytes;
900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932
      temp_data = g_malloc (tempPR.h * tempPR.rowstride);
      tempPR.data = temp_data;

      copy_region (&mask2PR, &tempPR);

      /* apparently, region operations can mutate some PR data. */
      tempPR.x = 0;
      tempPR.y = 0;
      tempPR.w = x2 - x1;
      tempPR.h = y2 - y1;
      tempPR.data = temp_data;

      apply_mask_to_region (&tempPR, maskPR, OPAQUE_OPACITY);

      tempPR.x = 0;
      tempPR.y = 0;
      tempPR.w = x2 - x1;
      tempPR.h = y2 - y1;
      tempPR.data = temp_data;

      combine_regions_replace (&src1PR, src2PR, &destPR, &tempPR, NULL,
		       opacity, active, operation);

      g_free (temp_data);
    }
  else
    combine_regions_replace (&src1PR, src2PR, &destPR, maskPR, NULL,
		     opacity, active, operation);
}

/* Get rid of these! A "foreground" is an UI concept.. */

void
933 934 935
gimp_image_get_foreground (GimpImage    *gimage, 
			   GimpDrawable *drawable, 
			   guchar       *fg)
936
{
937
  guchar pfg[3];
938 939

  /*  Get the palette color  */
940
  gimp_context_get_foreground (NULL, &pfg[0], &pfg[1], &pfg[2]);
941 942 943 944 945

  gimp_image_transform_color (gimage, drawable, pfg, fg, RGB);
}

void
946 947 948
gimp_image_get_background (GimpImage    *gimage, 
			   GimpDrawable *drawable, 
			   guchar       *bg)
949
{
950
  guchar pbg[3];
951 952

  /*  Get the palette color  */
953
  gimp_context_get_background (NULL, &pbg[0], &pbg[1], &pbg[2]);
954 955 956 957

  gimp_image_transform_color (gimage, drawable, pbg, bg, RGB);
}

958
guchar *
959
gimp_image_get_color_at (GimpImage *gimage, 
960 961
			 gint       x, 
			 gint       y)
962
{
963
  Tile   *tile;
964 965
  guchar *src;
  guchar *dest;
966

967 968
  g_return_val_if_fail (GIMP_IS_IMAGE (gimage), NULL);

969
  if (x < 0 || y < 0 || x >= gimage->width || y >= gimage->height)
970 971
    return NULL;
  
972
  dest = g_new (unsigned char, 5);
973 974 975 976
  tile = tile_manager_get_tile (gimp_image_composite (gimage), x, y,
				TRUE, FALSE);
  src = tile_data_pointer (tile, x % TILE_WIDTH, y % TILE_HEIGHT);
  gimp_image_get_color (gimage, gimp_image_composite_type (gimage), dest, src);
977

978
  if (GIMP_IMAGE_TYPE_HAS_ALPHA (gimp_image_composite_type (gimage)))
979 980 981
    dest[3] = src[gimp_image_composite_bytes (gimage) - 1];
  else
    dest[3] = 255;
982

983 984
  dest[4] = 0;
  tile_release (tile, FALSE);
985

986 987 988
  return dest;
}

989
void
990
gimp_image_get_color (GimpImage     *gimage, 
991
		      GimpImageType  d_type,
992 993
		      guchar        *rgb, 
		      guchar        *src)
994
{
995 996
  g_return_if_fail (GIMP_IS_IMAGE (gimage));

997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011
  switch (d_type)
    {
    case RGB_GIMAGE: case RGBA_GIMAGE:
      map_to_color (0, NULL, src, rgb);
      break;
    case GRAY_GIMAGE: case GRAYA_GIMAGE:
      map_to_color (1, NULL, src, rgb);
      break;
    case INDEXED_GIMAGE: case INDEXEDA_GIMAGE:
      map_to_color (2, gimage->cmap, src, rgb);
      break;
    }
}

void
1012 1013 1014 1015 1016
gimp_image_transform_color (GimpImage         *gimage, 
			    GimpDrawable      *drawable,
			    guchar            *src, 
			    guchar            *dest, 
			    GimpImageBaseType  type)
1017
{
1018
  GimpImageType d_type;