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:
@ -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, ®ion, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
GIMP_TIMER_END("histogram");
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
Reference in New Issue
Block a user