Ejemplo n.º 1
0
static gboolean
process (GeglOperation       *operation,
         GeglBuffer          *input,
         GeglBuffer          *output,
         const GeglRectangle *result,
         gint                 level)
{
  GeglChantO *o = GEGL_CHANT_PROPERTIES (operation);
  gboolean need_fill = FALSE;
  gdouble r,g,b,a;

  if (input)
    {
      gegl_buffer_copy (input, result, output, result);
    }
  else
    {
      gegl_buffer_clear (output, result);
    }


  if (o->opacity > 0.0001 && o->color)
    {
      gegl_color_get_rgba (o->color, &r,&g,&b,&a);
      a *= o->opacity;
      if (a>0.001)
          need_fill=TRUE;
    }

  if (need_fill)
    {
      GStaticMutex mutex = G_STATIC_MUTEX_INIT;
      cairo_t *cr;
      cairo_surface_t *surface;
      guchar *data;


      g_static_mutex_lock (&mutex);
      data = (void*)gegl_buffer_linear_open (output, result, NULL, babl_format ("B'aG'aR'aA u8"));
      surface = cairo_image_surface_create_for_data (data,
                                                     CAIRO_FORMAT_ARGB32,
                                                     result->width,
                                                     result->height,
                                                     result->width * 4);

      cr = cairo_create (surface);
      cairo_translate (cr, -result->x, -result->y);
      if (g_str_equal (o->fill_rule, "evenodd"))
          cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);

      gegl_path_cairo_play (o->d, cr);
      cairo_set_source_rgba (cr, r,g,b,a);
      cairo_fill (cr);
      cairo_destroy (cr);

      gegl_buffer_linear_close (output, data);
      g_static_mutex_unlock (&mutex);
    }
  return  TRUE;
}
Ejemplo n.º 2
0
TEST ()
{
  GeglBuffer   *buffer;
  GeglRectangle extent = {0,0,40,20};
  GeglRectangle roi = {1,1,30,10};
  test_start();
  buffer = gegl_buffer_new (&extent, babl_format ("Y float"));
  fill_rect (buffer, &roi, 0.5);
  roi.y+=3;
  roi.x+=20;

  {
    gint    rowstride;
    gfloat *buf;
    gint    x, y, i;

    buf = (gpointer)gegl_buffer_linear_open (buffer, &extent, &rowstride, NULL);
    g_assert (buf);

    i=0;
    for (y=0;y<extent.height;y++)
      for (x=0;x<extent.width;x++)
        {
          buf[i++]= ((x+y)*1.0) / extent.width;
        }
    gegl_buffer_linear_close (buffer, buf);
  }
  fill_rect (buffer, &roi, 0.2);

  print_buffer (buffer);
  gegl_buffer_destroy (buffer);
  test_end ();
}
Ejemplo n.º 3
0
static void
setup_helper_test(ViewHelperTest *test)
{
    gpointer buf;
    GeglRectangle rect = {0, 0, 512, 512};

    /* Create a buffer, fill it with white */
    test->buffer = gegl_buffer_new(&rect, babl_format("R'G'B' u8"));
    buf = gegl_buffer_linear_open(test->buffer, NULL, NULL, babl_format("Y' u8"));
    memset(buf, 255, rect.width * rect.height);
    gegl_buffer_linear_close(test->buffer, buf);

    /* Setup a graph with two nodes, one sourcing the buffer and a no-op */
    test->graph = gegl_node_new();
    test->loadbuf = gegl_node_new_child(test->graph,
                                        "operation", "gegl:buffer-source",
                                        "buffer", test->buffer, NULL);
    test->out  = gegl_node_new_child(test->graph, "operation", "gegl:nop", NULL);
    gegl_node_link_many(test->loadbuf, test->out, NULL);

    /* Setup the GeglView helper, hook up the output node to it */
    test->helper = view_helper_new();
    view_helper_set_node(test->helper, test->out);
}
Ejemplo n.º 4
0
gint
main (gint    argc,
      gchar **argv)
{
  g_thread_init (NULL);
  gtk_init (&argc, &argv);
  gegl_init (&argc, &argv);

  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  gtk_window_set_title (GTK_WINDOW (window), "GEGL destructive painter");

  if (argv[1] == NULL)
    {
      GeglRectangle rect = {0, 0, 512, 512};
      gpointer buf;

      /* XXX: for best overall performance, this format should probably
       * be RaGaBaA float, overeager in-place processing code makes that fail though.
       */
      buffer = gegl_buffer_new (&rect, babl_format("R'G'B' u8"));
      /* it would be useful to have a programmatic way of doing this, filling
       * with a given pixel value
       */
      buf    = gegl_buffer_linear_open (buffer, NULL, NULL, babl_format ("Y' u8"));
      memset (buf, 255, 512 * 512);
      gegl_buffer_linear_close (buffer, buf);
    }
  else
    {
      buffer = gegl_buffer_open (argv[1]);
    }

  gegl = gegl_node_new ();
  {
    GeglNode *loadbuf = gegl_node_new_child (gegl, "operation", "gegl:buffer-source", "buffer", buffer, NULL);
    out  = gegl_node_new_child (gegl, "operation", "gegl:nop", NULL);

    gegl_node_link_many (loadbuf, out, NULL);

    view = g_object_new (GEGL_TYPE_VIEW, "node", out, NULL);
    top  = loadbuf;
  }

  g_signal_connect (GTK_OBJECT (view), "motion-notify-event",
                    (GCallback) paint_motion, NULL);
  g_signal_connect (GTK_OBJECT (view), "button-press-event",
                    (GCallback) paint_press, NULL);
  g_signal_connect (GTK_OBJECT (view), "button-release-event",
                    (GCallback) paint_release, NULL);
  gtk_widget_add_events (view, GDK_BUTTON_RELEASE_MASK);

  gtk_container_add (GTK_CONTAINER (window), view);
  gtk_widget_set_size_request (view, 512, 512);

  g_signal_connect (G_OBJECT (window), "delete-event",
                    G_CALLBACK (gtk_main_quit), window);
  gtk_widget_show_all (window);

  gtk_main ();
  g_object_unref (gegl);
  gegl_buffer_destroy (buffer);

  gegl_exit ();
  return 0;
}
Ejemplo n.º 5
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;
}
Ejemplo n.º 6
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;
}