コード例 #1
0
/* ---------------------------------------
 * gap_drawable_foreground_extract_matting
 * ---------------------------------------
 *
 */
static void
gap_drawable_foreground_extract_matting (GimpDrawable       *maskDrawable,
                                         GimpDrawable       *resultDrawable,
                                         GappMattingState   *state,
                                         gfloat              start_percentage
                                         )
{
  GappTileManager *tmMask;
  GappTileManager *tmResult;
  gint x1, y1;
  gint x2, y2;
  gpointer progress_data;
  gdouble  progressDataUnused;

  if(gap_debug)
  {
    printf("extract_matting: START\n");
  }

  g_return_if_fail (state != NULL);

  progress_data = &progressDataUnused;

  x1 = 0;
  y1 = 0;
  x2 = maskDrawable->width;
  y2 = maskDrawable->height;

  tmMask = gapp_tile_manager_new(maskDrawable);
  tmResult = gapp_tile_manager_new(resultDrawable);

  matting_foreground_extract (state,
                              tmMask, x1, y1, x2, y2,
                              start_percentage,
                              (MattingProgressFunc) p_progressFunc,
                              progress_data,
                              tmResult);


  gimp_drawable_update (resultDrawable->drawable_id, x1, y1, x2, y2);
  gimp_drawable_update (maskDrawable->drawable_id, x1, y1, x2, y2);

  if(gap_debug)
  {
    printf("extract_matting: END\n");
  }

}  /* end gap_drawable_foreground_extract_matting */
コード例 #2
0
ファイル: pixelize.c プロジェクト: Amerekanets/gimp
/*
   This function operates on PixelArea, whose width and height are
   multiply of pixel width, and less than the tile size (to enhance
   its speed).

   If any coordinates of mask boundary is not multiply of pixel width
   (e.g.  x1 % pixelwidth != 0), operates on the region whose width
   or height is the remainder.
 */
