app: implement the GEGL histogram with an iterator loop for now

its body can later be reused in the working histogram sink op.
This commit is contained in:
Michael Natterer
2012-04-16 21:01:39 +02:00
parent 15711f6de5
commit 28f655ed27
3 changed files with 222 additions and 8 deletions

View File

@ -28,6 +28,7 @@
#include "gegl/gimp-gegl-nodes.h"
#include "gimp.h" /* gimp_use_gegl */
#include "gimp-utils.h"
#include "gimpchannel.h"
#include "gimpdrawable-histogram.h"
#include "gimphistogram.h"
@ -52,6 +53,8 @@ gimp_drawable_calculate_histogram (GimpDrawable *drawable,
image = gimp_item_get_image (GIMP_ITEM (drawable));
mask = gimp_image_get_mask (image);
GIMP_TIMER_START();
if (FALSE) // gimp_use_gegl (image->gimp))
{
GeglNode *node = gegl_node_new ();
@ -99,6 +102,29 @@ gimp_drawable_calculate_histogram (GimpDrawable *drawable,
g_object_unref (processor);
g_object_unref (node);
}
else if (gimp_use_gegl (image->gimp))
{
if (! gimp_channel_is_empty (mask))
{
gint off_x, off_y;
gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y);
gimp_histogram_calc_gegl (histogram,
gimp_drawable_get_buffer (drawable),
GEGL_RECTANGLE (x, y, width, height),
gimp_drawable_get_buffer (GIMP_DRAWABLE (mask)),
GEGL_RECTANGLE (x - off_x, y - off_y,
width, height));
}
else
{
gimp_histogram_calc_gegl (histogram,
gimp_drawable_get_buffer (drawable),
GEGL_RECTANGLE (x, y, width, height),
NULL, NULL);
}
}
else
{
PixelRegion region;
@ -122,4 +148,6 @@ gimp_drawable_calculate_histogram (GimpDrawable *drawable,
gimp_histogram_calculate (histogram, &region, NULL);
}
}
GIMP_TIMER_END("histogram");
}

View File

