gimpimage-merge.c 13.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 <glib-object.h>
Sven Neumann's avatar
Sven Neumann committed
22

23
#include "libgimpcolor/gimpcolor.h"
24
#include "libgimpmath/gimpmath.h"
25
#include "libgimpbase/gimpbase.h"
26

Michael Natterer's avatar
Michael Natterer committed
27 28
#include "core-types.h"

Michael Natterer's avatar
Michael Natterer committed
29 30 31
#include "base/pixel-region.h"
#include "base/temp-buf.h"
#include "base/tile-manager.h"
Sven Neumann's avatar
Sven Neumann committed
32

33 34
#include "paint-funcs/paint-funcs.h"

35
#include "gimp.h"
36
#include "gimpimage.h"
Michael Natterer's avatar
Michael Natterer committed
37
#include "gimpimage-colorhash.h"
38
#include "gimpimage-merge.h"
39
#include "gimpimage-projection.h"
40
#include "gimpimage-undo.h"
41
#include "gimplayer.h"
42
#include "gimplayermask.h"
43
#include "gimplist.h"
44
#include "gimpmarshal.h"
Manish Singh's avatar
Manish Singh committed
45
#include "gimpparasite.h"
46
#include "gimpparasitelist.h"
47
#include "gimpundostack.h"
48 49

#include "floating_sel.h"
50
#include "path.h"
51
#include "undo.h"
52

53 54
#include "libgimp/gimpintl.h"

55

56
/*  public functions  */
57

58 59 60
GimpLayer *
gimp_image_merge_visible_layers (GimpImage *gimage, 
				 MergeType  merge_type)
Sven Neumann's avatar
Sven Neumann committed
61
{
62 63 64 65
  GList     *list;
  GSList    *merge_list       = NULL;
  gboolean   had_floating_sel = FALSE;
  GimpLayer *layer            = NULL;
66

67
  g_return_val_if_fail (GIMP_IS_IMAGE (gimage), NULL);
68

69 70
  /* if there's a floating selection, anchor it */
  if (gimp_image_floating_sel (gimage))
71
    {
72 73
      floating_sel_anchor (gimage->floating_sel);
      had_floating_sel = TRUE;
74 75
    }

76 77 78
  for (list = GIMP_LIST (gimage->layers)->list;
       list;
       list = g_list_next (list))
79
    {
80
      layer = (GimpLayer *) list->data;
81

82 83
      if (gimp_drawable_get_visible (GIMP_DRAWABLE (layer)))
	merge_list = g_slist_append (merge_list, layer);
84
    }
85

86
  if (merge_list && merge_list->next)
87
    {
88
      gimp_set_busy (gimage->gimp);
89

90 91
      layer = gimp_image_merge_layers (gimage, merge_list, merge_type);
      g_slist_free (merge_list);
92

93
      gimp_unset_busy (gimage->gimp);
Michael Natterer's avatar
Michael Natterer committed
94

95
      return layer;
96
    }
97
  else
98
    {
99
      g_slist_free (merge_list);
100

101 102 103 104 105 106 107
      /* If there was a floating selection, we have done something.
	 No need to warn the user. Return the active layer instead */
      if (had_floating_sel)
	return layer;
      else
	g_message (_("Not enough visible layers for a merge.\n"
		     "There must be at least two."));
108

109
      return NULL;
110
    }
111
}
112

113 114
GimpLayer *
gimp_image_flatten (GimpImage *gimage)
115
{
116 117 118
  GList     *list;
  GSList    *merge_list = NULL;
  GimpLayer *layer;
119

120
  g_return_val_if_fail (GIMP_IS_IMAGE (gimage), NULL);
121

122
  gimp_set_busy (gimage->gimp);
123

124 125 126
  /* if there's a floating selection, anchor it */
  if (gimp_image_floating_sel (gimage))
    floating_sel_anchor (gimage->floating_sel);
127

128 129 130 131 132
  for (list = GIMP_LIST (gimage->layers)->list;
       list;
       list = g_list_next (list))
    {
      layer = (GimpLayer *) list->data;
133

134 135 136
      if (gimp_drawable_get_visible (GIMP_DRAWABLE (layer)))
	merge_list = g_slist_append (merge_list, layer);
    }
137

138 139
  layer = gimp_image_merge_layers (gimage, merge_list, FLATTEN_IMAGE);
  g_slist_free (merge_list);
140

141
  gimp_image_alpha_changed (gimage);
142

143
  gimp_unset_busy (gimage->gimp);
Michael Natterer's avatar
Michael Natterer committed
144

145
  return layer;
146 147
}

148 149 150 151
GimpLayer *
gimp_image_merge_down (GimpImage *gimage,
		       GimpLayer *current_layer,
		       MergeType  merge_type)
