예제 #1
0
파일: inpaint.c 프로젝트: jonnor/gegl
static gboolean
process (GeglOperation       *operation,
         GeglBuffer          *input,
         GeglBuffer          *output,
         const GeglRectangle *result,
         gint                 level)
{
  GeglProperties *o      = GEGL_PROPERTIES (operation);
  GeglRectangle in_rect = *gegl_buffer_get_extent (input);
  GeglRectangle out_rect = *gegl_buffer_get_extent (output);
  PixelDuster    *duster = pixel_duster_new (input, output, &in_rect, &out_rect,
                                             o->seek_distance,
                                             1,
                                             o->min_neigh,
                                             o->min_iter,
                                             o->chance_try,
                                             o->chance_retry,
                                             1.0,
                                             1.0,
                                             operation);
  seed_db (duster);
  gegl_buffer_copy (input, NULL, GEGL_ABYSS_NONE, output, NULL);
  fprintf (stderr, "adding transparent probes");
  pixel_duster_add_probes_for_transparent (duster);
  fprintf (stderr, "\n");
  pixel_duster_fill (duster);
  pixel_duster_destroy (duster);

  return TRUE;
}
예제 #2
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;
}
예제 #3
0
static int extract_mid_col (GeglBuffer *buffer, void *rgb_mid_col, int samples)
{
  GeglRectangle mid_col;
  mid_col.x = 0;
  mid_col.y =
     gegl_buffer_get_extent (buffer)-> height * 1.0 *
      samples / gegl_buffer_get_extent (buffer)->width / 2.0;
  mid_col.height = 1;
  mid_col.width = samples;
  gegl_buffer_get (video_frame, &mid_col,
     1.0 * samples / gegl_buffer_get_extent (buffer)->width,
     babl_format ("RGBA u8"),
     rgb_mid_col,
     GEGL_AUTO_ROWSTRIDE,
     GEGL_ABYSS_NONE);
  return 3 * samples;
}
예제 #4
0
static int extract_mid_row (GeglBuffer *buffer, void *rgb_mid_row, int samples)
{
  GeglRectangle mid_row;
  mid_row.width = 1;
  mid_row.height = samples;
  mid_row.x =
     gegl_buffer_get_extent (buffer)-> width * 1.0 *
      samples / gegl_buffer_get_extent (buffer)->height / 2.0;
  mid_row.y = 0;
  gegl_buffer_get (buffer, &mid_row,
    1.0 * samples / gegl_buffer_get_extent (buffer)->height,
    babl_format ("RGBA u8"),
    rgb_mid_row,
    GEGL_AUTO_ROWSTRIDE,
    GEGL_ABYSS_NONE);
  return 3 * samples;
}
예제 #5
0
static GeglRectangle
get_bounding_box (GeglOperation *operation)
{
  GeglRectangle result = {0,0,0,0};
  GeglBuffer   *buffer = ensure_buffer (operation);

  result = *gegl_buffer_get_extent (GEGL_BUFFER (buffer));
  return result;
}
예제 #6
0
파일: warp.c 프로젝트: AjayRamanathan/gegl
static gboolean
process (GeglOperation       *operation,
         GeglBuffer          *input,
         GeglBuffer          *output,
         const GeglRectangle *result,
         gint                 level)
{
  GeglChantO          *o = GEGL_CHANT_PROPERTIES (operation);
  WarpPrivate         *priv = (WarpPrivate*) o->chant_data;
  gdouble              dist;
  gdouble              stamps;
  gdouble              spacing = MAX (o->size * 0.01, 0.5); /*1% spacing for starters*/

  GeglPathPoint        prev, next, lerp;
  gulong               i;
  GeglPathList        *event;

  priv->buffer = gegl_buffer_dup (input);

  event = gegl_path_get_path (o->stroke);

  prev = *(event->d.point);

  while (event->next)
    {
      event = event->next;
      next = *(event->d.point);
      dist = gegl_path_point_dist (&next, &prev);
      stamps = dist / spacing;

      if (stamps < 1)
        {
          stamp (o, result, next.x, next.y);
          prev = next;
        }
      else
        {
          for (i = 0; i < stamps; i++)
            {
              gegl_path_point_lerp (&lerp, &prev, &next, (i * spacing) / dist);
              stamp (o, result, lerp.x, lerp.y);
            }
          prev = lerp;
        }
    }

  /* Affect the output buffer */
  gegl_buffer_copy (priv->buffer, result, output, result);
  gegl_buffer_set_extent (output, gegl_buffer_get_extent (input));
  g_object_unref (priv->buffer);

  /* prepare for the recomputing of the op */
  priv->last_point_set = FALSE;

  return TRUE;
}
예제 #7
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;
}
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 ();
}
예제 #9
0
static GeglRectangle
get_bounding_box (GeglOperation *operation)
{
    GeglRectangle result = {0,0,0,0};
    GeglProperties   *o = GEGL_PROPERTIES (operation);

    if (!o->buffer)
    {
        return result;
    }
    result = *gegl_buffer_get_extent (GEGL_BUFFER (o->buffer));
    return result;
}
예제 #10
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);
}
예제 #11
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;
}
예제 #12
0
static void
copy_one_component (GeglBuffer      *src,
                    GeglBuffer      *dst,
                    const gchar     *model,
                    const COMPONENT  component,
                    gboolean         clamp)
{
  const Babl *component_format, *dst_format;
  GeglBuffer *temp;
  const GeglRectangle *extent;

  /* We are working in linear double precison*/
  component_format = babl_format_new (babl_model (model),
                                      babl_type ("double"),
                                      babl_component (component.babl_name),
                                      NULL);

  /* We need to enforce linearity here
   * If the output is "Y'", the ouput of temp is already ok
   * If the output is "Y" , it will enforce gamma-decoding.
   * A bit tricky and suboptimal...
   */
  if (component.perceptual_channel)
    dst_format = babl_format ("Y' double");
  else
    dst_format = babl_format ("Y double");

  extent = gegl_buffer_get_extent (src);
  temp = gegl_buffer_new (extent, dst_format);

  /* we want to copy the component as is */
  gegl_buffer_set_format (temp, component_format);
  gegl_buffer_copy (src, NULL, temp, NULL);

  if (component.range_min != 0.0 || component.range_max != 1.0 || clamp)
    cpn_affine_transform_clamp (temp, component.range_min, component.range_max);

  /* This is our new "Y(') double" component buffer */
  gegl_buffer_set_format (temp, NULL);

  /* Now we let babl convert it back to the format that dst needs */
  gegl_buffer_copy (temp, NULL, dst, NULL);

  g_object_unref (temp);
}
예제 #13
0
static void
gimp_channel_combine_end (GimpChannel            *mask,
                          GimpChannelCombineData *data)
{
  GeglBuffer *buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (mask));

  gegl_buffer_set_abyss (buffer, gegl_buffer_get_extent (buffer));

  gegl_buffer_thaw_changed (buffer);

  mask->bounds_known = data->bounds_known;

  if (data->bounds_known)
    {
      mask->empty = data->empty;

      if (data->empty)
        {
          mask->x1 = 0;
          mask->y1 = 0;
          mask->x2 = gimp_item_get_width  (GIMP_ITEM (mask));
          mask->y2 = gimp_item_get_height (GIMP_ITEM (mask));
        }
      else
        {
          mask->x1 = data->bounds.x;
          mask->y1 = data->bounds.y;
          mask->x2 = data->bounds.x + data->bounds.width;
          mask->y2 = data->bounds.y + data->bounds.height;
        }
    }

  gimp_drawable_update (GIMP_DRAWABLE (mask),
                        data->rect.x, data->rect.y,
                        data->rect.width, data->rect.height);
}
예제 #14
0
/* this should only be possible if this buffer matches all the buffers down to
 * storage, all of those parent buffers would change size as well, no tiles
 * would be voided as a result of changing the extent.
 */
