Esempio n. 1
0
void
gimp_gegl_apply_transform (GeglBuffer            *src_buffer,
                           GimpProgress          *progress,
                           const gchar           *undo_desc,
                           GeglBuffer            *dest_buffer,
                           GimpInterpolationType  interpolation_type,
                           GimpMatrix3           *transform)
{
  GeglNode *node;

  g_return_if_fail (GEGL_IS_BUFFER (src_buffer));
  g_return_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress));
  g_return_if_fail (GEGL_IS_BUFFER (dest_buffer));

  node = gegl_node_new_child (NULL,
                              "operation", "gegl:transform",
                              "sampler",   interpolation_type,
                              NULL);

  gimp_gegl_node_set_matrix (node, transform);

  gimp_gegl_apply_operation (src_buffer, progress, undo_desc,
                             node, dest_buffer, NULL);
  g_object_unref (node);
}
Esempio n. 2
0
GeglBuffer *
gimp_drawable_transform_buffer_affine (GimpDrawable           *drawable,
                                       GimpContext            *context,
                                       GeglBuffer             *orig_buffer,
                                       gint                    orig_offset_x,
                                       gint                    orig_offset_y,
                                       const GimpMatrix3      *matrix,
                                       GimpTransformDirection  direction,
                                       GimpInterpolationType   interpolation_type,
                                       gint                    recursion_level,
                                       GimpTransformResize     clip_result,
                                       gint                   *new_offset_x,
                                       gint                   *new_offset_y,
                                       GimpProgress           *progress)
{
  GeglBuffer  *new_buffer;
  GimpMatrix3  m;
  GimpMatrix3  inv;
  gint         u1, v1, u2, v2;  /* source bounding box */
  gint         x1, y1, x2, y2;  /* target bounding box */
  GeglNode    *affine;
  GimpMatrix3  gegl_matrix;

  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);
  g_return_val_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)), NULL);
  g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
  g_return_val_if_fail (GEGL_IS_BUFFER (orig_buffer), NULL);
  g_return_val_if_fail (matrix != NULL, NULL);
  g_return_val_if_fail (new_offset_x != NULL, NULL);
  g_return_val_if_fail (new_offset_y != NULL, NULL);
  g_return_val_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress), NULL);

  m   = *matrix;
  inv = *matrix;

  if (direction == GIMP_TRANSFORM_BACKWARD)
    {
      /*  keep the original matrix here, so we dont need to recalculate
       *  the inverse later
       */
      gimp_matrix3_invert (&inv);
    }
  else
    {
      /*  Find the inverse of the transformation matrix  */
      gimp_matrix3_invert (&m);
    }

  u1 = orig_offset_x;
  v1 = orig_offset_y;
  u2 = u1 + gegl_buffer_get_width  (orig_buffer);
  v2 = v1 + gegl_buffer_get_height (orig_buffer);

  /*  Always clip unfloated buffers since they must keep their size  */
  if (G_TYPE_FROM_INSTANCE (drawable) == GIMP_TYPE_CHANNEL &&
      ! babl_format_has_alpha (gegl_buffer_get_format (orig_buffer)))
    clip_result = GIMP_TRANSFORM_RESIZE_CLIP;

  /*  Find the bounding coordinates of target */
  gimp_transform_resize_boundary (&inv, clip_result,
                                  u1, v1, u2, v2,
                                  &x1, &y1, &x2, &y2);

  /*  Get the new temporary buffer for the transformed result  */
  new_buffer = gimp_gegl_buffer_new (GEGL_RECTANGLE (0, 0, x2 - x1, y2 - y1),
                                     gegl_buffer_get_format (orig_buffer));

  gimp_matrix3_identity (&gegl_matrix);
  gimp_matrix3_translate (&gegl_matrix, u1, v1);
  gimp_matrix3_mult (&inv, &gegl_matrix);
  gimp_matrix3_translate (&gegl_matrix, -x1, -y1);

  affine = gegl_node_new_child (NULL,
                                "operation",  "gegl:transform",
                                "filter",     gimp_interpolation_to_gegl_filter (interpolation_type),
                                "hard-edges", TRUE,
                                NULL);

  gimp_gegl_node_set_matrix (affine, &gegl_matrix);

  gimp_apply_operation (orig_buffer, progress, NULL,
                        affine,
                        new_buffer, NULL);

  g_object_unref (affine);

  *new_offset_x = x1;
  *new_offset_y = y1;

  return new_buffer;
}
Esempio n. 3
0
static GeglBuffer *
gimp_perspective_clone_get_source (GimpSourceCore   *source_core,
                                   GimpDrawable     *drawable,
                                   GimpPaintOptions *paint_options,
                                   GimpPickable     *src_pickable,
                                   gint              src_offset_x,
                                   gint              src_offset_y,
                                   GeglBuffer       *paint_buffer,
                                   gint              paint_buffer_x,
                                   gint              paint_buffer_y,
                                   gint             *paint_area_offset_x,
                                   gint             *paint_area_offset_y,
                                   gint             *paint_area_width,
                                   gint             *paint_area_height,
                                   GeglRectangle    *src_rect)
{
  GimpPerspectiveClone *clone         = GIMP_PERSPECTIVE_CLONE (source_core);
  GimpCloneOptions     *clone_options = GIMP_CLONE_OPTIONS (paint_options);
  GeglBuffer           *src_buffer;
  GeglBuffer           *dest_buffer;
  const Babl           *src_format_alpha;
  gint                  x1d, y1d, x2d, y2d;
  gdouble               x1s, y1s, x2s, y2s, x3s, y3s, x4s, y4s;
  gint                  xmin, ymin, xmax, ymax;
  GimpMatrix3           matrix;
  GimpMatrix3           gegl_matrix;

  src_buffer       = gimp_pickable_get_buffer (src_pickable);
  src_format_alpha = gimp_pickable_get_format_with_alpha (src_pickable);

  /* Destination coordinates that will be painted */
  x1d = paint_buffer_x;
  y1d = paint_buffer_y;
  x2d = paint_buffer_x + gegl_buffer_get_width  (paint_buffer);
  y2d = paint_buffer_y + gegl_buffer_get_height (paint_buffer);

  /* Boundary box for source pixels to copy: Convert all the vertex of
   * the box to paint in destination area to its correspondent in
   * source area bearing in mind perspective
   */
  gimp_perspective_clone_get_source_point (clone, x1d, y1d, &x1s, &y1s);
  gimp_perspective_clone_get_source_point (clone, x1d, y2d, &x2s, &y2s);
  gimp_perspective_clone_get_source_point (clone, x2d, y1d, &x3s, &y3s);
  gimp_perspective_clone_get_source_point (clone, x2d, y2d, &x4s, &y4s);

  xmin = floor (MIN4 (x1s, x2s, x3s, x4s));
  ymin = floor (MIN4 (y1s, y2s, y3s, y4s));
  xmax = ceil  (MAX4 (x1s, x2s, x3s, x4s));
  ymax = ceil  (MAX4 (y1s, y2s, y3s, y4s));

  switch (clone_options->clone_type)
    {
    case GIMP_IMAGE_CLONE:
      if (! gimp_rectangle_intersect (xmin, ymin,
                                      xmax - xmin, ymax - ymin,
                                      0, 0,
                                      gegl_buffer_get_width  (src_buffer),
                                      gegl_buffer_get_height (src_buffer),
                                      NULL, NULL, NULL, NULL))
        {
          /* if the source area is completely out of the image */
          return NULL;
        }
      break;

    case GIMP_PATTERN_CLONE:
      gegl_node_set (clone->crop,
                     "x",      (gdouble) xmin,
                     "y",      (gdouble) ymin,
                     "width",  (gdouble) xmax - xmin,
                     "height", (gdouble) ymax - ymin,
                     NULL);
      break;
    }

  dest_buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0, x2d - x1d, y2d - y1d),
                                 src_format_alpha);

  gimp_perspective_clone_get_matrix (clone, &matrix);

  gimp_matrix3_identity (&gegl_matrix);
  gimp_matrix3_mult (&matrix, &gegl_matrix);
  gimp_matrix3_translate (&gegl_matrix, -x1d, -y1d);

  gimp_gegl_node_set_matrix (clone->transform_node, &gegl_matrix);

  gegl_node_set (clone->dest_node,
                 "buffer", dest_buffer,
                 NULL);

  gegl_node_blit (clone->dest_node, 1.0,
                  GEGL_RECTANGLE (0, 0, x2d - x1d, y2d - y1d),
                  NULL, NULL, 0, GEGL_BLIT_DEFAULT);

  *src_rect = *GEGL_RECTANGLE (0, 0, x2d - x1d, y2d - y1d);

  return dest_buffer;
}