152
{
153 154 155 156 157 158
  GimpLayer *layer;
  GList     *list;
  GList     *layer_list;
  GSList    *merge_list;
  
  g_return_val_if_fail (GIMP_IS_IMAGE (gimage), NULL);
159

160 161 162
  for (list = GIMP_LIST (gimage->layers)->list, layer_list = NULL;
       list && !layer_list;
       list = g_list_next (list))
163
    {
164 165 166 167
      layer = (GimpLayer *) list->data;
      
      if (layer == current_layer)
	break;
168
    }
169 170 171 172
    
  for (layer_list = g_list_next (list), merge_list = NULL; 
       layer_list && !merge_list; 
       layer_list = g_list_next (layer_list))
173
    {
174 175 176 177
      layer = (GimpLayer *) layer_list->data;
      
      if (gimp_drawable_get_visible (GIMP_DRAWABLE (layer)))
	merge_list = g_slist_append (NULL, layer);
178 179
    }

180
  if (merge_list)
181
    {
182
      merge_list = g_slist_prepend (merge_list, current_layer);
183

184
      gimp_set_busy (gimage->gimp);
185

186 187
      layer = gimp_image_merge_layers (gimage, merge_list, merge_type);
      g_slist_free (merge_list);
188

189
      gimp_unset_busy (gimage->gimp);
190

191
      return layer;
192
    }
193
  else 
Michael Natterer's avatar
Michael Natterer committed
194
    {
195 196
      g_message (_("There are not enough visible layers for a merge down."));
      return NULL;
Michael Natterer's avatar
Michael Natterer committed
197 198 199
    }
}

200 201 202 203
GimpLayer *
gimp_image_merge_layers (GimpImage *gimage, 
			 GSList    *merge_list, 
			 MergeType  merge_type)
