static void
gimp_projection_construct_gegl (GimpProjection *proj,
                                gint            x,
                                gint            y,
                                gint            w,
                                gint            h)
{
    GeglNode      *sink;
    GeglRectangle  rect;

    sink = gimp_projection_get_sink_node (proj);

    rect.x      = x;
    rect.y      = y;
    rect.width  = w;
    rect.height = h;

    if (! proj->processor)
        proj->processor = gegl_node_new_processor (sink, &rect);
    else
        gegl_processor_set_rectangle (proj->processor, &rect);

    while (gegl_processor_work (proj->processor, NULL));

    /* FIXME: Reuse it when it can handle dirty rects when painting
     * properly
     */
    g_object_unref (proj->processor);
    proj->processor = NULL;
}
示例#2
0
文件: gimpcagetool.c 项目: STRNG/gimp
static void
gimp_cage_tool_compute_coef (GimpCageTool *ct)
{
  GimpCageConfig *config = ct->config;
  GimpProgress   *progress;
  const Babl     *format;
  GeglNode       *gegl;
  GeglNode       *input;
  GeglNode       *output;
  GeglProcessor  *processor;
  GeglBuffer     *buffer;
  gdouble         value;

  progress = gimp_progress_start (GIMP_PROGRESS (ct),
                                  _("Computing Cage Coefficients"), FALSE);

  if (ct->coef)
    {
      g_object_unref (ct->coef);
      ct->coef = NULL;
    }

  format = babl_format_n (babl_type ("float"),
                          gimp_cage_config_get_n_points (config) * 2);


  gegl = gegl_node_new ();

  input = gegl_node_new_child (gegl,
                               "operation", "gimp:cage-coef-calc",
                               "config",    ct->config,
                               NULL);

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

  gegl_node_connect_to (input, "output",
                        output, "input");

  processor = gegl_node_new_processor (output, NULL);

  while (gegl_processor_work (processor, &value))
    {
      if (progress)
        gimp_progress_set_value (progress, value);
    }

  if (progress)
    gimp_progress_end (progress);

  g_object_unref (processor);

  ct->coef = buffer;
  g_object_unref (gegl);

  ct->dirty_coef = FALSE;
}
void
view_helper_set_node(ViewHelper *self, GeglNode *node)
{
    if (self->node == node)
        return;

    if (self->node)
        g_object_unref(self->node);

    if (node) {
        g_object_ref(node);
        self->node = node;

        g_signal_connect_object(self->node, "computed",
                                G_CALLBACK(computed_event),
                                self, 0);
        g_signal_connect_object(self->node, "invalidated",
                                G_CALLBACK(invalidated_event),
                                self, 0);

        if (self->processor)
            g_object_unref(self->processor);

        GeglRectangle bbox = gegl_node_get_bounding_box(self->node);
        self->processor = gegl_node_new_processor(self->node, &bbox);

        update_autoscale(self);
        trigger_processing(self, bbox);

    } else
        self->node = NULL;
}
示例#4
0
int dt_dev_pixelpipe_process(dt_dev_pixelpipe_t *pipe, dt_develop_t *dev, int x, int y, int width, int height, float scale)
{
  pipe->processing = 1;
  printf("pixelpipe process start\n");

  // have backbuf in right size:
  if(pipe->backbuf_size < width*height*4*sizeof(uint8_t))
  {
    pthread_mutex_lock(&pipe->backbuf_mutex);
    pipe->backbuf_size = width*height*4*sizeof(uint8_t);
    free(pipe->backbuf);
    pipe->backbuf = (uint8_t *)dt_alloc_align(16, pipe->backbuf_size);
    pthread_mutex_unlock(&pipe->backbuf_mutex);
  }

  // scale node (is slow):
  // scale *= 2;
  // FIXME: this seems to be a bug in gegl. need to manually adjust updated roi here.
  GeglRectangle roi  = (GeglRectangle)
  {
    x, y, width, height
  };
  GeglRectangle roio = (GeglRectangle)
  {
    roi.x/scale, roi.y/scale, roi.width/scale, roi.height/scale
  };
  roio.x      = MAX(0, roio.x);
  roio.y      = MAX(0, roio.y);
  roio.width  = MIN(pipe->iwidth -roio.x-1, roio.width);
  roio.height = MIN(pipe->iheight-roio.y-1, roio.height);
  GeglProcessor *processor = gegl_node_new_processor (pipe->output, &roio);
  // gegl_node_set(pipe->scale, "x", scale, "y", scale, NULL);
  // GeglProcessor *processor = gegl_node_new_processor (pipe->output, roi);
  double         progress;

  // TODO: insert constant scale node at beginning, maintain lo-res branch of pipeline (shadowed).
  // TODO: decide on scale param, which one to use.

  while (gegl_processor_work (processor, &progress))
  {
    // if history changed, abort processing?
    if(pipe->changed != DT_DEV_PIPE_UNCHANGED || dev->gui_leaving) return 1;
  }
  gegl_processor_destroy (processor);

  // gegl scale node turned out to be even slower :(
  gegl_node_blit (pipe->output, scale, &roi, babl_format("RGBA u8"), pipe->backbuf, GEGL_AUTO_ROWSTRIDE, GEGL_BLIT_CACHE);
  // gegl_node_blit (pipe->output, 1.0, roi, babl_format("RGBA u8"), output, GEGL_AUTO_ROWSTRIDE, GEGL_BLIT_CACHE);

  // TODO: update histograms here with this data?
  printf("pixelpipe process end\n");
  pipe->processing = 0;
  return 0;
}
示例#5
0
static void
gimp_drawable_apply_operation_private (GimpDrawable       *drawable,
                                       GimpProgress       *progress,
                                       const gchar        *undo_desc,
                                       GeglNode           *operation,
                                       gboolean            linear,
                                       TileManager         *dest_tiles,
                                       const GeglRectangle *rect)
{
  GeglNode      *gegl;
  GeglNode      *input;
  GeglNode      *output;
  GeglProcessor *processor;
  gdouble        value;

  gegl = gegl_node_new ();

  /* Disable caching on all children of the node unless explicitly re-enabled.
   */
  g_object_set (gegl,
                "dont-cache", TRUE,
                NULL);

  input  = gegl_node_new_child (gegl,
                                "operation",    "gimp:tilemanager-source",
                                "tile-manager", gimp_drawable_get_tiles (drawable),
                                "linear",       linear,
                                NULL);
  output = gegl_node_new_child (gegl,
                                "operation",    "gimp:tilemanager-sink",
                                "tile-manager", dest_tiles,
                                "linear",       linear,
                                NULL);

  gegl_node_add_child (gegl, operation);

  gegl_node_link_many (input, operation, output, NULL);

  processor = gegl_node_new_processor (output, rect);

  if (progress)
    gimp_progress_start (progress, undo_desc, FALSE);

  while (gegl_processor_work (processor, &value))
    if (progress)
      gimp_progress_set_value (progress, value);

  g_object_unref (processor);

  g_object_unref (gegl);
}
示例#6
0
static void
photos_thumbnailer_generate_thumbnail_pixbuf (GObject *source_object, GAsyncResult *res, gpointer user_data)
{
  GCancellable *cancellable;
  g_autoptr (GTask) task = G_TASK (user_data);
  g_autoptr (GdkPixbuf) pixbuf = NULL;
  g_autoptr (GeglBuffer) buffer = NULL;
  g_autoptr (GeglBuffer) buffer_oriented = NULL;
  GeglNode *buffer_source;
  GeglNode *pipeline_node;
  g_autoptr (GeglProcessor) processor = NULL;
  PhotosThumbnailerGenerateData *data;

  cancellable = g_task_get_cancellable (task);
  data = g_task_get_task_data (task);

  {
    g_autoptr (GError) error = NULL;

    pixbuf = photos_pixbuf_new_from_file_at_size_finish (res, &error);
    if (error != NULL)
      {
        g_task_return_error (task, g_steal_pointer (&error));
        goto out;
      }
  }

  buffer = photos_gegl_buffer_new_from_pixbuf (pixbuf);
  buffer_oriented = photos_gegl_buffer_apply_orientation (buffer, data->orientation);

  buffer_source = gegl_node_new_child (data->graph, "operation", "gegl:buffer-source", "buffer", buffer_oriented, NULL);
  pipeline_node = photos_pipeline_get_graph (data->pipeline);
  gegl_node_link (buffer_source, pipeline_node);

  processor = gegl_node_new_processor (pipeline_node, NULL);
  photos_gegl_processor_process_async (processor,
                                       cancellable,
                                       photos_thumbnailer_generate_thumbnail_process,
                                       g_object_ref (task));

 out:
  return;
}
示例#7
0
static gboolean paint_release (GtkWidget      *widget,
                               GdkEventButton *event)
{
  if (event->button == 1)
    {
      gdouble        x0, x1, y0, y1;
      GeglProcessor *processor;
      GeglNode      *writebuf;
      GeglRectangle  roi;

      gegl_path_get_bounds (vector, &x0, &x1, &y0, &y1);

      roi.x = x0 - LINEWIDTH;
      roi.y = y0 - LINEWIDTH;
      roi.width = x1 - x0 + LINEWIDTH * 2;
      roi.height = y1 - y0 + LINEWIDTH * 2;

      writebuf = gegl_node_new_child (gegl,
                                      "operation", "gegl:write-buffer",
                                      "buffer",    buffer,
                                      NULL);
      gegl_node_link_many (over, writebuf, NULL);

      processor = gegl_node_new_processor (writebuf, &roi);
      while (gegl_processor_work (processor, NULL)) ;

      gegl_processor_destroy (processor);
      g_object_unref (writebuf);

      gegl_node_link_many (top, out, NULL);
      g_object_unref (over);
      g_object_unref (stroke);

      over     = NULL;
      stroke   = NULL;
      pen_down = FALSE;

      return TRUE;
    }
  return FALSE;
}
示例#8
0
static void
gimp_seamless_clone_tool_filter_update (GimpSeamlessCloneTool *sc)
{
  GimpTool         *tool  = GIMP_TOOL (sc);
  GimpDisplayShell *shell = gimp_display_get_shell (tool->display);
  GimpItem         *item  = GIMP_ITEM (tool->drawable);
  gint              x, y;
  gint              w, h;
  gint              off_x, off_y;
  GeglRectangle     visible;
  GeglOperation    *op = NULL;

  GimpProgress     *progress;
  GeglNode         *output;
  GeglProcessor    *processor;
  gdouble           value;

  progress = gimp_progress_start (GIMP_PROGRESS (sc), FALSE,
                                  _("Cloning the foreground object"));

  /* Find out at which x,y is the top left corner of the currently
   * displayed part */
  gimp_display_shell_untransform_viewport (shell, &x, &y, &w, &h);

  /* Find out where is our drawable positioned */
  gimp_item_get_offset (item, &off_x, &off_y);

  /* Create a rectangle from the intersection of the currently displayed
   * part with the drawable */
  gimp_rectangle_intersect (x, y, w, h,
                            off_x,
                            off_y,
                            gimp_item_get_width  (item),
                            gimp_item_get_height (item),
                            &visible.x,
                            &visible.y,
                            &visible.width,
                            &visible.height);

  /* Since the filter_apply function receives a rectangle describing
   * where it should update the preview, and since that rectangle should
   * be relative to the drawable's location, we now offset back by the
   * drawable's offsetts. */
  visible.x -= off_x;
  visible.y -= off_y;

  g_object_get (sc->sc_node, "gegl-operation", &op, NULL);
  /* If any cache of the visible area was present, clear it!
   * We need to clear the cache in the sc_node, since that is
   * where the previous paste was located
   */
  gegl_operation_invalidate (op, &visible, TRUE);
  g_object_unref (op);

  /* Now update the image map and show this area */
  gimp_drawable_filter_apply (sc->filter, NULL);

  /* Show update progress. */
  output = gegl_node_get_output_proxy (sc->render_node, "output");
  processor = gegl_node_new_processor (output, NULL);

  while (gegl_processor_work (processor, &value))
    {
      if (progress)
        gimp_progress_set_value (progress, value);
    }

  if (progress)
    gimp_progress_end (progress);

  g_object_unref (processor);
}
int main(int argc, char *argv[])
{
  gint           result       = SUCCESS;
  GeglRectangle  rect1        = { 0, 0, 1, 1 };
  GeglRectangle  rect2        = { 1, 0, 1, 1 };
  GeglRectangle  rect3        = { 1, 1, 1, 1 };
  GeglRectangle  rect4        = { 0, 1, 1, 1 };
  GeglColor     *color_white = NULL;
  GeglColor     *color_black = NULL;
  GeglNode      *gegl        = NULL;
  GeglNode      *white       = NULL;
  GeglNode      *translate   = NULL;
  GeglNode      *over        = NULL;
  GeglNode      *black       = NULL;
  GeglNode      *crop        = NULL;
  GeglNode      *sink        = NULL;
  GeglProcessor *processor   = NULL;

  /* Convenient line to keep around:
  g_log_set_always_fatal (G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL);
   */

  gegl_init (&argc, &argv);

  color_white = gegl_color_new ("rgb(1.0, 1.0, 1.0)");
  color_black = gegl_color_new ("rgb(0.0, 0.0, 0.0)");

  gegl         = gegl_node_new ();
  white        = gegl_node_new_child (gegl,
                                      "operation", "gegl:color",
                                      "value", color_white,
                                      NULL);
  translate    = gegl_node_new_child (gegl,
                                      "operation", "gegl:translate",
                                      "x", -50.0,
                                      "y", -20.0,
                                      NULL);
  over         = gegl_node_new_child (gegl,
                                      "operation", "gegl:over",
                                      NULL);
  black        = gegl_node_new_child (gegl,
                                      "operation", "gegl:color",
                                      "value", color_black,
                                      NULL);
  crop         = gegl_node_new_child (gegl,
                                      "operation", "gegl:crop",
                                      "x", 10.0,
                                      "y", 10.0,
                                      "width", 100.0,
                                      "height", 100.0,
                                      NULL);
  sink         = gegl_node_new_child (gegl,
                                      "operation", "gegl:buffer-sink",
                                      NULL);

  /* We build our graph for processing complexity, not for compositing
   * complexity
   */
  gegl_node_link_many (black, over, sink, NULL);
  gegl_node_link_many (white, crop, translate, NULL);
  gegl_node_connect_to (translate, "output",  over, "aux");

  /* Create a processor */
  processor = gegl_node_new_processor (sink, NULL);

  /* Do the tests */
  if (!test_change_processor_rect_do_test (processor, &rect1, sink))
    {
      g_printerr ("test-change-processor-rect: First compare failed\n");
      result = FAILURE;
      goto abort;
    }
  if (!test_change_processor_rect_do_test (processor, &rect2, sink))
    {
      g_printerr ("test-change-processor-rect: Second compare failed\n");
      result = FAILURE;
      goto abort;
    }
  if (!test_change_processor_rect_do_test (processor, &rect3, sink))
    {
      g_printerr ("test-change-processor-rect: Third compare failed\n");
      result = FAILURE;
      goto abort;
    }
  if (!test_change_processor_rect_do_test (processor, &rect4, sink))
    {
      g_printerr ("test-change-processor-rect: Fourth compare failed\n");
      result = FAILURE;
      goto abort;
    }

  /* Cleanup */
 abort:
  g_object_unref (processor);
  g_object_unref (color_white);
  g_object_unref (color_black);
  g_object_unref (gegl);
  gegl_exit ();

  return result;
}
示例#10
0
void
gimp_gegl_apply_operation (GeglBuffer          *src_buffer,
                           GimpProgress        *progress,
                           const gchar         *undo_desc,
                           GeglNode            *operation,
                           GeglBuffer          *dest_buffer,
                           const GeglRectangle *dest_rect)
{
  GeglNode      *gegl;
  GeglNode      *dest_node;
  GeglRectangle  rect = { 0, };
  gdouble        value;
  gboolean       progress_active = FALSE;

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

  if (dest_rect)
    {
      rect = *dest_rect;
    }
  else
    {
      rect = *GEGL_RECTANGLE (0, 0, gegl_buffer_get_width  (dest_buffer),
                                    gegl_buffer_get_height (dest_buffer));
    }

  gegl = gegl_node_new ();

  if (! gegl_node_get_parent (operation))
    gegl_node_add_child (gegl, operation);

  if (src_buffer && gegl_node_has_pad (operation, "input"))
    {
      GeglNode *src_node;

      /* dup() because reading and writing the same buffer doesn't
       * work with area ops when using a processor. See bug #701875.
       */
      if (progress && (src_buffer == dest_buffer))
        src_buffer = gegl_buffer_dup (src_buffer);
      else
        g_object_ref (src_buffer);

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

      g_object_unref (src_buffer);

      gegl_node_connect_to (src_node,  "output",
                            operation, "input");
    }

  dest_node = gegl_node_new_child (gegl,
                                   "operation", "gegl:write-buffer",
                                   "buffer",    dest_buffer,
                                   NULL);


  gegl_node_connect_to (operation, "output",
                        dest_node, "input");

  if (progress)
    {
      GeglProcessor *processor;

      processor = gegl_node_new_processor (dest_node, &rect);

      progress_active = gimp_progress_is_active (progress);

      if (progress_active)
        {
          if (undo_desc)
            gimp_progress_set_text (progress, undo_desc);
        }
      else
        {
          gimp_progress_start (progress, undo_desc, FALSE);
        }

      while (gegl_processor_work (processor, &value))
        gimp_progress_set_value (progress, value);

      g_object_unref (processor);
    }
  else
    {
      gegl_node_blit (dest_node, 1.0, &rect,
                      NULL, NULL, 0, GEGL_BLIT_DEFAULT);
    }

  g_object_unref (gegl);

  if (progress && ! progress_active)
    gimp_progress_end (progress);
}
int main(int argc, char *argv[])
{
  gint           result       = SUCCESS;
  GeglRectangle  rect1        = { 0, 0, 1, 1 };
  GeglRectangle  rect2        = { 1, 0, 1, 1 };
  GeglRectangle  rect3        = { 1, 1, 1, 1 };
  GeglRectangle  rect4        = { 0, 1, 1, 1 };
  GeglColor     *common_color = NULL;
  GeglNode      *gegl         = NULL;
  GeglNode      *color        = NULL;
  GeglNode      *layer        = NULL;
  GeglNode      *text         = NULL;
  GeglNode      *sink         = NULL;
  GeglProcessor *processor    = NULL;

  /* Convenient line to keep around:
  g_log_set_always_fatal (G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL);
   */

  g_thread_init (NULL);
  gegl_init (&argc, &argv);

  common_color = gegl_color_new ("rgb(1.0, 1.0, 1.0)");

  gegl         = gegl_node_new ();
  color        = gegl_node_new_child (gegl,
                                      "operation", "gegl:color",
                                      "value", common_color,
                                      NULL);
  layer        = gegl_node_new_child (gegl,
                                      "operation", "gegl:layer",
                                      "x", 0.0,
                                      "y", 0.0,
                                      NULL);
  text         = gegl_node_new_child (gegl,
                                      "operation", "gegl:text",
                                      "color", common_color,
                                      "string", "█████████████████████████",
                                      "size", 200.0,
                                      NULL);
  sink         = gegl_node_new_child (gegl,
                                      "operation", "gegl:buffer-sink",
                                      NULL);

  /* We build our graph for processing complexity, not for compositing
   * complexity
   */
  gegl_node_link_many (color, layer, sink, NULL);
  gegl_node_connect_to (text, "output",  layer, "aux");

  /* Create a processor */
  processor = gegl_node_new_processor (sink, NULL);

  /* Do the tests */
  if (!test_change_processor_rect_do_test (processor, &rect1, sink))
    {
      g_printerr ("test-change-processor-rect: First compare failed\n");
      result = FAILURE;
      goto abort;
    }
  if (!test_change_processor_rect_do_test (processor, &rect2, sink))
    {
      g_printerr ("test-change-processor-rect: Second compare failed\n");
      result = FAILURE;
      goto abort;
    }
  if (!test_change_processor_rect_do_test (processor, &rect3, sink))
    {
      g_printerr ("test-change-processor-rect: Third compare failed\n");
      result = FAILURE;
      goto abort;
    }
  if (!test_change_processor_rect_do_test (processor, &rect4, sink))
    {
      g_printerr ("test-change-processor-rect: Fourth compare failed\n");
      result = FAILURE;
      goto abort;
    }

  /* Cleanup */
 abort:
  g_object_unref (processor);
  g_object_unref (common_color);
  g_object_unref (gegl);
  gegl_exit ();

  return result;
}
static void
gimp_foreground_select_tool_preview (GimpForegroundSelectTool *fg_select,
                                     GimpDisplay              *display)
{
  GimpTool                    *tool     = GIMP_TOOL (fg_select);
  GimpForegroundSelectOptions *options  = GIMP_FOREGROUND_SELECT_TOOL_GET_OPTIONS (tool);
  GimpImage                   *image    = gimp_display_get_image (display);
  GimpDrawable                *drawable = gimp_image_get_active_drawable (image);
  GeglBuffer                  *trimap_buffer;
  GeglBuffer                  *drawable_buffer;
  GeglNode                    *gegl;
  GeglNode                    *matting_node;
  GeglNode                    *input_image;
  GeglNode                    *input_trimap;
  GeglNode                    *output_mask;
  GeglBuffer                  *buffer;
  GimpProgress                *progress;
  GeglProcessor               *processor;
  gdouble                     value;

  if (fg_select->mask)
    {
      g_object_unref (fg_select->mask);
      fg_select->mask = NULL;
    }

  progress = gimp_progress_start (GIMP_PROGRESS (fg_select),
                                  _("Computing alpha of unknown pixels"),
                                  FALSE);

  trimap_buffer   = fg_select->trimap;
  drawable_buffer = gimp_drawable_get_buffer (drawable);

  gegl = gegl_node_new ();

  input_trimap = gegl_node_new_child (gegl,
                                      "operation", "gegl:buffer-source",
                                      "buffer",    trimap_buffer,
                                      NULL);
  input_image = gegl_node_new_child (gegl,
                                     "operation", "gegl:buffer-source",
                                     "buffer",    drawable_buffer,
                                     NULL);
  output_mask = gegl_node_new_child (gegl,
                                     "operation", "gegl:buffer-sink",
                                     "buffer",    &buffer,
                                     "format",    NULL,
                                     NULL);

  if (options->engine == GIMP_MATTING_ENGINE_GLOBAL)
    {
      matting_node = gegl_node_new_child (gegl,
                                          "operation",  "gegl:matting-global",
                                          "iterations", options->iterations,
                                          NULL);
    }
  else
    {
      matting_node = gegl_node_new_child (gegl,
                                          "operation",     "gegl:matting-levin",
                                          "levels",        options->levels,
                                          "active_levels", options->active_levels,
                                          NULL);
    }

  gegl_node_connect_to (input_image,  "output",
                        matting_node, "input");
  gegl_node_connect_to (input_trimap, "output",
                        matting_node, "aux");
  gegl_node_connect_to (matting_node, "output",
                        output_mask,  "input");

  processor = gegl_node_new_processor (output_mask, NULL);

  while (gegl_processor_work (processor, &value))
    {
      if (progress)
        gimp_progress_set_value (progress, value);
    }

  if (progress)
    gimp_progress_end (progress);

  g_object_unref (processor);

  fg_select->mask = buffer;

  gimp_foreground_select_tool_set_preview (fg_select, display);

  g_object_unref (gegl);
}
示例#13
0
GimpApplicator *
gimp_applicator_new (GeglBuffer        *dest_buffer,
                     GimpComponentMask  affect,
                     GeglBuffer        *mask_buffer,
                     gint               mask_offset_x,
                     gint               mask_offset_y)
{
    GimpApplicator *applicator;

    g_return_val_if_fail (GEGL_IS_BUFFER (dest_buffer), NULL);
    g_return_val_if_fail (mask_buffer == NULL || GEGL_IS_BUFFER (mask_buffer),
                          NULL);

    applicator = g_object_new (GIMP_TYPE_APPLICATOR, NULL);

    applicator->node = gegl_node_new ();

    applicator->mode_node = gegl_node_new_child (applicator->node,
                            "operation", "gimp:normal-mode",
                            NULL);

    applicator->src_node =
        gegl_node_new_child (applicator->node,
                             "operation", "gegl:buffer-source",
                             NULL);

    gegl_node_connect_to (applicator->src_node,  "output",
                          applicator->mode_node, "input");

    applicator->apply_src_node =
        gegl_node_new_child (applicator->node,
                             "operation", "gegl:buffer-source",
                             NULL);

    applicator->apply_offset_node =
        gegl_node_new_child (applicator->node,
                             "operation", "gegl:translate",
                             NULL);

    gegl_node_connect_to (applicator->apply_src_node,    "output",
                          applicator->apply_offset_node, "input");
    gegl_node_connect_to (applicator->apply_offset_node, "output",
                          applicator->mode_node,         "aux");

    if (mask_buffer)
    {
        GeglNode *mask_src;

        mask_src = gegl_node_new_child (applicator->node,
                                        "operation", "gegl:buffer-source",
                                        "buffer",    mask_buffer,
                                        NULL);

        if (mask_offset_x != 0 || mask_offset_y != 0)
        {
            GeglNode *offset;

            offset = gegl_node_new_child (applicator->node,
                                          "operation", "gegl:translate",
                                          "x",         (gdouble) mask_offset_x,
                                          "y",         (gdouble) mask_offset_y,
                                          NULL);

            gegl_node_connect_to (mask_src,              "output",
                                  offset,                "input");
            gegl_node_connect_to (offset,                "output",
                                  applicator->mode_node, "aux2");
        }
        else
        {
            gegl_node_connect_to (mask_src,              "output",
                                  applicator->mode_node, "aux2");
        }
    }

    applicator->dest_node =
        gegl_node_new_child (applicator->node,
                             "operation", "gegl:write-buffer",
                             "buffer",    dest_buffer,
                             "flush",     FALSE,
                             NULL);

    if (affect == GIMP_COMPONENT_ALL)
    {
        gegl_node_connect_to (applicator->mode_node, "output",
                              applicator->dest_node, "input");
    }
    else
    {
        GeglNode *affect_node;

        affect_node = gegl_node_new_child (applicator->node,
                                           "operation", "gimp:mask-components",
                                           "mask",      affect,
                                           NULL);

        gegl_node_connect_to (applicator->src_node,  "output",
                              affect_node,           "input");
        gegl_node_connect_to (applicator->mode_node, "output",
                              affect_node,           "aux");
        gegl_node_connect_to (affect_node,           "output",
                              applicator->dest_node, "input");
    }

    applicator->processor = gegl_node_new_processor (applicator->dest_node, NULL);

    return applicator;
}
GeglBuffer *
gimp_drawable_foreground_extract (GimpDrawable      *drawable,
                                  GimpMattingEngine  engine,
                                  gint               global_iterations,
                                  gint               levin_levels,
                                  gint               levin_active_levels,
                                  GeglBuffer        *trimap,
                                  GimpProgress      *progress)
{
  GeglBuffer    *drawable_buffer;
  GeglNode      *gegl;
  GeglNode      *input_node;
  GeglNode      *trimap_node;
  GeglNode      *matting_node;
  GeglNode      *output_node;
  GeglBuffer    *buffer;
  GeglProcessor *processor;
  gdouble        value;

  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);
  g_return_val_if_fail (GEGL_IS_BUFFER (trimap), NULL);
  g_return_val_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress), NULL);

  progress = gimp_progress_start (progress, FALSE,
                                  _("Computing alpha of unknown pixels"));

  drawable_buffer = gimp_drawable_get_buffer (drawable);

  gegl = gegl_node_new ();

  trimap_node = gegl_node_new_child (gegl,
                                     "operation", "gegl:buffer-source",
                                     "buffer",    trimap,
                                     NULL);
  input_node = gegl_node_new_child (gegl,
                                    "operation", "gegl:buffer-source",
                                    "buffer",    drawable_buffer,
                                    NULL);
  output_node = gegl_node_new_child (gegl,
                                     "operation", "gegl:buffer-sink",
                                     "buffer",    &buffer,
                                     "format",    NULL,
                                     NULL);

  if (engine == GIMP_MATTING_ENGINE_GLOBAL)
    {
      matting_node = gegl_node_new_child (gegl,
                                          "operation",  "gegl:matting-global",
                                          "iterations", global_iterations,
                                          NULL);
    }
  else
    {
      matting_node = gegl_node_new_child (gegl,
                                          "operation",     "gegl:matting-levin",
                                          "levels",        levin_levels,
                                          "active_levels", levin_active_levels,
                                          NULL);
    }

  gegl_node_connect_to (input_node,   "output",
                        matting_node, "input");
  gegl_node_connect_to (trimap_node,  "output",
                        matting_node, "aux");
  gegl_node_connect_to (matting_node, "output",
                        output_node,  "input");

  processor = gegl_node_new_processor (output_node, NULL);

  while (gegl_processor_work (processor, &value))
    {
      if (progress)
        gimp_progress_set_value (progress, value);
    }

  if (progress)
    gimp_progress_end (progress);

  g_object_unref (processor);

  g_object_unref (gegl);

  return buffer;
}
示例#15
0
gboolean
gimp_gegl_apply_cached_operation (GeglBuffer          *src_buffer,
                                  GimpProgress        *progress,
                                  const gchar         *undo_desc,
                                  GeglNode            *operation,
                                  GeglBuffer          *dest_buffer,
                                  const GeglRectangle *dest_rect,
                                  GeglBuffer          *cache,
                                  const GeglRectangle *valid_rects,
                                  gint                 n_valid_rects,
                                  gboolean             cancellable)
{
  GeglNode      *gegl;
  GeglNode      *dest_node;
  GeglRectangle  rect = { 0, };
  GeglProcessor *processor        = NULL;
  gboolean       progress_started = FALSE;
  gdouble        value;
  gboolean       cancel           = FALSE;

  g_return_val_if_fail (src_buffer == NULL || GEGL_IS_BUFFER (src_buffer), FALSE);
  g_return_val_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress), FALSE);
  g_return_val_if_fail (GEGL_IS_NODE (operation), FALSE);
  g_return_val_if_fail (GEGL_IS_BUFFER (dest_buffer), FALSE);
  g_return_val_if_fail (cache == NULL || GEGL_IS_BUFFER (cache), FALSE);
  g_return_val_if_fail (valid_rects == NULL || cache != NULL, FALSE);
  g_return_val_if_fail (valid_rects == NULL || n_valid_rects != 0, FALSE);

  if (dest_rect)
    {
      rect = *dest_rect;
    }
  else
    {
      rect = *GEGL_RECTANGLE (0, 0, gegl_buffer_get_width  (dest_buffer),
                                    gegl_buffer_get_height (dest_buffer));
    }

  gegl = gegl_node_new ();

  if (! gegl_node_get_parent (operation))
    gegl_node_add_child (gegl, operation);

  if (src_buffer && gegl_node_has_pad (operation, "input"))
    {
      GeglNode *src_node;

      /* dup() because reading and writing the same buffer doesn't
       * work with area ops when using a processor. See bug #701875.
       */
      if (progress && (src_buffer == dest_buffer))
        src_buffer = gegl_buffer_dup (src_buffer);
      else
        g_object_ref (src_buffer);

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

      g_object_unref (src_buffer);

      gegl_node_connect_to (src_node,  "output",
                            operation, "input");
    }

  dest_node = gegl_node_new_child (gegl,
                                   "operation", "gegl:write-buffer",
                                   "buffer",    dest_buffer,
                                   NULL);

  gegl_node_connect_to (operation, "output",
                        dest_node, "input");

  if (progress)
    {
      processor = gegl_node_new_processor (dest_node, &rect);

      if (gimp_progress_is_active (progress))
        {
          if (undo_desc)
            gimp_progress_set_text_literal (progress, undo_desc);

          progress_started = FALSE;
          cancellable      = FALSE;
        }
      else
        {
          gimp_progress_start (progress, cancellable, "%s", undo_desc);

          if (cancellable)
            g_signal_connect (progress, "cancel",
                              G_CALLBACK (gimp_gegl_apply_operation_cancel),
                              &cancel);

          progress_started = TRUE;
        }
    }

  if (cache)
    {
      cairo_region_t *region;
      gint            all_pixels;
      gint            done_pixels = 0;
      gint            n_rects;
      gint            i;

      region = cairo_region_create_rectangle ((cairo_rectangle_int_t *) &rect);

      all_pixels = rect.width * rect.height;

      for (i = 0; i < n_valid_rects; i++)
        {
          gegl_buffer_copy (cache,       valid_rects + i, GEGL_ABYSS_NONE,
                            dest_buffer, valid_rects + i);

          cairo_region_subtract_rectangle (region,
                                           (cairo_rectangle_int_t *)
                                           valid_rects + i);

          done_pixels += valid_rects[i].width * valid_rects[i].height;

          if (progress)
            gimp_progress_set_value (progress,
                                     (gdouble) done_pixels /
                                     (gdouble) all_pixels);
        }

      n_rects = cairo_region_num_rectangles (region);

      for (i = 0; ! cancel && (i < n_rects); i++)
        {
          cairo_rectangle_int_t render_rect;

          cairo_region_get_rectangle (region, i, &render_rect);

          if (progress)
            {
              gint rect_pixels = render_rect.width * render_rect.height;

#ifdef REUSE_PROCESSOR
              gegl_processor_set_rectangle (processor,
                                            (GeglRectangle *) &render_rect);
#else
              g_object_unref (processor);
              processor = gegl_node_new_processor (dest_node,
                                                   (GeglRectangle *) &render_rect);
#endif

              while (! cancel && gegl_processor_work (processor, &value))
                {
                  gimp_progress_set_value (progress,
                                           ((gdouble) done_pixels +
                                            value * rect_pixels) /
                                           (gdouble) all_pixels);

                  if (cancellable)
                    while (! cancel && g_main_context_pending (NULL))
                      g_main_context_iteration (NULL, FALSE);
                }

              done_pixels += rect_pixels;
            }
          else
            {
              gegl_node_blit (dest_node, 1.0, (GeglRectangle *) &render_rect,
                              NULL, NULL, 0, GEGL_BLIT_DEFAULT);
            }
        }

      cairo_region_destroy (region);
    }
  else
    {
      if (progress)
        {
          while (! cancel && gegl_processor_work (processor, &value))
            {
              gimp_progress_set_value (progress, value);

              if (cancellable)
                while (! cancel && g_main_context_pending (NULL))
                  g_main_context_iteration (NULL, FALSE);
            }
        }
      else
        {
          gegl_node_blit (dest_node, 1.0, &rect,
                          NULL, NULL, 0, GEGL_BLIT_DEFAULT);
        }
    }

  if (processor)
    g_object_unref (processor);

  g_object_unref (gegl);

  if (progress_started)
    {
      gimp_progress_end (progress);

      if (cancellable)
        g_signal_handlers_disconnect_by_func (progress,
                                              gimp_gegl_apply_operation_cancel,
                                              &cancel);
    }

  return ! cancel;
}