예제 #1
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);
}
예제 #2
0
static gboolean
process (GeglOperation       *operation,
         GeglBuffer          *input,
         GeglBuffer          *output,
         const GeglRectangle *result,
         gint                 level)
{
  GeglChantO          *o = GEGL_CHANT_PROPERTIES (operation);
  LensDistortion       old_lens;
  GeglRectangle        boundary = *gegl_operation_source_get_bounding_box
    (operation, "input");

  gint     x, y;
  gfloat  *src_buf, *dst_buf;

  src_buf    = g_new0 (gfloat, result->width * result->height * 4);
  dst_buf    = g_new0 (gfloat, result->width * result->height * 4);

  lens_setup_calc (o, boundary, &old_lens);

  gegl_buffer_get (input, result, 1.0, babl_format ("RGBA float"), src_buf,
                   GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);

  for (y = result->y; y < result->y + result->height; y++)
    for (x = result->x; x < result->x + result->width; x++)
      {
        lens_distort_func (src_buf, dst_buf, result, result, &boundary,
                           old_lens, x, y, input);
      }


  gegl_buffer_set (output, result, 0, babl_format ("RGBA float"),
                   dst_buf, GEGL_AUTO_ROWSTRIDE);

  g_free (dst_buf);
  g_free (src_buf);

  return TRUE;
}
예제 #3
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);
}
예제 #4
0
static gboolean
process (GeglOperation       *operation,
         GeglBuffer          *input,
         GeglBuffer          *output,
         const GeglRectangle *result,
         gint                 level)
{
  GeglChantO    *o = GEGL_CHANT_PROPERTIES (operation);
  LensValues     lens;
  GeglRectangle  boundary;
  gint           i, j;
  gfloat        *src_buf, *dst_buf;
  gfloat         background[4];

  boundary = *gegl_operation_source_get_bounding_box (operation, "input");
  lens     =  lens_setup_calc (o, boundary);

  src_buf = g_new0 (gfloat, SQR (MAX_WH) * 4);
  dst_buf = g_new0 (gfloat, SQR (CHUNK_SIZE) * 4);

  gegl_color_get_pixel (o->background, babl_format ("RGBA float"), background);

  for (j = 0; (j-1) * CHUNK_SIZE < result->height; j++)
    for (i = 0; (i-1) * CHUNK_SIZE < result->width; i++)
      {
        GeglRectangle chunked_result;
        GeglRectangle area;
        gint          x, y;

        chunked_result = *GEGL_RECTANGLE (result->x + i * CHUNK_SIZE,
                                          result->y + j * CHUNK_SIZE,
                                          CHUNK_SIZE, CHUNK_SIZE);

        gegl_rectangle_intersect (&chunked_result, &chunked_result, result);

        if (chunked_result.width < 1  || chunked_result.height < 1)
          continue;

        area = get_required (&boundary, &chunked_result, operation);

        clamp_area (&area, lens.centre_x, lens.centre_y);

        gegl_buffer_get (input, &area, 1.0, babl_format ("RGBA float"), src_buf,
                         GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_CLAMP);

        for (y = chunked_result.y; y < chunked_result.y + chunked_result.height; y++)
          for (x = chunked_result.x; x < chunked_result.x + chunked_result.width; x++)
            {
              lens_distort_func (src_buf, dst_buf, &area, &chunked_result, &boundary,
                                 &lens, x, y, input, background);
            }

        gegl_buffer_set (output, &chunked_result, 0, babl_format ("RGBA float"),
                         dst_buf, GEGL_AUTO_ROWSTRIDE);
      }

  g_free (dst_buf);
  g_free (src_buf);

  return TRUE;
}
예제 #5
0
/* FIXME: not 100% bullet proof */
static GeglRectangle
get_required (GeglRectangle       *boundary,
              const GeglRectangle *roi,
              GeglOperation       *operation)
{

  GeglChantO    *o;
  GeglRectangle  area;
  LensValues     lens;
  gdouble        x1, y1, x2, y2, x3, y3, x4, y4, mag;
  gint           x, y, width, height;

  o = GEGL_CHANT_PROPERTIES (operation);

  lens = lens_setup_calc (o, *boundary);

  x = roi->x;
  y = roi->y;
  width = roi->width;
  height = roi->height;

  lens_get_source_coord (x,         y,          &x1, &y1, &mag, &lens);
  lens_get_source_coord (x + width, y,          &x2, &y2, &mag, &lens);
  lens_get_source_coord (x,         y + height, &x3, &y3, &mag, &lens);
  lens_get_source_coord (x + width, y + height, &x4, &y4, &mag, &lens);

  /* This is ugly, and happens
   * with a crazy set of parameters */
  reorder (&x1, &x2);
  reorder (&x3, &x4);

  reorder (&y1, &y3);
  reorder (&y2, &y4);

  if (lens.centre_y > y && lens.centre_y < y + height)
    {
      gdouble x5, y5, x6, y6;

      lens_get_source_coord (x,         lens.centre_y, &x5, &y5, &mag, &lens);
      lens_get_source_coord (x + width, lens.centre_y, &x6, &y6, &mag, &lens);

      reorder (&x5, &x6);

      area.x = floor (MIN3 (x1, x3, x5)) - 1;
      area.width = ceil (MAX3 (x2, x4, x6)) + 3 - area.x;
    }
  else
    {
      area.x = floor (MIN (x1, x3)) - 1;
      area.width = ceil (MAX (x2, x4)) + 3 - area.x;
    }

  if (lens.centre_x > x && lens.centre_x < x + width)
    {
      gdouble x5, y5, x6, y6;

      lens_get_source_coord (lens.centre_x, y,          &x5, &y5, &mag, &lens);
      lens_get_source_coord (lens.centre_x, y + height, &x6, &y6, &mag, &lens);

      reorder (&y5, &y6);

      area.y = floor (MIN3 (y1, y2, y5)) - 1;
      area.height = ceil (MAX3 (y3, y4, y6)) + 3 - area.y;
    }
  else
    {
      area.y = floor (MIN (y1, y2)) - 1;
      area.height = ceil (MAX (y3, y4)) + 3 - area.y;
    }

  return area;
}