Ejemplo n.º 1
0
static int
pf_set_edge_mode(PyGimpPixelFetcher *self, PyObject *value, void *closure)
{
    if (value == NULL) {
        PyErr_SetString(PyExc_TypeError, "cannot delete edge_mode");
        return -1;
    }

    if (!PyInt_Check(value)) {
        PyErr_SetString(PyExc_TypeError, "type mismatch");
        return -1;
    }

    self->edge_mode = PyInt_AsLong(value);

    gimp_pixel_fetcher_set_edge_mode(self->pf, self->edge_mode);

    return 0;
}
Ejemplo n.º 2
0
static void
lens_distort_preview (GimpDrawable *drawable,
                      GimpPreview  *preview)
{
  guchar               *dest;
  guchar               *pixel;
  gint                  width, height, bpp;
  gint                  x, y;
  GimpPixelFetcher     *pft;
  GimpRGB               background;

  pft = gimp_pixel_fetcher_new (drawable, FALSE);

  gimp_context_get_background (&background);
  gimp_rgb_set_alpha (&background, 0.0);
  gimp_pixel_fetcher_set_bg_color (pft, &background);
  gimp_pixel_fetcher_set_edge_mode (pft, GIMP_PIXEL_FETCHER_EDGE_BACKGROUND);

  lens_setup_calc (drawable->width, drawable->height);

  dest = gimp_zoom_preview_get_source (GIMP_ZOOM_PREVIEW (preview),
                                       &width, &height, &bpp);
  pixel = dest;

  for (y = 0; y < height; y++)
    {
      for (x = 0; x < width; x++)
        {
          gint sx, sy;

          gimp_preview_untransform (preview, x, y, &sx, &sy);

          lens_distort_func (sx, sy, pixel, bpp, pft);

          pixel += bpp;
        }
    }

  gimp_pixel_fetcher_destroy (pft);

  gimp_preview_draw_buffer (preview, dest, width * bpp);
  g_free (dest);
}
Ejemplo n.º 3
0
static void
polarize (GimpDrawable *drawable)
{
  GimpRgnIterator  *iter;
  GimpPixelFetcher *pft;
  GimpRGB           background;

  pft = gimp_pixel_fetcher_new (drawable, FALSE);

  gimp_context_get_background (&background);
  gimp_rgb_set_alpha (&background, 0.0);
  gimp_pixel_fetcher_set_bg_color (pft, &background);
  gimp_pixel_fetcher_set_edge_mode (pft, GIMP_PIXEL_FETCHER_EDGE_SMEAR);

  gimp_progress_init (_("Polar coordinates"));

  iter = gimp_rgn_iterator_new (drawable, 0);
  gimp_rgn_iterator_dest (iter, polarize_func, pft);
  gimp_rgn_iterator_free (iter);

  gimp_pixel_fetcher_destroy (pft);
}
Ejemplo n.º 4
0
static int
pf_init(PyGimpPixelFetcher *self, PyObject *args, PyObject *kwargs)
{
    PyGimpDrawable *drw;
    gboolean shadow = FALSE;
    GimpRGB bg_color = { 0.0, 0.0, 0.0, 1.0 };
    GimpPixelFetcherEdgeMode edge_mode = GIMP_PIXEL_FETCHER_EDGE_NONE;
    static char *kwlist[] = { "drawable", "shadow", "bg_color", "edge_mode",
	                      NULL };

    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
                                     "O!|iO&i:gimp.PixelFetcher.__init__",
                                     kwlist,
                                     &PyGimpDrawable_Type, &drw, &shadow,
                                     pygimp_rgb_from_pyobject, &bg_color,
                                     &edge_mode))
        return -1;

    if(!drw->drawable)
        drw->drawable = gimp_drawable_get(drw->ID);

    self->pf = gimp_pixel_fetcher_new(drw->drawable, shadow);

    Py_INCREF(drw);
    self->drawable = drw;

    self->shadow = shadow;
    self->bg_color = bg_color;
    self->edge_mode = edge_mode;

    self->bpp = gimp_drawable_bpp(drw->drawable->drawable_id);

    gimp_pixel_fetcher_set_bg_color(self->pf, &bg_color);
    gimp_pixel_fetcher_set_edge_mode(self->pf, edge_mode);

    return 0;
}
Ejemplo n.º 5
0
static void
lens_distort (GimpDrawable *drawable)
{
  GimpRgnIterator  *iter;
  GimpPixelFetcher *pft;
  GimpRGB           background;

  lens_setup_calc (drawable->width, drawable->height);

  pft = gimp_pixel_fetcher_new (drawable, FALSE);

  gimp_context_get_background (&background);
  gimp_rgb_set_alpha (&background, 0.0);
  gimp_pixel_fetcher_set_bg_color (pft, &background);
  gimp_pixel_fetcher_set_edge_mode (pft, GIMP_PIXEL_FETCHER_EDGE_BACKGROUND);

  gimp_progress_init (_("Lens distortion"));

  iter = gimp_rgn_iterator_new (drawable, 0);
  gimp_rgn_iterator_dest (iter, (GimpRgnFuncDest) lens_distort_func, pft);
  gimp_rgn_iterator_free (iter);

  gimp_pixel_fetcher_destroy (pft);
}
Ejemplo n.º 6
0
static void
dialog_update_preview (GimpDrawable *drawable,
                       GimpPreview  *preview)
{
  gdouble               cx, cy;
  gint                  x, y;
  gint                  sx, sy;
  gint                  width, height;
  guchar               *pixel;
  guchar                outside[4];
  GimpRGB               background;
  guchar               *dest;
  gint                  j;
  gint                  bpp;
  GimpPixelFetcher     *pft;
  guchar                in_pixels[4][4];
  guchar               *in_values[4];

  for (j = 0; j < 4; j++)
    in_values[j] = in_pixels[j];

  pft = gimp_pixel_fetcher_new (drawable, FALSE);

  gimp_context_get_background (&background);
  gimp_rgb_set_alpha (&background, 0.0);
  gimp_drawable_get_color_uchar (drawable->drawable_id, &background, outside);
  gimp_pixel_fetcher_set_bg_color (pft, &background);
  gimp_pixel_fetcher_set_edge_mode (pft, GIMP_PIXEL_FETCHER_EDGE_SMEAR);

  dest = gimp_zoom_preview_get_source (GIMP_ZOOM_PREVIEW (preview),
                                       &width, &height, &bpp);
  pixel = dest;

  for (y = 0; y < height; y++)
    {
      for (x = 0; x < width; x++)
        {
          gimp_preview_untransform (preview, x, y, &sx, &sy);
          if (calc_undistorted_coords ((gdouble)sx, (gdouble)sy,
                                       &cx, &cy))
            {

              gimp_pixel_fetcher_get_pixel (pft, cx, cy, in_pixels[0]);
              gimp_pixel_fetcher_get_pixel (pft, cx + 1, cy, in_pixels[1]);
              gimp_pixel_fetcher_get_pixel (pft, cx, cy + 1, in_pixels[2]);
              gimp_pixel_fetcher_get_pixel (pft, cx + 1, cy + 1, in_pixels[3]);

              gimp_bilinear_pixels_8 (pixel, cx, cy, bpp,
                                      img_has_alpha, in_values);
            }
          else
            {
              for (j = 0; j < bpp; j++)
                pixel[j] = outside[j];
            }

          pixel += bpp;
        }
    }

  gimp_pixel_fetcher_destroy (pft);

  gimp_preview_draw_buffer (preview, dest, width * bpp);
  g_free (dest);
}
Ejemplo n.º 7
0
/* ----------------------------------------
 * gap_edgeDetection
 * ----------------------------------------
 *
 * returns the drawable id of a newly created channel
 * representing edges of the specified image.
 *
 * black pixels indicate areas of same or similar colors,
 * white indicates sharp edges.
 *
 */