static void
pixelize_small (GimpDrawable *drawable,
                gint          pixelwidth,
                gint          pixelheight,
                gint          tile_width,
                gint          tile_height)
{
  GimpPixelRgn src_rgn, dest_rgn;
  gint         bpp, has_alpha;
  gint         x1, y1, x2, y2;
  gint         progress, max_progress;

  gimp_drawable_mask_bounds (drawable->drawable_id, &x1, &y1, &x2, &y2);
  gimp_pixel_rgn_init (&src_rgn, drawable, x1, y1, x2-x1, y2-y1, FALSE, FALSE);
  gimp_pixel_rgn_init (&dest_rgn, drawable, x1, y1, x2-x1, y2-y1, TRUE, TRUE);

  /* Initialize progress */
  progress = 0;
  max_progress = (x2 - x1) * (y2 - y1);

  bpp = drawable->bpp;
  has_alpha = gimp_drawable_has_alpha (drawable->drawable_id);

  area.width  = (tile_width  / pixelwidth)  * pixelwidth;
  area.height = (tile_height / pixelheight) * pixelheight;
  area.data= g_new (guchar, (glong) bpp * area.width * area.height);

  for (area.y = y1; area.y < y2;
       area.y += area.height - (area.y % area.height))
    {
      area.h = area.height - (area.y % area.height);
      area.h = MIN (area.h, y2 - area.y);

      for (area.x = x1; area.x < x2;
           area.x += area.width - (area.x % area.width))
        {
          area.w = area.width - (area.x % area.width);
          area.w = MIN(area.w, x2 - area.x);

          gimp_pixel_rgn_get_rect (&src_rgn, area.data,
                                   area.x, area.y, area.w, area.h);

          pixelize_sub (pixelwidth, pixelheight, bpp, has_alpha);

          gimp_pixel_rgn_set_rect (&dest_rgn, area.data,
                                   area.x, area.y, area.w, area.h);

          /* Update progress */
          progress += area.w * area.h;
          gimp_progress_update ((double) progress / (double) max_progress);
      }
    }

  g_free(area.data);

  /*  update the pixelized region  */
  gimp_drawable_flush (drawable);
  gimp_drawable_merge_shadow (drawable->drawable_id, TRUE);
  gimp_drawable_update (drawable->drawable_id, x1, y1, (x2 - x1), (y2 - y1));
}
コード例 #3
0
ファイル: sepiaFilter.c プロジェクト: irstavr/Hipstagram
static void octave (GimpDrawable *drawable)
{
	GimpPixelRgn srcPR, destPR;
	gint         x1, y1, x2, y2;
	gint         x, y, width, height;

	/* initialize pixel regions */
	gimp_pixel_rgn_init (&srcPR, drawable,
				0, 0, drawable->width, drawable->height, FALSE, FALSE);
	gimp_pixel_rgn_init (&destPR, drawable,
				0, 0, drawable->width, drawable->height, TRUE, TRUE);

	/* Get the input */
	gimp_drawable_mask_bounds (drawable->drawable_id, &x1, &y1, &x2, &y2);

	x=x1;
	y=y1;
	width=x2-x1;
	height=y2-y1;

	/* Run */
	octave_region (&srcPR, &destPR, drawable->bpp, x, y, width, height);

	gimp_drawable_flush (drawable);
	gimp_drawable_merge_shadow (drawable->drawable_id, TRUE);
	gimp_drawable_update (drawable->drawable_id, x1, y1, x2 - x1, y2 - y1);
}
コード例 #4
0
ファイル: gimplayermask.c プロジェクト: Amerekanets/gimp
void
gimp_layer_mask_set_apply (GimpLayerMask *layer_mask,
                           gboolean       apply,
                           gboolean       push_undo)
{
  g_return_if_fail (GIMP_IS_LAYER_MASK (layer_mask));

  if (layer_mask->apply_mask != apply)
    {
      GimpImage *image = GIMP_ITEM (layer_mask)->image;

      if (push_undo)
        gimp_image_undo_push_layer_mask_apply (image, _("Apply Layer Mask"),
                                               layer_mask);

      layer_mask->apply_mask = apply ? TRUE : FALSE;

      if (layer_mask->layer)
        {
          GimpDrawable *drawable = GIMP_DRAWABLE (layer_mask->layer);

          gimp_drawable_update (drawable,
                                0, 0,
                                gimp_item_width  (GIMP_ITEM (drawable)),
                                gimp_item_height (GIMP_ITEM (drawable)));
        }

      g_signal_emit (layer_mask, layer_mask_signals[APPLY_CHANGED], 0);
    }
}
コード例 #5
0
ファイル: gimplayermask.c プロジェクト: Amerekanets/gimp
void
gimp_layer_mask_set_show (GimpLayerMask *layer_mask,
                          gboolean       show,
                          gboolean       push_undo)
{
  g_return_if_fail (GIMP_IS_LAYER_MASK (layer_mask));

  if (layer_mask->show_mask != show)
    {
      GimpImage *image = GIMP_ITEM (layer_mask)->image;

      if (push_undo)
        gimp_image_undo_push_layer_mask_show (image, _("Show Layer Mask"),
                                              layer_mask);

      layer_mask->show_mask = show ? TRUE : FALSE;

      if (layer_mask->layer)
        {
          GimpDrawable *drawable = GIMP_DRAWABLE (layer_mask->layer);

          gimp_drawable_update (drawable,
                                0, 0,
                                gimp_item_width  (GIMP_ITEM (drawable)),
                                gimp_item_height (GIMP_ITEM (drawable)));
        }

      g_signal_emit (layer_mask, layer_mask_signals[SHOW_CHANGED], 0);
    }
}
コード例 #6
0
ファイル: gimptextlayer.c プロジェクト: vidyashree/gimp-tito
static void
gimp_text_layer_render_layout (GimpTextLayer  *layer,
                               GimpTextLayout *layout)
{
  GimpDrawable    *drawable = GIMP_DRAWABLE (layer);
  GimpItem        *item     = GIMP_ITEM (layer);
  GeglBuffer      *buffer;
  cairo_t         *cr;
  cairo_surface_t *surface;
  gint             width;
  gint             height;

  g_return_if_fail (gimp_drawable_has_alpha (drawable));

  width  = gimp_item_get_width  (item);
  height = gimp_item_get_height (item);

  surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);

  cr = cairo_create (surface);
  gimp_text_layout_render (layout, cr, layer->text->base_dir, FALSE);
  cairo_destroy (cr);

  cairo_surface_flush (surface);

  buffer = gimp_cairo_surface_create_buffer (surface);

  gegl_buffer_copy (buffer, NULL,
                    gimp_drawable_get_buffer (drawable), NULL);

  g_object_unref (buffer);
  cairo_surface_destroy (surface);

  gimp_drawable_update (drawable, 0, 0, width, height);
}
コード例 #7
0
ファイル: waves.c プロジェクト: WilfR/Gimp-Matting
static void
waves (GimpDrawable *drawable)
{
  GimpPixelRgn  srcPr, dstPr;
  guchar       *src, *dst;
  guint         width, height, bpp, has_alpha;

  width     = drawable->width;
  height    = drawable->height;
  bpp       = drawable->bpp;
  has_alpha = gimp_drawable_has_alpha (drawable->drawable_id);

  src = g_new (guchar, width * height * bpp);
  dst = g_new (guchar, width * height * bpp);
  gimp_pixel_rgn_init (&srcPr, drawable, 0, 0, width, height, FALSE, FALSE);
  gimp_pixel_rgn_init (&dstPr, drawable, 0, 0, width, height, TRUE, TRUE);
  gimp_pixel_rgn_get_rect (&srcPr, src, 0, 0, width, height);

  wave (src, dst, width, height, bpp, has_alpha,
        width / 2.0, height / 2.0,
        wvals.amplitude, wvals.wavelength, wvals.phase,
        wvals.type == MODE_SMEAR, wvals.reflective, TRUE);
  gimp_pixel_rgn_set_rect (&dstPr, dst, 0, 0, width, height);

  g_free (src);
  g_free (dst);

  gimp_drawable_flush (drawable);
  gimp_drawable_merge_shadow (drawable->drawable_id, TRUE);
  gimp_drawable_update (drawable->drawable_id, 0, 0, width, height);

  gimp_displays_flush ();
}
コード例 #8
0
void
gimp_channel_combine_buffer (GimpChannel    *mask,
                             GeglBuffer     *add_on_buffer,
                             GimpChannelOps  op,
                             gint            off_x,
                             gint            off_y)
{
  GeglBuffer *buffer;
  gint        x, y, w, h;

  g_return_if_fail (GIMP_IS_CHANNEL (mask));
  g_return_if_fail (GEGL_IS_BUFFER (add_on_buffer));

  buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (mask));

  if (! gimp_gegl_mask_combine_buffer (buffer, add_on_buffer,
                                       op, off_x, off_y))
    return;

  gimp_rectangle_intersect (off_x, off_y,
                            gegl_buffer_get_width  (add_on_buffer),
                            gegl_buffer_get_height (add_on_buffer),
                            0, 0,
                            gimp_item_get_width  (GIMP_ITEM (mask)),
                            gimp_item_get_height (GIMP_ITEM (mask)),
                            &x, &y, &w, &h);

  mask->bounds_known = FALSE;

  gimp_drawable_update (GIMP_DRAWABLE (mask), x, y, w, h);
}
コード例 #9
0
ファイル: van-gogh-lic.c プロジェクト: AdamGrzonkowski/gimp-1
static void
compute_image (GimpDrawable *drawable)
{
  GimpDrawable *effect;
  guchar       *scalarfield = NULL;

  /* Get some useful info on the input drawable */
  /* ========================================== */
  if (! gimp_drawable_mask_intersect (drawable->drawable_id,
                                      &border_x, &border_y, &border_w, &border_h))
    return;

  gimp_progress_init (_("Van Gogh (LIC)"));

  if (licvals.effect_convolve == 0)
    generatevectors ();

  if (licvals.filtlen < 0.1)
    licvals.filtlen = 0.1;

  l = licvals.filtlen;
  dx = dy = licvals.noisemag;
  minv = licvals.minv / 10.0;
  maxv = licvals.maxv / 10.0;
  isteps = licvals.intsteps;

  source_drw_has_alpha = gimp_drawable_has_alpha (drawable->drawable_id);

  effect = gimp_drawable_get (licvals.effect_image_id);

  effect_width = effect->width;
  effect_height = effect->height;

  switch (licvals.effect_channel)
    {
      case 0:
        scalarfield = rgb_to_hsl (effect, LIC_HUE);
        break;
      case 1:
        scalarfield = rgb_to_hsl (effect, LIC_SATURATION);
        break;
      case 2:
        scalarfield = rgb_to_hsl (effect, LIC_BRIGHTNESS);
        break;
    }

  compute_lic (drawable, scalarfield, licvals.effect_operator);

  g_free (scalarfield);

  /* Update image */
  /* ============ */

  gimp_drawable_flush (drawable);
  gimp_drawable_merge_shadow (drawable->drawable_id, TRUE);
  gimp_drawable_update (drawable->drawable_id, border_x, border_y,
                        border_w, border_h);

  gimp_displays_flush ();
}
コード例 #10
0
ファイル: source_code.c プロジェクト: latree/color2gray
//-------------------------------------------------------------------------
static void
c2g_mask (GimpDrawable *drawable,
              gdouble       radius,
              gdouble       amount,
              gdouble       gamma)
{

  GimpPixelRgn srcPR, destPR;
  gint         x1, y1, x2, y2;

  /* initialize pixel regions */
  gimp_pixel_rgn_init (&srcPR, drawable,
                       0, 0, drawable->width, drawable->height, FALSE, FALSE);
  gimp_pixel_rgn_init (&destPR, drawable,
                       0, 0, drawable->width, drawable->height, TRUE, TRUE);

  /* Get the input */
  gimp_drawable_mask_bounds (drawable->drawable_id, &x1, &y1, &x2, &y2);

  c2g_region (&srcPR, &destPR, drawable->bpp,
                  radius, amount, gamma,
                  x1, x2, y1, y2,
                  TRUE);

  gimp_drawable_flush (drawable);
  gimp_drawable_merge_shadow (drawable->drawable_id, TRUE);
  gimp_drawable_update (drawable->drawable_id, x1, y1, x2 - x1, y2 - y1);
}
コード例 #11
0
ファイル: gimp-edit.c プロジェクト: LebedevRI/gimp
void
gimp_edit_fill (GimpImage       *image,
                GimpDrawable    *drawable,
                GimpFillOptions *options,
                const gchar     *undo_desc)
{
  GeglBuffer  *buffer;
  gint         x, y, width, height;

  g_return_if_fail (GIMP_IS_IMAGE (image));
  g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
  g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)));
  g_return_if_fail (GIMP_IS_FILL_OPTIONS (options));

  if (! gimp_item_mask_intersect (GIMP_ITEM (drawable), &x, &y, &width, &height))
    return;  /*  nothing to do, but the fill succeeded  */

  buffer = gimp_fill_options_create_buffer (options, drawable,
                                            GEGL_RECTANGLE (0, 0,
                                                            width, height));

  if (! undo_desc)
    undo_desc = gimp_fill_options_get_undo_desc (options);

  gimp_drawable_apply_buffer (drawable, buffer,
                              GEGL_RECTANGLE (0, 0, width, height),
                              TRUE, undo_desc,
                              gimp_context_get_opacity (GIMP_CONTEXT (options)),
                              gimp_context_get_paint_mode (GIMP_CONTEXT (options)),
                              NULL, x, y);

  g_object_unref (buffer);

  gimp_drawable_update (drawable, x, y, width, height);
}
コード例 #12
0
ファイル: sinus.c プロジェクト: Minoos/gimp
static void
sinus (void)
{
  params  p;
  gint    bytes;
  GimpPixelRgn dest_rgn;
  gint     x1, y1, x2, y2;
  gpointer pr;
  gint progress, max_progress;

  prepare_coef(&p);

  gimp_drawable_mask_bounds(drawable->drawable_id, &x1, &y1, &x2, &y2);

  p.width = drawable->width;
  p.height = drawable->height;
  bytes = drawable->bpp;

  gimp_pixel_rgn_init (&dest_rgn, drawable,
                       x1, y1, x2 - x1, y2 - y1, TRUE,TRUE);
  progress = 0;
  max_progress = (x2 - x1) * (y2 - y1);

  for (pr = gimp_pixel_rgns_register (1, &dest_rgn);
       pr != NULL;
       pr = gimp_pixel_rgns_process (pr))
    {
      switch (bytes)
        {
        case 4:
          compute_block_x (dest_rgn.data, dest_rgn.rowstride,
                           dest_rgn.x, dest_rgn.y, dest_rgn.w, dest_rgn.h,
                           4, assign_block_4, &p);
          break;
        case 3:
          compute_block_x (dest_rgn.data, dest_rgn.rowstride,
                           dest_rgn.x, dest_rgn.y, dest_rgn.w, dest_rgn.h,
                           3, assign_block_3, &p);
          break;
        case 2:
          compute_block_x (dest_rgn.data, dest_rgn.rowstride,
                           dest_rgn.x, dest_rgn.y, dest_rgn.w, dest_rgn.h,
                           2, assign_block_2, &p);
          break;
        case 1:
          compute_block_x (dest_rgn.data, dest_rgn.rowstride,
                           dest_rgn.x, dest_rgn.y, dest_rgn.w, dest_rgn.h,
                           1, assign_block_1, &p);
          break;
        }
      progress += dest_rgn.w * dest_rgn.h;
      gimp_progress_update ((double) progress / (double) max_progress);
    }

  gimp_drawable_flush (drawable);
  gimp_drawable_merge_shadow (drawable->drawable_id, TRUE);
  gimp_drawable_update (drawable->drawable_id, x1, y1, x2 - x1, y2 - y1);
}
コード例 #13
0
ファイル: gimpchannel-combine.c プロジェクト: 1ynx/gimp
void
gimp_channel_combine_mask (GimpChannel    *mask,
                           GimpChannel    *add_on,
                           GimpChannelOps  op,
                           gint            off_x,
                           gint            off_y)
{
  PixelRegion srcPR, destPR;
  gint        x, y, w, h;

  g_return_if_fail (GIMP_IS_CHANNEL (mask));
  g_return_if_fail (GIMP_IS_CHANNEL (add_on));

  if (! gimp_rectangle_intersect (off_x, off_y,
                                  gimp_item_get_width  (GIMP_ITEM (add_on)),
                                  gimp_item_get_height (GIMP_ITEM (add_on)),
                                  0, 0,
                                  gimp_item_get_width  (GIMP_ITEM (mask)),
                                  gimp_item_get_height (GIMP_ITEM (mask)),
                                  &x, &y, &w, &h))
    return;

  pixel_region_init (&srcPR, gimp_drawable_get_tiles (GIMP_DRAWABLE (add_on)),
                     x - off_x, y - off_y, w, h, FALSE);
  pixel_region_init (&destPR, gimp_drawable_get_tiles (GIMP_DRAWABLE (mask)),
                     x, y, w, h, TRUE);

  switch (op)
    {
    case GIMP_CHANNEL_OP_ADD:
    case GIMP_CHANNEL_OP_REPLACE:
      pixel_regions_process_parallel ((PixelProcessorFunc)
                                      gimp_channel_combine_sub_region_add,
                                      NULL, 2, &srcPR, &destPR);
      break;

    case GIMP_CHANNEL_OP_SUBTRACT:
      pixel_regions_process_parallel ((PixelProcessorFunc)
                                      gimp_channel_combine_sub_region_sub,
                                      NULL, 2, &srcPR, &destPR);
      break;

    case GIMP_CHANNEL_OP_INTERSECT:
      pixel_regions_process_parallel ((PixelProcessorFunc)
                                      gimp_channel_combine_sub_region_intersect,
                                      NULL, 2, &srcPR, &destPR);
      break;

    default:
      g_warning ("%s: unknown operation type", G_STRFUNC);
      break;
    }

  mask->bounds_known = FALSE;

  gimp_drawable_update (GIMP_DRAWABLE (mask), x, y, w, h);
}
コード例 #14
0
void
floating_sel_to_layer (GimpLayer *layer)
{
  GimpItem  *item;
  GimpImage *image;

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

  item = GIMP_ITEM (layer);

  if (! (image = gimp_item_get_image (item)))
    return;

  /*  Check if the floating layer belongs to a channel...  */
  if (GIMP_IS_CHANNEL (layer->fs.drawable))
    {
      gimp_message (image->gimp, NULL, GIMP_MESSAGE_WARNING,
                    _("Cannot create a new layer from the floating selection "
                      "because it belongs to a layer mask or channel."));
      return;
    }

  gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_FS_TO_LAYER,
                               _("Floating Selection to Layer"));

  /*  restore the contents of the drawable  */
  floating_sel_restore (layer,
                        item->offset_x,
                        item->offset_y,
                        item->width,
                        item->height);

  gimp_image_undo_push_fs_to_layer (image, NULL, layer);

  /*  clear the selection  */
  gimp_drawable_invalidate_boundary (GIMP_DRAWABLE (layer));

  /*  Set pointers  */
  layer->fs.drawable   = NULL;
  image->floating_sel = NULL;

  gimp_item_set_visible (GIMP_ITEM (layer), TRUE, TRUE);
  gimp_layer_set_lock_alpha (layer, FALSE, TRUE);

  gimp_image_undo_group_end (image);

  gimp_object_name_changed (GIMP_OBJECT (layer));

  gimp_drawable_update (GIMP_DRAWABLE (layer),
                        0, 0,
                        GIMP_ITEM (layer)->width,
                        GIMP_ITEM (layer)->height);

  gimp_image_floating_selection_changed (image);
}
コード例 #15
0
ファイル: mapmake.c プロジェクト: bogado/mapa_gimp_plugin
gint32 execute_plugin(GimpDrawable* d, const char *nome, param_type *p)
{
//	gint i;
	guchar *img, *org;
	gint x,y,x2,y2,w,h;
//	guchar *work;
	GimpPixelRgn region, rgn_org;
	gint bpp = d->bpp;

	gimp_drawable_mask_bounds(d->drawable_id, &x, &y, &x2, &y2);
	w = x2 - x;
	h = y2 - y;

	img = malloc(w * h * bpp);
	org = malloc(w * h * bpp);
//	work = malloc(d.width * d.height * bpp);

	gimp_pixel_rgn_init(&region, d, x, y, w, h, TRUE, TRUE);
	//este é buffer para gravar a imagem modificada.
	gimp_pixel_rgn_init(&rgn_org, d, x, y, w, h, FALSE, FALSE);
	// Esta é a imagem em si 

	gimp_pixel_rgn_get_rect(&region, img, x, y, w, h);
	gimp_pixel_rgn_get_rect(&rgn_org, org, x, y, w, h);

	switch (*nome) {
		case 'S':
			super_grow(p, org, img, w, h, bpp);
			break;
		case 'G':
			memcpy(img, org, w * h * bpp);
			grow(p, org, img, w, h, bpp);
			break;
		case 'A':
			find_iso(p, org, img, w, h, bpp);
			break;
		default:
			make_height_field(p, org, img, w, h, bpp);
			break;
			
	}

	gimp_pixel_rgn_set_rect(&region, img, x, y, w, h);

	/* finish the process */
	gimp_drawable_flush (d);
	gimp_drawable_merge_shadow (d->drawable_id, TRUE);
	gimp_drawable_update (d->drawable_id, x, y, w, h);
	gimp_displays_flush();
	gimp_drawable_detach(d);

	free(img);
	free(org);

	return GIMP_PDB_SUCCESS;	
}
コード例 #16
0
void
gimp_channel_combine_rect (GimpChannel    *mask,
                           GimpChannelOps  op,
                           gint            x,
                           gint            y,
                           gint            w,
                           gint            h)
{
  GeglBuffer *buffer;

  g_return_if_fail (GIMP_IS_CHANNEL (mask));

  buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (mask));

  if (! gimp_gegl_mask_combine_rect (buffer, op, x, y, w, h))
    return;

  gimp_rectangle_intersect (x, y, w, h,
                            0, 0,
                            gimp_item_get_width  (GIMP_ITEM (mask)),
                            gimp_item_get_height (GIMP_ITEM (mask)),
                            &x, &y, &w, &h);

  /*  Determine new boundary  */
  if (mask->bounds_known && (op == GIMP_CHANNEL_OP_ADD) && ! mask->empty)
    {
      if (x < mask->x1)
        mask->x1 = x;
      if (y < mask->y1)
        mask->y1 = y;
      if ((x + w) > mask->x2)
        mask->x2 = (x + w);
      if ((y + h) > mask->y2)
        mask->y2 = (y + h);
    }
  else if (op == GIMP_CHANNEL_OP_REPLACE || mask->empty)
    {
      mask->empty = FALSE;
      mask->x1    = x;
      mask->y1    = y;
      mask->x2    = x + w;
      mask->y2    = y + h;
    }
  else
    {
      mask->bounds_known = FALSE;
    }

  mask->x1 = CLAMP (mask->x1, 0, gimp_item_get_width  (GIMP_ITEM (mask)));
  mask->y1 = CLAMP (mask->y1, 0, gimp_item_get_height (GIMP_ITEM (mask)));
  mask->x2 = CLAMP (mask->x2, 0, gimp_item_get_width  (GIMP_ITEM (mask)));
  mask->y2 = CLAMP (mask->y2, 0, gimp_item_get_height (GIMP_ITEM (mask)));

  gimp_drawable_update (GIMP_DRAWABLE (mask), x, y, w, h);
}
コード例 #17
0
ファイル: gap_edge_detection.c プロジェクト: nhorman/gimp-gap
 /* ----------------------------------------
  * p_subtract_ref_layer
  * ----------------------------------------
  * setup pixel regions and perform edge detection by subtracting RGB channels 
  * of the orignal (refDrawable) from the blurred copy (edgeDrawable)
  * and convert the rgb differences to lightness.
  *
  * as result of this processing in the edgeDrawable contains a desaturated
  * colordifference of the original versus blured copy.
  */
 static void
 p_subtract_ref_layer(gint32 image_id, GimpDrawable *edgeDrawable, GimpDrawable *refDrawable
   , gdouble threshold, gint32 shift, gboolean invert)
 {
   GimpPixelRgn edgePR;
   GimpPixelRgn refPR;
   GimpPixelRgn ref2PR;
   gpointer  pr;
   gdouble   threshold01f;
   gdouble   threshold255f;
   gint      threshold255;
   gint      cx;
   gint      cy;
   
   threshold01f = CLAMP((threshold / 100.0), 0, 1);
   threshold255f = 255.0 * threshold01f;
   threshold255 = threshold255f;

   p_get_debug_coords_from_guides(image_id, &cx, &cy);
   
   gimp_pixel_rgn_init (&edgePR, edgeDrawable, 0, 0
                       , edgeDrawable->width - shift, edgeDrawable->height - shift
                       , TRUE     /* dirty */
                       , FALSE    /* shadow */
                        );

   /* start at shifted offset 0/+1 */ 
   gimp_pixel_rgn_init (&refPR, refDrawable, 0, shift
                       , refDrawable->width - shift, refDrawable->height - shift
                       , FALSE     /* dirty */
                       , FALSE     /* shadow */
                        );
   /* start at shifted offset +1/0 */ 
   gimp_pixel_rgn_init (&ref2PR, refDrawable, shift, 0
                       , refDrawable->width - shift, refDrawable->height - shift
                       , FALSE     /* dirty */
                       , FALSE     /* shadow */
                        );
 
   /* compare pixel areas in tiled portions via pixel region processing loops.
    */
   for (pr = gimp_pixel_rgns_register (3, &edgePR, &refPR, &ref2PR);
        pr != NULL;
        pr = gimp_pixel_rgns_process (pr))
   {
     p_colordiffProcessingForOneRegion (&edgePR, &refPR, &ref2PR, threshold01f, invert, cx, cy);
   }
 
   gimp_drawable_flush (edgeDrawable);
   gimp_drawable_update (edgeDrawable->drawable_id
                          , 0, 0
                          , edgeDrawable->width, edgeDrawable->height
                          );
 
 }  /* end  p_subtract_ref_layer */
