Esempio n. 1
0
GimpLayerMask *
gimp_layer_mask_new (GimpImage     *image,
                     gint           width,
                     gint           height,
                     const gchar   *name,
                     const GimpRGB *color)
{
  GimpLayerMask *layer_mask;

  g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);
  g_return_val_if_fail (width > 0, NULL);
  g_return_val_if_fail (height > 0, NULL);
  g_return_val_if_fail (color != NULL, NULL);

  layer_mask =
    GIMP_LAYER_MASK (gimp_drawable_new (GIMP_TYPE_LAYER_MASK,
                                        image, name,
                                        0, 0, width, height,
                                        gimp_image_get_mask_format (image)));

  /*  set the layer_mask color and opacity  */
  gimp_channel_set_color (GIMP_CHANNEL (layer_mask), color, FALSE);
  gimp_channel_set_show_masked (GIMP_CHANNEL (layer_mask), TRUE);

  /*  selection mask variables  */
  GIMP_CHANNEL (layer_mask)->x2 = width;
  GIMP_CHANNEL (layer_mask)->y2 = height;

  return layer_mask;
}
Esempio n. 2
0
GimpLayerMask *
gimp_layer_mask_new (GimpImage     *image,
                     gint           width,
                     gint           height,
                     const gchar   *name,
                     const GimpRGB *color)
{
  GimpLayerMask *layer_mask;

  layer_mask = g_object_new (GIMP_TYPE_LAYER_MASK, NULL);

  gimp_drawable_configure (GIMP_DRAWABLE (layer_mask),
                           image,
                           0, 0, width, height,
                           GIMP_GRAY_IMAGE, name);

  /*  set the layer_mask color and opacity  */
  GIMP_CHANNEL (layer_mask)->color       = *color;
  GIMP_CHANNEL (layer_mask)->show_masked = TRUE;

  /*  selection mask variables  */
  GIMP_CHANNEL (layer_mask)->x2          = width;
  GIMP_CHANNEL (layer_mask)->y2          = height;

  return layer_mask;
}
Esempio n. 3
0
static void
gimp_image_duplicate_mask (GimpImage *image,
                           GimpImage *new_image)
{
  GimpDrawable *mask;
  GimpDrawable *new_mask;

  mask     = GIMP_DRAWABLE (gimp_image_get_mask (image));
  new_mask = GIMP_DRAWABLE (gimp_image_get_mask (new_image));

  gegl_buffer_copy (gimp_drawable_get_buffer (mask), NULL,
                    gimp_drawable_get_buffer (new_mask), NULL);

  GIMP_CHANNEL (new_mask)->bounds_known   = FALSE;
  GIMP_CHANNEL (new_mask)->boundary_known = FALSE;
}
Esempio n. 4
0
static GimpChannel *
gimp_image_duplicate_channels (GimpImage *image,
                               GimpImage *new_image)
{
  GimpChannel *active_channel = NULL;
  GList       *list;
  gint         count;

  for (list = gimp_image_get_channel_iter (image), count = 0;
       list;
       list = g_list_next (list))
    {
      GimpChannel  *channel = list->data;
      GimpChannel  *new_channel;

      new_channel = GIMP_CHANNEL (gimp_image_duplicate_item (GIMP_ITEM (channel),
                                                             new_image));

      if (gimp_image_get_active_channel (image) == channel)
        active_channel = new_channel;

      gimp_image_add_channel (new_image, new_channel,
                              NULL, count++, FALSE);
    }

  return active_channel;
}
Esempio n. 5
0
static GValueArray *
channel_copy_invoker (GimpProcedure     *procedure,
                      Gimp              *gimp,
                      GimpContext       *context,
                      GimpProgress      *progress,
                      const GValueArray *args)
{
  gboolean success = TRUE;
  GValueArray *return_vals;
  GimpChannel *channel;
  GimpChannel *channel_copy = NULL;

  channel = gimp_value_get_channel (&args->values[0], gimp);

  if (success)
    {
      channel_copy = GIMP_CHANNEL (gimp_item_duplicate (GIMP_ITEM (channel),
                                   G_TYPE_FROM_INSTANCE (channel), FALSE));

      if (! channel_copy)
        success = FALSE;
    }

  return_vals = gimp_procedure_get_return_values (procedure, success);

  if (success)
    gimp_value_set_channel (&return_vals->values[1], channel_copy);

  return return_vals;
}
void
floating_sel_activate_drawable (GimpLayer *layer)
{
  GimpImage    *image;
  GimpDrawable *drawable;

  g_return_if_fail (GIMP_IS_LAYER (layer));
  g_return_if_fail (gimp_layer_is_floating_sel (layer));

  image = gimp_item_get_image (GIMP_ITEM (layer));

  drawable = gimp_layer_get_floating_sel_drawable (layer);

  /*  set the underlying drawable to active  */
  if (GIMP_IS_LAYER_MASK (drawable))
    {
      GimpLayerMask *mask = GIMP_LAYER_MASK (drawable);

      gimp_image_set_active_layer (image, gimp_layer_mask_get_layer (mask));
    }
  else if (GIMP_IS_CHANNEL (drawable))
    {
      gimp_image_set_active_channel (image, GIMP_CHANNEL (drawable));
    }
  else
    {
      gimp_image_set_active_layer (image, GIMP_LAYER (drawable));
    }
}
Esempio n. 7
0
static void
gimp_mask_undo_constructed (GObject *object)
{
  GimpMaskUndo *mask_undo = GIMP_MASK_UNDO (object);
  GimpChannel  *channel;
  GimpDrawable *drawable;
  gint          x1, y1, x2, y2;

  if (G_OBJECT_CLASS (parent_class)->constructed)
    G_OBJECT_CLASS (parent_class)->constructed (object);

  g_assert (GIMP_IS_CHANNEL (GIMP_ITEM_UNDO (object)->item));

  channel  = GIMP_CHANNEL (GIMP_ITEM_UNDO (object)->item);
  drawable = GIMP_DRAWABLE (channel);

  if (gimp_channel_bounds (channel, &x1, &y1, &x2, &y2))
    {
      mask_undo->buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0,
                                                           x2 - x1, y2 - y1),
                                           gimp_drawable_get_format (drawable));

      gegl_buffer_copy (gimp_drawable_get_buffer (drawable),
                        GEGL_RECTANGLE (x1, y1, x2 - x1, y2 - y1),
                        mask_undo->buffer,
                        GEGL_RECTANGLE (0, 0, 0, 0));

      mask_undo->x = x1;
      mask_undo->y = y1;
    }

  mask_undo->format = gimp_drawable_get_format (drawable);
}
Esempio n. 8
0
static GimpValueArray *
channel_copy_invoker (GimpProcedure         *procedure,
                      Gimp                  *gimp,
                      GimpContext           *context,
                      GimpProgress          *progress,
                      const GimpValueArray  *args,
                      GError               **error)
{
  gboolean success = TRUE;
  GimpValueArray *return_vals;
  GimpChannel *channel;
  GimpChannel *channel_copy = NULL;

  channel = gimp_value_get_channel (gimp_value_array_index (args, 0), gimp);

  if (success)
    {
      channel_copy = GIMP_CHANNEL (gimp_item_duplicate (GIMP_ITEM (channel),
                                   G_TYPE_FROM_INSTANCE (channel)));

      if (! channel_copy)
        success = FALSE;
    }

  return_vals = gimp_procedure_get_return_values (procedure, success,
                                                  error ? *error : NULL);

  if (success)
    gimp_value_set_channel (gimp_value_array_index (return_vals, 1), channel_copy);

  return return_vals;
}
void
gimp_drawable_foreground_extract_siox (GimpDrawable       *mask,
                                       SioxState          *state,
                                       SioxRefinementType  refinement,
                                       gint                smoothness,
                                       const gdouble       sensitivity[3],
                                       gboolean            multiblob,
                                       GimpProgress       *progress)
{
  GeglBuffer *buffer;
  gint        x1, y1;
  gint        x2, y2;

  g_return_if_fail (GIMP_IS_DRAWABLE (mask));
  g_return_if_fail (babl_format_get_bytes_per_pixel (gimp_drawable_get_format (mask)) == 1);

  g_return_if_fail (state != NULL);

  g_return_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress));

  if (progress)
    gimp_progress_start (progress, _("Foreground Extraction"), FALSE);

  if (GIMP_IS_CHANNEL (mask))
    {
      gimp_channel_bounds (GIMP_CHANNEL (mask), &x1, &y1, &x2, &y2);
    }
  else
    {
      x1 = 0;
      y1 = 0;
      x2 = gimp_item_get_width  (GIMP_ITEM (mask));
      y2 = gimp_item_get_height (GIMP_ITEM (mask));
    }

  buffer = gimp_drawable_get_buffer (mask);

  siox_foreground_extract (state, refinement,
                           gimp_gegl_buffer_get_tiles (buffer),
                           x1, y1, x2, y2,
                           smoothness, sensitivity, multiblob,
                           (SioxProgressFunc) gimp_progress_set_value,
                           progress);

  if (progress)
    gimp_progress_end (progress);

  gimp_drawable_update (mask, x1, y1, x2, y2);
}
Esempio n. 10
0
static void
gimp_channel_undo_pop (GimpUndo            *undo,
                       GimpUndoMode         undo_mode,
                       GimpUndoAccumulator *accum)
{
  GimpChannelUndo *channel_undo = GIMP_CHANNEL_UNDO (undo);
  GimpChannel     *channel      = GIMP_CHANNEL (GIMP_ITEM_UNDO (undo)->item);

  GIMP_UNDO_CLASS (parent_class)->pop (undo, undo_mode, accum);

  if ((undo_mode       == GIMP_UNDO_MODE_UNDO &&
       undo->undo_type == GIMP_UNDO_CHANNEL_ADD) ||
      (undo_mode       == GIMP_UNDO_MODE_REDO &&
       undo->undo_type == GIMP_UNDO_CHANNEL_REMOVE))
    {
      /*  remove channel  */

      /*  record the current parent and position  */
      channel_undo->prev_parent   = gimp_channel_get_parent (channel);
      channel_undo->prev_position = gimp_item_get_index (GIMP_ITEM (channel));

      gimp_image_remove_channel (undo->image, channel, FALSE,
                                 channel_undo->prev_channel);
    }
  else
    {
      /*  restore channel  */

      /*  record the active channel  */
      channel_undo->prev_channel = gimp_image_get_active_channel (undo->image);

      gimp_image_add_channel (undo->image, channel,
                              channel_undo->prev_parent,
                              channel_undo->prev_position, FALSE);
    }
}
Esempio n. 11
0
void
gimp_image_set_quick_mask_state (GimpImage *image,
                                 gboolean   active)
{
  GimpChannel *selection;
  GimpChannel *mask;
  gboolean     channel_was_active;

  g_return_if_fail (GIMP_IS_IMAGE (image));

  if (active == gimp_image_get_quick_mask_state (image))
    return;

  /*  Keep track of the state so that we can make the right drawable
   *  active again when deactiviting quick mask (see bug #134371).
   */
  if (image->quick_mask_state)
    channel_was_active = (image->quick_mask_state & CHANNEL_WAS_ACTIVE) != 0;
  else
    channel_was_active = gimp_image_get_active_channel (image) != NULL;

  /*  Set image->quick_mask_state early so we can return early when
   *  being called recursively.
   */
  image->quick_mask_state = (active
                             ? TRUE | (channel_was_active ?
                                       CHANNEL_WAS_ACTIVE : 0)
                             : FALSE);

  selection = gimp_image_get_mask (image);
  mask      = gimp_image_get_quick_mask (image);

  if (active)
    {
      if (! mask)
        {
          gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_IMAGE_QUICK_MASK,
                                       _("Enable Quick Mask"));

          if (gimp_channel_is_empty (selection))
            {
              /* if no selection */

              GimpLayer *floating_sel = gimp_image_floating_sel (image);

              if (floating_sel)
                floating_sel_to_layer (floating_sel);

              mask = gimp_channel_new (image,
                                       image->width,
                                       image->height,
                                       GIMP_IMAGE_QUICK_MASK_NAME,
                                       &image->quick_mask_color);

              /* Clear the mask */
              gimp_channel_clear (mask, NULL, FALSE);
            }
          else
            {
              /* if selection */

              mask = GIMP_CHANNEL (gimp_item_duplicate (GIMP_ITEM (selection),
                                                        GIMP_TYPE_CHANNEL,
                                                        FALSE));

              /* Clear the selection */
              gimp_channel_clear (selection, NULL, TRUE);

              gimp_channel_set_color (mask, &image->quick_mask_color, FALSE);
              gimp_item_rename (GIMP_ITEM (mask), GIMP_IMAGE_QUICK_MASK_NAME);
            }

          if (image->quick_mask_inverted)
            gimp_channel_invert (mask, FALSE);

          gimp_image_add_channel (image, mask, 0);

          gimp_image_undo_group_end (image);
        }
    }
  else
    {
      if (mask)
        {
          GimpLayer *floating_sel = gimp_image_floating_sel (image);

          gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_IMAGE_QUICK_MASK,
                                       _("Disable Quick Mask"));

          if (image->quick_mask_inverted)
            gimp_channel_invert (mask, TRUE);

          if (floating_sel && floating_sel->fs.drawable == GIMP_DRAWABLE (mask))
            floating_sel_anchor (floating_sel);

          gimp_selection_load (gimp_image_get_mask (image), mask);
          gimp_image_remove_channel (image, mask);

          if (! channel_was_active)
            gimp_image_unset_active_channel (image);

          gimp_image_undo_group_end (image);
        }
    }

  gimp_image_quick_mask_changed (image);
}
Esempio n. 12
0
static void
compute_offset (GObject *object,
                GimpAlignmentType  alignment)
{
  gint object_offset_x = 0;
  gint object_offset_y = 0;
  gint object_height   = 0;
  gint object_width    = 0;
  gint offset          = 0;

  if (GIMP_IS_IMAGE (object))
    {
      GimpImage *image = GIMP_IMAGE (object);

      object_offset_x = 0;
      object_offset_y = 0;
      object_height   = gimp_image_get_height (image);
      object_width    = gimp_image_get_width (image);
    }
  else if (GIMP_IS_CHANNEL (object))
    {
      /* for channels, we use the bounds of the visible area, not
         the layer bounds.  This includes the selection channel */

      GimpChannel *channel = GIMP_CHANNEL (object);

      if (gimp_channel_is_empty (channel))
        {
          /* fall back on using the offsets instead */
          GimpItem *item = GIMP_ITEM (object);

          gimp_item_get_offset (item, &object_offset_x, &object_offset_y);
          object_width  = gimp_item_get_width  (item);
          object_height = gimp_item_get_height (item);
        }
      else
        {
          gint x1, x2, y1, y2;

          gimp_channel_bounds (channel, &x1, &y1, &x2, &y2);
          object_offset_x = x1;
          object_offset_y = y1;
          object_width    = x2 - x1;
          object_height   = y2 - y1;
        }
    }
  else if (GIMP_IS_ITEM (object))
    {
      GimpItem *item = GIMP_ITEM (object);

      if (GIMP_IS_VECTORS (object))
        {
          gdouble x1_f, y1_f, x2_f, y2_f;

          gimp_vectors_bounds (GIMP_VECTORS (item),
                               &x1_f, &y1_f,
                               &x2_f, &y2_f);

          object_offset_x = ROUND (x1_f);
          object_offset_y = ROUND (y1_f);
          object_height   = ROUND (y2_f - y1_f);
          object_width    = ROUND (x2_f - x1_f);
        }
      else
        {
          gimp_item_get_offset (item, &object_offset_x, &object_offset_y);
          object_width  = gimp_item_get_width  (item);
          object_height = gimp_item_get_height (item);
        }
    }
  else if (GIMP_IS_GUIDE (object))
    {
      GimpGuide *guide = GIMP_GUIDE (object);

      switch (gimp_guide_get_orientation (guide))
        {
        case GIMP_ORIENTATION_VERTICAL:
          object_offset_x = gimp_guide_get_position (guide);
          object_width = 0;
          break;

        case GIMP_ORIENTATION_HORIZONTAL:
          object_offset_y = gimp_guide_get_position (guide);
          object_height = 0;
          break;

        default:
          break;
        }
    }
  else
    {
      g_printerr ("Alignment object is not an image, item or guide.\n");
    }

  switch (alignment)
    {
    case GIMP_ALIGN_LEFT:
    case GIMP_ARRANGE_LEFT:
      offset = object_offset_x;
      break;
    case GIMP_ALIGN_HCENTER:
    case GIMP_ARRANGE_HCENTER:
      offset = object_offset_x + object_width/2;
      break;
    case GIMP_ALIGN_RIGHT:
    case GIMP_ARRANGE_RIGHT:
      offset = object_offset_x + object_width;
      break;
    case GIMP_ALIGN_TOP:
    case GIMP_ARRANGE_TOP:
      offset = object_offset_y;
      break;
    case GIMP_ALIGN_VCENTER:
    case GIMP_ARRANGE_VCENTER:
      offset = object_offset_y + object_height/2;
      break;
    case GIMP_ALIGN_BOTTOM:
    case GIMP_ARRANGE_BOTTOM:
      offset = object_offset_y + object_height;
      break;
    default:
      g_assert_not_reached ();
    }

  g_object_set_data (object, "align-offset",
                     GINT_TO_POINTER (offset));
}
Esempio n. 13
0
static void
gimp_mask_undo_pop (GimpUndo            *undo,
                    GimpUndoMode         undo_mode,
                    GimpUndoAccumulator *accum)
{
  GimpMaskUndo *mask_undo = GIMP_MASK_UNDO (undo);
  GimpChannel  *channel   = GIMP_CHANNEL (GIMP_ITEM_UNDO (undo)->item);
  GimpDrawable *drawable  = GIMP_DRAWABLE (channel);
  GeglBuffer   *new_buffer;
  const Babl   *format;
  gint          x1, y1, x2, y2;
  gint          width  = 0;
  gint          height = 0;

  GIMP_UNDO_CLASS (parent_class)->pop (undo, undo_mode, accum);

  if (gimp_channel_bounds (channel, &x1, &y1, &x2, &y2))
    {
      new_buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0, x2 - x1, y2 - y1),
                                    gimp_drawable_get_format (drawable));

      gegl_buffer_copy (gimp_drawable_get_buffer (drawable),
                        GEGL_RECTANGLE (x1, y1, x2 - x1, y2 - y1),
                        new_buffer,
                        GEGL_RECTANGLE (0, 0, 0, 0));

      gegl_buffer_clear (gimp_drawable_get_buffer (drawable),
                         GEGL_RECTANGLE (x1, y1, x2 - x1, y2 - y1));
    }
  else
    {
      new_buffer = NULL;
    }

  format = gimp_drawable_get_format (drawable);

  if (mask_undo->convert_format)
    {
      GeglBuffer *buffer;
      gint        width  = gimp_item_get_width  (GIMP_ITEM (channel));
      gint        height = gimp_item_get_height (GIMP_ITEM (channel));

      buffer = gimp_gegl_buffer_new (GEGL_RECTANGLE (0, 0, width, height),
                                     mask_undo->format);
      gegl_buffer_clear (buffer, NULL);

      gimp_drawable_set_buffer (drawable, FALSE, NULL, buffer);
      g_object_unref (buffer);
    }

  if (mask_undo->buffer)
    {
      width  = gegl_buffer_get_width  (mask_undo->buffer);
      height = gegl_buffer_get_height (mask_undo->buffer);

      gegl_buffer_copy (mask_undo->buffer,
                        NULL,
                        gimp_drawable_get_buffer (drawable),
                        GEGL_RECTANGLE (mask_undo->x, mask_undo->y, 0, 0));

      g_object_unref (mask_undo->buffer);
    }

  /* invalidate the current bounds and boundary of the mask */
  gimp_drawable_invalidate_boundary (drawable);

  if (mask_undo->buffer)
    {
      channel->empty = FALSE;
      channel->x1    = mask_undo->x;
      channel->y1    = mask_undo->y;
      channel->x2    = mask_undo->x + width;
      channel->y2    = mask_undo->y + height;
    }
  else
    {
      channel->empty = TRUE;
      channel->x1    = 0;
      channel->y1    = 0;
      channel->x2    = gimp_item_get_width  (GIMP_ITEM (channel));
      channel->y2    = gimp_item_get_height (GIMP_ITEM (channel));
    }

  /* we know the bounds */
  channel->bounds_known = TRUE;

  /*  set the new mask undo parameters  */
  mask_undo->buffer = new_buffer;
  mask_undo->x      = x1;
  mask_undo->y      = y1;
  mask_undo->format = format;

  gimp_drawable_update (GIMP_DRAWABLE (channel),
                        0, 0,
                        gimp_item_get_width  (GIMP_ITEM (channel)),
                        gimp_item_get_height (GIMP_ITEM (channel)));
}
Esempio n. 14
0
GimpImage *
gimp_image_duplicate (GimpImage *image)
{
  GimpImage    *new_image;
  GimpLayer    *floating_layer;
  GList        *list;
  GimpLayer    *active_layer              = NULL;
  GimpChannel  *active_channel            = NULL;
  GimpVectors  *active_vectors            = NULL;
  GimpDrawable *new_floating_sel_drawable = NULL;
  GimpDrawable *floating_sel_drawable     = NULL;
  gchar        *filename;
  gint          count;

  g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);

  gimp_set_busy_until_idle (image->gimp);

  /*  Create a new image  */
  new_image = gimp_create_image (image->gimp,
                                 image->width, image->height,
                                 image->base_type,
                                 FALSE);
  gimp_image_undo_disable (new_image);

  /*  Store the folder to be used by the save dialog  */
  filename = gimp_image_get_filename (image);
  if (filename)
    {
      g_object_set_data_full (G_OBJECT (new_image), "gimp-image-dirname",
                              g_path_get_dirname (filename),
                              (GDestroyNotify) g_free);
      g_free (filename);
    }

  /*  Copy the colormap if necessary  */
  if (new_image->base_type == GIMP_INDEXED)
    gimp_image_set_colormap (new_image,
                             gimp_image_get_colormap (image),
                             gimp_image_get_colormap_size (image),
                             FALSE);

  /*  Copy resolution information  */
  new_image->xresolution     = image->xresolution;
  new_image->yresolution     = image->yresolution;
  new_image->resolution_unit = image->resolution_unit;

  /*  Copy floating layer  */
  floating_layer = gimp_image_floating_sel (image);
  if (floating_layer)
    {
      floating_sel_relax (floating_layer, FALSE);

      floating_sel_drawable = floating_layer->fs.drawable;
      floating_layer = NULL;
    }

  /*  Copy the layers  */
  for (list = GIMP_LIST (image->layers)->list, count = 0;
       list;
       list = g_list_next (list))
    {
      GimpLayer *layer = list->data;
      GimpLayer *new_layer;

      new_layer = GIMP_LAYER (gimp_item_convert (GIMP_ITEM (layer),
                                                 new_image,
                                                 G_TYPE_FROM_INSTANCE (layer),
                                                 FALSE));

      /*  Make sure the copied layer doesn't say: "<old layer> copy"  */
      gimp_object_set_name (GIMP_OBJECT (new_layer),
                            gimp_object_get_name (GIMP_OBJECT (layer)));

      /*  Make sure that if the layer has a layer mask,
       *  its name isn't screwed up
       */
      if (new_layer->mask)
        gimp_object_set_name (GIMP_OBJECT (new_layer->mask),
                              gimp_object_get_name (GIMP_OBJECT (layer->mask)));

      if (gimp_image_get_active_layer (image) == layer)
        active_layer = new_layer;

      if (image->floating_sel == layer)
        floating_layer = new_layer;

      if (floating_sel_drawable == GIMP_DRAWABLE (layer))
        new_floating_sel_drawable = GIMP_DRAWABLE (new_layer);

      if (floating_layer != new_layer)
        gimp_image_add_layer (new_image, new_layer, count++);
    }

  /*  Copy the channels  */
  for (list = GIMP_LIST (image->channels)->list, count = 0;
       list;
       list = g_list_next (list))
    {
      GimpChannel *channel = list->data;
      GimpChannel *new_channel;

      new_channel =
        GIMP_CHANNEL (gimp_item_convert (GIMP_ITEM (channel),
                                         new_image,
                                         G_TYPE_FROM_INSTANCE (channel),
                                         FALSE));

      /*  Make sure the copied channel doesn't say: "<old channel> copy"  */
      gimp_object_set_name (GIMP_OBJECT (new_channel),
                            gimp_object_get_name (GIMP_OBJECT (channel)));

      if (gimp_image_get_active_channel (image) == channel)
        active_channel = (new_channel);

      if (floating_sel_drawable == GIMP_DRAWABLE (channel))
        new_floating_sel_drawable = GIMP_DRAWABLE (new_channel);

      gimp_image_add_channel (new_image, new_channel, count++);
    }

  /*  Copy any vectors  */
  for (list = GIMP_LIST (image->vectors)->list, count = 0;
       list;
       list = g_list_next (list))
    {
      GimpVectors *vectors = list->data;
      GimpVectors *new_vectors;

      new_vectors =
        GIMP_VECTORS (gimp_item_convert (GIMP_ITEM (vectors),
                                         new_image,
                                         G_TYPE_FROM_INSTANCE (vectors),
                                         FALSE));

      /*  Make sure the copied vectors doesn't say: "<old vectors> copy"  */
      gimp_object_set_name (GIMP_OBJECT (new_vectors),
                            gimp_object_get_name (GIMP_OBJECT (vectors)));

      if (gimp_image_get_active_vectors (image) == vectors)
        active_vectors = new_vectors;

      gimp_image_add_vectors (new_image, new_vectors, count++);
    }

  /*  Copy the selection mask  */
  {
    TileManager *src_tiles;
    TileManager *dest_tiles;
    PixelRegion  srcPR, destPR;

    src_tiles  =
      gimp_drawable_get_tiles (GIMP_DRAWABLE (image->selection_mask));
    dest_tiles =
      gimp_drawable_get_tiles (GIMP_DRAWABLE (new_image->selection_mask));

    pixel_region_init (&srcPR, src_tiles,
                       0, 0, image->width, image->height, FALSE);
    pixel_region_init (&destPR, dest_tiles,
                       0, 0, image->width, image->height, TRUE);

    copy_region (&srcPR, &destPR);

    new_image->selection_mask->bounds_known   = FALSE;
    new_image->selection_mask->boundary_known = FALSE;
  }

  if (floating_layer)
    floating_sel_attach (floating_layer, new_floating_sel_drawable);

  /*  Set active layer, active channel, active vectors  */
  if (active_layer)
    gimp_image_set_active_layer (new_image, active_layer);

  if (active_channel)
    gimp_image_set_active_channel (new_image, active_channel);

  if (active_vectors)
    gimp_image_set_active_vectors (new_image, active_vectors);

  /*  Copy state of all color channels  */
  for (count = 0; count < MAX_CHANNELS; count++)
    {
      new_image->visible[count] = image->visible[count];
      new_image->active[count]  = image->active[count];
    }

  /*  Copy any guides  */
  for (list = image->guides; list; list = g_list_next (list))
    {
      GimpGuide *guide    = list->data;
      gint       position = gimp_guide_get_position (guide);

      switch (gimp_guide_get_orientation (guide))
        {
        case GIMP_ORIENTATION_HORIZONTAL:
          gimp_image_add_hguide (new_image, position, FALSE);
          break;

        case GIMP_ORIENTATION_VERTICAL:
          gimp_image_add_vguide (new_image, position, FALSE);
          break;

        default:
          g_error ("Unknown guide orientation.\n");
        }
    }

  /*  Copy any sample points  */
  for (list = image->sample_points; list; list = g_list_next (list))
    {
      GimpSamplePoint *sample_point = list->data;

      gimp_image_add_sample_point_at_pos (new_image,
                                          sample_point->x,
                                          sample_point->y,
                                          FALSE);
    }

  /*  Copy the grid  */
  if (image->grid)
    gimp_image_set_grid (new_image, image->grid, FALSE);

  /*  Copy the quick mask info  */
  new_image->quick_mask_state    = image->quick_mask_state;
  new_image->quick_mask_inverted = image->quick_mask_inverted;
  new_image->quick_mask_color    = image->quick_mask_color;

  /*  Copy parasites  */
  if (image->parasites)
    {
      g_object_unref (new_image->parasites);
      new_image->parasites = gimp_parasite_list_copy (image->parasites);
    }

  gimp_image_undo_enable (new_image);

  return new_image;
}