gint32 gap_edgeDetection(gint32  refDrawableId
  , gdouble edgeColordiffThreshold
  , gint32 *countEdgePixels
  )
{
  GapEdgeContext  edgeContext;
  GapEdgeContext *ectx;
  gdouble         edgeOpacityThreshold;

  /* init context */  
  ectx = &edgeContext;
  ectx->refDrawable = gimp_drawable_get(refDrawableId);
  ectx->edgeDrawable = NULL;
  ectx->edgeColordiffThreshold = CLAMP(edgeColordiffThreshold, 0.0, 1.0);
  edgeOpacityThreshold = CLAMP((edgeColordiffThreshold * 255), 0, 255);
  ectx->edgeOpacityThreshold255 = edgeOpacityThreshold;
  ectx->edgeDrawableId = -1;
  ectx->countEdgePixels = 0;

  if(gap_debug)
  {
    printf("gap_edgeDetection START edgeColordiffThreshold:%.5f refDrawableId:%d\n"
       , (float)ectx->edgeColordiffThreshold
       , (int)refDrawableId
       );
  }
 
  if(ectx->refDrawable != NULL)
  {
    ectx->pftRef = gimp_pixel_fetcher_new (ectx->refDrawable, FALSE /* shadow */);
    gimp_pixel_fetcher_set_edge_mode (ectx->pftRef, GIMP_PIXEL_FETCHER_EDGE_BLACK);

    p_edgeDetection(ectx);

    gimp_pixel_fetcher_destroy (ectx->pftRef);
  }

  if(ectx->refDrawable != NULL)
  {
    gimp_drawable_detach(ectx->refDrawable);
    ectx->refDrawable = NULL;
  }
  if(ectx->edgeDrawable != NULL)
  {
    gimp_drawable_detach(ectx->edgeDrawable);
    ectx->edgeDrawable = NULL;
  }

  *countEdgePixels = ectx->countEdgePixels;

  if(gap_debug)
  {
    printf("gap_edgeDetection END resulting edgeDrawableId:%d countEdgePixels:%d\n"
       , (int)ectx->edgeDrawableId
       , (int)*countEdgePixels
       );
  }
  
  return (ectx->edgeDrawableId);
  
}  /* end gap_edgeDetection */
Ejemplo n.º 8
0
static void
edge (GimpDrawable *drawable)
{
  GimpPixelRgn      src_rgn, dest_rgn;
  gpointer          pr;
  GimpPixelFetcher *pft;
  guchar           *srcrow, *src;
  guchar           *destrow, *dest;
  guchar            pix00[4], pix01[4], pix02[4];
  guchar            pix10[4], pix11[4], pix12[4];
  guchar            pix20[4], pix21[4], pix22[4];
  glong             width, height;
  gint              alpha;
  gboolean          has_alpha;
  gint              chan;
  gint              x, y;
  gint              x1, y1, x2, y2;
  gint              maxval;
  gint              cur_progress;
  gint              max_progress;
  gdouble           per_progress;

  if (evals.amount < 1.0)
    evals.amount = 1.0;

  pft = gimp_pixel_fetcher_new (drawable, FALSE);
  gimp_pixel_fetcher_set_edge_mode (pft, evals.wrapmode);

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

  width     = gimp_drawable_width (drawable->drawable_id);
  height    = gimp_drawable_height (drawable->drawable_id);
  alpha     = gimp_drawable_bpp (drawable->drawable_id);
  has_alpha = gimp_drawable_has_alpha (drawable->drawable_id);
  if (has_alpha)
    alpha--;

  maxval = 255;

  cur_progress = 0;
  per_progress = 0.0;
  max_progress = (x2 - x1) * (y2 - y1) / 100;

  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);

  for (pr = gimp_pixel_rgns_register (2, &src_rgn, &dest_rgn);
       pr != NULL;
       pr = gimp_pixel_rgns_process (pr))
    {
      srcrow  = src_rgn.data;
      destrow = dest_rgn.data;

      for (y = dest_rgn.y;
           y < (dest_rgn.y + dest_rgn.h);
           y++, srcrow += src_rgn.rowstride, destrow += dest_rgn.rowstride)
        {
          src  = srcrow;
          dest = destrow;

          for (x = dest_rgn.x;
               x < (dest_rgn.x + dest_rgn.w);
               x++,  src += src_rgn.bpp, dest += dest_rgn.bpp)
            {
              if (dest_rgn.x < x &&  x < dest_rgn.x + dest_rgn.w - 2 &&
                  dest_rgn.y < y &&  y < dest_rgn.y + dest_rgn.h - 2)
                {
                  /*
                   * 3x3 kernel is inside of the tile -- do fast
                   * version
                   */
                  for (chan = 0; chan < alpha; chan++)
                    {
                      /* get the 3x3 kernel into a guchar array,
                       * and send it to edge_detect */
                      guchar kernel[9];
                      gint   i,j;

#define PIX(X,Y)  src[ (Y-1)*(int)src_rgn.rowstride + (X-1)*(int)src_rgn.bpp + chan ]
                      /* make convolution */
                      for(i = 0; i < 3; i++)
                        for(j = 0; j < 3; j++)
                          kernel[3*i + j] = PIX(i,j);

#undef  PIX

                      dest[chan] = edge_detect (kernel);
                    }
                }
              else
                {
                  /*
                   * The kernel is not inside of the tile -- do slow
                   * version
                   */

                  gimp_pixel_fetcher_get_pixel (pft, x-1, y-1, pix00);
                  gimp_pixel_fetcher_get_pixel (pft, x  , y-1, pix10);
                  gimp_pixel_fetcher_get_pixel (pft, x+1, y-1, pix20);
                  gimp_pixel_fetcher_get_pixel (pft, x-1, y  , pix01);
                  gimp_pixel_fetcher_get_pixel (pft, x  , y  , pix11);
                  gimp_pixel_fetcher_get_pixel (pft, x+1, y  , pix21);
                  gimp_pixel_fetcher_get_pixel (pft, x-1, y+1, pix02);
                  gimp_pixel_fetcher_get_pixel (pft, x  , y+1, pix12);
                  gimp_pixel_fetcher_get_pixel (pft, x+1, y+1, pix22);

                  for (chan = 0; chan < alpha; chan++)
                    {
                      guchar kernel[9];

                      kernel[0] = pix00[chan];
                      kernel[1] = pix01[chan];
                      kernel[2] = pix02[chan];
                      kernel[3] = pix10[chan];
                      kernel[4] = pix11[chan];
                      kernel[5] = pix12[chan];
                      kernel[6] = pix20[chan];
                      kernel[7] = pix21[chan];
                      kernel[8] = pix22[chan];

                      dest[chan] = edge_detect (kernel);
                    }
                }
              if (has_alpha)
                dest[alpha] = src[alpha];
            }
        }
      cur_progress += dest_rgn.w * dest_rgn.h;

      if (cur_progress > max_progress)
        {
          cur_progress = cur_progress - max_progress;
          per_progress = per_progress + 0.01;
          gimp_progress_update (per_progress);
        }
    }

  gimp_progress_update (1.0);

  gimp_pixel_fetcher_destroy (pft);

  gimp_drawable_flush (drawable);
  gimp_drawable_merge_shadow (drawable->drawable_id, TRUE);
  gimp_drawable_update (drawable->drawable_id, x1, y1, (x2 - x1), (y2 - y1));
}
Ejemplo n.º 9
0
static void
displace (GimpDrawable *drawable,
          GimpPreview  *preview)
{
  GimpDrawable     *map_x = NULL;
  GimpDrawable     *map_y = NULL;
  GimpPixelRgn      dest_rgn;
  GimpPixelRgn      map_x_rgn;
  GimpPixelRgn      map_y_rgn;
  gpointer          pr;
  GimpPixelFetcher *pft;

  gint              width;
  gint              height;
  gint              bytes;
  guchar           *destrow, *dest;
  guchar           *mxrow, *mx;
  guchar           *myrow, *my;
  guchar            pixel[4][4];
  gint              x1, y1, x2, y2;
  gint              x, y;
  gdouble           cx, cy;
  gint              progress, max_progress;

  gdouble           amnt;
  gdouble           needx, needy;
  gdouble           radius, d_alpha;
  gint              xi, yi;

  guchar            values[4];
  guchar            val;

  gint              k;

  gdouble           xm_val, ym_val;
  gint              xm_alpha = 0;
  gint              ym_alpha = 0;
  gint              xm_bytes = 1;
  gint              ym_bytes = 1;
  guchar           *buffer   = NULL;
  gdouble           pi;

  /* initialize */

  /* get rid of uninitialized warnings */
  cx = cy = needx = needy = radius = d_alpha = 0.0;

  pi = 4 * atan (1);

  mxrow = NULL;
  myrow = NULL;

  pft = gimp_pixel_fetcher_new (drawable, FALSE);
  gimp_pixel_fetcher_set_edge_mode (pft, dvals.displace_type);

  bytes  = drawable->bpp;

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

  if (dvals.mode == POLAR_MODE)
    {
      cx = x1 + width / 2.0;
      cy = y1 + height / 2.0;
    }

  if (preview)
    {
      gimp_preview_get_position (preview, &x1, &y1);
      gimp_preview_get_size (preview, &width, &height);
      x2 = x1 + width;
      y2 = y1 + height;
      buffer = g_new (guchar, width * height * bytes);
    }

  progress     = 0;
  max_progress = width * height;

  /*
   * The algorithm used here is simple - see
   * http://the-tech.mit.edu/KPT/Tips/KPT7/KPT7.html for a description.
   */

  /* Get the drawables  */
  if (dvals.displace_map_x != -1 && dvals.do_x)
    {
      map_x = gimp_drawable_get (dvals.displace_map_x);
      gimp_pixel_rgn_init (&map_x_rgn, map_x,
                           x1, y1, width, height, FALSE, FALSE);

      if (gimp_drawable_has_alpha (map_x->drawable_id))
        xm_alpha = 1;

      xm_bytes = gimp_drawable_bpp (map_x->drawable_id);
    }

  if (dvals.displace_map_y != -1 && dvals.do_y)
    {
      map_y = gimp_drawable_get (dvals.displace_map_y);
      gimp_pixel_rgn_init (&map_y_rgn, map_y,
                           x1, y1, width, height, FALSE, FALSE);

      if (gimp_drawable_has_alpha (map_y->drawable_id))
        ym_alpha = 1;

      ym_bytes = gimp_drawable_bpp (map_y->drawable_id);
    }

  gimp_pixel_rgn_init (&dest_rgn, drawable,
                       x1, y1, width, height,
                       preview == NULL, preview == NULL);

  /*  Register the pixel regions  */
  if (dvals.do_x && dvals.do_y)
    pr = gimp_pixel_rgns_register (3, &dest_rgn, &map_x_rgn, &map_y_rgn);
  else if (dvals.do_x)
    pr = gimp_pixel_rgns_register (2, &dest_rgn, &map_x_rgn);
  else if (dvals.do_y)
    pr = gimp_pixel_rgns_register (2, &dest_rgn, &map_y_rgn);
  else
    pr = NULL;

  for (pr = pr; pr != NULL; pr = gimp_pixel_rgns_process (pr))
    {
      destrow = dest_rgn.data;
      if (dvals.do_x)
        mxrow = map_x_rgn.data;
      if (dvals.do_y)
        myrow = map_y_rgn.data;

      for (y = dest_rgn.y; y < (dest_rgn.y + dest_rgn.h); y++)
        {
          if (preview)
            dest = buffer + ((y - y1) * width + (dest_rgn.x - x1)) * bytes;
          else
            dest = destrow;
          mx = mxrow;
          my = myrow;

          /*
           * We could move the displacement image address calculation
           * out of here, but when we can have different sized
           * displacement and destination images we'd have to move it
           * back anyway.
           */

          for (x = dest_rgn.x; x < (dest_rgn.x + dest_rgn.w); x++)
            {
              if (dvals.do_x)
                {
                  xm_val = displace_map_give_value(mx, xm_alpha, xm_bytes);
                  amnt = dvals.amount_x * (xm_val - 127.5) / 127.5;
                  /* CARTESIAN_MODE == 0 - performance important here */
                  if (! dvals.mode)
                    {
                      needx = x + amnt;
                    }
                  else
                    {
                      radius = sqrt (SQR (x - cx) + SQR (y - cy)) + amnt;
                    }
                  mx += xm_bytes;
                }
              else
                {
                  if (! dvals.mode)
                    needx = x;
                  else
                    radius = sqrt ((x - cx) * (x - cx) + (y - cy) * (y - cy));
                }


              if (dvals.do_y)
                {
                  ym_val = displace_map_give_value(my, ym_alpha, ym_bytes);
                  amnt = dvals.amount_y * (ym_val - 127.5) / 127.5;
                  if (! dvals.mode)
                    {
                      needy = y + amnt;
                    }
                  else
                    {
                      d_alpha = atan2 (x - cx, y - cy) + (dvals.amount_y / 180)
                                * pi * (ym_val - 127.5) / 127.5;
                    }
                  my += ym_bytes;
                }
              else
                {
                  if (! dvals.mode)
                    needy = y;
                  else
                    d_alpha = atan2 (x - cx, y - cy);
                }
              if (dvals.mode)
                {
                   needx = cx + radius * sin (d_alpha);
                   needy = cy + radius * cos (d_alpha);
                }
              /* Calculations complete; now copy the proper pixel */

              if (needx >= 0.0)
                xi = (int) needx;
              else
                xi = -((int) -needx + 1);

              if (needy >= 0.0)
                yi = (int) needy;
              else
                yi = -((int) -needy + 1);

              gimp_pixel_fetcher_get_pixel (pft, xi, yi, pixel[0]);
              gimp_pixel_fetcher_get_pixel (pft, xi + 1, yi, pixel[1]);
              gimp_pixel_fetcher_get_pixel (pft, xi, yi + 1, pixel[2]);
              gimp_pixel_fetcher_get_pixel (pft, xi + 1, yi + 1, pixel[3]);

              for (k = 0; k < bytes; k++)
                {
                  values[0] = pixel[0][k];
                  values[1] = pixel[1][k];
                  values[2] = pixel[2][k];
                  values[3] = pixel[3][k];
                  val = gimp_bilinear_8 (needx, needy, values);

                  *dest++ = val;
                } /* for */
            }

          destrow += dest_rgn.rowstride;

          if (dvals.do_x)
            mxrow += map_x_rgn.rowstride;
          if (dvals.do_y)
            myrow += map_y_rgn.rowstride;
        }

      if (!preview)
        {
          progress += dest_rgn.w * dest_rgn.h;
          gimp_progress_update ((double) progress / (double) max_progress);
        }
    } /* for */

  gimp_pixel_fetcher_destroy (pft);

  /*  detach from the map drawables  */
  if (dvals.do_x)
    gimp_drawable_detach (map_x);
  if (dvals.do_y)
    gimp_drawable_detach (map_y);

  if (preview)
    {
/*      gimp_drawable_preview_draw_region (GIMP_DRAWABLE_PREVIEW (preview),
                                         &dest_rgn);*/
      gimp_preview_draw_buffer (preview, buffer, width * bytes);
      g_free (buffer);
    }
  else
    {
      /*  update the region  */
      gimp_drawable_flush (drawable);
      gimp_drawable_merge_shadow (drawable->drawable_id, TRUE);
      gimp_drawable_update (drawable->drawable_id, x1, y1, width, height);
    }
}
Ejemplo n.º 10
0
static void
shift (GimpDrawable *drawable,
       GimpPreview  *preview)
{
  GimpPixelRgn      dest_rgn;
  gpointer          pr;
  GimpPixelFetcher *pft;
  gint              width, height;
  gint              bytes;
  guchar           *destline;
  guchar           *dest;
  gint              x1, y1, x2, y2;
  gint              x, y;
  gint              progress, max_progress;
  gint              i, n = 0;
  gint             *offsets;
  GRand            *gr;

  if (preview)
    {
      gimp_preview_get_position (preview, &x1, &y1);
      gimp_preview_get_size (preview, &width, &height);
    }
  else
    {
      gimp_drawable_mask_bounds (drawable->drawable_id, &x1, &y1, &x2, &y2);
      width  = x2 - x1;
      height = y2 - y1;
    }

  bytes  = drawable->bpp;

  progress     = 0;
  max_progress = width * height;

  /* Shift the image.  It's a pretty simple algorithm.  If horizontal
     is selected, then every row is shifted a random number of pixels
     in the range of -shift_amount/2 to shift_amount/2.  The effect is
     just reproduced with columns if vertical is selected.
   */

  n = (shvals.orientation == HORIZONTAL) ? height : width;

  offsets = g_new (gint, n);
  gr = g_rand_new ();

  for (i = 0; i < n; i++)
    offsets[i] = g_rand_int_range (gr,
                                   - (shvals.shift_amount + 1) / 2.0,
                                   + (shvals.shift_amount + 1) / 2.0);

  g_rand_free (gr);

  pft = gimp_pixel_fetcher_new (drawable, FALSE);
  gimp_pixel_fetcher_set_edge_mode (pft, GIMP_PIXEL_FETCHER_EDGE_WRAP);

  gimp_pixel_rgn_init (&dest_rgn, drawable,
                       x1, y1, width, height, (preview == NULL), TRUE);

  for (pr = gimp_pixel_rgns_register (1, &dest_rgn);
       pr != NULL;
       pr = gimp_pixel_rgns_process (pr))
    {
      destline = dest_rgn.data;

      switch (shvals.orientation)
        {
        case HORIZONTAL:
          for (y = dest_rgn.y; y < dest_rgn.y + dest_rgn.h; y++)
            {
              dest = destline;

              for (x = dest_rgn.x; x < dest_rgn.x + dest_rgn.w; x++)
                {
                  gimp_pixel_fetcher_get_pixel (pft,
                                                x + offsets[y - y1], y, dest);
                  dest += bytes;
                }

              destline += dest_rgn.rowstride;
            }
          break;

        case VERTICAL:
          for (x = dest_rgn.x; x < dest_rgn.x + dest_rgn.w; x++)
            {
              dest = destline;

              for (y = dest_rgn.y; y < dest_rgn.y + dest_rgn.h; y++)
                {
                  gimp_pixel_fetcher_get_pixel (pft,
                                                x, y + offsets[x - x1], dest);
                  dest += dest_rgn.rowstride;
                }

              destline += bytes;
            }
          break;
        }

      if (preview)
        {
          gimp_drawable_preview_draw_region (GIMP_DRAWABLE_PREVIEW (preview),
                                             &dest_rgn);
        }
      else
        {
          progress += dest_rgn.w * dest_rgn.h;
          gimp_progress_update ((double) progress / (double) max_progress);
        }
    }

  gimp_pixel_fetcher_destroy (pft);
  g_free (offsets);

  if (! preview)
    {
      gimp_progress_update (1.0);
      /*  update the region  */
      gimp_drawable_flush (drawable);
      gimp_drawable_merge_shadow (drawable->drawable_id, TRUE);
      gimp_drawable_update (drawable->drawable_id, x1, y1, width, height);
    }
}
Ejemplo n.º 11
0
/* --------------------------------
 * gap_moprhShapeDetectionEdgeBased
 * --------------------------------
 *
 * generates morph workpoints via edge based shape detection.
 * This is done by edge detection in the source image
 *  (specified via mgup->mgpp->osrc_layer_id)
 *
 * and picking workpoints on the detected edges
 * and locating the corresponding point in the destination image.
 *
 * IN: mgup->num_shapepoints  specifies the number of workpoints to be generated.
 */
