Пример #1
0
/* --------------------------
 * p_create_corpus_layer
 * --------------------------
 * create the corpus layer that builds the reference pattern
 * for the resynthesizer call. The reference pattern is built
 * as duplicate of the original image reduced to the area around the current selection.
 * (grown by corpus_border_radius)
 * Note that the duplicate image has a selection, that includes the gorwn area
 * around the orignal selection, but EXCLUDES the original selection
 * (that is the area holding the object that has to be replaced
 * by pattern of the surrounding area)
 * returns the layer_id of the reference pattern.
 */
static gint32
p_create_corpus_layer(gint32 image_id, gint32 drawable_id, TransValues *val_ptr)
{
  gint32 dup_image_id;
  gint32 channel_id;
  gint32 channel_2_id;
  GimpRGB  bck_color;
  GimpRGB  white_opaque_color;
  /* gboolean has_selection; */
  gboolean non_empty;
  gint     x1, y1, x2, y2;
  gint32   active_layer_stackposition;
  gint32   active_dup_layer_id;


  active_layer_stackposition = gap_layer_get_stackposition(image_id, drawable_id);

  dup_image_id = gimp_image_duplicate(image_id);

  channel_id = gimp_selection_save(dup_image_id);
  gimp_selection_grow(dup_image_id, val_ptr->corpus_border_radius);
  gimp_selection_invert(dup_image_id);

  gimp_context_get_background(&bck_color);
  channel_2_id = gimp_selection_save(dup_image_id);

  gimp_image_select_item(dup_image_id, GIMP_CHANNEL_OP_REPLACE, channel_id);

  gimp_rgba_set_uchar (&white_opaque_color, 255, 255, 255, 255);
  gimp_context_set_background(&white_opaque_color);
  gimp_edit_clear(channel_2_id);


  gimp_context_set_background(&bck_color);  /* restore original background color */

  gimp_selection_load(channel_2_id);

  gimp_selection_invert(dup_image_id);

  /* has_selection  = */ gimp_selection_bounds(dup_image_id, &non_empty, &x1, &y1, &x2, &y2);
  gimp_image_crop(dup_image_id, (x2 - x1), (y2 - y1), x1, y1);

  gimp_selection_invert(dup_image_id);
  active_dup_layer_id = gap_layer_get_id_by_stackposition(dup_image_id, active_layer_stackposition);

  if (1==0)
  {
    /* debug code shows the duplicate image by adding a display */
    gimp_display_new(dup_image_id);
  }
  return (active_dup_layer_id);

}  /* end p_create_corpus_layer */
Пример #2
0
static GimpValueArray *
selection_save_invoker (GimpProcedure         *procedure,
                        Gimp                  *gimp,
                        GimpContext           *context,
                        GimpProgress          *progress,
                        const GimpValueArray  *args,
                        GError               **error)
{
  gboolean success = TRUE;
  GimpValueArray *return_vals;
  GimpImage *image;
  GimpChannel *channel = NULL;

  image = gimp_value_get_image (gimp_value_array_index (args, 0), gimp);

  if (success)
    {
      channel = gimp_selection_save (GIMP_SELECTION (gimp_image_get_mask (image)));

      if (! channel)
        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);

  return return_vals;
}
Пример #3
0
static GValueArray *
selection_save_invoker (GimpProcedure      *procedure,
                        Gimp               *gimp,
                        GimpContext        *context,
                        GimpProgress       *progress,
                        const GValueArray  *args,
                        GError            **error)
{
  gboolean success = TRUE;
  GValueArray *return_vals;
  GimpImage *image;
  GimpChannel *channel = NULL;

  image = gimp_value_get_image (&args->values[0], gimp);

  if (success)
    {
      channel = gimp_selection_save (gimp_image_get_mask (image));

      if (! channel)
        success = FALSE;
    }

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

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

  return return_vals;
}
Пример #4
0
void
select_save_cmd_callback (GtkAction *action,
                          gpointer   data)
{
  GimpImage *image;
  GtkWidget *widget;
  return_if_no_image (image, data);
  return_if_no_widget (widget, data);

  gimp_selection_save (gimp_image_get_mask (image));
  gimp_image_flush (image);

  gimp_dialog_factory_dialog_raise (global_dock_factory,
                                    gtk_widget_get_screen (widget),
                                    "gimp-channel-list", -1);
}
Пример #5
0
void
select_save_cmd_callback (GtkAction *action,
                          gpointer   data)
{
  GimpImage *image;
  GtkWidget *widget;
  return_if_no_image (image, data);
  return_if_no_widget (widget, data);

  gimp_selection_save (GIMP_SELECTION (gimp_image_get_mask (image)));
  gimp_image_flush (image);

  gimp_window_strategy_show_dockable_dialog (GIMP_WINDOW_STRATEGY (gimp_get_window_strategy (image->gimp)),
                                             image->gimp,
                                             gimp_dialog_factory_get_singleton (),
                                             gtk_widget_get_screen (widget),
                                             gimp_widget_get_monitor (widget),
                                             "gimp-channel-list");
}
Пример #6
0
static gboolean
lcms_image_apply_profile (gint32                    image,
                          cmsHPROFILE               src_profile,
                          cmsHPROFILE               dest_profile,
                          const gchar              *filename,
                          GimpColorRenderingIntent  intent,
                          gboolean                  bpc)
{
  gint32 saved_selection = -1;

  gimp_image_undo_group_start (image);

  if (! lcms_image_set_profile (image, dest_profile, filename, FALSE))
    {
      gimp_image_undo_group_end (image);

      return FALSE;
    }

  {
    gchar  *src  = lcms_icc_profile_get_desc (src_profile);
    gchar  *dest = lcms_icc_profile_get_desc (dest_profile);

      /* ICC color profile conversion */
      gimp_progress_init_printf (_("Converting from '%s' to '%s'"), src, dest);

      g_printerr ("lcms: converting from '%s' to '%s'\n", src, dest);

      g_free (dest);
      g_free (src);
  }

  if (! gimp_selection_is_empty (image))
    {
      saved_selection = gimp_selection_save (image);
      gimp_selection_none (image);
    }

  switch (gimp_image_base_type (image))
    {
    case GIMP_RGB:
      lcms_image_transform_rgb (image,
                                src_profile, dest_profile, intent, bpc);
      break;

    case GIMP_GRAY:
      g_warning ("colorspace conversion not implemented for "
                 "grayscale images");
      break;

    case GIMP_INDEXED:
      lcms_image_transform_indexed (image,
                                    src_profile, dest_profile, intent, bpc);
      break;
    }

  if (saved_selection != -1)
    {
      gimp_image_select_item (image, GIMP_CHANNEL_OP_REPLACE, saved_selection);
      gimp_image_remove_channel (image, saved_selection);
    }

  gimp_progress_update (1.0);

  gimp_image_undo_group_end (image);

  return TRUE;
}
Пример #7
0
static void
do_zcrop (gint32  drawable_id,
          gint32  image_id)
{
  GeglBuffer  *drawable_buffer;
  GeglBuffer  *shadow_buffer;
  gfloat      *linear_buf;
  const Babl  *format;

  gint         x, y, width, height;
  gint         components;
  gint8       *killrows;
  gint8       *killcols;
  gint32       livingrows, livingcols, destrow, destcol;
  gint32       selection_copy_id;
  gboolean     has_alpha;

  drawable_buffer = gimp_drawable_get_buffer (drawable_id);
  shadow_buffer   = gimp_drawable_get_shadow_buffer (drawable_id);

  width  = gegl_buffer_get_width (drawable_buffer);
  height = gegl_buffer_get_height (drawable_buffer);
  has_alpha = gimp_drawable_has_alpha (drawable_id);

  if (has_alpha)
    format = babl_format ("R'G'B'A float");
  else
    format = babl_format ("R'G'B' float");

  components = babl_format_get_n_components (format);

  killrows = g_new (gint8, height);
  killcols = g_new (gint8, width);

  linear_buf = g_new (gfloat, (width > height ? width : height) * components);

  /* search which rows to remove */

  livingrows = 0;
  for (y = 0; y < height; y++)
    {
      gegl_buffer_get (drawable_buffer, GEGL_RECTANGLE (0, y, width, 1),
                       1.0, format, linear_buf,
                       GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);

      killrows[y] = TRUE;

      for (x = components; x < width * components; x += components)
        {
          if (! colors_equal (linear_buf, &linear_buf[x], components, has_alpha))
            {
              livingrows++;
              killrows[y] = FALSE;
              break;
            }
        }
    }

  gimp_progress_update (0.25);

  /* search which columns to remove */

  livingcols = 0;
  for (x = 0; x < width; x++)
    {
      gegl_buffer_get (drawable_buffer, GEGL_RECTANGLE (x, 0, 1, height),
                       1.0, format, linear_buf,
                       GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);

      killcols[x] = TRUE;

      for (y = components; y < height * components; y += components)
        {
          if (! colors_equal (linear_buf, &linear_buf[y], components, has_alpha))
            {
              livingcols++;
              killcols[x] = FALSE;
              break;
            }
        }
    }

  gimp_progress_update (0.5);

  if ((livingcols == 0 || livingrows == 0) ||
      (livingcols == width && livingrows == height))
    {
      g_message (_("Nothing to crop."));
      g_free (linear_buf);
      g_free (killrows);
      g_free (killcols);
      return;
    }

  /* restitute living rows */

  destrow = 0;
  for (y = 0; y < height; y++)
    {
      if (!killrows[y])
        {
          gegl_buffer_copy (drawable_buffer,
                            GEGL_RECTANGLE (0, y, width, 1),
                            GEGL_ABYSS_NONE,
                            shadow_buffer,
                            GEGL_RECTANGLE (0, destrow, width, 1));

          destrow++;
        }
    }

  gimp_progress_update (0.75);

  /* restitute living columns */

  destcol = 0;
  for (x = 0; x < width; x++)
    {
      if (!killcols[x])
        {
          gegl_buffer_copy (shadow_buffer,
                            GEGL_RECTANGLE (x, 0, 1, height),
                            GEGL_ABYSS_NONE,
                            shadow_buffer,
                            GEGL_RECTANGLE (destcol, 0, 1, height));

          destcol++;
        }
    }

  gimp_progress_update (1.00);

  gimp_image_undo_group_start (image_id);

  selection_copy_id = gimp_selection_save (image_id);
  gimp_selection_none (image_id);

  gegl_buffer_flush (shadow_buffer);
  gimp_drawable_merge_shadow (drawable_id, TRUE);
  gegl_buffer_flush (drawable_buffer);

  gimp_image_select_item (image_id, GIMP_CHANNEL_OP_REPLACE, selection_copy_id);
  gimp_image_remove_channel (image_id, selection_copy_id);

  gimp_image_crop (image_id, livingcols, livingrows, 0, 0);

  gimp_image_undo_group_end (image_id);

  g_object_unref (shadow_buffer);
  g_object_unref (drawable_buffer);

  g_free (linear_buf);
  g_free (killrows);
  g_free (killcols);
}
Пример #8
0
/* --------------------------------------------
 * gap_fg_from_selection_exec_apply_run
 * --------------------------------------------
 * generate a tri map from the current selection by filling the shrinked
 * shape with white, the expanded shape with black and the borderline
 * between shrinked and expanded selection with medium gray.
 * the trimap is attached as layermask to the input drawable,
 * and used as input for the foreground selection via alpha matting algorithm,
 * that creates a resulting layer with trimmed selection.
 *
 */
