Пример #1
0
static void
gimp_view_renderer_transform_create (GimpViewRenderer *renderer,
                                     GtkWidget        *widget,
                                     GeglBuffer       *src_buffer,
                                     GeglBuffer       *dest_buffer)
{
  if (GIMP_IS_COLOR_MANAGED (renderer->viewable))
    {
      GimpColorManaged *managed  = GIMP_COLOR_MANAGED (renderer->viewable);
      GimpPickable     *pickable = GIMP_PICKABLE (renderer->viewable);
      GimpColorProfile *profile;

      profile = gimp_color_managed_get_color_profile (managed);

      if (profile)
        {
          GimpImage       *image  = gimp_pickable_get_image (pickable);
          GimpColorConfig *config = image->gimp->config->color_management;

          renderer->profile_src_format  = gegl_buffer_get_format (src_buffer);
          renderer->profile_dest_format = gegl_buffer_get_format (dest_buffer);

          renderer->profile_transform =
            gimp_widget_get_color_transform (widget, config,
                                             profile,
                                             &renderer->profile_src_format,
                                             &renderer->profile_dest_format);
        }
    }
}
Пример #2
0
static void
transfer_registration_color (GeglBuffer  *src,
                             GeglBuffer **dst,
                             gint         count)
{
  GimpRGB color, test;
  GeglBufferIterator *gi;
  const Babl *src_format, *dst_format;
  gint i, src_bpp, dst_bpp;
  gdouble white;

  gimp_context_get_foreground (&color);
  white = 1.0;

  src_format = gegl_buffer_get_format (src);
  src_bpp = babl_format_get_bytes_per_pixel (src_format);

  dst_format = gegl_buffer_get_format (dst[0]);
  dst_bpp = babl_format_get_bytes_per_pixel (dst_format);

  gi = gegl_buffer_iterator_new (src, NULL, 0, NULL,
                                 GEGL_BUFFER_READ, GEGL_ABYSS_NONE);

  for (i = 0; i < count; i++)
    {
      gegl_buffer_iterator_add (gi, dst[i], NULL, 0, NULL,
                                GEGL_BUFFER_READWRITE, GEGL_ABYSS_NONE);
    }

  while (gegl_buffer_iterator_next (gi))
    {
      guint j, k;
      gpointer src_data, dst_data[MAX_EXTRACT_IMAGES];

      src_data = gi->data[0];
      for (j = 0; j < count; j++)
        dst_data[j] = gi->data[j+1];

      for (k = 0; k < gi->length; k++)
        {
          gulong pos;
          pos = k * src_bpp;
          gimp_rgba_set_pixel (&test, src_format, ((guchar *)src_data) + pos);

          if (gimp_rgb_distance (&test, &color) < 1e-6)
            {
              for (j = 0; j < count; j++)
                {
                  gpointer data;
                  data = dst_data[j];
                  babl_process (babl_fish (babl_format ("Y double"), dst_format),
                                &white, (guchar *)data + (k * dst_bpp), 1);
                }
            }
        }
    }
}
Пример #3
0
static gboolean
test_opacity_common (const Babl *in_format,
                     const Babl *out_format)
{
  /* Validate that gegl:opacity produces out_format when given in_format */
  gboolean result = TRUE;

  GeglNode *ptn, *src, *opacity, *sink;
  GeglBuffer *src_buffer;
  GeglBuffer *sink_buffer = NULL;

  src_buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0, 10, 10), in_format);

  ptn  = gegl_node_new ();

  src  = gegl_node_new_child (ptn,
                              "operation", "gegl:buffer-source",
                              "buffer", src_buffer,
                              NULL);

  opacity = gegl_node_new_child (ptn,
                                 "operation", "gegl:opacity",
                                 "value", 0.5,
                                 NULL);

  sink = gegl_node_new_child (ptn,
                              "operation", "gegl:buffer-sink",
                              "buffer", &sink_buffer,
                              "format", NULL,
                              NULL);

  gegl_node_link_many (src, opacity, sink, NULL);

  gegl_node_blit_buffer (sink, NULL, NULL, 0, GEGL_ABYSS_NONE);

  if (out_format != gegl_buffer_get_format (sink_buffer))
    {
      printf ("Got %s expected %s\n", babl_get_name (gegl_buffer_get_format (sink_buffer)),
                                      babl_get_name (out_format));
      result = FALSE;
    }

  if (!gegl_rectangle_equal (gegl_buffer_get_extent (src_buffer),
                             gegl_buffer_get_extent (sink_buffer)))
    result = FALSE;

  g_object_unref (ptn);
  g_object_unref (src_buffer);
  g_object_unref (sink_buffer);

  return result;
}
Пример #4
0
static void
gegl_affine_fast_reflect_x (GeglBuffer              *dest,
                            GeglBuffer              *src,
                            const GeglRectangle     *dest_rect,
                            const GeglRectangle     *src_rect)
{
  const Babl              *format = gegl_buffer_get_format (src);
  const gint               px_size = babl_format_get_bytes_per_pixel (format),
                           rowstride = src_rect->width * px_size;
  gint                     i;
  guchar                  *buf = (guchar *) g_malloc (src_rect->height * rowstride);

  gegl_buffer_get (src, 1.0, src_rect, format, buf, GEGL_AUTO_ROWSTRIDE);

  for (i = 0; i < src_rect->height / 2; i++)
    {
      gint      dest_offset = (src_rect->height - i - 1) * rowstride,
                src_offset = i * rowstride,
                j;

      for (j = 0; j < rowstride; j++)
        {
          const guchar      tmp = buf[src_offset];

          buf[src_offset] = buf[dest_offset];
          buf[dest_offset] = tmp;

          dest_offset++;
          src_offset++;
        }
    }

  gegl_buffer_set (dest, dest_rect, format, buf, GEGL_AUTO_ROWSTRIDE);
  g_free (buf);
}
Пример #5
0
const Babl *
gimp_buffer_get_format (const GimpBuffer *buffer)
{
  g_return_val_if_fail (GIMP_IS_BUFFER (buffer), NULL);

  return gegl_buffer_get_format (buffer->buffer);
}
Пример #6
0
TileManager *
gimp_buffer_to_tiles (GeglBuffer *buffer)
{
  const Babl    *format     = gegl_buffer_get_format (buffer);
  TileManager   *new_tiles  = NULL;
  GeglNode      *source     = NULL;
  GeglNode      *sink       = NULL;

  g_return_val_if_fail (buffer != NULL, NULL);

  /* Setup and process the graph */
  new_tiles = tile_manager_new (gegl_buffer_get_width (buffer),
                                gegl_buffer_get_height (buffer),
                                gimp_babl_format_to_legacy_bpp (format));
  source = gegl_node_new_child (NULL,
                                "operation", "gegl:buffer-source",
                                "buffer",    buffer,
                                NULL);
  sink = gegl_node_new_child (NULL,
                              "operation",    "gimp:tilemanager-sink",
                              "tile-manager", new_tiles,
                              NULL);
  gegl_node_link_many (source, sink, NULL);
  gegl_node_process (sink);

  /* Clenaup */
  g_object_unref (sink);
  g_object_unref (source);

  return new_tiles;
}
Пример #7
0
gboolean
gimp_gegl_mask_is_empty (GeglBuffer *buffer)
{
  GeglBufferIterator *iter;
  const Babl         *format;
  gint                bpp;

  g_return_val_if_fail (GEGL_IS_BUFFER (buffer), FALSE);

  format = gegl_buffer_get_format (buffer);
  bpp    = babl_format_get_bytes_per_pixel (format);

  iter = gegl_buffer_iterator_new (buffer, NULL, 0, format,
                                   GEGL_ACCESS_READ, GEGL_ABYSS_NONE, 1);

  while (gegl_buffer_iterator_next (iter))
    {
      if (! gegl_memeq_zero (iter->items[0].data, bpp * iter->length))
        {
          gegl_buffer_iterator_stop (iter);

          return FALSE;
        }
    }

  return TRUE;
}
Пример #8
0
void
gimp_create_image_from_buffer (Gimp       *gimp,
                               GeglBuffer *buffer)
{
  GimpImage  *image;
  GimpLayer  *layer;
  const Babl *format;

  g_return_if_fail (GIMP_IS_GIMP (gimp));
  g_return_if_fail (GEGL_IS_BUFFER (buffer));

  format = gegl_buffer_get_format (buffer);

  image = gimp_create_image (gimp,
                             gegl_buffer_get_width  (buffer),
                             gegl_buffer_get_height (buffer),
                             gimp_babl_format_get_base_type (format),
                             gimp_babl_format_get_precision (format),
                             FALSE);

  layer = gimp_layer_new_from_buffer (buffer, image, format,
                                      "Debug Image",
                                      GIMP_OPACITY_OPAQUE,
                                      GIMP_NORMAL_MODE);
  gimp_image_add_layer (image, layer, NULL, -1, FALSE);

  gimp_create_display (gimp, image, GIMP_UNIT_PIXEL, 1.0);
}
Пример #9
0
GimpTransformResize
gimp_drawable_transform_get_effective_clip (GimpDrawable        *drawable,
                                            GeglBuffer          *orig_buffer,
                                            GimpTransformResize  clip_result)
{
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), clip_result);
  g_return_val_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)),
                                               clip_result);
  g_return_val_if_fail (orig_buffer == NULL || GEGL_IS_BUFFER (orig_buffer),
                        clip_result);

  /*  Always clip unfloated buffers since they must keep their size  */
  if (GIMP_IS_CHANNEL (drawable))
    {
      if (orig_buffer)
        {
          if (! babl_format_has_alpha (gegl_buffer_get_format (orig_buffer)))
            clip_result = GIMP_TRANSFORM_RESIZE_CLIP;
        }
      else
        {
          GimpImage *image = gimp_item_get_image (GIMP_ITEM (drawable));

          if (gimp_channel_is_empty (gimp_image_get_mask (image)))
            clip_result = GIMP_TRANSFORM_RESIZE_CLIP;
        }
    }

  return clip_result;
}
guchar *
gegl_buffer_introspectable_get (GeglBuffer          *buffer,
                                const GeglRectangle *rect,
                                gdouble              scale,
                                const gchar         *format_name,
                                GeglAbyssPolicy      repeat_mode,
                                guint               *data_length)
{
  const Babl *format;
  guint bpp;
  guchar *result;

  *data_length = 0;

  if (format_name)
    format = babl_format (format_name);
  else
    format = gegl_buffer_get_format (buffer);

  if (rect->width <= 0 || rect->height <= 0)
    return NULL;
  if (scale <= 0.0)
    return NULL;

  bpp = babl_format_get_bytes_per_pixel (format);
  *data_length = bpp * rect->width * rect->height;

  result = g_malloc (*data_length);

  gegl_buffer_get (buffer, rect, scale, format, result, GEGL_AUTO_ROWSTRIDE, repeat_mode);

  return result;
}
static gboolean
gimp_operation_histogram_sink_process (GeglOperation        *operation,
                                       GeglOperationContext *context,
                                       const gchar          *output_prop,
                                       const GeglRectangle  *result,
                                       gint                  level)
{
  GeglBuffer *input;
  GeglBuffer *aux;

  if (strcmp (output_prop, "output"))
    {
      g_warning ("requested processing of %s pad on a sink", output_prop);
      return FALSE;
    }

  input = gegl_operation_context_get_source (context, "input");
  aux   = gegl_operation_context_get_source (context, "aux");

  if (! input)
    {
      g_warning ("received NULL input");

      return FALSE;
    }

  if (aux)
    {
      /* do hist with mask */

      g_printerr ("aux format: %s\n",
                  babl_get_name (gegl_buffer_get_format (aux)));

      g_object_unref (aux);
    }
  else
    {
      /* without */
    }

  g_printerr ("input format: %s\n",
              babl_get_name (gegl_buffer_get_format (input)));

  g_object_unref (input);

  return TRUE;
}
Пример #12
0
/* Do the final setup of the iter struct */
static void
prepare_iteration (GeglBufferIterator *iter)
{
  int index;
  GeglBufferIteratorPriv *priv = iter->priv;
  gint origin_offset_x;
  gint origin_offset_y;

  /* Set up the origin tile */
  /* FIXME: Pick the most compatable buffer, not just the first */
  {
    GeglBuffer *buf = priv->sub_iter[0].buffer;

    priv->origin_tile.x      = buf->shift_x;
    priv->origin_tile.y      = buf->shift_y;
    priv->origin_tile.width  = buf->tile_width;
    priv->origin_tile.height = buf->tile_height;

    origin_offset_x = buf->shift_x + priv->sub_iter[0].full_rect.x;
    origin_offset_y = buf->shift_y + priv->sub_iter[0].full_rect.y;
  }

  for (index = 0; index < priv->num_buffers; index++)
    {
      SubIterState *sub = &priv->sub_iter[index];
      GeglBuffer *buf   = sub->buffer;

      gint current_offset_x = buf->shift_x + priv->sub_iter[index].full_rect.x;
      gint current_offset_y = buf->shift_y + priv->sub_iter[index].full_rect.y;

      /* Format converison needed */
      if (gegl_buffer_get_format (sub->buffer) != sub->format)
        sub->access_mode |= GEGL_ITERATOR_INCOMPATIBLE;
      /* Incompatable tiles */
      else if ((priv->origin_tile.width  != buf->tile_width) ||
               (priv->origin_tile.height != buf->tile_height) ||
               (abs(origin_offset_x - current_offset_x) % priv->origin_tile.width != 0) ||
               (abs(origin_offset_y - current_offset_y) % priv->origin_tile.height != 0))
        {
          /* Check if the buffer is a linear buffer */
          if ((buf->extent.x      == -buf->shift_x) &&
              (buf->extent.y      == -buf->shift_y) &&
              (buf->extent.width  == buf->tile_width) &&
              (buf->extent.height == buf->tile_height))
            {
              sub->linear_tile = gegl_buffer_get_tile (sub->buffer, 0, 0, 0);

              if (sub->access_mode & GEGL_ACCESS_WRITE)
                gegl_tile_lock (sub->linear_tile);
            }
          else
            sub->access_mode |= GEGL_ITERATOR_INCOMPATIBLE;
        }

      gegl_buffer_lock (sub->buffer);
    }
}
Пример #13
0
int
gegl_buffer_iterator_add (GeglBufferIterator  *iter,
                          GeglBuffer          *buf,
                          const GeglRectangle *roi,
                          gint                 level,
                          const Babl          *format,
                          GeglAccessMode       access_mode,
                          GeglAbyssPolicy      abyss_policy)
{
  GeglBufferIteratorPriv *priv = iter->priv;
  int                     index;
  SubIterState           *sub;

  g_return_val_if_fail (priv->num_buffers < GEGL_BUFFER_MAX_ITERATORS, 0);


  index = priv->num_buffers++;
  sub = &priv->sub_iter[index];

  if (!format)
    format = gegl_buffer_get_format (buf);

  if (!roi)
    roi = &buf->extent;

  sub->buffer       = buf;
  sub->full_rect    = *roi;

  if (level)
  {
    sub->full_rect.x >>= level;
    sub->full_rect.y >>= level;
    sub->full_rect.width >>= level;
    sub->full_rect.height >>= level;
  }

  sub->access_mode  = access_mode;
  sub->abyss_policy = abyss_policy;
  sub->current_tile = NULL;
  sub->real_data    = NULL;
  sub->linear_tile  = NULL;
  sub->format       = format;
  sub->format_bpp   = babl_format_get_bytes_per_pixel (format);
  sub->level        = level;

  if (index > 0)
    {
      priv->sub_iter[index].full_rect.width  = priv->sub_iter[0].full_rect.width;
      priv->sub_iter[index].full_rect.height = priv->sub_iter[0].full_rect.height;
    }

  //if (level != 0)
  //  g_warning ("iterator level != 0");

  return index;
}
Пример #14
0
static gboolean
test_buffer_sink_001 (void)
{
  /* Validate that gegl:buffer-sink doesn't modify the format of its input */
  gboolean result = TRUE;

  GeglNode *ptn, *src, *sink;
  GeglBuffer *src_buffer;
  GeglBuffer *sink_buffer = NULL;

  src_buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0, 10, 10), babl_format ("RGB u8"));

  ptn  = gegl_node_new ();

  src  = gegl_node_new_child (ptn,
                              "operation", "gegl:buffer-source",
                              "buffer", src_buffer,
                              NULL);

  sink = gegl_node_new_child (ptn,
                              "operation", "gegl:buffer-sink",
                              "buffer", &sink_buffer,
                              "format", NULL,
                              NULL);

  gegl_node_link_many (src, sink, NULL);

  gegl_node_blit_buffer (sink, NULL, NULL, 0, GEGL_ABYSS_NONE);

  if (gegl_buffer_get_format (src_buffer) != gegl_buffer_get_format (sink_buffer))
    result = FALSE;

  if (!gegl_rectangle_equal (gegl_buffer_get_extent (src_buffer),
                             gegl_buffer_get_extent (sink_buffer)))
    result = FALSE;

  g_object_unref (ptn);
  g_object_unref (src_buffer);
  g_object_unref (sink_buffer);

  return result;
}
Пример #15
0
static void
gegl_buffer_source_prepare (GeglOperation *operation)
{
    const Babl *format = NULL;
    GeglProperties *o = GEGL_PROPERTIES (operation);

    if (o->buffer)
        format = gegl_buffer_get_format (GEGL_BUFFER (o->buffer));

    gegl_operation_set_format (operation, "output", format);
}
Пример #16
0
void
gegl_apply_op_valist (GeglBuffer  *buffer,
                      const gchar *first_property_name,
                      va_list      var_args)
{
    GeglBuffer  *tempbuf = NULL;
    GeglNode    *node;
    GeglNode    *source;
    GeglNode    *sink;

    g_return_if_fail (GEGL_IS_BUFFER (buffer));

    g_object_ref (buffer);

    source  = gegl_node_new_child (NULL, "operation", "gegl:buffer-source",
                                   "buffer", buffer,
                                   NULL);
    node   = gegl_node_new_child (NULL, "operation", first_property_name, NULL);

    if (!GEGL_IS_OPERATION_POINT_FILTER (node->operation))
    {
        tempbuf = gegl_buffer_new (gegl_buffer_get_extent (buffer), gegl_buffer_get_format (buffer));

        sink = gegl_node_new_child (NULL, "operation", "gegl:write-buffer",
                                    "buffer", tempbuf,
                                    NULL);
    }
    else
    {
        sink = gegl_node_new_child (NULL, "operation", "gegl:write-buffer",
                                    "buffer", buffer,
                                    NULL);
    }

    gegl_node_link_many (source, node, sink, NULL);

    gegl_node_set_props (node, var_args);

    gegl_node_process (sink);

    g_object_unref (source);
    g_object_unref (node);
    g_object_unref (sink);

    if (tempbuf)
    {
        gegl_buffer_copy (tempbuf, NULL, buffer, NULL);
        g_object_unref (tempbuf);
    }
    g_object_unref (buffer);
}
Пример #17
0
/* Do the final setup of the iter struct */
static void
prepare_iteration (GeglBufferIterator *iter)
{
  int index;
  GeglBufferIteratorPriv *priv = iter->priv;

  /* Set up the origin tile */
  /* FIXME: Pick the most compatable buffer, not just the first */
  {
    GeglBuffer *buf = priv->sub_iter[0].buffer;

    priv->origin_tile.x      = buf->shift_x;
    priv->origin_tile.y      = buf->shift_y;
    priv->origin_tile.width  = buf->tile_width;
    priv->origin_tile.height = buf->tile_height;
  }

  for (index = 0; index < priv->num_buffers; index++)
    {
      SubIterState *sub = &priv->sub_iter[index];
      GeglBuffer *buf   = sub->buffer;

      /* Format converison needed */
      if (gegl_buffer_get_format (sub->buffer) != sub->format)
        sub->flags |= GEGL_ITERATOR_INCOMPATIBLE;
      /* Incompatable tiles */
      else if ((priv->origin_tile.x      != buf->shift_x) ||
               (priv->origin_tile.y      != buf->shift_y) ||
               (priv->origin_tile.width  != buf->tile_width) ||
               (priv->origin_tile.height != buf->tile_height))
        {
          /* Check if the buffer is a linear buffer */
          if ((buf->extent.x      == -buf->shift_x) &&
              (buf->extent.y      == -buf->shift_y) &&
              (buf->extent.width  == buf->tile_width) &&
              (buf->extent.height == buf->tile_height))
            {
              sub->linear_tile = gegl_tile_source_get_tile ((GeglTileSource *)(sub->buffer), 0, 0, 0);

              if (sub->flags & GEGL_BUFFER_WRITE)
                gegl_tile_lock (sub->linear_tile);
            }
          else
            sub->flags |= GEGL_ITERATOR_INCOMPATIBLE;
        }

      gegl_buffer_lock (sub->buffer);
    }
}
Пример #18
0
gboolean
gegl_can_do_inplace_processing (GeglOperation       *operation,
                                GeglBuffer          *input,
                                const GeglRectangle *result)
{
  if (!input)
    return FALSE;
  if (gegl_object_get_has_forked (G_OBJECT (input)))
    return FALSE;

  if (gegl_buffer_get_format (input) == gegl_operation_get_format (operation, "output") &&
      gegl_rectangle_contains (gegl_buffer_get_extent (input), result))
    return TRUE;
  return FALSE;
}
Пример #19
0
static gboolean
buffer_is_native(MyPaintGeglTiledSurface *self) {
    const int tile_size = self->parent.tile_size;

    int tile_height = -1;
    int tile_width = -1;
    g_object_get(self->buffer, "tile-width", &tile_width, "tile-height", &tile_height, NULL);
    g_assert(tile_height != -1);
    g_assert(tile_width != -1);

    const gboolean correct_format = gegl_buffer_get_format(self->buffer) == self->format;
    const gboolean correct_tile_size = tile_height == tile_size && tile_width == tile_size;

    return correct_format && correct_tile_size;
}
Пример #20
0
gint64
gimp_gegl_buffer_get_memsize (GeglBuffer *buffer)
{
  if (buffer)
    {
      const Babl *format = gegl_buffer_get_format (buffer);

      return (babl_format_get_bytes_per_pixel (format) *
              gegl_buffer_get_width (buffer) *
              gegl_buffer_get_height (buffer) +
              gimp_g_object_get_memsize (G_OBJECT (buffer)));
    }

  return 0;
}
Пример #21
0
gint64
gimp_gegl_pyramid_get_memsize (GeglBuffer *buffer)
{
  if (buffer)
    {
      const Babl *format = gegl_buffer_get_format (buffer);

      /* The pyramid levels constitute a geometric sum with a ratio of 1/4. */
      return ((gint64) babl_format_get_bytes_per_pixel (format) *
              (gint64) gegl_buffer_get_width (buffer) *
              (gint64) gegl_buffer_get_height (buffer) * 1.33 +
              gimp_g_object_get_memsize (G_OBJECT (buffer)));
    }

  return 0;
}
static const Babl *
choose_format (GeglBuffer          *buffer,
               GimpSelectCriterion  select_criterion,
               gint                *n_components,
               gboolean            *has_alpha)
{
  const Babl *format = gegl_buffer_get_format (buffer);

  *has_alpha = babl_format_has_alpha (format);

  switch (select_criterion)
    {
    case GIMP_SELECT_CRITERION_COMPOSITE:
      if (babl_format_is_palette (format))
        format = babl_format ("R'G'B'A float");
      else
        format = gimp_babl_format (gimp_babl_format_get_base_type (format),
                                   GIMP_PRECISION_FLOAT_GAMMA,
                                   *has_alpha);
      break;

    case GIMP_SELECT_CRITERION_R:
    case GIMP_SELECT_CRITERION_G:
    case GIMP_SELECT_CRITERION_B:
    case GIMP_SELECT_CRITERION_A:
      format = babl_format ("R'G'B'A float");
      break;

    case GIMP_SELECT_CRITERION_H:
    case GIMP_SELECT_CRITERION_S:
    case GIMP_SELECT_CRITERION_V:
      format = babl_format ("HSVA float");
      break;

    default:
      g_return_val_if_reached (NULL);
      break;
    }

  *n_components = babl_format_get_n_components (format);

  return format;
}
TEST ()
{
  GeglBuffer    *buffer, *buffer2;
  GeglRectangle  bound = {0, 0, 20, 20};
  test_start ();
  buffer = gegl_buffer_new (&bound, babl_format ("Y float"));
  vgrad (buffer);
  {
    GeglRectangle rect = *gegl_buffer_get_extent(buffer);

    rect.width-=10;
    rect.height-=10;
  buffer2 = gegl_buffer_new (gegl_buffer_get_extent (buffer), gegl_buffer_get_format (buffer));
  gegl_buffer_copy (buffer, &rect, buffer2, &rect);
  }
  print_buffer (buffer2);
  g_object_unref (buffer);
  g_object_unref (buffer2);
  test_end ();
}
Пример #24
0
static gboolean
export_numpy (GeglOperation       *operation,
              GeglBuffer          *input,
              const GeglRectangle *result,
              GOutputStream       *stream)
{
  const Babl *input_format, *output_format;
  gint nb_components;

  input_format = gegl_buffer_get_format (input);
  nb_components = babl_format_get_n_components (input_format);
  if (nb_components >= 3)
    {
      output_format = babl_format ("RGB float");
      nb_components = 3;
    }
  else
    {
      output_format = babl_format ("Y float");
      nb_components = 1;
    }

  return !save_array (stream, input, result, output_format);
}
Пример #25
0
gint
gegl_buffer_export_png (GeglBuffer  *gegl_buffer,
                        const gchar *path,
                        gint         compression,
                        gint         bd,
                        gint         src_x,
                        gint         src_y,
                        gint         width,
                        gint         height)
{
    FILE          *fp;
    gint           i;
    png_struct    *png;
    png_info      *info;
    guchar        *pixels;
    png_color_16   white;
    int            png_color_type;
    gchar          format_string[16];
    const Babl    *format;
    gint           bit_depth = 8;

    if (!strcmp (path, "-"))
    {
        fp = stdout;
    }
    else
    {
        fp = fopen (path, "wb");
    }
    if (!fp)
    {
        return -1;
    }

    {
        const Babl *babl = gegl_buffer_get_format (gegl_buffer);

        if (bd == 16)
            bit_depth = 16;
        else
            bit_depth = 8;

        if (babl_format_has_alpha (babl))
            if (babl_format_get_n_components (babl) != 2)
            {
                png_color_type = PNG_COLOR_TYPE_RGB_ALPHA;
                strcpy (format_string, "R'G'B'A ");
            }
            else
            {
                png_color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
                strcpy (format_string, "Y'A ");
            }
        else if (babl_format_get_n_components (babl) != 1)
        {
            png_color_type = PNG_COLOR_TYPE_RGB;
            strcpy (format_string, "R'G'B' ");
        }
        else
        {
            png_color_type = PNG_COLOR_TYPE_GRAY;
            strcpy (format_string, "Y' ");
        }
    }

    if (bit_depth == 16)
        strcat (format_string, "u16");
    else
        strcat (format_string, "u8");

    png = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (png == NULL)
    {
        if (stdout != fp)
            fclose (fp);

        return -1;
    }

    info = png_create_info_struct (png);

    if (setjmp (png_jmpbuf (png)))
    {
        if (stdout != fp)
            fclose (fp);

        return -1;
    }

    png_set_compression_level (png, compression);
    png_init_io (png, fp);

    png_set_IHDR (png, info,
                  width, height, bit_depth, png_color_type,
                  PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_DEFAULT);

    if (png_color_type == PNG_COLOR_TYPE_RGB || png_color_type == PNG_COLOR_TYPE_RGB_ALPHA)
    {
        white.red = 0xff;
        white.blue = 0xff;
        white.green = 0xff;
    }
    else
        white.gray = 0xff;
    png_set_bKGD (png, info, &white);

    png_write_info (png, info);

#if BYTE_ORDER == LITTLE_ENDIAN
    if (bit_depth > 8)
        png_set_swap (png);
#endif

    format = babl_format (format_string);
    pixels = g_malloc0 (width * babl_format_get_bytes_per_pixel (format));

    for (i=0; i< height; i++)
    {
        GeglRectangle rect;

        rect.x = src_x;
        rect.y = src_y+i;
        rect.width = width;
        rect.height = 1;

        gegl_buffer_get (gegl_buffer, &rect, 1.0, babl_format (format_string), pixels, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);

        png_write_rows (png, &pixels, 1);
    }

    png_write_end (png, info);

    png_destroy_write_struct (&png, &info);
    g_free (pixels);

    if (stdout != fp)
        fclose (fp);

    return 0;
}
Пример #26
0
gboolean
gimp_gegl_mask_bounds (GeglBuffer *buffer,
                       gint        *x1,
                       gint        *y1,
                       gint        *x2,
                       gint        *y2)
{
  GeglBufferIterator *iter;
  GeglRectangle      *roi;
  const Babl         *format;
  gint                bpp;
  gint                tx1, tx2, ty1, ty2;

  g_return_val_if_fail (GEGL_IS_BUFFER (buffer), FALSE);
  g_return_val_if_fail (x1 != NULL, FALSE);
  g_return_val_if_fail (y1 != NULL, FALSE);
  g_return_val_if_fail (x2 != NULL, FALSE);
  g_return_val_if_fail (y2 != NULL, FALSE);

  /*  go through and calculate the bounds  */
  tx1 = gegl_buffer_get_width  (buffer);
  ty1 = gegl_buffer_get_height (buffer);
  tx2 = 0;
  ty2 = 0;

  format = gegl_buffer_get_format (buffer);
  bpp    = babl_format_get_bytes_per_pixel (format);

  iter = gegl_buffer_iterator_new (buffer, NULL, 0, format,
                                   GEGL_ACCESS_READ, GEGL_ABYSS_NONE, 1);
  roi = &iter->items[0].roi;

  while (gegl_buffer_iterator_next (iter))
    {
      const guint8 *data_u8 = iter->items[0].data;
      gint          ex      = roi->x + roi->width;
      gint          ey      = roi->y + roi->height;

      /*  only check the pixels if this tile is not fully within the
       *  currently computed bounds
       */
      if (roi->x < tx1 || ex > tx2 ||
          roi->y < ty1 || ey > ty2)
        {
          /* Check upper left and lower right corners to see if we can
           * avoid checking the rest of the pixels in this tile
           */
          if (! gegl_memeq_zero (data_u8,                            bpp) &&
              ! gegl_memeq_zero (data_u8 + (iter->length - 1) * bpp, bpp))
            {
              /*  "ex/ey - 1" because the internal variables are the
               *  right/bottom pixel of the mask's contents, not one
               *  right/below it like the return values.
               */

              if (roi->x < tx1) tx1 = roi->x;
              if (ex > tx2)     tx2 = ex - 1;

              if (roi->y < ty1) ty1 = roi->y;
              if (ey > ty2)     ty2 = ey - 1;
            }
          else
            {
              #define FIND_BOUNDS(bpp, type)                                 \
                G_STMT_START                                                 \
                  {                                                          \
                    const type *data;                                        \
                    gint        y;                                           \
                                                                             \
                    if ((guintptr) data_u8 % bpp)                            \
                      goto generic;                                          \
                                                                             \
                    data = (const type *) data_u8;                           \
                                                                             \
                    for (y = roi->y; y < ey; y++)                            \
                      {                                                      \
                        gint x1;                                             \
                                                                             \
                        for (x1 = 0; x1 < roi->width; x1++)                  \
                          {                                                  \
                            if (data[x1])                                    \
                              {                                              \
                                gint x2;                                     \
                                gint x2_end = MAX (x1, tx2 - roi->x);        \
                                                                             \
                                for (x2 = roi->width - 1; x2 > x2_end; x2--) \
                                  {                                          \
                                    if (data[x2])                            \
                                      break;                                 \
                                  }                                          \
                                                                             \
                                x1 += roi->x;                                \
                                x2 += roi->x;                                \
                                                                             \
                                if (x1 < tx1) tx1 = x1;                      \
                                if (x2 > tx2) tx2 = x2;                      \
                                                                             \
                                if (y < ty1) ty1 = y;                        \
                                if (y > ty2) ty2 = y;                        \
                              }                                              \
                          }                                                  \
                                                                             \
                        data += roi->width;                                  \
                      }                                                      \
                  }                                                          \
                G_STMT_END

              switch (bpp)
                {
                case 1:
                  FIND_BOUNDS (1, guint8);
                  break;

                case 2:
                  FIND_BOUNDS (2, guint16);
                  break;

                case 4:
                  FIND_BOUNDS (4, guint32);
                  break;

                case 8:
                  FIND_BOUNDS (8, guint64);
                  break;

                default:
                generic:
                  {
                    const guint8 *data = data_u8;
                    gint          y;

                    for (y = roi->y; y < ey; y++)
                      {
                        gint x1;

                        for (x1 = 0; x1 < roi->width; x1++)
                          {
                            if (! gegl_memeq_zero (data + x1 * bpp, bpp))
                              {
                                gint x2;
                                gint x2_end = MAX (x1, tx2 - roi->x);

                                for (x2 = roi->width - 1; x2 > x2_end; x2--)
                                  {
                                    if (! gegl_memeq_zero (data + x2 * bpp,
                                                           bpp))
                                      {
                                        break;
                                      }
                                  }

                                x1 += roi->x;
                                x2 += roi->x;

                                if (x1 < tx1) tx1 = x1;
                                if (x2 > tx2) tx2 = x2;

                                if (y < ty1) ty1 = y;
                                if (y > ty2) ty2 = y;
                              }
                          }

                        data += roi->width * bpp;
                      }
                  }
                  break;
                }

              #undef FIND_BOUNDS
            }
        }
    }

  tx2 = CLAMP (tx2 + 1, 0, gegl_buffer_get_width  (buffer));
  ty2 = CLAMP (ty2 + 1, 0, gegl_buffer_get_height (buffer));

  if (tx1 == gegl_buffer_get_width  (buffer) &&
      ty1 == gegl_buffer_get_height (buffer))
    {
      *x1 = 0;
      *y1 = 0;
      *x2 = gegl_buffer_get_width  (buffer);
      *y2 = gegl_buffer_get_height (buffer);

      return FALSE;
    }

  *x1 = tx1;
  *y1 = ty1;
  *x2 = tx2;
  *y2 = ty2;

  return TRUE;
}
Пример #27
0
GeglBuffer *
gimp_drawable_transform_buffer_rotate (GimpDrawable     *drawable,
                                       GimpContext      *context,
                                       GeglBuffer       *orig_buffer,
                                       gint              orig_offset_x,
                                       gint              orig_offset_y,
                                       GimpRotationType  rotate_type,
                                       gdouble           center_x,
                                       gdouble           center_y,
                                       gboolean          clip_result,
                                       gint             *new_offset_x,
                                       gint             *new_offset_y)
{
  GeglBuffer    *new_buffer;
  GeglRectangle  src_rect;
  GeglRectangle  dest_rect;
  gint           orig_x, orig_y;
  gint           orig_width, orig_height;
  gint           orig_bpp;
  gint           new_x, new_y;
  gint           new_width, new_height;

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

  orig_x      = orig_offset_x;
  orig_y      = orig_offset_y;
  orig_width  = gegl_buffer_get_width (orig_buffer);
  orig_height = gegl_buffer_get_height (orig_buffer);
  orig_bpp    = babl_format_get_bytes_per_pixel (gegl_buffer_get_format (orig_buffer));

  switch (rotate_type)
    {
    case GIMP_ROTATE_90:
      gimp_drawable_transform_rotate_point (orig_x,
                                            orig_y + orig_height,
                                            rotate_type, center_x, center_y,
                                            &new_x, &new_y);
      new_width  = orig_height;
      new_height = orig_width;
      break;

    case GIMP_ROTATE_180:
      gimp_drawable_transform_rotate_point (orig_x + orig_width,
                                            orig_y + orig_height,
                                            rotate_type, center_x, center_y,
                                            &new_x, &new_y);
      new_width  = orig_width;
      new_height = orig_height;
      break;

    case GIMP_ROTATE_270:
      gimp_drawable_transform_rotate_point (orig_x + orig_width,
                                            orig_y,
                                            rotate_type, center_x, center_y,
                                            &new_x, &new_y);
      new_width  = orig_height;
      new_height = orig_width;
      break;

    default:
      g_return_val_if_reached (NULL);
      break;
    }

  if (clip_result && (new_x != orig_x || new_y != orig_y ||
                      new_width != orig_width || new_height != orig_height))

    {
      GimpRGB    bg;
      GeglColor *color;
      gint       clip_x, clip_y;
      gint       clip_width, clip_height;

      new_buffer = gimp_gegl_buffer_new (GEGL_RECTANGLE (0, 0,
                                                         orig_width, orig_height),
                                         gegl_buffer_get_format (orig_buffer));

      *new_offset_x = orig_x;
      *new_offset_y = orig_y;

      /*  "Outside" a channel is transparency, not the bg color  */
      if (GIMP_IS_CHANNEL (drawable))
        gimp_rgba_set (&bg, 0.0, 0.0, 0.0, 0.0);
      else
        gimp_context_get_background (context, &bg);

      color = gimp_gegl_color_new (&bg);
      gegl_buffer_set_color (new_buffer, NULL, color);
      g_object_unref (color);

      if (gimp_rectangle_intersect (orig_x, orig_y, orig_width, orig_height,
                                    new_x, new_y, new_width, new_height,
                                    &clip_x, &clip_y,
                                    &clip_width, &clip_height))
        {
          gint saved_orig_x = orig_x;
          gint saved_orig_y = orig_y;

          new_x = clip_x - orig_x;
          new_y = clip_y - orig_y;

          switch (rotate_type)
            {
            case GIMP_ROTATE_90:
              gimp_drawable_transform_rotate_point (clip_x + clip_width,
                                                    clip_y,
                                                    GIMP_ROTATE_270,
                                                    center_x,
                                                    center_y,
                                                    &orig_x,
                                                    &orig_y);
              orig_x      -= saved_orig_x;
              orig_y      -= saved_orig_y;
              orig_width   = clip_height;
              orig_height  = clip_width;
              break;

            case GIMP_ROTATE_180:
              orig_x      = clip_x - orig_x;
              orig_y      = clip_y - orig_y;
              orig_width  = clip_width;
              orig_height = clip_height;
              break;

            case GIMP_ROTATE_270:
              gimp_drawable_transform_rotate_point (clip_x,
                                                    clip_y + clip_height,
                                                    GIMP_ROTATE_90,
                                                    center_x,
                                                    center_y,
                                                    &orig_x,
                                                    &orig_y);
              orig_x      -= saved_orig_x;
              orig_y      -= saved_orig_y;
              orig_width   = clip_height;
              orig_height  = clip_width;
              break;
            }

          new_width  = clip_width;
          new_height = clip_height;
        }
      else
        {
          new_width  = 0;
          new_height = 0;
        }
    }
  else
    {
      new_buffer = gimp_gegl_buffer_new (GEGL_RECTANGLE (0, 0,
                                                         new_width, new_height),
                                         gegl_buffer_get_format (orig_buffer));

      *new_offset_x = new_x;
      *new_offset_y = new_y;

      orig_x = 0;
      orig_y = 0;
      new_x  = 0;
      new_y  = 0;
    }

  if (new_width < 1 || new_height < 1)
    return new_buffer;

  src_rect.x      = orig_x;
  src_rect.y      = orig_y;
  src_rect.width  = orig_width;
  src_rect.height = orig_height;

  dest_rect.x      = new_x;
  dest_rect.y      = new_y;
  dest_rect.width  = new_width;
  dest_rect.height = new_height;

  switch (rotate_type)
    {
    case GIMP_ROTATE_90:
      {
        guchar *buf = g_new (guchar, new_height * orig_bpp);
        gint    i;

        g_assert (new_height == orig_width);

        src_rect.y      = orig_y + orig_height - 1;
        src_rect.height = 1;

        dest_rect.x     = new_x;
        dest_rect.width = 1;

        for (i = 0; i < orig_height; i++)
          {
            src_rect.y  = orig_y + orig_height - 1 - i;
            dest_rect.x = new_x + i;

            gegl_buffer_get (orig_buffer, &src_rect, 1.0, NULL, buf,
                             GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
            gegl_buffer_set (new_buffer, &dest_rect, 0, NULL, buf,
                             GEGL_AUTO_ROWSTRIDE);
          }

        g_free (buf);
      }
      break;

    case GIMP_ROTATE_180:
      {
        guchar *buf = g_new (guchar, new_width * orig_bpp);
        gint    i, j, k;

        g_assert (new_width == orig_width);

        src_rect.y      = orig_y + orig_height - 1;
        src_rect.height = 1;

        dest_rect.y      = new_y;
        dest_rect.height = 1;

        for (i = 0; i < orig_height; i++)
          {
            src_rect.y  = orig_y + orig_height - 1 - i;
            dest_rect.y = new_y + i;

            gegl_buffer_get (orig_buffer, &src_rect, 1.0, NULL, buf,
                             GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);

            for (j = 0; j < orig_width / 2; j++)
              {
                guchar *left  = buf + j * orig_bpp;
                guchar *right = buf + (orig_width - 1 - j) * orig_bpp;

                for (k = 0; k < orig_bpp; k++)
                  {
                    guchar tmp = left[k];
                    left[k]    = right[k];
                    right[k]   = tmp;
                  }
              }

            gegl_buffer_set (new_buffer, &dest_rect, 0, NULL, buf,
                             GEGL_AUTO_ROWSTRIDE);
          }

        g_free (buf);
      }
      break;

    case GIMP_ROTATE_270:
      {
        guchar *buf = g_new (guchar, new_width * orig_bpp);
        gint    i;

        g_assert (new_width == orig_height);

        src_rect.x     = orig_x + orig_width - 1;
        src_rect.width = 1;

        dest_rect.y      = new_y;
        dest_rect.height = 1;

        for (i = 0; i < orig_width; i++)
          {
            src_rect.x  = orig_x + orig_width - 1 - i;
            dest_rect.y = new_y + i;

            gegl_buffer_get (orig_buffer, &src_rect, 1.0, NULL, buf,
                             GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
            gegl_buffer_set (new_buffer, &dest_rect, 0, NULL, buf,
                             GEGL_AUTO_ROWSTRIDE);
          }

        g_free (buf);
      }
      break;
    }

  return new_buffer;
}
Пример #28
0
GimpDrawable *
gimp_drawable_transform_rotate (GimpDrawable     *drawable,
                                GimpContext      *context,
                                GimpRotationType  rotate_type,
                                gdouble           center_x,
                                gdouble           center_y,
                                gboolean          clip_result)
{
  GimpImage    *image;
  GeglBuffer   *orig_buffer;
  gint          orig_offset_x;
  gint          orig_offset_y;
  gboolean      new_layer;
  GimpDrawable *result = NULL;

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

  image = gimp_item_get_image (GIMP_ITEM (drawable));

  /* Start a transform undo group */
  gimp_image_undo_group_start (image,
                               GIMP_UNDO_GROUP_TRANSFORM,
                               C_("undo-type", "Rotate"));

  /* Cut/Copy from the specified drawable */
  orig_buffer = gimp_drawable_transform_cut (drawable, context,
                                             &orig_offset_x, &orig_offset_y,
                                             &new_layer);

  if (orig_buffer)
    {
      GeglBuffer *new_buffer;
      gint        new_offset_x;
      gint        new_offset_y;

      /*  always clip unfloated buffers so they keep their size  */
      if (GIMP_IS_CHANNEL (drawable) &&
          ! babl_format_has_alpha (gegl_buffer_get_format (orig_buffer)))
        clip_result = TRUE;

      /*  also transform the mask if we are transforming an entire layer  */
      if (GIMP_IS_LAYER (drawable) &&
          gimp_layer_get_mask (GIMP_LAYER (drawable)) &&
          gimp_channel_is_empty (gimp_image_get_mask (image)))
        {
          GimpLayerMask *mask = gimp_layer_get_mask (GIMP_LAYER (drawable));

          gimp_item_rotate (GIMP_ITEM (mask), context,
                            rotate_type,
                            center_x,
                            center_y,
                            clip_result);
        }

      /* transform the buffer */
      new_buffer = gimp_drawable_transform_buffer_rotate (drawable, context,
                                                          orig_buffer,
                                                          orig_offset_x,
                                                          orig_offset_y,
                                                          rotate_type,
                                                          center_x, center_y,
                                                          clip_result,
                                                          &new_offset_x,
                                                          &new_offset_y);

      /* Free the cut/copied buffer */
      g_object_unref (orig_buffer);

      if (new_buffer)
        {
          result = gimp_drawable_transform_paste (drawable, new_buffer,
                                                  new_offset_x, new_offset_y,
                                                  new_layer);
          g_object_unref (new_buffer);
        }
    }

  /*  push the undo group end  */
  gimp_image_undo_group_end (image);

  return result;
}
Пример #29
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;
}
Пример #30
0
GimpDrawable *
gimp_drawable_transform_affine (GimpDrawable           *drawable,
                                GimpContext            *context,
                                const GimpMatrix3      *matrix,
                                GimpTransformDirection  direction,
                                GimpInterpolationType   interpolation_type,
                                gint                    recursion_level,
                                GimpTransformResize     clip_result,
                                GimpProgress           *progress)
{
  GimpImage    *image;
  GeglBuffer   *orig_buffer;
  gint          orig_offset_x;
  gint          orig_offset_y;
  gboolean      new_layer;
  GimpDrawable *result = NULL;

  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 (matrix != NULL, NULL);
  g_return_val_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress), NULL);

  image = gimp_item_get_image (GIMP_ITEM (drawable));

  /* Start a transform undo group */
  gimp_image_undo_group_start (image,
                               GIMP_UNDO_GROUP_TRANSFORM,
                               C_("undo-type", "Transform"));

  /* Cut/Copy from the specified drawable */
  orig_buffer = gimp_drawable_transform_cut (drawable, context,
                                             &orig_offset_x, &orig_offset_y,
                                             &new_layer);

  if (orig_buffer)
    {
      GeglBuffer *new_buffer;
      gint        new_offset_x;
      gint        new_offset_y;

      /*  always clip unfloated buffers so they keep their size  */
      if (GIMP_IS_CHANNEL (drawable) &&
          ! babl_format_has_alpha (gegl_buffer_get_format (orig_buffer)))
        clip_result = GIMP_TRANSFORM_RESIZE_CLIP;

      /*  also transform the mask if we are transforming an entire layer  */
      if (GIMP_IS_LAYER (drawable) &&
          gimp_layer_get_mask (GIMP_LAYER (drawable)) &&
          gimp_channel_is_empty (gimp_image_get_mask (image)))
        {
          GimpLayerMask *mask = gimp_layer_get_mask (GIMP_LAYER (drawable));

          gimp_item_transform (GIMP_ITEM (mask), context,
                               matrix,
                               direction,
                               interpolation_type,
                               recursion_level,
                               clip_result,
                               progress);
        }

      /* transform the buffer */
      new_buffer = gimp_drawable_transform_buffer_affine (drawable, context,
                                                          orig_buffer,
                                                          orig_offset_x,
                                                          orig_offset_y,
                                                          matrix,
                                                          direction,
                                                          interpolation_type,
                                                          recursion_level,
                                                          clip_result,
                                                          &new_offset_x,
                                                          &new_offset_y,
                                                          progress);

      /* Free the cut/copied buffer */
      g_object_unref (orig_buffer);

      if (new_buffer)
        {
          result = gimp_drawable_transform_paste (drawable, new_buffer,
                                                  new_offset_x, new_offset_y,
                                                  new_layer);
          g_object_unref (new_buffer);
        }
    }

  /*  push the undo group end  */
  gimp_image_undo_group_end (image);

  return result;
}