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 "gegl/gimp-gegl-nodes.h"
|
||||||
|
|
||||||
#include "gimp.h" /* gimp_use_gegl */
|
#include "gimp.h" /* gimp_use_gegl */
|
||||||
|
#include "gimp-utils.h"
|
||||||
#include "gimpchannel.h"
|
#include "gimpchannel.h"
|
||||||
#include "gimpdrawable-histogram.h"
|
#include "gimpdrawable-histogram.h"
|
||||||
#include "gimphistogram.h"
|
#include "gimphistogram.h"
|
||||||
@ -52,6 +53,8 @@ gimp_drawable_calculate_histogram (GimpDrawable *drawable,
|
|||||||
image = gimp_item_get_image (GIMP_ITEM (drawable));
|
image = gimp_item_get_image (GIMP_ITEM (drawable));
|
||||||
mask = gimp_image_get_mask (image);
|
mask = gimp_image_get_mask (image);
|
||||||
|
|
||||||
|
GIMP_TIMER_START();
|
||||||
|
|
||||||
if (FALSE) // gimp_use_gegl (image->gimp))
|
if (FALSE) // gimp_use_gegl (image->gimp))
|
||||||
{
|
{
|
||||||
GeglNode *node = gegl_node_new ();
|
GeglNode *node = gegl_node_new ();
|
||||||
@ -99,6 +102,29 @@ gimp_drawable_calculate_histogram (GimpDrawable *drawable,
|
|||||||
g_object_unref (processor);
|
g_object_unref (processor);
|
||||||
g_object_unref (node);
|
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
|
else
|
||||||
{
|
{
|
||||||
PixelRegion region;
|
PixelRegion region;
|
||||||
@ -122,4 +148,6 @@ gimp_drawable_calculate_histogram (GimpDrawable *drawable,
|
|||||||
gimp_histogram_calculate (histogram, ®ion, NULL);
|
gimp_histogram_calculate (histogram, ®ion, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GIMP_TIMER_END("histogram");
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#undef G_DISABLE_DEPRECATED /* GStaticMutex */
|
#undef G_DISABLE_DEPRECATED /* GStaticMutex */
|
||||||
#include <glib-object.h>
|
#include <gegl.h>
|
||||||
|
|
||||||
#include "libgimpmath/gimpmath.h"
|
#include "libgimpmath/gimpmath.h"
|
||||||
|
|
||||||
@ -33,7 +33,6 @@
|
|||||||
|
|
||||||
#include "gimphistogram.h"
|
#include "gimphistogram.h"
|
||||||
|
|
||||||
|
|
||||||
#ifdef ENABLE_MP
|
#ifdef ENABLE_MP
|
||||||
#define NUM_SLOTS GIMP_MAX_NUM_THREADS
|
#define NUM_SLOTS GIMP_MAX_NUM_THREADS
|
||||||
#else
|
#else
|
||||||
@ -135,6 +134,183 @@ gimp_histogram_duplicate (GimpHistogram *histogram)
|
|||||||
return dup;
|
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
|
void
|
||||||
gimp_histogram_calculate (GimpHistogram *histogram,
|
gimp_histogram_calculate (GimpHistogram *histogram,
|
||||||
PixelRegion *region,
|
PixelRegion *region,
|
||||||
@ -147,11 +323,6 @@ gimp_histogram_calculate (GimpHistogram *histogram,
|
|||||||
|
|
||||||
gimp_histogram_alloc_values (histogram, region->bytes);
|
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)
|
pixel_regions_process_parallel ((PixelProcessorFunc)
|
||||||
gimp_histogram_calculate_sub_region,
|
gimp_histogram_calculate_sub_region,
|
||||||
histogram, 2, region, mask);
|
histogram, 2, region, mask);
|
||||||
@ -565,7 +736,16 @@ gimp_histogram_alloc_values (GimpHistogram *histogram,
|
|||||||
|
|
||||||
histogram->n_channels = bytes + 1;
|
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);
|
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,
|
void gimp_histogram_calculate (GimpHistogram *histogram,
|
||||||
PixelRegion *region,
|
PixelRegion *region,
|
||||||
PixelRegion *mask);
|
PixelRegion *mask);
|
||||||
|
Reference in New Issue
Block a user