gint
gap_fg_from_selection_exec_apply_run (gint32 image_id, gint32 drawable_id
                             , gboolean doProgress, gboolean doFlush
                             , GapFgSelectValues *fsValPtr)
{
  GimpRGB   color;
  gint32    activeSelection;
  gint32    shrinkedSelection;
  gint32    trimap;
  gboolean  hadSelection;
  gint      rc;

  rc = 0;
  trimap = -1;
  activeSelection = -1;
  shrinkedSelection = -1;
  hadSelection = FALSE;
  
  gimp_context_push();
  gimp_image_undo_group_start(image_id);
  

  if (gimp_selection_is_empty(image_id) == TRUE)
  {
     if (gimp_drawable_has_alpha(drawable_id) == FALSE)
     {
       /* if the layer has no alpha select all */
       gimp_selection_all(image_id);
     }
     else
     {
       gimp_selection_layer_alpha(drawable_id);
     }
     activeSelection = gimp_selection_save(image_id);
  }
  else
  {
    activeSelection = gimp_selection_save(image_id);
    hadSelection = TRUE;
  }


  trimap = gimp_layer_get_mask(drawable_id);
  if (trimap < 0)
  {
    /* create trimap as new layermask */
    trimap = gimp_layer_create_mask(drawable_id, GIMP_ADD_BLACK_MASK);
    gimp_layer_add_mask(drawable_id, trimap);
  }
  else
  {
    /* use BLACK color to fill the already existing layermask
     * (note that gimp_drawable_fill is used to fill the entire mask
     * regardless to the current selection)
     */
    color.r = 0.0;
    color.g = 0.0;
    color.b = 0.0;
    color.a = 1.0;
    gimp_context_set_background (&color);
    gimp_drawable_fill(trimap, GIMP_BACKGROUND_FILL);
  }
  
  gimp_selection_sharpen(image_id);
  if (fsValPtr->innerRadius > 0)
  {
    gimp_selection_shrink(image_id, fsValPtr->innerRadius);
  }
  shrinkedSelection = gimp_selection_save(image_id);
  
  
  /* use WHITE color to mark foreground regions
   */
  color.r = 1.0;
  color.g = 1.0;
  color.b = 1.0;
  color.a = 1.0;
  gimp_context_set_background (&color);
  gimp_edit_fill(trimap, GIMP_BACKGROUND_FILL);
  
  gimp_selection_load(activeSelection);
  gimp_selection_sharpen(image_id);
  if (fsValPtr->outerRadius > 0)
  {
    gimp_selection_grow(image_id, fsValPtr->outerRadius);
  }
  gimp_selection_combine(shrinkedSelection, GIMP_CHANNEL_OP_SUBTRACT);

  /* use medium GRAY to mark undefined regions
   */
  color.r = 0.5;
  color.g = 0.5;
  color.b = 0.5;
  color.a = 1.0;
  gimp_context_set_background (&color);
  gimp_edit_fill(trimap, GIMP_BACKGROUND_FILL);

  gimp_selection_none(image_id);

  /* perform the foreground selection (that creates the resulting layer) */
  {
    GapFgExtractValues fgExtractValues;
    GapFgExtractValues *fgValPtr;
    
    fgValPtr = &fgExtractValues;
    fgValPtr->input_drawable_id = drawable_id;
    fgValPtr->tri_map_drawable_id = trimap;
    fgValPtr->create_result = TRUE;
    fgValPtr->create_layermask = fsValPtr->create_layermask;
    fgValPtr->lock_color = fsValPtr->lock_color;
    fgValPtr->colordiff_threshold = fsValPtr->colordiff_threshold;

    rc = gap_fg_matting_exec_apply_run (image_id, drawable_id
                                 , doProgress, doFlush
                                 , fgValPtr
                                 );
  }
  
  
  /* restore original selection */
  if (hadSelection == TRUE)
  {
    gimp_selection_load(activeSelection);
  }

  gimp_image_undo_group_end(image_id);
  gimp_context_pop();
  
  return (rc);

}  /* end gap_fg_from_selection_exec_apply_run */
Пример #9
0
/* -------------------------------------------------------
 * gap_image_set_selection_from_selection_or_drawable
 * -------------------------------------------------------
 * create a selection in the specified image_id.
 * The selection is a scaled copy of the selection in another image,
 * referred by ref_drawable_id, or a Grayscale copy of the specified ref_drawable_id
 * (in case the referred image has no selection or the flag force_from_drawable is TRUE)
 *
 *  - operates on a duplicate of the image referred by ref_drawable_id.
 *  - this duplicate is scaled to same size as specified image_id
 *
 * return TRUE in case the selection was successfully created .
 */