void
gap_moprhShapeDetectionEdgeBased(GapMorphGUIParams *mgup, gboolean *cancelFlagPtr)
{
  GapMorphShapeContext  morphShapeContext;
  GapMorphShapeContext *msctx;
  gboolean deleteEdgeImage;
  GapMorphGlobalParams *mgpp;

  mgpp = mgup->mgpp;

  if(mgup->workpointGenerationBusy == TRUE)
  {
    return;
  }
  mgup->workpointGenerationBusy = TRUE;
  deleteEdgeImage = TRUE;
  
  /* init context */  
  msctx = &morphShapeContext;
  msctx->edgeColordiffThreshold = CLAMP(mgpp->edgeColordiffThreshold, 0.0, 1.0);
  msctx->locateColordiffThreshold = CLAMP(mgpp->locateColordiffThreshold, 0.0, 1.0);
  msctx->locateDetailShapeRadius = mgpp->locateDetailShapeRadius;
  msctx->locateDetailMoveRadius = mgpp->locateDetailMoveRadius;
  msctx->colorSensitivity = GAP_COLORDIFF_DEFAULT_SENSITIVITY;
  msctx->refLayerId = mgpp->osrc_layer_id;
  msctx->targetLayerId = mgpp->fdst_layer_id;
  msctx->numShapePoints = mgpp->numWorkpoints;
  msctx->countGeneratedPoints = 0;

  msctx->doProgress = TRUE;
  msctx->progressBar = mgup->progressBar;
  if(msctx->progressBar == NULL)
  {
    msctx->doProgress = FALSE;
  }
  msctx->cancelWorkpointGenerationPtr = cancelFlagPtr;

  if(gap_debug)
  {
    printf("gap_moprhShapeDetectionEdgeBased START edgeThres:%.5f  locateThres:%.5f locateRadius:%d\n"
       , (float)msctx->edgeColordiffThreshold
       , (float)msctx->locateDetailMoveRadius
       , (int)msctx->locateDetailMoveRadius
       );
  }


  msctx->edgeLayerId = gap_edgeDetection(mgup->mgpp->osrc_layer_id   /* refDrawableId */
                                 ,mgup->mgpp->edgeColordiffThreshold
                                 ,&msctx->countEdgePixels
                                 );

  msctx->edgeImageId = gimp_drawable_get_image(msctx->edgeLayerId);

  if(gap_debug)
  {
    /* show the edge image for debug purpose
     * (this image is intended for internal processing usage)
     */
    gimp_display_new(msctx->edgeImageId);
    deleteEdgeImage = FALSE;
  }
  msctx->edgeDrawable = gimp_drawable_get(msctx->edgeLayerId);

 
  if(msctx->edgeDrawable != NULL)
  {
    gint      maxWidth;
    gint      maxHeight;
    
    maxWidth = msctx->edgeDrawable->width-1;
    maxHeight = msctx->edgeDrawable->height-1;
    
    if((mgup->src_win.zoom < 1.0) && (mgup->src_win.zoom > 0.0))
    {
      gdouble   fwidth;
      gdouble   fheight;
      gint      width;
      gint      height;
      
      fwidth  = mgup->src_win.zoom * (gdouble)mgup->src_win.pv_ptr->pv_width;
      fheight = mgup->src_win.zoom * (gdouble)mgup->src_win.pv_ptr->pv_height;
      width  = CLAMP((gint)fwidth,  1, maxWidth);
      height = CLAMP((gint)fheight, 1, maxHeight);
      msctx->sel1X = CLAMP(mgup->src_win.offs_x, 0, maxWidth);
      msctx->sel1Y = CLAMP(mgup->src_win.offs_y, 0, maxHeight);
      msctx->sel2X = CLAMP((msctx->sel1X + width), 0, maxWidth);
      msctx->sel2Y = CLAMP((msctx->sel1Y + height), 0, maxHeight);
    }
    else
    {
      msctx->sel1X = 0;
      msctx->sel1Y = 0;
      msctx->sel2X = maxWidth;
      msctx->sel2Y = maxHeight;
    }
   

    if(gap_debug)
    {
      printf("Boundaries: sel1: %d / %d sel2: %d / %d  zoom:%.5f\n"
        , (int)msctx->sel1X
        , (int)msctx->sel1Y
        , (int)msctx->sel2X
        , (int)msctx->sel2Y
        , (float)mgup->src_win.zoom
        );
    }


    msctx->pftEdge = gimp_pixel_fetcher_new (msctx->edgeDrawable, FALSE /* shadow */);
    gimp_pixel_fetcher_set_edge_mode (msctx->pftEdge, GIMP_PIXEL_FETCHER_EDGE_BLACK);

    p_generateWorkpoints(msctx, mgpp);

    gimp_pixel_fetcher_destroy (msctx->pftEdge);
  }

  if(msctx->edgeDrawable != NULL)
  {
    gimp_drawable_detach(msctx->edgeDrawable);
    msctx->edgeDrawable = NULL;
  }
  
  if(deleteEdgeImage == TRUE)
  {
    gap_image_delete_immediate(msctx->edgeImageId);
  }

  if(gap_debug)
  {
    printf("gap_moprhShapeDetectionEdgeBased END\n");
  }
  mgup->workpointGenerationBusy = FALSE;
  
  return ;

}  /* end gap_moprhShapeDetectionEdgeBased */