コード例 #18
0
ファイル: dog.c プロジェクト: Amerekanets/gimp
static void
preview_update_preview (GimpPreview  *preview,
                        GimpDrawable *drawable)
{
  gint          x1, y1;
  gint          width, height;
  gint          bpp;
  guchar       *buffer;
  GimpPixelRgn  src_rgn;
  GimpPixelRgn  preview_rgn;
  gint32        image_id, src_image_id;
  gint32        preview_id;
  GimpDrawable *preview_drawable;

  bpp = gimp_drawable_bpp (drawable->drawable_id);

  gimp_preview_get_position (preview, &x1, &y1);
  gimp_preview_get_size (preview, &width, &height);

  buffer = g_new (guchar, width * height * bpp);

  gimp_pixel_rgn_init (&src_rgn, drawable,
                       x1, y1, width, height, FALSE, FALSE);
  gimp_pixel_rgn_get_rect (&src_rgn, buffer,
                           x1, y1, width, height);

  /* set up gimp drawable for rendering preview into */
  src_image_id = gimp_drawable_get_image (drawable->drawable_id);
  image_id = gimp_image_new (width, height,
                             gimp_image_base_type (src_image_id));
  preview_id = gimp_layer_new (image_id, "preview", width, height,
                               gimp_drawable_type (drawable->drawable_id),
                               100,
                               GIMP_NORMAL_MODE);
  preview_drawable = gimp_drawable_get (preview_id);
  gimp_image_add_layer (image_id, preview_id, 0);
  gimp_layer_set_offsets (preview_id, 0, 0);
  gimp_pixel_rgn_init (&preview_rgn, preview_drawable,
                       0, 0, width, height, TRUE, TRUE);
  gimp_pixel_rgn_set_rect (&preview_rgn, buffer,
                           0, 0, width, height);
  gimp_drawable_flush (preview_drawable);
  gimp_drawable_merge_shadow (preview_id, TRUE);
  gimp_drawable_update (preview_id, 0, 0, width, height);

  dog (image_id, preview_drawable, dogvals.inner, dogvals.outer, FALSE);

  gimp_pixel_rgn_get_rect (&preview_rgn, buffer,
                           0, 0, width, height);

  gimp_preview_draw_buffer (preview, buffer, width * bpp);

  gimp_image_delete (image_id);
  g_free (buffer);
}
コード例 #19
0
/* 
Update Gimp image from local pixmap. Canonical postlude for plugins.
!!! Called in the postlude but also for debugging: animate results during processing.
*/
static void 
post_results_to_gimp(
  GimpDrawable *drawable,
  Map targetMap) 
{
  pixmap_to_drawable(targetMap, drawable, FIRST_PIXELEL_INDEX);   // our pixels to region
  gimp_drawable_flush(drawable);    // regions back to core
  gimp_drawable_merge_shadow(drawable->drawable_id,TRUE);   // temp buffers merged
  gimp_drawable_update(drawable->drawable_id,0,0,targetMap.width,targetMap.height);
  gimp_displays_flush();
}
コード例 #20
0
ファイル: main.c プロジェクト: GNOME/gimp-pspi
static GimpPDBStatusType
run_pspi (const gchar  	  *pdb_name,
	  gint       	   n_params, 
	  const GimpParam *param)
{
  GimpRunMode run_mode = param[0].data.d_int32;
  GimpDrawable *drawable;
  GimpPDBStatusType status = GIMP_PDB_SUCCESS;
  PSPlugInEntry *pspie;
  gint x1, y1, x2, y2;

  get_saved_plugin_data ();

  if ((pspie = g_hash_table_lookup (entry_hash, pdb_name)) != NULL)
    {
      gchar *name;

      if (run_mode == GIMP_RUN_NONINTERACTIVE)
	{
	  if (n_params != standard_nargs)
	    return GIMP_PDB_CALLING_ERROR;
	}
      else if (run_mode == GIMP_RUN_INTERACTIVE)
	{
	  if ((status = pspi_params (pspie)) != GIMP_PDB_SUCCESS)
	    return status;
	}
      drawable = gimp_drawable_get (param[2].data.d_drawable);

      gimp_ui_init (PLUGIN_NAME, TRUE);

      if ((status = pspi_prepare (pspie, drawable)) != GIMP_PDB_SUCCESS)
	return status;

      name = g_strdup_printf (_("Applying %s:"),
			      strrchr (pspie->menu_path, '/') + 1);
      gimp_progress_init (name);
      g_free (name);

      if ((status = pspi_apply (pspie, drawable)) != GIMP_PDB_SUCCESS)
	return status;

      gimp_drawable_flush (drawable);
      gimp_drawable_merge_shadow (drawable->drawable_id, TRUE);
      gimp_drawable_mask_bounds (drawable->drawable_id, &x1, &y1, &x2, &y2);
      gimp_drawable_update (drawable->drawable_id, x1, y1, (x2 - x1), (y2 - y1));
      gimp_displays_flush ();

      return GIMP_PDB_SUCCESS;
    }

  return GIMP_PDB_CALLING_ERROR;
}
コード例 #21
0
ファイル: mblur.c プロジェクト: Amerekanets/gimp
static void
mblur (GimpDrawable *drawable,
       GimpPreview  *preview)
{
  gint x, y;
  gint width, height;

  if (preview)
    {
      gimp_preview_get_position (preview, &x, &y);
      gimp_preview_get_size (preview, &width, &height);
    }
  else
    {
      gimp_drawable_mask_bounds (drawable->drawable_id,
                                 &x, &y, &width, &height);
      width  -= x;
      height -= y;
    }

  if (width < 1 || height < 1)
    return;

  if (! preview)
    gimp_progress_init (_("Motion blurring"));

  switch (mbvals.mblur_type)
    {
    case MBLUR_LINEAR:
      mblur_linear (drawable, preview, x, y, width, height);
      break;

    case MBLUR_RADIAL:
      mblur_radial (drawable, preview, x, y, width, height);
      break;

    case MBLUR_ZOOM:
      mblur_zoom (drawable, preview, x, y, width, height);
      break;

    default:
      break;
    }

  if (! preview)
    {
      gimp_drawable_flush (drawable);
      gimp_drawable_merge_shadow (drawable->drawable_id, TRUE);
      gimp_drawable_update (drawable->drawable_id, x, y, width, height);
    }
}
コード例 #22
0
gboolean
floating_sel_to_layer (GimpLayer  *layer,
                       GError    **error)
{
  GimpItem  *item;
  GimpImage *image;

  g_return_val_if_fail (GIMP_IS_LAYER (layer), FALSE);
  g_return_val_if_fail (gimp_layer_is_floating_sel (layer), FALSE);
  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);

  item  = GIMP_ITEM (layer);
  image = gimp_item_get_image (item);

  /*  Check if the floating layer belongs to a channel  */
  if (GIMP_IS_CHANNEL (gimp_layer_get_floating_sel_drawable (layer)))
    {
      g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED,
			   _("Cannot create a new layer from the floating "
			     "selection because it belongs to a layer mask "
			     "or channel."));
      return FALSE;
    }

  gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_FS_TO_LAYER,
                               C_("undo-type", "Floating Selection to Layer"));

  gimp_image_undo_push_fs_to_layer (image, NULL, layer);

  gimp_drawable_detach_floating_sel (gimp_layer_get_floating_sel_drawable (layer));
  gimp_layer_set_floating_sel_drawable (layer, NULL);

  gimp_item_set_visible (item, TRUE, TRUE);
  gimp_layer_set_lock_alpha (layer, FALSE, TRUE);

  gimp_image_undo_group_end (image);

  /* When the floating selection is converted to/from a normal layer
   * it does something resembling a name change, so emit the
   * "name-changed" signal
   */
  gimp_object_name_changed (GIMP_OBJECT (layer));

  gimp_drawable_update (GIMP_DRAWABLE (layer),
                        0, 0,
                        gimp_item_get_width  (item),
                        gimp_item_get_height (item));

  return TRUE;
}
コード例 #23
0
ファイル: color-rotate.c プロジェクト: DevMaggio/gimp
static void
color_rotate (GimpDrawable *drawable)
{
  GimpPixelRgn srcPR, destPR;
  gint         width, height;
  gint         bytes;
  guchar      *src_row, *dest_row;
  gint         row;
  gint         x, y;

  if (! gimp_drawable_mask_intersect (drawable->drawable_id,
                                      &x, &y, &width, &height))
    {
      return;
    }

  bytes = drawable->bpp;

  src_row  = g_new (guchar, width * bytes);
  dest_row = g_new (guchar, width * bytes);

  gimp_pixel_rgn_init (&srcPR, drawable, 0, 0,
                       drawable->width,
                       drawable->height, FALSE, FALSE);
  gimp_pixel_rgn_init (&destPR, drawable, 0, 0,
                       drawable->width,
                       drawable->height, TRUE, TRUE);

  for (row = y; row < (y + height); row++)
    {
      gimp_pixel_rgn_get_row (&srcPR, src_row, x, row, width);

      color_rotate_row (src_row, dest_row, row, width, bytes);

      gimp_pixel_rgn_set_row (&destPR, dest_row, x, row, width);

      if ((row % 10) == 0)
        gimp_progress_update ((double) row / (double) height);
    }

  /*  update the processed region  */

  gimp_progress_update (1.0);
  gimp_drawable_flush (drawable);
  gimp_drawable_merge_shadow (drawable->drawable_id, TRUE);
  gimp_drawable_update (drawable->drawable_id, x, y, width, height);

  g_free (src_row);
  g_free (dest_row);
}
コード例 #24
0
void
gimp_drawable_bucket_fill (GimpDrawable         *drawable,
                           GimpFillOptions      *options,
                           gboolean              fill_transparent,
                           GimpSelectCriterion   fill_criterion,
                           gdouble               threshold,
                           gboolean              sample_merged,
                           gboolean              diagonal_neighbors,
                           gdouble               seed_x,
                           gdouble               seed_y)
{
  GimpImage  *image;
  GeglBuffer *buffer;
  gdouble     mask_x;
  gdouble     mask_y;
  gint        width, height;

  g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
  g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)));
  g_return_if_fail (GIMP_IS_FILL_OPTIONS (options));

  image = gimp_item_get_image (GIMP_ITEM (drawable));
  gimp_set_busy (image->gimp);
  buffer = gimp_drawable_get_bucket_fill_buffer (drawable, options,
                                                 fill_transparent, fill_criterion,
                                                 threshold, sample_merged,
                                                 diagonal_neighbors,
                                                 seed_x, seed_y, NULL,
                                                 &mask_x, &mask_y, &width, &height);

  if (buffer)
    {
      /*  Apply it to the image  */
      gimp_drawable_apply_buffer (drawable, buffer,
                                  GEGL_RECTANGLE (0, 0, width, height),
                                  TRUE, C_("undo-type", "Bucket Fill"),
                                  gimp_context_get_opacity (GIMP_CONTEXT (options)),
                                  gimp_context_get_paint_mode (GIMP_CONTEXT (options)),
                                  GIMP_LAYER_COLOR_SPACE_AUTO,
                                  GIMP_LAYER_COLOR_SPACE_AUTO,
                                  gimp_layer_mode_get_paint_composite_mode (
                                                                            gimp_context_get_paint_mode (GIMP_CONTEXT (options))),
                                  NULL, (gint) mask_x, mask_y);
      g_object_unref (buffer);

      gimp_drawable_update (drawable, mask_x, mask_y, width, height);
    }
  gimp_unset_busy (image->gimp);
}
コード例 #25
0
// !!! Note GIMP abbreviates Rgn instead of region, and gimp_ prefix to functions
// Compare to plug-ins/pygimp/pygimp-tile.c
static gboolean
process (GeglOperation        *operation,
         GeglBuffer           *data,
         const GeglRectangle  *result)
{
  GeglChantO *o = GEGL_CHANT_PROPERTIES (operation);

  g_printf("Process sink\n");
  if (! o->drawableID)
    return FALSE;
  else
  {
    GimpDrawable            *drawable;
    const Babl              *format;
    GimpPixelRgn             io_pixel_region;
    gpointer                 pr;
    
    g_printf("result width %d\n", result->width);
    
    drawable = gimp_drawable_get(o->drawableID);
    // format = gegl_operation_get_format (operation, "output");
    format = babl_format ("RGBA u8");
    // TODO test format of operation with format of drawable

    gimp_pixel_rgn_init (&io_pixel_region, drawable,
                     result->x,     result->y,
                     result->width, result->height,
                     TRUE, TRUE);

    for (pr = gimp_pixel_rgns_register (1, &io_pixel_region);
         pr;
         pr = gimp_pixel_rgns_process (pr))
      {
        GeglRectangle rect = { io_pixel_region.x, io_pixel_region.y, io_pixel_region.w, io_pixel_region.h };

        gegl_buffer_get (data, GIMP_SINK_SCALE, &rect, format, io_pixel_region.data, io_pixel_region.rowstride);
      }

    /* 
    Drawable is set of tiles private to this sink.
    Not the same as the caller's, nor the same as the source node's.
    */
    gimp_drawable_flush(drawable);
    gimp_drawable_merge_shadow(o->drawableID, FALSE);
    gimp_drawable_update(o->drawableID, result->x,     result->y,
                     result->width, result->height);
    return TRUE;
  }
}
コード例 #26
0
void
focusblur_fft_buffer_draw (FblurFftBuffer *fft)
{
  GimpDrawablePreview *preview;
  gboolean             dirty;
  guint8              *data;
  GimpPixelRgn         pr;

  if (! fft->source.preview)
    {
      preview = NULL;
      dirty = TRUE;
      data = fft->source.data;
    }
  else
    {
      preview = GIMP_DRAWABLE_PREVIEW (fft->source.preview);
      g_assert (preview != NULL);

      dirty = FALSE;
      data = fft->source.data_preview;
    }

  g_assert (data != NULL);

  gimp_pixel_rgn_init (&pr, fft->source.drawable,
                       fft->source.x1, fft->source.y1,
                       fft->source.width, fft->source.height, dirty, TRUE);
  gimp_pixel_rgn_set_rect (&pr, data,
                           fft->source.x1, fft->source.y1,
                           fft->source.width, fft->source.height);

  if (! preview)
    {
      gimp_drawable_flush (fft->source.drawable);
      gimp_drawable_merge_shadow (fft->source.drawable->drawable_id, TRUE);
      gimp_drawable_update (fft->source.drawable->drawable_id,
                            fft->source.x1, fft->source.y1,
                            fft->source.width, fft->source.height);

      /* this buffer has been dirty */
      focusblur_fft_buffer_clear_source (fft);
    }
  else
    {
      gimp_drawable_preview_draw_region (preview, &pr);

    }
}
コード例 #27
0
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);
}
コード例 #28
0
ファイル: gimpregioniterator.c プロジェクト: Amerekanets/gimp
void
gimp_rgn_iterate2 (GimpDrawable *drawable,
                   GimpRunMode   unused,
                   GimpRgnFunc2  func,
                   gpointer      data)
{
  GimpPixelRgn  srcPR, destPR;
  gint          x1, y1, x2, y2;
  gpointer      pr;
  gint          total_area;
  gint          area_so_far;
  gint          progress_skip;

  g_return_if_fail (drawable != NULL);

  gimp_drawable_mask_bounds (drawable->drawable_id, &x1, &y1, &x2, &y2);

  total_area = (x2 - x1) * (y2 - y1);

  if (total_area <= 0)
    return;

  area_so_far   = 0;
  progress_skip = 0;

  /* Initialize the pixel regions. */
  gimp_pixel_rgn_init (&srcPR, drawable, x1, y1, (x2 - x1), (y2 - y1),
                       FALSE, FALSE);
  gimp_pixel_rgn_init (&destPR, drawable, x1, y1, (x2 - x1), (y2 - y1),
                       TRUE, TRUE);

  for (pr = gimp_pixel_rgns_register (2, &srcPR, &destPR);
       pr != NULL;
       pr = gimp_pixel_rgns_process (pr))
    {
      gimp_rgn_render_region (&srcPR, &destPR, func, data);

      area_so_far += srcPR.w * srcPR.h;

      if (((progress_skip++) % 10) == 0)
        gimp_progress_update ((gdouble) area_so_far / (gdouble) total_area);
    }

  /*  update the processed region  */
  gimp_drawable_flush (drawable);
  gimp_drawable_merge_shadow (drawable->drawable_id, TRUE);
  gimp_drawable_update (drawable->drawable_id, x1, y1, (x2 - x1), (y2 - y1));
}
コード例 #29
0
static void
gimp_floating_sel_undo_pop (GimpUndo            *undo,
                            GimpUndoMode         undo_mode,
                            GimpUndoAccumulator *accum)
{
  GimpFloatingSelUndo *floating_sel_undo = GIMP_FLOATING_SEL_UNDO (undo);
  GimpLayer           *floating_layer    = GIMP_LAYER (GIMP_ITEM_UNDO (undo)->item);

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

  switch (undo->undo_type)
    {
    case GIMP_UNDO_FS_TO_LAYER:
      if (undo_mode == GIMP_UNDO_MODE_UNDO)
        {
          /*  Update the preview for the floating sel  */
          gimp_viewable_invalidate_preview (GIMP_VIEWABLE (floating_layer));

          gimp_layer_set_floating_sel_drawable (floating_layer,
                                                floating_sel_undo->drawable);
          gimp_image_set_active_layer (undo->image, floating_layer);

          gimp_drawable_attach_floating_sel (gimp_layer_get_floating_sel_drawable (floating_layer),
                                             floating_layer);
        }
      else
        {
          gimp_drawable_detach_floating_sel (gimp_layer_get_floating_sel_drawable (floating_layer));
          gimp_layer_set_floating_sel_drawable (floating_layer, NULL);
        }

      /* When the floating selection is converted to/from a normal
       * layer it does something resembling a name change, so emit the
       * "name-changed" signal
       */
      gimp_object_name_changed (GIMP_OBJECT (floating_layer));

      gimp_drawable_update (GIMP_DRAWABLE (floating_layer),
                            0, 0,
                            gimp_item_get_width  (GIMP_ITEM (floating_layer)),
                            gimp_item_get_height (GIMP_ITEM (floating_layer)));
      break;

    default:
      g_assert_not_reached ();
    }
}
コード例 #30
0
ファイル: red-eye-removal.c プロジェクト: Amerekanets/gimp-1
/*
 * Red Eye Removal Alorithm, based on using a threshold to detect
 * red pixels. Having a user-made selection around the eyes will
 * prevent incorrect pixels from being selected.
 */