gboolean
gap_image_set_selection_from_selection_or_drawable(gint32 image_id, gint32 ref_drawable_id
  , gboolean force_from_drawable)
{
  gint32        l_aux_channel_id;
  gint32        ref_image_id;
  gint32        work_drawable_id;   /* the duplicate of the layer that is used as selction mask */
  gint32        dup_image_id;
  gboolean has_selection;
  gboolean non_empty;
  gint     x1, y1, x2, y2;

  if ((image_id < 0) || (ref_drawable_id < 0))
  {
    return (FALSE);
  }
  ref_image_id = gimp_item_get_image(ref_drawable_id);

  if (ref_image_id < 0)
  {
    printf("ref_drawable_id does not refer to a valid image layer_id:%d\n", (int)ref_drawable_id);
    return (FALSE);
  }



  dup_image_id = gimp_image_duplicate(ref_image_id);
  if (dup_image_id < 0)
  {
    printf("duplicating of image failed, referred souce image_id:%d\n", (int)ref_image_id);
    return (FALSE);
  }
  /* clear undo stack */
  if (gimp_image_undo_is_enabled(dup_image_id))
  {
    gimp_image_undo_disable(dup_image_id);
  }

  if ((gimp_image_width(image_id) != gimp_image_width(dup_image_id))
  ||  (gimp_image_height(image_id) != gimp_image_height(dup_image_id)))
  {
     if(gap_debug)
     {
       printf("scaling tmp image_id: %d\n", (int)dup_image_id);
     }
     gimp_image_scale(dup_image_id, gimp_image_width(image_id), gimp_image_height(image_id));
  }

  has_selection  = gimp_selection_bounds(ref_image_id, &non_empty, &x1, &y1, &x2, &y2);
  if ((has_selection) && (non_empty) && (force_from_drawable != TRUE))
  {
    /* use scaled copy of the already exisating selection in the referred image */
    work_drawable_id = gimp_image_get_selection(dup_image_id);
  }
  else
  {
    gint32        active_layer_stackposition;

    /* create selection as gray copy of the alt_selection layer */

    active_layer_stackposition = gap_layer_get_stackposition(ref_image_id, ref_drawable_id);

    if(gimp_image_base_type(dup_image_id) != GIMP_GRAY)
    {
       if(gap_debug)
       {
         printf("convert to GRAYSCALE tmp image_id: %d\n", (int)dup_image_id);
       }
       gimp_image_convert_grayscale(dup_image_id);
    }
    work_drawable_id = gap_layer_get_id_by_stackposition(dup_image_id, active_layer_stackposition);
    gimp_layer_resize_to_image_size (work_drawable_id);
  }

  gimp_selection_all(image_id);
  //l_sel_channel_id = gimp_image_get_selection(image_id);
  l_aux_channel_id = gimp_selection_save(image_id);

  /* copy the work drawable (layer or channel) into the selection channel
   * the work layer is a grayscale copy GRAY or GRAYA of the alt_selection layer
   *  that is already scaled and resized to fit the size of the target image
   * the work channel is the scaled selection of the image refred by ref_drawable_id
   *
   * copying is done into an auxiliary channel from where we regulary load the selection.
   * this is done because subseqent queries of the selection boudaries will deliver
   * full channel size rectangle after a direct copy into the selection.
   */
  gap_layer_copy_picked_channel (l_aux_channel_id  /* dst_drawable_id*/
                              , 0                  /* dst_channel_pick */
                              , work_drawable_id   /* src_drawable_id */
                              , 0                  /* src_channel_pick */
                              , FALSE              /* gboolean shadow */
                              );

  gimp_image_select_item(image_id, GIMP_CHANNEL_OP_REPLACE, l_aux_channel_id);
  gimp_image_remove_channel(image_id, l_aux_channel_id);

  gap_image_delete_immediate(dup_image_id);
  return (TRUE);

}  /* end gap_image_set_selection_from_selection_or_drawable */