Пример #1
0
static GeglNode *
gegl_affine_detect (GeglOperation *operation,
                    gint           x,
                    gint           y)
{
  OpAffine    *affine      = OP_AFFINE (operation);
  GeglNode    *source_node = gegl_operation_get_source_node (operation, "input");
  GeglMatrix3  inverse;
  gdouble      need_points [2];
  gint         i;

  if (gegl_affine_is_intermediate_node (affine) ||
      gegl_matrix3_is_identity (&inverse))
    {
      return gegl_operation_detect (source_node->operation, x, y);
    }

  need_points [0] = x;
  need_points [1] = y;

  gegl_affine_create_matrix (affine, &inverse);
  gegl_matrix3_invert (&inverse);

  for (i = 0; i < 2; i += 2)
    gegl_matrix3_transform_point (&inverse,
                             need_points + i, need_points + i + 1);

  return gegl_operation_detect (source_node->operation,
                                need_points[0], need_points[1]);
}
Пример #2
0
gboolean
gegl_matrix3_is_translate (GeglMatrix3 *matrix)
{
  GeglMatrix3 copy;
  gegl_matrix3_copy_into (&copy, matrix);
  copy.coeff [0][2] = copy.coeff [1][2] = 0.;
  return gegl_matrix3_is_identity (&copy);
}
Пример #3
0
static GeglRectangle
gegl_affine_get_bounding_box (GeglOperation *op)
{
  OpAffine      *affine  = OP_AFFINE (op);
  GeglMatrix3    matrix;
  GeglRectangle  in_rect = {0,0,0,0},
                 have_rect;
  gdouble        have_points [8];
  gint           i;

  GeglRectangle  context_rect;
  GeglSampler   *sampler;

  sampler = gegl_buffer_sampler_new (NULL, babl_format("RaGaBaA float"),
      gegl_sampler_type_from_string (affine->filter));
  context_rect = *gegl_sampler_get_context_rect (sampler);
  g_object_unref (sampler);

  if (gegl_operation_source_get_bounding_box (op, "input"))
    in_rect = *gegl_operation_source_get_bounding_box (op, "input");

  gegl_affine_create_composite_matrix (affine, &matrix);

  if (gegl_affine_is_intermediate_node (affine) ||
      gegl_matrix3_is_identity (&matrix))
    {
      return in_rect;
    }

  in_rect.x      += context_rect.x;
  in_rect.y      += context_rect.y;
  in_rect.width  += context_rect.width;
  in_rect.height += context_rect.height;

  have_points [0] = in_rect.x;
  have_points [1] = in_rect.y;

  have_points [2] = in_rect.x + in_rect.width ;
  have_points [3] = in_rect.y;

  have_points [4] = in_rect.x + in_rect.width ;
  have_points [5] = in_rect.y + in_rect.height ;

  have_points [6] = in_rect.x;
  have_points [7] = in_rect.y + in_rect.height ;

  for (i = 0; i < 8; i += 2)
    gegl_matrix3_transform_point (&matrix,
                             have_points + i, have_points + i + 1);

  gegl_affine_bounding_box (have_points, 4, &have_rect);
  return have_rect;
}
Пример #4
0
static GeglRectangle
gegl_affine_get_required_for_output (GeglOperation       *op,
                                     const gchar         *input_pad,
                                     const GeglRectangle *region)
{
  OpAffine      *affine = OP_AFFINE (op);
  GeglMatrix3    inverse;
  GeglRectangle  requested_rect,
                 need_rect;
  GeglRectangle  context_rect;
  GeglSampler   *sampler;
  gdouble        need_points [8];
  gint           i;

  requested_rect = *region;
  sampler = gegl_buffer_sampler_new (NULL, babl_format("RaGaBaA float"),
      gegl_sampler_type_from_string (affine->filter));
  context_rect = *gegl_sampler_get_context_rect (sampler);
  g_object_unref (sampler);

  gegl_affine_create_composite_matrix (affine, &inverse);
  gegl_matrix3_invert (&inverse);

  if (gegl_affine_is_intermediate_node (affine) ||
      gegl_matrix3_is_identity (&inverse))
    {
      return requested_rect;
    }

  need_points [0] = requested_rect.x;
  need_points [1] = requested_rect.y;

  need_points [2] = requested_rect.x + requested_rect.width ;
  need_points [3] = requested_rect.y;

  need_points [4] = requested_rect.x + requested_rect.width ;
  need_points [5] = requested_rect.y + requested_rect.height ;

  need_points [6] = requested_rect.x;
  need_points [7] = requested_rect.y + requested_rect.height ;

  for (i = 0; i < 8; i += 2)
    gegl_matrix3_transform_point (&inverse,
                             need_points + i, need_points + i + 1);
  gegl_affine_bounding_box (need_points, 4, &need_rect);

  need_rect.x      += context_rect.x;
  need_rect.y      += context_rect.y;
  need_rect.width  += context_rect.width;
  need_rect.height += context_rect.height;
  return need_rect;
}
Пример #5
0
static gboolean
gegl_affine_process (GeglOperation        *operation,
                     GeglOperationContext *context,
                     const gchar          *output_prop,
                     const GeglRectangle  *result)
{
  GeglBuffer          *input;
  GeglBuffer          *output;
  GeglMatrix3          matrix;
  OpAffine            *affine = (OpAffine *) operation;

  gegl_affine_create_composite_matrix (affine, &matrix);

  if (gegl_affine_is_intermediate_node (affine) ||
      gegl_matrix3_is_identity (&matrix))
    {
      /* passing straight through (like gegl:nop) */
      input  = gegl_operation_context_get_source (context, "input");
      if (!input)
        {
          g_warning ("transform received NULL input");
          return FALSE;
        }

      gegl_operation_context_take_object (context, "output", G_OBJECT (input));
    }
  else if (gegl_affine_matrix3_allow_fast_translate (&matrix) ||
           (gegl_matrix3_is_translate (&matrix) &&
            ! strcmp (affine->filter, "nearest")))
    {
      /* doing a buffer shifting trick, (enhanced nop) */
      input  = gegl_operation_context_get_source (context, "input");

      output = g_object_new (GEGL_TYPE_BUFFER,
                             "source",    input,
                             "shift-x",   (int)-matrix.coeff[0][2],
                             "shift-y",   (int)-matrix.coeff[1][2],
                             "abyss-width", -1,  /* turn of abyss
                                                    (relying on abyss
                                                    of source) */
                         NULL);

      if (gegl_object_get_has_forked (input))
        gegl_object_set_has_forked (output);

      gegl_operation_context_take_object (context, "output", G_OBJECT (output));

      if (input != NULL)
        g_object_unref (input);
    }
  else if (gegl_affine_matrix3_allow_fast_reflect_x (&matrix))
    {
      GeglRectangle      src_rect;
      GeglSampler       *sampler;
      GeglRectangle      context_rect;

      input  = gegl_operation_context_get_source (context, "input");
      if (!input)
        {
          g_warning ("transform received NULL input");
          return FALSE;
        }

      output = gegl_operation_context_get_target (context, "output");

      src_rect = gegl_operation_get_required_for_output (operation, "output", result);
      src_rect.y += 1;

      sampler = gegl_buffer_sampler_new (input, babl_format("RaGaBaA float"),
          gegl_sampler_type_from_string (affine->filter));
      context_rect = *gegl_sampler_get_context_rect (sampler);

      src_rect.width -= context_rect.width;
      src_rect.height -= context_rect.height;

      gegl_affine_fast_reflect_x (output, input, result, &src_rect);
      g_object_unref (sampler);

      if (input != NULL)
        g_object_unref (input);
    }
  else if (gegl_affine_matrix3_allow_fast_reflect_y (&matrix))
    {
      GeglRectangle      src_rect;
      GeglSampler       *sampler;
      GeglRectangle      context_rect;

      input  = gegl_operation_context_get_source (context, "input");
      if (!input)
        {
          g_warning ("transform received NULL input");
          return FALSE;
        }

      output = gegl_operation_context_get_target (context, "output");

      src_rect = gegl_operation_get_required_for_output (operation, "output", result);
      src_rect.x += 1;

      sampler = gegl_buffer_sampler_new (input, babl_format("RaGaBaA float"),
          gegl_sampler_type_from_string (affine->filter));
      context_rect = *gegl_sampler_get_context_rect (sampler);

      src_rect.width -= context_rect.width;
      src_rect.height -= context_rect.height;

      gegl_affine_fast_reflect_y (output, input, result, &src_rect);
      g_object_unref (sampler);

      if (input != NULL)
        g_object_unref (input);
    }
  else
    {
      /* for all other cases, do a proper resampling */
      GeglSampler *sampler;

      input  = gegl_operation_context_get_source (context, "input");
      output = gegl_operation_context_get_target (context, "output");

      sampler = gegl_buffer_sampler_new (input, babl_format("RaGaBaA float"),
          gegl_sampler_type_from_string (affine->filter));
      affine_generic (output, input, &matrix, sampler);
      g_object_unref (sampler);

      if (input != NULL)
        g_object_unref (input);
    }

  return TRUE;
}
Пример #6
0
static GeglRectangle
gegl_affine_get_invalidated_by_change (GeglOperation       *op,
                                       const gchar         *input_pad,
                                       const GeglRectangle *input_region)
{
  OpAffine          *affine = OP_AFFINE (op);
  GeglMatrix3        matrix;
  GeglRectangle      affected_rect;
  GeglRectangle      context_rect;
  GeglSampler       *sampler;
  gdouble            affected_points [8];
  gint               i;
  GeglRectangle      region = *input_region;

  sampler = gegl_buffer_sampler_new (NULL, babl_format("RaGaBaA float"),
      gegl_sampler_type_from_string (affine->filter));
  context_rect = *gegl_sampler_get_context_rect (sampler);
  g_object_unref (sampler);

  gegl_affine_create_matrix (affine, &matrix);

  if (affine->origin_x || affine->origin_y)
    gegl_matrix3_originate (&matrix, affine->origin_x, affine->origin_y);

  if (gegl_affine_is_composite_node (affine))
    {
      GeglMatrix3 source;

      gegl_affine_get_source_matrix (affine, &source);
      gegl_matrix3_multiply (&source, &matrix, &matrix);
    }

  if (gegl_affine_is_intermediate_node (affine) ||
      gegl_matrix3_is_identity (&matrix))
    {
      return region;
    }

  region.x      += context_rect.x;
  region.y      += context_rect.y;
  region.width  += context_rect.width;
  region.height += context_rect.height;

  affected_points [0] = region.x;
  affected_points [1] = region.y;

  affected_points [2] = region.x + region.width ;
  affected_points [3] = region.y;

  affected_points [4] = region.x + region.width ;
  affected_points [5] = region.y + region.height ;

  affected_points [6] = region.x;
  affected_points [7] = region.y + region.height ;

  for (i = 0; i < 8; i += 2)
    gegl_matrix3_transform_point (&matrix,
                             affected_points + i, affected_points + i + 1);

  gegl_affine_bounding_box (affected_points, 4, &affected_rect);
  return affected_rect;
}