static void
remove_redeye (GimpDrawable *drawable)
{
  GimpPixelRgn  src_rgn;
  GimpPixelRgn  dest_rgn;
  gint          progress, max_progress;
  gboolean      has_alpha;
  gint          x, y;
  gint          width, height;
  gint          i;
  gpointer      pr;

  if (! gimp_drawable_mask_intersect (drawable->drawable_id,
                                      &x, &y, &width, &height))
    return;

  gimp_progress_init (_("Removing red eye"));

  has_alpha = gimp_drawable_has_alpha (drawable->drawable_id);

  progress = 0;
  max_progress = width * height;

  gimp_pixel_rgn_init (&src_rgn, drawable,
                       x, y, width, height, FALSE, FALSE);
  gimp_pixel_rgn_init (&dest_rgn, drawable,
                       x, y, width, height, TRUE, TRUE);

  for (pr = gimp_pixel_rgns_register (2, &src_rgn, &dest_rgn), i = 0;
       pr != NULL;
       pr = gimp_pixel_rgns_process (pr), i++)
    {
      redeye_inner_loop (src_rgn.data, dest_rgn.data, src_rgn.w, src_rgn.h,
                         src_rgn.bpp, has_alpha, src_rgn.rowstride);

      progress += src_rgn.w * src_rgn.h;

      if (i % 16 == 0)
        gimp_progress_update ((gdouble) progress / (gdouble) max_progress);
    }

  gimp_progress_update (1.0);
  gimp_drawable_flush (drawable);
  gimp_drawable_merge_shadow (drawable->drawable_id, TRUE);
  gimp_drawable_update (drawable->drawable_id, x, y, width, height);
}