@ -22,7 +22,7 @@
#include <string.h>
#undef G_DISABLE_DEPRECATED /* GStaticMutex */
#include <glib-object.h>
#include <gegl.h>
#include "libgimpmath/gimpmath.h"
@ -33,7 +33,6 @@
#include "gimphistogram.h"
#ifdef ENABLE_MP
#define NUM_SLOTS GIMP_MAX_NUM_THREADS
#else
@ -135,6 +134,183 @@ gimp_histogram_duplicate (GimpHistogram *histogram)
return dup;
}
void
gimp_histogram_calc_gegl (GimpHistogram *histogram,
GeglBuffer *buffer,
const GeglRectangle *buffer_rect,
GeglBuffer *mask,
const GeglRectangle *mask_rect)
{
GeglBufferIterator *iter;
const Babl *format;
gint bpp;
gdouble *values;
g_return_if_fail (histogram != NULL);
g_return_if_fail (GEGL_IS_BUFFER (buffer));
g_return_if_fail (buffer_rect != NULL);
format = gegl_buffer_get_format (buffer);
bpp = babl_format_get_bytes_per_pixel (format);
gimp_histogram_alloc_values (histogram, bpp);
iter = gegl_buffer_iterator_new (buffer, buffer_rect, 0, NULL,
GEGL_BUFFER_READ, GEGL_ABYSS_NONE);
if (mask)
gegl_buffer_iterator_add (iter, mask, mask_rect, 0,
babl_format ("Y float"),
GEGL_BUFFER_READ, GEGL_ABYSS_NONE);
values = histogram->values[0];
#define VALUE(c,i) (values[(c) * 256 + (i)])
while (gegl_buffer_iterator_next (iter))
{
const guchar *data = iter->data[0];
gint max;
if (mask)
{
const gfloat *mask_data = iter->data[1];
switch (bpp)
{
case 1:
while (iter->length)
{
const gdouble masked = *mask_data;
VALUE (0, data[0]) += masked;
data += bpp;
mask_data += 1;
}
break;
case 2:
while (iter->length--)
{
const gdouble masked = *mask_data;
const gdouble weight = data[1] / 255.0;
VALUE (0, data[0]) += weight * masked;
VALUE (1, data[1]) += masked;
data += bpp;
mask_data += 1;
}
break;
case 3: /* calculate separate value values */
while (iter->length--)
{
const gdouble masked = *mask_data;
VALUE (1, data[0]) += masked;
VALUE (2, data[1]) += masked;
VALUE (3, data[2]) += masked;
max = MAX (data[0], data[1]);
max = MAX (data[2], max);
VALUE (0, max) += masked;
data += bpp;
mask_data += 1;
}
break;
case 4: /* calculate separate value values */
while (iter->length--)
{
const gdouble masked = *mask_data;
const gdouble weight = data[3] / 255.0;
VALUE (1, data[0]) += weight * masked;
VALUE (2, data[1]) += weight * masked;
VALUE (3, data[2]) += weight * masked;
VALUE (4, data[3]) += masked;
max = MAX (data[0], data[1]);
max = MAX (data[2], max);
VALUE (0, max) += weight * masked;
data += bpp;
mask_data += 1;
}
break;
}
}
else /* no mask */
{
switch (bpp)
{
case 1:
while (iter->length--)
{
VALUE (0, data[0]) += 1.0;
data += bpp;
}
break;
case 2:
while (iter->length--)
{
const gdouble weight = data[1] / 255;
VALUE (0, data[0]) += weight;
VALUE (1, data[1]) += 1.0;
data += bpp;
}
break;
case 3: /* calculate separate value values */
while (iter->length--)
{
VALUE (1, data[0]) += 1.0;
VALUE (2, data[1]) += 1.0;
VALUE (3, data[2]) += 1.0;
max = MAX (data[0], data[1]);
max = MAX (data[2], max);
VALUE (0, max) += 1.0;
data += bpp;
}
break;
case 4: /* calculate separate value values */
while (iter->length--)
{
const gdouble weight = data[3] / 255;
VALUE (1, data[0]) += weight;
VALUE (2, data[1]) += weight;
VALUE (3, data[2]) += weight;
VALUE (4, data[3]) += 1.0;
max = MAX (data[0], data[1]);
max = MAX (data[2], max);
VALUE (0, max) += weight;
data += bpp;
}
break;
}
}
}
#undef VALUE
}
void
gimp_histogram_calculate (GimpHistogram *histogram,
PixelRegion *region,
@ -147,11 +323,6 @@ gimp_histogram_calculate (GimpHistogram *histogram,
gimp_histogram_alloc_values (histogram, region->bytes);
for (i = 0; i < NUM_SLOTS; i++)
if (histogram->values[i])
memset (histogram->values[i],
0, histogram->n_channels * 256 * sizeof (gdouble));
pixel_regions_process_parallel ((PixelProcessorFunc)
gimp_histogram_calculate_sub_region,
histogram, 2, region, mask);
@ -565,7 +736,16 @@ gimp_histogram_alloc_values (GimpHistogram *histogram,
histogram->n_channels = bytes + 1;
histogram->values[0] = g_new (gdouble, histogram->n_channels * 256);
histogram->values[0] = g_new0 (gdouble, histogram->n_channels * 256);
}
else
{
gint i;
for (i = 0; i < NUM_SLOTS; i++)
if (histogram->values[i])
memset (histogram->values[i],
0, histogram->n_channels * 256 * sizeof (gdouble));
}
}

View File

@ -28,6 +28,12 @@ void gimp_histogram_unref (GimpHistogram *histogram);
GimpHistogram * gimp_histogram_duplicate (GimpHistogram *histogram);
void gimp_histogram_calc_gegl (GimpHistogram *histogram,
GeglBuffer *buffer,
const GeglRectangle *buffer_rect,
GeglBuffer *mask,
const GeglRectangle *mask_rect);
void gimp_histogram_calculate (GimpHistogram *histogram,
PixelRegion *region,
PixelRegion *mask);