gboolean
gegl_buffer_set_extent (GeglBuffer          *buffer,
                        const GeglRectangle *extent)
{
  g_return_val_if_fail(GEGL_IS_BUFFER(buffer), FALSE);
   (*(GeglRectangle*)gegl_buffer_get_extent (buffer))=*extent;

  if ((GeglBufferHeader*)(gegl_buffer_backend (buffer)->priv->header))
    {
      GeglBufferHeader *header =
        ((GeglBufferHeader*)(gegl_buffer_backend (buffer)->priv->header));
      header->x = buffer->extent.x;
      header->y = buffer->extent.y;
      header->width = buffer->extent.width;
      header->height = buffer->extent.height;
    }

  if (buffer->abyss_tracks_extent)
    {
      buffer->abyss = *extent;
    }

  return TRUE;
}
예제 #15
0
static int extract_thumb (GeglBuffer *buffer, void *rgb_thumb, int samples, int samples2)
{
  GeglRectangle thumb_scan;
  static float vpos = 0.0;
  if (horizontal)
  {
    thumb_scan.y = 0;
    thumb_scan.x =
       gegl_buffer_get_extent (buffer)-> width * 1.0 *
       samples / gegl_buffer_get_extent (buffer)->width * vpos;
    vpos += (1.0/samples2);
    if (vpos > 1.0) vpos = 0.0;
    thumb_scan.width = 1;
    thumb_scan.height = samples;
  }
  else
  {
    thumb_scan.x = 0;
    thumb_scan.y =
       gegl_buffer_get_extent (buffer)-> height * 1.0 *
       samples / gegl_buffer_get_extent (buffer)->width * vpos;
    vpos += (1.0/samples2);
    if (vpos > 1.0) vpos = 0.0;
    thumb_scan.height = 1;
    thumb_scan.width = samples;
  }
  gegl_buffer_get (buffer, &thumb_scan,
     horizontal?1.0 * samples/ gegl_buffer_get_extent (buffer)->height:
                1.0 * samples/ gegl_buffer_get_extent (buffer)->width,
     babl_format ("RGBA u8"),
     (void*)rgb_thumb,
     //(void*)&(info->rgb_thumb)[0],
     GEGL_AUTO_ROWSTRIDE,
     GEGL_ABYSS_NONE);
  return 3 * samples;
}
예제 #16
0
static void
copy_through_lens (LensCorrectionModel *oip,
                   GeglBuffer *src,
                   GeglBuffer *dst)
{
  const GeglRectangle *src_extent;
  const GeglRectangle *dst_extent;
  gfloat *src_buf;
  gfloat *dst_buf;
  gint x,y;             /* Coordinate of current dst pixel. */
  gint rgb;             /* Color channel of dst pixel being processed. */
  gint doffset;             /* Buffer offset of current dst pixel. */
  gint tmpx, tmpy, toff;
  ChannelCorrectionModel *ccm[3];   /* Allow access to red,green,blue models in loop. */

  src_extent = gegl_buffer_get_extent (src);
  #ifdef TRACE
    g_warning ("> copy_through_lens src_extent = %dx%d+%d+%d",
                 src_extent->width, src_extent->height, src_extent->x,src_extent->y);
  #endif
  if (dst == NULL)
    {
      #ifdef TRACE
        g_warning ("  dst is NULL");
        g_warning ("< copy_through_lens");
      #endif
      return;
    }
  dst_extent = gegl_buffer_get_extent (dst);
  if (dst_extent == NULL) {
      #ifdef TRACE
        g_warning ("  dst_extent is NULL");
        g_warning ("< copy_through_lens");
      #endif
      return;
  }

  /* Get src pixels. */
  src_buf = g_new0 (gfloat, gegl_buffer_get_pixel_count (src) * 3);
  gegl_buffer_get (src, 1.0, NULL, babl_format ("RGB float"), src_buf, GEGL_AUTO_ROWSTRIDE);

  /* Get buffer in which to place dst pixels. */
  dst_buf = g_new0 (gfloat, gegl_buffer_get_pixel_count (dst) * 3);

  /* Compute each dst pixel in turn and store into dst buffer. */
  ccm[0] = &oip->red;
  ccm[1] = &oip->green;
  ccm[2] = &oip->blue;
  doffset = 0;
  for (y=dst_extent->y; y<dst_extent->height + dst_extent->y; y++)
    {
      for (x=dst_extent->x; x<dst_extent->width + dst_extent->x; x++)
    {
      for (rgb = 0; rgb < 3; rgb++)
        {
          gfloat gx, gy;
          gfloat val = 0.0;
          gint xx, yy;
          gfloat wx[2], wy[2], wt = 0.0;

          find_src_pixel (oip, ccm[rgb], (gfloat)x, (gfloat)y, &gx, &gy);
          tmpx = gx;
          tmpy = gy;
          wx[1] = gx - tmpx;
          wx[0] = 1.0 - wx[1];
          wy[1] = gy - tmpy;
          wy[0] = 1.0 - wy[1];
          tmpx -= src_extent->x;
          tmpy -= src_extent->y;
          toff = (tmpy * ROW + tmpx) * 3;
          for (xx = 0; xx < 2; xx++)
            {
          for (yy = 0; yy < 2; yy++)
            {
              if (tmpx+xx >= 0 && tmpx+xx < src_extent->width &&
                  tmpy+yy >= 0 && tmpy+yy < src_extent->height)
                {
              val += src_buf[toff+(yy*ROW+xx)*3+rgb] * wx[xx] * wy[yy];
              wt += wx[xx] * wy[yy];
            }
            }
        }
          if (wt <= 0)
        {
          g_warning ("gegl_lens_correct: mapped pixel %g,%g not in %dx%d+%d+%d", gx, gy,
                 src_extent->width, src_extent->height, src_extent->x, src_extent->y);
          g_warning ("                   dst = %dx%d+%d+%d", dst_extent->width, dst_extent->height, dst_extent->x,dst_extent->y);
          dst_buf [doffset+rgb] = 0.0;
        }
          else
        {
          dst_buf [doffset+rgb] = val / wt;
        }
        }
      doffset+=3;
    }
    }

  /* Store dst pixels. */
  gegl_buffer_set (dst, NULL, babl_format ("RGB float"), dst_buf, GEGL_AUTO_ROWSTRIDE);

  /* Free acquired storage. */
  g_free (src_buf);
  g_free (dst_buf);

  #ifdef TRACE
    g_warning ("< copy_through_lens");
  #endif
}
static void
gimp_n_point_deformation_tool_start (GimpNPointDeformationTool *npd_tool,
                                     GimpDisplay               *display)
{
  GimpTool                     *tool = GIMP_TOOL (npd_tool);
  GimpNPointDeformationOptions *npd_options;
  GimpImage                    *image;
  GeglBuffer                   *source_buffer;
  GeglBuffer                   *preview_buffer;
  NPDModel                     *model;

  npd_options = GIMP_N_POINT_DEFORMATION_TOOL_GET_OPTIONS (npd_tool);

  gimp_tool_control (tool, GIMP_TOOL_ACTION_HALT, display);

  image = gimp_display_get_image (display);

  tool->display  = display;
  tool->drawable = gimp_image_get_active_drawable (image);

  npd_tool->active = TRUE;

  /* create GEGL graph */
  source_buffer  = gimp_drawable_get_buffer (tool->drawable);

  preview_buffer = gegl_buffer_new (gegl_buffer_get_extent (source_buffer),
                                    babl_format ("cairo-ARGB32"));

  npd_tool->graph    = gegl_node_new ();

  npd_tool->source   = gegl_node_new_child (npd_tool->graph,
                                            "operation", "gegl:buffer-source",
                                            "buffer",    source_buffer,
                                            NULL);
  npd_tool->npd_node = gegl_node_new_child (npd_tool->graph,
                                            "operation", "gegl:npd",
                                            NULL);
  npd_tool->sink     = gegl_node_new_child (npd_tool->graph,
                                            "operation", "gegl:write-buffer",
                                            "buffer",    preview_buffer,
                                            NULL);

  gegl_node_link_many (npd_tool->source,
                       npd_tool->npd_node,
                       npd_tool->sink,
                       NULL);

  /* initialize some options */
  g_object_set (G_OBJECT (npd_options), "mesh-visible", TRUE, NULL);
  gimp_n_point_deformation_options_set_sensitivity (npd_options, TRUE);

  /* compute and get model */
  gegl_node_process (npd_tool->npd_node);
  gegl_node_get (npd_tool->npd_node, "model", &model, NULL);

  npd_tool->model          = model;
  npd_tool->preview_buffer = preview_buffer;
  npd_tool->selected_cp    = NULL;
  npd_tool->hovering_cp    = NULL;
  npd_tool->selected_cps   = NULL;
  npd_tool->rubber_band    = FALSE;
  npd_tool->lattice_points = g_new (GimpVector2,
                                    5 * model->hidden_model->num_of_bones);

  gimp_item_get_offset (GIMP_ITEM (tool->drawable),
                        &npd_tool->offset_x, &npd_tool->offset_y);
  gimp_npd_debug (("offset: %f %f\n", npd_tool->offset_x, npd_tool->offset_y));

  gimp_draw_tool_start (GIMP_DRAW_TOOL (npd_tool), display);

  gimp_n_point_deformation_tool_perform_deformation (npd_tool);

  /* hide original image */
  gimp_item_set_visible (GIMP_ITEM (tool->drawable), FALSE, FALSE);
  gimp_image_flush (image);

  /* create and start a deformation thread */
  npd_tool->deform_thread =
    g_thread_new ("deform thread",
                  (GThreadFunc) gimp_n_point_deformation_tool_deform_thread_func,
                  npd_tool);

  /* create and start canvas update timeout */
  npd_tool->draw_timeout_id =
    gdk_threads_add_timeout_full (G_PRIORITY_DEFAULT_IDLE,
                                  GIMP_NPD_DRAW_INTERVAL,
                                  (GSourceFunc) gimp_n_point_deformation_tool_canvas_update_timeout,
                                  npd_tool,
                                  NULL);
}
예제 #18
0
static int
gimp_mypaint_surface_draw_dab (MyPaintSurface *base_surface,
                               float           x,
                               float           y,
                               float           radius,
                               float           color_r,
                               float           color_g,
                               float           color_b,
                               float           opaque,
                               float           hardness,
                               float           color_a,
                               float           aspect_ratio,
                               float           angle,
                               float           lock_alpha,
                               float           colorize)
{
  GimpMybrushSurface *surface = (GimpMybrushSurface *)base_surface;
  GeglBufferIterator *iter;
  GeglRectangle       dabRect;
  GimpComponentMask   component_mask = surface->component_mask;

  const float one_over_radius2 = 1.0f / (radius * radius);
  const double angle_rad = angle / 360 * 2 * M_PI;
  const float cs = cos(angle_rad);
  const float sn = sin(angle_rad);
  float normal_mode;
  float segment1_slope;
  float segment2_slope;
  float r_aa_start;

  hardness = CLAMP (hardness, 0.0f, 1.0f);
  segment1_slope = -(1.0f / hardness - 1.0f);
  segment2_slope = -hardness / (1.0f - hardness);
  aspect_ratio = MAX (1.0f, aspect_ratio);

  r_aa_start = radius - 1.0f;
  r_aa_start = MAX (r_aa_start, 0);
  r_aa_start = (r_aa_start * r_aa_start) / aspect_ratio;

  normal_mode = opaque * (1.0f - colorize);
  colorize = opaque * colorize;

  /* FIXME: This should use the real matrix values to trim aspect_ratio dabs */
  dabRect = calculate_dab_roi (x, y, radius);
  gegl_rectangle_intersect (&dabRect, &dabRect, gegl_buffer_get_extent (surface->buffer));

  if (dabRect.width <= 0 || dabRect.height <= 0)
    return 0;

  gegl_rectangle_bounding_box (&surface->dirty, &surface->dirty, &dabRect);

  iter = gegl_buffer_iterator_new (surface->buffer, &dabRect, 0,
                                   babl_format ("R'G'B'A float"),
                                   GEGL_BUFFER_READWRITE,
                                   GEGL_ABYSS_NONE);
  if (surface->paint_mask)
    {
      GeglRectangle mask_roi = dabRect;
      mask_roi.x -= surface->paint_mask_x;
      mask_roi.y -= surface->paint_mask_y;
      gegl_buffer_iterator_add (iter, surface->paint_mask, &mask_roi, 0,
                                babl_format ("Y float"),
                                GEGL_ACCESS_READ, GEGL_ABYSS_NONE);
    }

  while (gegl_buffer_iterator_next (iter))
    {
      float *pixel = (float *)iter->data[0];
      float *mask;
      int iy, ix;

      if (surface->paint_mask)
        mask = iter->data[1];
      else
        mask = NULL;

      for (iy = iter->roi[0].y; iy < iter->roi[0].y + iter->roi[0].height; iy++)
        {
          for (ix = iter->roi[0].x; ix < iter->roi[0].x +  iter->roi[0].width; ix++)
            {
              float rr, base_alpha, alpha, dst_alpha, r, g, b, a;
              if (radius < 3.0f)
                rr = calculate_rr_antialiased (ix, iy, x, y, aspect_ratio, sn, cs, one_over_radius2, r_aa_start);
              else
                rr = calculate_rr (ix, iy, x, y, aspect_ratio, sn, cs, one_over_radius2);
              base_alpha = calculate_alpha_for_rr (rr, hardness, segment1_slope, segment2_slope);
              alpha = base_alpha * normal_mode;
              if (mask)
                alpha *= *mask;
              dst_alpha = pixel[ALPHA];
              /* a = alpha * color_a + dst_alpha * (1.0f - alpha);
               * which converts to: */
              a = alpha * (color_a - dst_alpha) + dst_alpha;
              r = pixel[RED];
              g = pixel[GREEN];
              b = pixel[BLUE];

              if (a > 0.0f)
                {
                  /* By definition the ratio between each color[] and pixel[] component in a non-pre-multipled blend always sums to 1.0f.
                   * Originaly this would have been "(color[n] * alpha * color_a + pixel[n] * dst_alpha * (1.0f - alpha)) / a",
                   * instead we only calculate the cheaper term. */
                  float src_term = (alpha * color_a) / a;
                  float dst_term = 1.0f - src_term;
                  r = color_r * src_term + r * dst_term;
                  g = color_g * src_term + g * dst_term;
                  b = color_b * src_term + b * dst_term;
                }

              if (colorize > 0.0f && base_alpha > 0.0f)
                {
                  alpha = base_alpha * colorize;
                  a = alpha + dst_alpha - alpha * dst_alpha;
                  if (a > 0.0f)
                    {
                      GimpHSL pixel_hsl, out_hsl;
                      GimpRGB pixel_rgb = {color_r, color_g, color_b};
                      GimpRGB out_rgb   = {r, g, b};
                      float src_term = alpha / a;
                      float dst_term = 1.0f - src_term;

                      gimp_rgb_to_hsl (&pixel_rgb, &pixel_hsl);
                      gimp_rgb_to_hsl (&out_rgb, &out_hsl);

                      out_hsl.h = pixel_hsl.h;
                      out_hsl.s = pixel_hsl.s;
                      gimp_hsl_to_rgb (&out_hsl, &out_rgb);

                      r = (float)out_rgb.r * src_term + r * dst_term;
                      g = (float)out_rgb.g * src_term + g * dst_term;
                      b = (float)out_rgb.b * src_term + b * dst_term;
                    }
                }

              if (component_mask != GIMP_COMPONENT_MASK_ALL)
                {
                  if (component_mask & GIMP_COMPONENT_MASK_RED)
                    pixel[RED]   = r;
                  if (component_mask & GIMP_COMPONENT_MASK_GREEN)
                    pixel[GREEN] = g;
                  if (component_mask & GIMP_COMPONENT_MASK_BLUE)
                    pixel[BLUE]  = b;
                  if (component_mask & GIMP_COMPONENT_MASK_ALPHA)
                    pixel[ALPHA] = a;
                }
              else
                {
                  pixel[RED]   = r;
                  pixel[GREEN] = g;
                  pixel[BLUE]  = b;
                  pixel[ALPHA] = a;
                }

              pixel += 4;
              if (mask)
                mask += 1;
            }
        }
    }

  return 1;
}
GeglBuffer *
gimp_image_contiguous_region_by_color (GimpImage            *image,
                                       GimpDrawable         *drawable,
                                       gboolean              sample_merged,
                                       gboolean              antialias,
                                       gfloat                threshold,
                                       gboolean              select_transparent,
                                       GimpSelectCriterion   select_criterion,
                                       const GimpRGB        *color)
{
  /*  Scan over the image's active layer, finding pixels within the
   *  specified threshold from the given R, G, & B values.  If
   *  antialiasing is on, use the same antialiasing scheme as in
   *  fuzzy_select.  Modify the image's mask to reflect the
   *  additional selection
   */
  GeglBufferIterator *iter;
  GimpPickable       *pickable;
  GeglBuffer         *src_buffer;
  GeglBuffer         *mask_buffer;
  const Babl         *format;
  gint                n_components;
  gboolean            has_alpha;
  gfloat              start_col[MAX_CHANNELS];

  g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);
  g_return_val_if_fail (color != NULL, NULL);

  if (sample_merged)
    pickable = GIMP_PICKABLE (image);
  else
    pickable = GIMP_PICKABLE (drawable);

  gimp_pickable_flush (pickable);

  src_buffer = gimp_pickable_get_buffer (pickable);

  format = choose_format (src_buffer, select_criterion,
                          &n_components, &has_alpha);

  gimp_rgba_get_pixel (color, format, start_col);

  if (has_alpha)
    {
      if (select_transparent)
        {
          /*  don't select transparancy if "color" isn't fully transparent
           */
          if (start_col[n_components - 1] > 0.0)
            select_transparent = FALSE;
        }
    }
  else
    {
      select_transparent = FALSE;
    }

  mask_buffer = gegl_buffer_new (gegl_buffer_get_extent (src_buffer),
                                 babl_format ("Y float"));

  iter = gegl_buffer_iterator_new (src_buffer,
                                   NULL, 0, format,
                                   GEGL_BUFFER_READ, GEGL_ABYSS_NONE);

  gegl_buffer_iterator_add (iter, mask_buffer,
                            NULL, 0, babl_format ("Y float"),
                            GEGL_BUFFER_WRITE, GEGL_ABYSS_NONE);

  while (gegl_buffer_iterator_next (iter))
    {
      const gfloat *src   = iter->data[0];
      gfloat       *dest  = iter->data[1];
      gint          count = iter->length;

      while (count--)
        {
          /*  Find how closely the colors match  */
          *dest = pixel_difference (start_col, src,
                                    antialias,
                                    threshold,
                                    n_components,
                                    has_alpha,
                                    select_transparent,
                                    select_criterion);

          src  += n_components;
          dest += 1;
        }
    }

  return mask_buffer;
}
예제 #20
0
static void
stamp (GeglProperties *o,
       gdouble         x,
       gdouble         y)
{
  WarpPrivate         *priv = (WarpPrivate*) o->user_data;
  GeglBufferIterator  *it;
  const Babl          *format;
  gdouble              stamp_force, influence;
  gdouble              x_mean = 0.0;
  gdouble              y_mean = 0.0;
  gint                 x_iter, y_iter;
  GeglRectangle        area;
  const GeglRectangle *src_extent;
  gfloat              *srcbuf, *stampbuf;
  gint                 buf_rowstride = 0;
  gfloat               s = 0, c = 0;

  area.x = floor (x - o->size / 2.0);
  area.y = floor (y - o->size / 2.0);
  area.width   = ceil (x + o->size / 2.0);
  area.height  = ceil (y + o->size / 2.0);
  area.width  -= area.x;
  area.height -= area.y;

  format = babl_format_n (babl_type ("float"), 2);

  /* If needed, compute the mean deformation */
  if (o->behavior == GEGL_WARP_BEHAVIOR_SMOOTH)
    {
      gint pixel_count = 0;

      it = gegl_buffer_iterator_new (priv->buffer, &area, 0, format,
                                     GEGL_ACCESS_READ, GEGL_ABYSS_NONE);

      while (gegl_buffer_iterator_next (it))
        {
          gint    n_pixels    = it->length;
          gfloat *coords      = it->data[0];

          while (n_pixels--)
            {
              x_mean += coords[0];
              y_mean += coords[1];
              coords += 2;
            }
          pixel_count += it->roi->width * it->roi->height;
        }
      x_mean /= pixel_count;
      y_mean /= pixel_count;
    }
  else if (o->behavior == GEGL_WARP_BEHAVIOR_SWIRL_CW ||
           o->behavior == GEGL_WARP_BEHAVIOR_SWIRL_CCW)
    {
      /* swirl by 5 degrees per stamp (for strength 100).
       * not exactly sin/cos factors,
       * since we calculate an off-center offset-vector */

      /* note that this is fudged for stamp_force < 1.0 and
       * results in a slight upscaling there. It is a compromise
       * between exactness and calculation speed. */
      s = sin (0.01 * o->strength * 5.0 / 180 * G_PI);
      c = cos (0.01 * o->strength * 5.0 / 180 * G_PI) - 1.0;
    }

  srcbuf = gegl_buffer_linear_open (priv->buffer, NULL, &buf_rowstride, NULL);
  buf_rowstride /= sizeof (gfloat);
  src_extent = gegl_buffer_get_extent (priv->buffer);

  stampbuf = g_new0 (gfloat, 2 * area.height * area.width);

  for (y_iter = 0; y_iter < area.height; y_iter++)
    {
      for (x_iter = 0; x_iter < area.width; x_iter++)
        {
          gfloat nvx, nvy;
          gfloat xi, yi;
          gfloat *vals;
          gint dx, dy;
          gfloat weight_x, weight_y;
          gfloat *srcptr;

          xi = area.x + x_iter;
          xi += -x + 0.5;
          yi = area.y + y_iter;
          yi += -y + 0.5;

          stamp_force = get_stamp_force (o, xi, yi);
          influence = 0.01 * o->strength * stamp_force;

          switch (o->behavior)
            {
              case GEGL_WARP_BEHAVIOR_MOVE:
                nvx = influence * (priv->last_x - x);
                nvy = influence * (priv->last_y - y);
                break;
              case GEGL_WARP_BEHAVIOR_GROW:
                nvx = influence * -0.1 * xi;
                nvy = influence * -0.1 * yi;
                break;
              case GEGL_WARP_BEHAVIOR_SHRINK:
                nvx = influence * 0.1 * xi;
                nvy = influence * 0.1 * yi;
                break;
              case GEGL_WARP_BEHAVIOR_SWIRL_CW:
                nvx = stamp_force * ( c * xi + s * yi);
                nvy = stamp_force * (-s * xi + c * yi);
                break;
              case GEGL_WARP_BEHAVIOR_SWIRL_CCW:
                nvx = stamp_force * ( c * xi - s * yi);
                nvy = stamp_force * ( s * xi + c * yi);
                break;
              case GEGL_WARP_BEHAVIOR_ERASE:
              case GEGL_WARP_BEHAVIOR_SMOOTH:
              default:
                nvx = 0.0;
                nvy = 0.0;
                break;
            }

          vals = stampbuf + (y_iter * area.width + x_iter) * 2;

          dx = floorf (nvx);
          dy = floorf (nvy);

          if (area.x + x_iter + dx     <  src_extent->x                     ||
              area.x + x_iter + dx + 1 >= src_extent->x + src_extent->width ||
              area.y + y_iter + dy     <  src_extent->y                     ||
              area.y + y_iter + dy + 1 >= src_extent->y + src_extent->height)
            {
              continue;
            }

          srcptr = srcbuf + (area.y - src_extent->y + y_iter + dy) * buf_rowstride +
                            (area.x - src_extent->x + x_iter + dx) * 2;

          if (o->behavior == GEGL_WARP_BEHAVIOR_ERASE)
            {
              vals[0] = srcptr[0] * (1.0 - MIN (influence, 1.0));
              vals[1] = srcptr[1] * (1.0 - MIN (influence, 1.0));
            }
          else if (o->behavior == GEGL_WARP_BEHAVIOR_SMOOTH)
            {
              vals[0] = (1.0 - influence) * srcptr[0] + influence * x_mean;
              vals[1] = (1.0 - influence) * srcptr[1] + influence * y_mean;
            }
          else
            {
              weight_x = nvx - dx;
              weight_y = nvy - dy;

              /* bilinear interpolation of the vectors */

              vals[0]  = srcptr[0] * (1.0 - weight_x) * (1.0 - weight_y);
              vals[1]  = srcptr[1] * (1.0 - weight_x) * (1.0 - weight_y);

              vals[0] += srcptr[2] * weight_x * (1.0 - weight_y);
              vals[1] += srcptr[3] * weight_x * (1.0 - weight_y);

              vals[0] += srcptr[buf_rowstride + 0] * (1.0 - weight_x) * weight_y;
              vals[1] += srcptr[buf_rowstride + 1] * (1.0 - weight_x) * weight_y;

              vals[0] += srcptr[buf_rowstride + 2] * weight_x * weight_y;
              vals[1] += srcptr[buf_rowstride + 3] * weight_x * weight_y;

              vals[0] += nvx;
              vals[1] += nvy;
            }
        }
    }

  gegl_buffer_linear_close (priv->buffer, srcbuf);
  gegl_buffer_set (priv->buffer, &area, 0, format,
                   stampbuf, GEGL_AUTO_ROWSTRIDE);
  g_free (stampbuf);

  /* Memorize the stamp location for movement dependant behavior like move */
  priv->last_x = x;
  priv->last_y = y;
}
예제 #21
0
gint
main (gint    argc,
      gchar **argv)
{
  GeglBuffer *bufferA = NULL;
  GeglBuffer *bufferB = NULL;
  GeglBuffer *debug_buf = NULL;

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

  if (argc != 3)
    {
      g_print ("This is simple image difference detection tool for use in regression testing"
               "return message is non zero if images are different, if they are equal"
               "the output will contain the string identical.");
      g_print ("Usage: %s <imageA> <imageB>\n", argv[0]);
      return 1;
    }

  {
    GeglNode *graph, *sink;
    graph = gegl_graph (sink=gegl_node ("gegl:buffer-sink", "buffer", &bufferA, NULL,
                             gegl_node ("gegl:load", "path", argv[1], NULL)));
    gegl_node_process (sink);
    g_object_unref (graph);
    if (!bufferA)
      {
        g_printerr ("Failed to open %s\n", argv[1]);
        return 1;
      }

    graph = gegl_graph (sink=gegl_node ("gegl:buffer-sink", "buffer", &bufferB, NULL,
                             gegl_node ("gegl:load", "path", argv[2], NULL)));
    gegl_node_process (sink);
    g_object_unref (graph);
    if (!bufferB)
      {
        g_printerr ("Failed to open %s\n", argv[2]);
        return 1;
      }
  }

  if (gegl_buffer_get_width (bufferA) != gegl_buffer_get_width (bufferB) ||
      gegl_buffer_get_height (bufferA) != gegl_buffer_get_height (bufferB))
    {
      g_printerr ("%s and %s differ in size\n", argv[1], argv[2]);
      g_printerr ("  %ix%i vs %ix%i\n",
                  gegl_buffer_get_width (bufferA), gegl_buffer_get_height (bufferA),
                  gegl_buffer_get_width (bufferB), gegl_buffer_get_height (bufferB));
      return 1;
    }

  debug_buf = gegl_buffer_new (gegl_buffer_get_extent (bufferA), babl_format ("R'G'B' u8"));
  
   

  {
     gfloat *bufA, *bufB;
     gfloat *a, *b;
     guchar *debug, *d;
     gint   rowstrideA, rowstrideB, dRowstride;
     gint   pixels;
     gint   wrong_pixels=0;
     gint   i;
     gdouble diffsum = 0.0;
     gdouble max_diff = 0.0;

     pixels = gegl_buffer_get_pixel_count (bufferA);

     bufA = (void*)gegl_buffer_linear_open (bufferA, NULL, &rowstrideA,
                                            babl_format ("CIE Lab float"));
     bufB = (void*)gegl_buffer_linear_open (bufferB, NULL, &rowstrideB,
                                            babl_format ("CIE Lab float"));
     debug = (void*)gegl_buffer_linear_open (debug_buf, NULL, &dRowstride, babl_format ("R'G'B' u8"));

     a = bufA;
     b = bufB;
     d = debug;

     for (i=0;i<pixels;i++)
       {
         gdouble diff = sqrt ( SQR(a[0]-b[0])+
                               SQR(a[1]-b[1])+
                               SQR(a[2]-b[2])
                               /*+SQR(a[3]-b[3])*/);
         if (diff>=0.01)
           {
             wrong_pixels++;
             diffsum += diff;
             if (diff > max_diff)
               max_diff = diff;
             d[0]=(diff/100.0 * 255);
             d[1]=0;
             d[2]=a[0]/100.0*255;
           }
         else
           {
             d[0]=a[0]/100.0*255;
             d[1]=a[0]/100.0*255;
             d[2]=a[0]/100.0*255;
           }
         a+=3;
         b+=3;
         d+=3;
       }

     a = bufA;
     b = bufB;
     d = debug;

     if (wrong_pixels)
       for (i=0;i<pixels;i++)
         {
           gdouble diff = sqrt ( SQR(a[0]-b[0])+
                                 SQR(a[1]-b[1])+
                                 SQR(a[2]-b[2])
                                 /*+SQR(a[3]-b[3])*/);
           if (diff>=0.01)
             {
               d[0]=(100-a[0])/100.0*64+32;
               d[1]=(diff/max_diff * 255);
               d[2]=0;
             }
           else
             {
               d[0]=a[0]/100.0*255;
               d[1]=a[0]/100.0*255;
               d[2]=a[0]/100.0*255;
             }
           a+=3;
           b+=3;
           d+=3;
         }

     gegl_buffer_linear_close (bufferA, bufA);
     gegl_buffer_linear_close (bufferB, bufB);
     gegl_buffer_linear_close (debug_buf, debug);

     if (max_diff >= 0.1)
       {
         g_printerr ("%s and %s differ\n"
                     "  wrong pixels   : %i/%i (%2.2f%%)\n"
                     "  max Δe         : %2.3f\n"
                     "  avg Δe (wrong) : %2.3f(wrong) %2.3f(total)\n",
                     argv[1], argv[2],
                     wrong_pixels, pixels, (wrong_pixels*100.0/pixels),
                     max_diff,
                     diffsum/wrong_pixels,
                     diffsum/pixels);
         if (max_diff > 1.5 &&
             !strstr (argv[2], "broken"))
           {
             GeglNode *sink;
             gchar *debug_path = g_malloc (strlen (argv[2])+16);
             memcpy (debug_path, argv[2], strlen (argv[2])+1);
             memcpy (debug_path + strlen(argv[2])-4, "-diff.png", 11);
             gegl_graph (sink=gegl_node ("gegl:png-save",
                                 "path", debug_path, NULL,
                                 gegl_node ("gegl:buffer-source", "buffer", debug_buf, NULL)));
             gegl_node_process (sink);
             return 1;
           }
         if (strstr (argv[2], "broken"))
           g_print ("because the test is expected to fail ");
         else
           g_print ("because the error is small ");
         g_print ("we'll say ");
       }

  }

  g_print ("%s and %s are identical\n", argv[1], argv[2]);
  g_object_unref (debug_buf); 
  g_object_unref (bufferA); 
  g_object_unref (bufferB); 
  gegl_exit ();
  return 0;
}
GeglBuffer *
gegl_operation_context_get_target (GeglOperationContext *context,
                                   const gchar          *padname)
{
  GeglBuffer          *output;
  const GeglRectangle *result;
  const Babl          *format;
  GeglNode            *node;
  GeglOperation       *operation;

#if 0
  g_return_val_if_fail (GEGL_IS_OPERATION_CONTEXT (context), NULL);
#endif

  operation = context->operation;
  node = operation->node; /* <ick */
  format = gegl_operation_get_format (operation, padname);

  if (format == NULL)
    {
      g_warning ("no format for %s presuming RGBA float\n",
                 gegl_node_get_debug_name (node));
      format = babl_format ("RGBA float");
    }
  g_assert (format != NULL);
  g_assert (!strcmp (padname, "output"));

  result = &context->result_rect;

  if (result->width == 0 ||
      result->height == 0)
    {
      output = g_object_ref (emptybuf());
    }
  else if (node->dont_cache == FALSE &&
      ! GEGL_OPERATION_CLASS (G_OBJECT_GET_CLASS (operation))->no_cache)
    {
      GeglBuffer    *cache;
      cache = GEGL_BUFFER (gegl_node_get_cache (node));

      /* Only use the cache if the result is within the cache
       * extent. This is certainly not optimal. My gut feeling is that
       * the current caching mechanism needs to be redesigned
       */
      if (gegl_rectangle_contains (gegl_buffer_get_extent (cache), result))
        {
          output = g_object_ref (cache);
        }
      else
        {
          output = gegl_buffer_new_ram (result, format);
        }
    }
  else
    {
      output = gegl_buffer_new_ram (result, format);
    }

  gegl_operation_context_take_object (context, padname, G_OBJECT (output));
  return output;
}
예제 #23
0
/* Save a layer from an image */
gboolean save_layer(gint32             drawable_ID,
                    WebPWriterFunction writer,
                    void              *custom_ptr,
#ifdef WEBP_0_5
                    gboolean           animation,
                    WebPAnimEncoder   *enc,
                    int                frame_timestamp,
#endif
                    WebPSaveParams    *params,
                    GError           **error)
{
    gboolean          status   = FALSE;
    gint              bpp;
    gint              width;
    gint              height;
    GimpImageType     drawable_type;
    WebPConfig        config;
    WebPPicture       picture;
    guchar           *buffer   = NULL;
#ifdef GIMP_2_9
    GeglBuffer       *geglbuffer;
    GeglRectangle     extent;
#else
    GimpDrawable     *drawable = NULL;
    GimpPixelRgn      region;
#endif

    /* Retrieve the image data */
    bpp = gimp_drawable_bpp(drawable_ID);
    width = gimp_drawable_width(drawable_ID);
    height = gimp_drawable_height(drawable_ID);
    drawable_type = gimp_drawable_type(drawable_ID);

    /* Initialize the WebP configuration with a preset and fill in the
     * remaining values */
    WebPConfigPreset(&config,
                     webp_preset_by_name(params->preset),
                     params->quality);

    config.lossless      = params->lossless;
    config.method        = 6;  /* better quality */
    config.alpha_quality = params->alpha_quality;

    /* Prepare the WebP structure */
    WebPPictureInit(&picture);
    picture.use_argb      = 1;
    picture.width         = width;
    picture.height        = height;
    picture.writer        = writer;
    picture.custom_ptr    = custom_ptr;
    picture.progress_hook = webp_file_progress;

    do {
        /* Attempt to allocate a buffer of the appropriate size */
        buffer = (guchar *)g_malloc(bpp * width * height);
        if(!buffer) {
            g_set_error(error,
                        G_FILE_ERROR,
                        0,
                        "Unable to allocate buffer for layer");
            break;
        }

#ifdef GIMP_2_9
        /* Obtain the buffer and get its extent */
        geglbuffer = gimp_drawable_get_buffer(drawable_ID);
        extent = *gegl_buffer_get_extent(geglbuffer);

        /* Read the layer buffer into our buffer */
        gegl_buffer_get(geglbuffer, &extent, 1.0, NULL, buffer,
                        GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);

        g_object_unref(geglbuffer);
#else
        /* Get the drawable */
        drawable = gimp_drawable_get(drawable_ID);

        /* Obtain the pixel region for the drawable */
        gimp_pixel_rgn_init(&region,
                            drawable,
                            0, 0,
                            width,
                            height,
                            FALSE, FALSE);

        /* Read the region into the buffer */
        gimp_pixel_rgn_get_rect(&region,
                                buffer,
                                0, 0,
                                width,
                                height);

        gimp_drawable_detach(drawable);
#endif

        /* Use the appropriate function to import the data from the buffer */
        if(drawable_type == GIMP_RGB_IMAGE) {
            WebPPictureImportRGB(&picture, buffer, width * bpp);
        } else {
            WebPPictureImportRGBA(&picture, buffer, width * bpp);
        }

#ifdef WEBP_0_5
        if (animation == TRUE) {

            if (!WebPAnimEncoderAdd(enc, &picture, frame_timestamp, &config)) {
                g_set_error(error,
                            G_FILE_ERROR,
                            picture.error_code,
                            "WebP error: '%s'",
                            webp_error_string(picture.error_code));
                break;
            }
        } else {
#endif
            if(!WebPEncode(&config, &picture)) {
                g_set_error(error,
                            G_FILE_ERROR,
                            picture.error_code,
                            "WebP error: '%s'",
                            webp_error_string(picture.error_code));
                break;
            }
#ifdef WEBP_0_5
        }
#endif

        /* Everything succeeded */
        status = TRUE;

    } while(0);

    /* Free the buffer */
    if (buffer) {
        free(buffer);
    }

    return status;
}
예제 #24
0
static void
affine_generic (GeglBuffer  *dest,
                GeglBuffer  *src,
                GeglMatrix3 *matrix,
                GeglSampler *sampler)
{
  GeglBufferIterator *i;
  const GeglRectangle *dest_extent;
  gint                  x, y;
  gfloat * restrict     dest_buf,
                       *dest_ptr;
  GeglMatrix3           inverse;
  GeglMatrix2           inverse_jacobian;
  gdouble               u_start,
                        v_start,
                        u_float,
                        v_float;

  Babl                 *format;

  gint                  dest_pixels;

  format = babl_format ("RaGaBaA float");

  /* XXX: fast paths as existing in files in the same dir as affine.c
   *      should probably be hooked in here, and bailing out before using
   *      the generic code.
   */
  g_object_get (dest, "pixels", &dest_pixels, NULL);
  dest_extent = gegl_buffer_get_extent (dest);


  i = gegl_buffer_iterator_new (dest, dest_extent, format, GEGL_BUFFER_WRITE);
  while (gegl_buffer_iterator_next (i))
    {
      GeglRectangle *roi = &i->roi[0];
      dest_buf           = (gfloat *)i->data[0];

      gegl_matrix3_copy_into (&inverse, matrix);
      gegl_matrix3_invert (&inverse);
      inverse_jacobian.coeff[0][0] = inverse.coeff[0][0];
      inverse_jacobian.coeff[0][1] = inverse.coeff[0][1];
      inverse_jacobian.coeff[1][0] = inverse.coeff[1][0];
      inverse_jacobian.coeff[1][1] = inverse.coeff[1][1];

     /* set inverse_jacobian for samplers that support it */
      u_start = inverse.coeff[0][0] * roi->x + inverse.coeff[0][1]
                    * roi->y + inverse.coeff[0][2];
      v_start = inverse.coeff[1][0] * roi->x + inverse.coeff[1][1]
                    * roi->y + inverse.coeff[1][2];

      /* correct rounding on e.g. negative scaling (is this sound?) */
      if (inverse.coeff [0][0] < 0.)  u_start -= .001;
      if (inverse.coeff [1][1] < 0.)  v_start -= .001;

      for (dest_ptr = dest_buf, y = roi->height; y--;)
        {
           u_float = u_start;
           v_float = v_start;

           for (x = roi->width; x--;)
             {
               gegl_sampler_get (sampler, u_float, v_float, &inverse_jacobian, dest_ptr);
               dest_ptr+=4;
               u_float += inverse.coeff [0][0];
               v_float += inverse.coeff [1][0];
             }
           u_start += inverse.coeff [0][1];
           v_start += inverse.coeff [1][1];
        }
    }
}
GeglBuffer *
gimp_image_contiguous_region_by_seed (GimpImage           *image,
                                      GimpDrawable        *drawable,
                                      gboolean             sample_merged,
                                      gboolean             antialias,
                                      gfloat               threshold,
                                      gboolean             select_transparent,
                                      GimpSelectCriterion  select_criterion,
                                      gint                 x,
                                      gint                 y)
{
  GimpPickable *pickable;
  GeglBuffer   *src_buffer;
  GeglBuffer   *mask_buffer;
  const Babl   *format;
  gint          n_components;
  gboolean      has_alpha;
  gfloat        start_col[MAX_CHANNELS];

  g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);

  if (sample_merged)
    pickable = GIMP_PICKABLE (image);
  else
    pickable = GIMP_PICKABLE (drawable);

  gimp_pickable_flush (pickable);

  src_buffer = gimp_pickable_get_buffer (pickable);

  format = choose_format (src_buffer, select_criterion,
                          &n_components, &has_alpha);

  gegl_buffer_sample (src_buffer, x, y, NULL, start_col, format,
                      GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE);

  if (has_alpha)
    {
      if (select_transparent)
        {
          /*  don't select transparent regions if the start pixel isn't
           *  fully transparent
           */
          if (start_col[n_components - 1] > 0)
            select_transparent = FALSE;
        }
    }
  else
    {
      select_transparent = FALSE;
    }

  mask_buffer = gegl_buffer_new (gegl_buffer_get_extent (src_buffer),
                                 babl_format ("Y float"));

  find_contiguous_region_helper (src_buffer, mask_buffer,
                                 format, n_components, has_alpha,
                                 select_transparent, select_criterion,
                                 antialias, threshold,
                                 x, y, start_col);

  return mask_buffer;
}
예제 #26
0
gint
main (gint    argc,
      gchar **argv)
{
  GeglRectangle terrain_rect;
  if (argc < 2)
    usage();

  gegl_init (&argc, &argv);
  parse_args (argc, argv);

  gegl_decode = gegl_node_new ();

  store = gegl_node_new_child (gegl_decode,
                               "operation", "gegl:buffer-sink",
                               "buffer", &video_frame, NULL);
  load = gegl_node_new_child (gegl_decode,
                              "operation", "gegl:ff-load",
                              "frame", 0,
                              "path", video_path,
                              NULL);
  gegl_node_link_many (load, store, NULL);

  decode_frame_no (0); /* we issue a processing/decoding of a frame - to get metadata */
  {
    gegl_node_get (load, "frame-rate", &frame_rate, NULL);
    total_frames = 0; gegl_node_get (load, "frames", &total_frames, NULL);

    if (frame_end == 0)
      frame_end = total_frames;
  }

  if (horizontal)
   terrain_rect = (GeglRectangle){0, 0,
                                frame_end - frame_start + 1,
                                1024};
  else
   terrain_rect = (GeglRectangle){0, 0,
                                1024,
                                frame_end - frame_start + 1};

  if (input_analysis_path && g_file_test (input_analysis_path, G_FILE_TEST_IS_REGULAR))
  {
    GeglNode *load_graph = gegl_node_new ();
    GeglNode *load = gegl_node_new_child (load_graph, "operation", "gegl:load", "path", input_analysis_path, NULL);
    GeglNode *store = gegl_node_new_child (load_graph, "operation",
                                           "gegl:buffer-sink",
                                           "buffer", &terrain, NULL);
    gegl_node_link_many (load, store, NULL);
    gegl_node_process (store);
    g_object_unref (load_graph);

    frame_end = frame_start + gegl_buffer_get_extent (terrain)->height;
    /* the last frame aavilavle for analysis is the last one loaded rom cache,.. perhaps with some timeout */
  }
  else
  {
    terrain = gegl_buffer_new (&terrain_rect, babl_format ("RGBA u8"));
    {
      gint frame;
      gint max_buf_pos = 0;
      for (frame = frame_start; frame <= frame_end; frame++)
        {
          FrameInfo info = {{0}};
          uint8_t buffer[4096] = {0,};
          int buffer_pos = 0;
          GeglRectangle terrain_row;
          char *p = format;
          GString *word = g_string_new ("");

          if (show_progress)
          {
            double percent_full = 100.0 * (frame-frame_start) / (frame_end-frame_start);
            double percent_time = time_out?100.0 * babl_ticks()/1000.0/1000.0 / time_out:0.0;
            fprintf (stdout, "\r%2.1f%% %i/%i (%i)",
                     percent_full>percent_time?percent_full:percent_time,
                     frame-frame_start,
                     frame_end-frame_start,
                     frame);
            fflush (stdout);
          }

          if (horizontal)
            terrain_row = (GeglRectangle){frame-frame_start, 0, 1, 1024};
          else
            terrain_row = (GeglRectangle){0, frame-frame_start, 1024, 1};

          decode_frame_no (frame);

          //for (int i=0;i<(signed)sizeof(buffer);i++)buffer[i]=0;

          while (*p == ' ') p++;
          for (p= format;p==format || p[-1]!='\0';p++)
          {
            if (*p != '\0' && *p != ' ')
              {
                g_string_append_c (word, *p);
              }
            else
              {
               if (!strcmp (word->str, "histogram"))
               {
                 record_pix_stats (video_frame, previous_video_frame,
                                   &(info.rgb_hist[0]),
                                   &(info.rgb_square_diff)[0]);
                 for (int i = 0; i < NEGL_RGB_HIST_SLOTS; i++)
                 {
                  buffer[buffer_pos] = info.rgb_hist[i];
                  buffer_pos++;
                 }
                 for (int i = 0; i < 3; i++)
                 {
                   buffer[buffer_pos] = info.rgb_square_diff[i];
                   buffer_pos++;
                 }
               }
               else if (!strcmp (word->str, "mid-row"))
               {
                  int samples = NEGL_RGB_HEIGHT;
                  if (p[1] >= '0' && p[1] <= '9')
                  {
                    samples = g_strtod (&p[1], &p);
                  }
                  buffer_pos += extract_mid_row (video_frame, &(buffer)[buffer_pos], samples);
               }
               else if (!strcmp (word->str, "mid-col"))
               {
                  int samples = NEGL_RGB_HEIGHT;
                  if (p[1] >= '0' && p[1] <= '9')
                  {
                    samples = g_strtod (&p[1], &p);
                  }
                  buffer_pos += extract_mid_col (video_frame, &(buffer)[buffer_pos], samples);
               }
               else if (!strcmp (word->str, "thumb"))
               {
                  int samples  = NEGL_RGB_THEIGHT;
                  int samples2;

                  if (p[1] >= '0' && p[1] <= '9')
                  {
                    samples = g_strtod (&p[1], &p);
                  }

                  if (horizontal)
                    samples2 = samples * gegl_buffer_get_width (video_frame)/gegl_buffer_get_height(video_frame);
                  else
                    samples2 = samples * gegl_buffer_get_height (video_frame)/gegl_buffer_get_width(video_frame);

                  buffer_pos += extract_thumb (video_frame, &(buffer)[buffer_pos], samples, samples2);
               }
               else if (!strcmp (word->str, "audio"))
               {
                  int dups = 1;
                  GeglAudioFragment *audio = NULL;

                  if (p[1] >= '0' && p[1] <= '9')
                  {
                    dups = g_strtod (&p[1], &p);
                  }
                 gegl_node_get (load, "audio", &audio, NULL);
                 if (audio)
                  {
                    extract_audio_energy (audio, &buffer[buffer_pos], dups);
                    g_object_unref (audio);
                  }
                 buffer_pos+=3 * dups;
               }
               g_string_assign (word, "");
            }
          }
          max_buf_pos = buffer_pos;
          g_string_free (word, TRUE);

          gegl_buffer_set (terrain, &terrain_row, 0, babl_format("RGB u8"),
                           buffer,
                           GEGL_AUTO_ROWSTRIDE);

          if (time_out > 1.0 &&
              babl_ticks()/1000.0/1000.0 > time_out)
            {
               frame_end = frame;
               if (horizontal)
                 terrain_rect.width = frame_end - frame_start + 1;
               else
                 terrain_rect.height = frame_end - frame_start + 1;
          //     gegl_buffer_set_extent (terrain, &terrain_rect);
            }

          if (horizontal)
            terrain_rect.height = max_buf_pos/3;
          else
            terrain_rect.width = max_buf_pos/3;
          gegl_buffer_set_extent (terrain, &terrain_rect);
        }
        if (show_progress)
        {
          fprintf (stdout, "\n");
          fflush (stdout);
        }
    }

    if (output_analysis_path)
    {
      GeglNode *save_graph = gegl_node_new ();
      GeglNode *readbuf = gegl_node_new_child (save_graph, "operation", "gegl:buffer-source", "buffer", terrain, NULL);
      GeglNode *save = gegl_node_new_child (save_graph, "operation", "gegl:png-save",
        "path", output_analysis_path, NULL);
        gegl_node_link_many (readbuf, save, NULL);
      gegl_node_process (save);
      g_object_unref (save_graph);
    }
  }

  if (thumb_path)
  {
    GeglNode *save_graph = gegl_node_new ();
    find_best_thumb ();
    if (frame_thumb != 0)
      decode_frame_no (frame_thumb-1);
    decode_frame_no (frame_thumb);
    {
    GeglNode *readbuf = gegl_node_new_child (save_graph, "operation", "gegl:buffer-source", "buffer", video_frame, NULL);
    GeglNode *save = gegl_node_new_child (save_graph, "operation", "gegl:png-save",
      "path", thumb_path, NULL);
      gegl_node_link_many (readbuf, save, NULL);
    gegl_node_process (save);
    g_object_unref (save_graph);
    }
  }

  if (video_frame)
    g_object_unref (video_frame);
  video_frame = NULL;
  if (previous_video_frame)
    g_object_unref (previous_video_frame);
  previous_video_frame = NULL;
  if (terrain)
    g_object_unref (terrain);
  terrain = NULL;
  g_object_unref (gegl_decode);

  gegl_exit ();

  return 0;
}
예제 #27
0
static gboolean
test_buffer_change_extent (void)
{
  gboolean         result = TRUE;
  gchar           *tmpdir = NULL;
  gchar           *buf_a_path = NULL;
  GeglBuffer      *buf_a = NULL;
  const Babl      *format = babl_format ("R'G'B'A u8");
  GeglRectangle    roi = {0, 0, 128, 128};
  GeglRectangle    roi2 = {0, 0, 64, 64};

  tmpdir = g_dir_make_tmp ("test-backend-file-XXXXXX", NULL);
  g_return_val_if_fail (tmpdir, FALSE);

  buf_a_path = g_build_filename (tmpdir, "buf_a.gegl", NULL);

  buf_a = g_object_new (GEGL_TYPE_BUFFER,
                        "format", format,
                        "path", buf_a_path,
                        "x", roi.x,
                        "y", roi.y,
                        "width", roi.width,
                        "height", roi.height,
                        NULL);

  gegl_buffer_flush (buf_a);
  g_object_unref (buf_a);

  buf_a = g_object_new (GEGL_TYPE_BUFFER,
                        "format", babl_format ("RGBA u16"),
                        "path", buf_a_path,
                        NULL);

  if (!gegl_rectangle_equal (gegl_buffer_get_extent (buf_a), &roi))
    {
      printf ("Extent does not match:\n");
      gegl_rectangle_dump (gegl_buffer_get_extent (buf_a));
      gegl_rectangle_dump (&roi);
      result = FALSE;
    }

  gegl_buffer_set_extent (buf_a, &roi2);

  gegl_buffer_flush (buf_a);
  g_object_unref (buf_a);

  buf_a = g_object_new (GEGL_TYPE_BUFFER,
                        "format", babl_format ("RGBA u16"),
                        "path", buf_a_path,
                        NULL);

  if (!gegl_rectangle_equal (gegl_buffer_get_extent (buf_a), &roi2))
    {
      printf ("Extent does not match:\n");
      gegl_rectangle_dump (gegl_buffer_get_extent (buf_a));
      gegl_rectangle_dump (&roi2);
      result = FALSE;
    }

  g_object_unref (buf_a);

  g_unlink (buf_a_path);
  g_remove (tmpdir);

  g_free (tmpdir);
  g_free (buf_a_path);

  return result;
}
GeglBuffer *
gimp_pickable_contiguous_region_by_seed (GimpPickable        *pickable,
                                         gboolean             antialias,
                                         gfloat               threshold,
                                         gboolean             select_transparent,
                                         GimpSelectCriterion  select_criterion,
                                         gboolean             diagonal_neighbors,
                                         gint                 x,
                                         gint                 y)
{
  GeglBuffer    *src_buffer;
  GeglBuffer    *mask_buffer;
  const Babl    *format;
  GeglRectangle  extent;
  gint           n_components;
  gboolean       has_alpha;
  gfloat         start_col[MAX_CHANNELS];

  g_return_val_if_fail (GIMP_IS_PICKABLE (pickable), NULL);

  gimp_pickable_flush (pickable);

  src_buffer = gimp_pickable_get_buffer (pickable);

  format = choose_format (src_buffer, select_criterion,
                          &n_components, &has_alpha);

  gegl_buffer_sample (src_buffer, x, y, NULL, start_col, format,
                      GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE);

  if (has_alpha)
    {
      if (select_transparent)
        {
          /*  don't select transparent regions if the start pixel isn't
           *  fully transparent
           */
          if (start_col[n_components - 1] > 0)
            select_transparent = FALSE;
        }
    }
  else
    {
      select_transparent = FALSE;
    }

  extent = *gegl_buffer_get_extent (src_buffer);

  mask_buffer = gegl_buffer_new (&extent, babl_format ("Y float"));

  if (x >= extent.x && x < (extent.x + extent.width) &&
      y >= extent.y && y < (extent.y + extent.height))
    {
      GIMP_TIMER_START();

      find_contiguous_region (src_buffer, mask_buffer,
                              format, n_components, has_alpha,
                              select_transparent, select_criterion,
                              antialias, threshold, diagonal_neighbors,
                              x, y, start_col);

      GIMP_TIMER_END("foo");
    }

  return mask_buffer;
}
예제 #29
0
static gboolean
test_buffer_same_path (void)
{
  gboolean         result = TRUE;
  gchar           *tmpdir = NULL;
  gchar           *buf_a_path = NULL;
  GeglBuffer      *buf_a = NULL;
  const Babl      *format = babl_format ("R'G'B'A u8");
  GeglRectangle    roi = {0, 0, 128, 128};

  tmpdir = g_dir_make_tmp ("test-backend-file-XXXXXX", NULL);
  g_return_val_if_fail (tmpdir, FALSE);

  buf_a_path = g_build_filename (tmpdir, "buf_a.gegl", NULL);

  buf_a = g_object_new (GEGL_TYPE_BUFFER,
                        "format", format,
                        "path", buf_a_path,
                        "x", roi.x,
                        "y", roi.y,
                        "width", roi.width,
                        "height", roi.height,
                        NULL);

  gegl_buffer_flush (buf_a);
  g_object_unref (buf_a);

  buf_a = g_object_new (GEGL_TYPE_BUFFER,
                        /* FIXME: Currently the buffer must always have a format specified */
                        "format", babl_format ("RGBA u16"),
                        "path", buf_a_path,
                        NULL);

  if (!GEGL_IS_BUFFER (buf_a))
    {
      printf ("Failed to load file:%s\n",
              buf_a_path);
      result = FALSE;
    }

  if (!gegl_rectangle_equal (gegl_buffer_get_extent (buf_a), &roi))
    {
      printf ("Extent does not match:\n");
      gegl_rectangle_dump (gegl_buffer_get_extent (buf_a));
      gegl_rectangle_dump (&roi);
      result = FALSE;
    }

  if (gegl_buffer_get_format (buf_a) != format)
    {
      printf ("Formats do not match:\n%s\n%s\n",
        babl_get_name (gegl_buffer_get_format (buf_a)),
        babl_get_name (format));
      result = FALSE;
    }

  g_object_unref (buf_a);

  g_unlink (buf_a_path);
  g_remove (tmpdir);

  g_free (tmpdir);
  g_free (buf_a_path);

  return result;
}