Exemplo n.º 1
0
static GeglRectangle
gimp_operation_cage_coef_calc_get_bounding_box (GeglOperation *operation)
{
  GimpOperationCageCoefCalc *occc   = GIMP_OPERATION_CAGE_COEF_CALC (operation);
  GimpCageConfig            *config = GIMP_CAGE_CONFIG (occc->config);

  return gimp_cage_config_get_bounding_box (config);
}
Exemplo n.º 2
0
static gboolean
gimp_operation_cage_transform_process (GeglOperation       *operation,
                                       GeglBuffer          *in_buf,
                                       GeglBuffer          *aux_buf,
                                       GeglBuffer          *out_buf,
                                       const GeglRectangle *roi,
                                       gint                 level)
{
  GimpOperationCageTransform *oct    = GIMP_OPERATION_CAGE_TRANSFORM (operation);
  GimpCageConfig             *config = GIMP_CAGE_CONFIG (oct->config);
  GeglRectangle               cage_bb;
  gfloat                     *coords;
  gfloat                     *coef;
  const Babl                 *format_coef;
  GimpVector2                 plain_color;
  GeglBufferIterator         *it;
  gint                        x, y;
  gboolean                    output_set;
  GimpCagePoint              *point;
  guint                       n_cage_vertices;

  /* pre-fill the out buffer with no-displacement coordinate */
  it      = gegl_buffer_iterator_new (out_buf, roi, 0, NULL, GEGL_BUFFER_WRITE, GEGL_ABYSS_NONE);
  cage_bb = gimp_cage_config_get_bounding_box (config);

  point = &(g_array_index (config->cage_points, GimpCagePoint, 0));
  plain_color.x = (gint) point->src_point.x;
  plain_color.y = (gint) point->src_point.y;

  n_cage_vertices   = gimp_cage_config_get_n_points (config);

  while (gegl_buffer_iterator_next (it))
    {
      /* iterate inside the roi */
      gint    n_pixels = it->length;
      gfloat *output   = it->data[0];

      x = it->roi->x; /* initial x         */
      y = it->roi->y; /* and y coordinates */

      while (n_pixels--)
        {
          output_set = FALSE;
          if (oct->fill_plain_color)
            {
              if (x > cage_bb.x &&
                  y > cage_bb.y &&
                  x < cage_bb.x + cage_bb.width &&
                  y < cage_bb.y + cage_bb.height)
                {
                  if (gimp_cage_config_point_inside (config, x, y))
                    {
                      output[0] = plain_color.x;
                      output[1] = plain_color.y;
                      output_set = TRUE;
                    }
                }
            }
          if (!output_set)
            {
              output[0] = x;
              output[1] = y;
            }

          output += 2;

          /* update x and y coordinates */
          x++;
          if (x >= (it->roi->x + it->roi->width))
            {
              x = it->roi->x;
              y++;
            }
        }
    }

  oct->progress = 0.0;
  g_object_notify (G_OBJECT (oct), "progress");

  /* pre-allocate memory outside of the loop */
  coords      = g_slice_alloc (2 * sizeof (gfloat));
  coef        = g_malloc (n_cage_vertices * 2 * sizeof (gfloat));
  format_coef = babl_format_n (babl_type ("float"), 2 * n_cage_vertices);

  /* compute, reverse and interpolate the transformation */
  for (y = cage_bb.y; y < cage_bb.y + cage_bb.height - 1; y++)
    {
      GimpVector2 p1_d, p2_d, p3_d, p4_d;
      GimpVector2 p1_s, p2_s, p3_s, p4_s;

      p1_s.y = y;
      p2_s.y = y+1;
      p3_s.y = y+1;
      p3_s.x = cage_bb.x;
      p4_s.y = y;
      p4_s.x = cage_bb.x;

      p3_d = gimp_cage_transform_compute_destination (config, coef, format_coef, aux_buf, p3_s);
      p4_d = gimp_cage_transform_compute_destination (config, coef, format_coef, aux_buf, p4_s);

      for (x = cage_bb.x; x < cage_bb.x + cage_bb.width - 1; x++)
        {
          p1_s = p4_s;
          p2_s = p3_s;
          p3_s.x = x+1;
          p4_s.x = x+1;

          p1_d = p4_d;
          p2_d = p3_d;
          p3_d = gimp_cage_transform_compute_destination (config, coef, format_coef, aux_buf, p3_s);
          p4_d = gimp_cage_transform_compute_destination (config, coef, format_coef, aux_buf, p4_s);

          if (gimp_cage_config_point_inside (config, x, y))
            {
              gimp_operation_cage_transform_interpolate_source_coords_recurs (oct,
                                                                              out_buf,
                                                                              roi,
                                                                              p1_s, p1_d,
                                                                              p2_s, p2_d,
                                                                              p3_s, p3_d,
                                                                              0,
                                                                              coords);

              gimp_operation_cage_transform_interpolate_source_coords_recurs (oct,
                                                                              out_buf,
                                                                              roi,
                                                                              p1_s, p1_d,
                                                                              p3_s, p3_d,
                                                                              p4_s, p4_d,
                                                                              0,
                                                                              coords);
            }
        }

      if ((y - cage_bb.y) % 20 == 0)
        {
          gdouble fraction = ((gdouble) (y - cage_bb.y) /
                              (gdouble) (cage_bb.height));

          /*  0.0 and 1.0 indicate progress start/end, so avoid them  */
          if (fraction > 0.0 && fraction < 1.0)
            {
              oct->progress = fraction;
              g_object_notify (G_OBJECT (oct), "progress");
            }
        }
    }

  g_free (coef);
  g_slice_free1 (2 * sizeof (gfloat), coords);

  oct->progress = 1.0;
  g_object_notify (G_OBJECT (oct), "progress");

  return TRUE;
}