204
{
205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222
  GList                *list;
  GSList               *reverse_list = NULL;
  PixelRegion          src1PR, src2PR, maskPR;
  PixelRegion          *mask;
  GimpLayer            *merge_layer;
  GimpLayer            *layer;
  GimpLayer            *bottom_layer;
  GimpLayerModeEffects  bottom_mode;
  guchar                bg[4] = {0, 0, 0, 0};
  GimpImageType         type;
  gint                  count;
  gint                  x1, y1, x2, y2;
  gint                  x3, y3, x4, y4;
  gint                  operation;
  gint                  position;
  gint                  active[MAX_CHANNELS] = {1, 1, 1, 1};
  gint                  off_x, off_y;
  gchar                *name;
223

224 225
  g_return_val_if_fail (GIMP_IS_IMAGE (gimage), NULL);

226
  layer        = NULL;
227
  type         = GIMP_RGBA_IMAGE;
228 229 230
  x1 = y1      = 0;
  x2 = y2      = 0;
  bottom_layer = NULL;
231
  bottom_mode  = GIMP_NORMAL_MODE;
232

233 234 235
  /*  Get the layer extents  */
  count = 0;
  while (merge_list)
236
    {
237 238
      layer = (GimpLayer *) merge_list->data;
      gimp_drawable_offsets (GIMP_DRAWABLE (layer), &off_x, &off_y);
239

240
      switch (merge_type)
241
	{
242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269
	case EXPAND_AS_NECESSARY:
	case CLIP_TO_IMAGE:
	  if (!count)
	    {
	      x1 = off_x;
	      y1 = off_y;
	      x2 = off_x + gimp_drawable_width (GIMP_DRAWABLE (layer));
	      y2 = off_y + gimp_drawable_height (GIMP_DRAWABLE (layer));
	    }
	  else
	    {
	      if (off_x < x1)
		x1 = off_x;
	      if (off_y < y1)
		y1 = off_y;
	      if ((off_x + gimp_drawable_width (GIMP_DRAWABLE (layer))) > x2)
		x2 = (off_x + gimp_drawable_width (GIMP_DRAWABLE (layer)));
	      if ((off_y + gimp_drawable_height (GIMP_DRAWABLE (layer))) > y2)
		y2 = (off_y + gimp_drawable_height (GIMP_DRAWABLE (layer)));
	    }
	  if (merge_type == CLIP_TO_IMAGE)
	    {
	      x1 = CLAMP (x1, 0, gimage->width);
	      y1 = CLAMP (y1, 0, gimage->height);
	      x2 = CLAMP (x2, 0, gimage->width);
	      y2 = CLAMP (y2, 0, gimage->height);
	    }
	  break;
270

271 272 273 274 275 276 277 278 279
	case CLIP_TO_BOTTOM_LAYER:
	  if (merge_list->next == NULL)
	    {
	      x1 = off_x;
	      y1 = off_y;
	      x2 = off_x + gimp_drawable_width (GIMP_DRAWABLE (layer));
	      y2 = off_y + gimp_drawable_height (GIMP_DRAWABLE (layer));
	    }
	  break;
280

281 282 283 284 285 286 287 288 289 290
	case FLATTEN_IMAGE:
	  if (merge_list->next == NULL)
	    {
	      x1 = 0;
	      y1 = 0;
	      x2 = gimage->width;
	      y2 = gimage->height;
	    }
	  break;
	}
291

292 293 294 295
      count ++;
      reverse_list = g_slist_prepend (reverse_list, layer);
      merge_list = g_slist_next (merge_list);
    }
296

297 298
  if ((x2 - x1) == 0 || (y2 - y1) == 0)
    return NULL;
299

300 301
  /*  Start a merge undo group  */
  undo_push_group_start (gimage, LAYER_MERGE_UNDO);
302

303
  name = g_strdup (gimp_object_get_name (GIMP_OBJECT (layer)));
304

305
  if (merge_type == FLATTEN_IMAGE ||
306
      gimp_drawable_type (GIMP_DRAWABLE (layer)) == GIMP_INDEXED_IMAGE)
307
    {
308
      type = GIMP_IMAGE_TYPE_FROM_BASE_TYPE (gimp_image_base_type (gimage));
309

310 311 312
      merge_layer = gimp_layer_new (gimage, (x2 - x1), (y2 - y1),
				    type,
				    gimp_object_get_name (GIMP_OBJECT (layer)),
313
				    OPAQUE_OPACITY, GIMP_NORMAL_MODE);
314 315 316 317 318 319
      if (!merge_layer)
	{
	  g_warning ("%s: could not allocate merge layer.",
		     G_GNUC_PRETTY_FUNCTION);
	  return NULL;
	}
320

321 322
      GIMP_DRAWABLE (merge_layer)->offset_x = x1;
      GIMP_DRAWABLE (merge_layer)->offset_y = y1;
323

324 325
      /*  get the background for compositing  */
      gimp_image_get_background (gimage, GIMP_DRAWABLE (merge_layer), bg);
326

327 328 329 330 331 332
      /*  init the pixel region  */
      pixel_region_init (&src1PR, 
			 gimp_drawable_data (GIMP_DRAWABLE (merge_layer)), 
			 0, 0, 
			 gimage->width, gimage->height, 
			 TRUE);
333

334 335
      /*  set the region to the background color  */
      color_region (&src1PR, bg);
336

337
      position = 0;
338 339 340
    }
  else
    {
341 342 343 344
      /*  The final merged layer inherits the name of the bottom most layer
       *  and the resulting layer has an alpha channel
       *  whether or not the original did
       *  Opacity is set to 100% and the MODE is set to normal
345 346
       */

347 348 349 350
      merge_layer =
	gimp_layer_new (gimage, (x2 - x1), (y2 - y1),
			gimp_drawable_type_with_alpha (GIMP_DRAWABLE (layer)),
			"merged layer",
351
			OPAQUE_OPACITY, GIMP_NORMAL_MODE);
352

353 354 355 356 357 358
      if (!merge_layer)
	{
	  g_warning ("%s: could not allocate merge layer",
		     G_GNUC_PRETTY_FUNCTION);
	  return NULL;
	}
359

360 361
      GIMP_DRAWABLE (merge_layer)->offset_x = x1;
      GIMP_DRAWABLE (merge_layer)->offset_y = y1;
362

363 364 365 366 367 368
      /*  Set the layer to transparent  */
      pixel_region_init (&src1PR, 
			 gimp_drawable_data (GIMP_DRAWABLE (merge_layer)), 
			 0, 0, 
			 (x2 - x1), (y2 - y1), 
			 TRUE);
369

370 371
      /*  set the region to 0's  */
      color_region (&src1PR, bg);
372

373 374 375 376 377 378 379 380 381 382 383 384 385 386 387
      /*  Find the index in the layer list of the bottom layer--we need this
       *  in order to add the final, merged layer to the layer list correctly
       */
      layer = (GimpLayer *) reverse_list->data;
      position = 
	gimp_container_num_children (gimage->layers) - 
	gimp_container_get_child_index (gimage->layers, GIMP_OBJECT (layer));
      
      /* set the mode of the bottom layer to normal so that the contents
       *  aren't lost when merging with the all-alpha merge_layer
       *  Keep a pointer to it so that we can set the mode right after it's
       *  been merged so that undo works correctly.
       */
      bottom_layer = layer;
      bottom_mode  = bottom_layer->mode;
388

389 390 391 392
      /* DISSOLVE_MODE is special since it is the only mode that does not
       *  work on the projection with the lower layer, but only locally on
       *  the layers alpha channel. 
       */
393 394
      if (bottom_layer->mode != GIMP_DISSOLVE_MODE)
	gimp_layer_set_mode (bottom_layer, GIMP_NORMAL_MODE);
395 396
    }

397 398 399 400 401
  /* Copy the tattoo and parasites of the bottom layer to the new layer */
  gimp_drawable_set_tattoo (GIMP_DRAWABLE (merge_layer),
			    gimp_drawable_get_tattoo (GIMP_DRAWABLE (layer)));
  GIMP_DRAWABLE (merge_layer)->parasites =
    gimp_parasite_list_copy (GIMP_DRAWABLE (layer)->parasites);
402

403
  while (reverse_list)
404
    {
405
      layer = (GimpLayer *) reverse_list->data;
406

407 408 409 410 411 412 413 414 415 416 417 418 419
      /*  determine what sort of operation is being attempted and
       *  if it's actually legal...
       */
      operation = gimp_image_get_combination_mode (gimp_drawable_type (GIMP_DRAWABLE (merge_layer)),
                                                   gimp_drawable_bytes (GIMP_DRAWABLE (layer)));

      if (operation == -1)
	{
	  g_warning ("%s: attempting to merge incompatible layers.",
		     G_GNUC_PRETTY_FUNCTION);
	  return NULL;
	}

420
      gimp_drawable_offsets (GIMP_DRAWABLE (layer), &off_x, &off_y);
421 422 423 424
      x3 = CLAMP (off_x, x1, x2);
      y3 = CLAMP (off_y, y1, y2);
      x4 = CLAMP (off_x + gimp_drawable_width (GIMP_DRAWABLE (layer)), x1, x2);
      y4 = CLAMP (off_y + gimp_drawable_height (GIMP_DRAWABLE (layer)), y1, y2);
425

426 427 428 429 430 431 432 433 434 435
      /* configure the pixel regions  */
      pixel_region_init (&src1PR, 
			 gimp_drawable_data (GIMP_DRAWABLE (merge_layer)), 
			 (x3 - x1), (y3 - y1), (x4 - x3), (y4 - y3), 
			 TRUE);
      pixel_region_init (&src2PR, 
			 gimp_drawable_data (GIMP_DRAWABLE (layer)), 
			 (x3 - off_x), (y3 - off_y),
			 (x4 - x3), (y4 - y3), 
			 FALSE);
436

437
      if (layer->mask && layer->mask->apply_mask)
438
	{
439 440 441 442 443
	  pixel_region_init (&maskPR, 
			     gimp_drawable_data (GIMP_DRAWABLE (layer->mask)), 
			     (x3 - off_x), (y3 - off_y),
			     (x4 - x3), (y4 - y3), 
			     FALSE);
444 445 446
	  mask = &maskPR;
	}
      else
447 448 449
	{
	  mask = NULL;
	}
450

451 452
      combine_regions (&src1PR, &src2PR, &src1PR, mask, NULL,
		       layer->opacity, layer->mode, active, operation);
453

454 455 456
      gimp_image_remove_layer (gimage, layer);
      reverse_list = g_slist_next (reverse_list);
    }
457

458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473
  /* Save old mode in undo */
  if (bottom_layer)
    gimp_layer_set_mode (bottom_layer, bottom_mode);

  g_slist_free (reverse_list);

  /*  if the type is flatten, remove all the remaining layers  */
  if (merge_type == FLATTEN_IMAGE)
    {
      list = GIMP_LIST (gimage->layers)->list;
      while (list)
	{
	  layer = (GimpLayer *) list->data;

	  list = g_list_next (list);
	  gimp_image_remove_layer (gimage, layer);
474 475
	}

476 477 478 479 480 481 482
      gimp_image_add_layer (gimage, merge_layer, position);
    }
  else
    {
      /*  Add the layer to the gimage  */
      gimp_image_add_layer (gimage, merge_layer,
	 gimp_container_num_children (gimage->layers) - position + 1);
483 484
    }

485 486 487 488 489 490 491 492
  /* set the name after the original layers have been removed so we
   * don't end up with #2 appended to the name
   */
  gimp_object_set_name (GIMP_OBJECT (merge_layer), name);
  g_free (name);

  /*  End the merge undo group  */
  undo_push_group_end (gimage);
493

494 495 496 497 498 499 500 501
  gimp_drawable_set_visible (GIMP_DRAWABLE (merge_layer), TRUE);

  gimp_drawable_update (GIMP_DRAWABLE (merge_layer), 
			0, 0, 
			gimp_drawable_width (GIMP_DRAWABLE (merge_layer)), 
			gimp_drawable_height (GIMP_DRAWABLE (merge_layer)));

  return merge_layer;
502
}