mirror of
https://gitlab.gnome.org/GNOME/gimp.git
synced 2025-07-04 01:43:24 +00:00
widgets: implement unique color count
This patch reintroduce the unique color counting in an image, an old feature from old color-cube-analyze plug-in. See #13026
This commit is contained in:
parent
d028b96654
commit
be1496a91e
4 changed files with 141 additions and 8 deletions
|
@ -37,6 +37,7 @@
|
||||||
#include "gimp-atomic.h"
|
#include "gimp-atomic.h"
|
||||||
#include "gimp-parallel.h"
|
#include "gimp-parallel.h"
|
||||||
#include "gimpasync.h"
|
#include "gimpasync.h"
|
||||||
|
#include "gimpdrawable.h"
|
||||||
#include "gimphistogram.h"
|
#include "gimphistogram.h"
|
||||||
#include "gimpwaitable.h"
|
#include "gimpwaitable.h"
|
||||||
|
|
||||||
|
@ -119,6 +120,9 @@ static void gimp_histogram_calculate_area (const GeglRectangle
|
||||||
CalculateData *data);
|
CalculateData *data);
|
||||||
static void gimp_histogram_calculate_async_callback (GimpAsync *async,
|
static void gimp_histogram_calculate_async_callback (GimpAsync *async,
|
||||||
CalculateContext *context);
|
CalculateContext *context);
|
||||||
|
static guint hash_color_bytes (gpointer *key);
|
||||||
|
static gboolean color_bytes_equal (gpointer *key1,
|
||||||
|
gpointer *key2);
|
||||||
|
|
||||||
|
|
||||||
G_DEFINE_TYPE_WITH_PRIVATE (GimpHistogram, gimp_histogram, GIMP_TYPE_OBJECT)
|
G_DEFINE_TYPE_WITH_PRIVATE (GimpHistogram, gimp_histogram, GIMP_TYPE_OBJECT)
|
||||||
|
@ -229,6 +233,49 @@ gimp_histogram_get_memsize (GimpObject *object,
|
||||||
gui_size);
|
gui_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static guint
|
||||||
|
hash_color_bytes (gpointer *key)
|
||||||
|
{
|
||||||
|
GBytes *bytes = (GBytes *) key;
|
||||||
|
gsize size;
|
||||||
|
const guint8 *data;
|
||||||
|
guint64 max_value = 0;
|
||||||
|
guint64 value = 0;
|
||||||
|
guint hash;
|
||||||
|
|
||||||
|
data = g_bytes_get_data (bytes, &size);
|
||||||
|
|
||||||
|
for (gsize i = 0; i < size; ++i)
|
||||||
|
{
|
||||||
|
value = value * 256 + data[i];
|
||||||
|
max_value = max_value * 256 + 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (max_value == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
hash = (guint) ((value * (guint64) G_MAXUINT) / max_value);
|
||||||
|
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
color_bytes_equal (gpointer *key1,
|
||||||
|
gpointer *key2)
|
||||||
|
{
|
||||||
|
GBytes *bytes1 = (GBytes *) key1;
|
||||||
|
GBytes *bytes2 = (GBytes *) key2;
|
||||||
|
gsize size1;
|
||||||
|
gsize size2;
|
||||||
|
const guint8 *data1 = g_bytes_get_data (bytes1, &size1);
|
||||||
|
const guint8 *data2 = g_bytes_get_data (bytes2, &size2);
|
||||||
|
|
||||||
|
if (size1 != size2)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
return memcmp (data1, data2, size1) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* public functions */
|
/* public functions */
|
||||||
|
|
||||||
GimpHistogram *
|
GimpHistogram *
|
||||||
|
@ -1230,3 +1277,52 @@ gimp_histogram_calculate_async_callback (GimpAsync *async,
|
||||||
|
|
||||||
g_slice_free (CalculateContext, context);
|
g_slice_free (CalculateContext, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
guint
|
||||||
|
gimp_histogram_unique_colors (GimpDrawable *drawable)
|
||||||
|
{
|
||||||
|
const Babl *format;
|
||||||
|
guint bpp;
|
||||||
|
GeglBufferIterator *iter;
|
||||||
|
GHashTable *hash_table;
|
||||||
|
GBytes *key = NULL;
|
||||||
|
guint uniques = 0;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), 0);
|
||||||
|
|
||||||
|
format = gimp_drawable_get_format (drawable);
|
||||||
|
bpp = babl_format_get_bytes_per_pixel (format);
|
||||||
|
|
||||||
|
iter = gegl_buffer_iterator_new (gimp_drawable_get_buffer (drawable),
|
||||||
|
NULL, 0, format,
|
||||||
|
GEGL_ACCESS_READ, GEGL_ABYSS_NONE, 1);
|
||||||
|
|
||||||
|
|
||||||
|
hash_table = g_hash_table_new ((GHashFunc) hash_color_bytes,
|
||||||
|
(GEqualFunc) color_bytes_equal);
|
||||||
|
|
||||||
|
while (gegl_buffer_iterator_next (iter))
|
||||||
|
{
|
||||||
|
guint8 *data = iter->items[0].data;
|
||||||
|
guint length = iter->length;
|
||||||
|
|
||||||
|
while (length--)
|
||||||
|
{
|
||||||
|
key = g_bytes_new (data, bpp);
|
||||||
|
|
||||||
|
if (! g_hash_table_lookup (hash_table, key))
|
||||||
|
{
|
||||||
|
g_hash_table_insert (hash_table, key, key);
|
||||||
|
key = NULL;
|
||||||
|
uniques++;
|
||||||
|
}
|
||||||
|
|
||||||
|
data += bpp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_hash_table_destroy (hash_table);
|
||||||
|
g_bytes_unref (key);
|
||||||
|
|
||||||
|
return uniques;
|
||||||
|
}
|
|
@ -100,6 +100,7 @@ gint gimp_histogram_n_components (GimpHistogram *histogram)
|
||||||
gint gimp_histogram_n_bins (GimpHistogram *histogram);
|
gint gimp_histogram_n_bins (GimpHistogram *histogram);
|
||||||
gboolean gimp_histogram_has_channel (GimpHistogram *histogram,
|
gboolean gimp_histogram_has_channel (GimpHistogram *histogram,
|
||||||
GimpHistogramChannel channel);
|
GimpHistogramChannel channel);
|
||||||
|
guint gimp_histogram_unique_colors (GimpDrawable *drawable);
|
||||||
|
|
||||||
|
|
||||||
#endif /* __GIMP_HISTOGRAM_H__ */
|
#endif /* __GIMP_HISTOGRAM_H__ */
|
||||||
|
|
|
@ -132,12 +132,12 @@ gimp_histogram_editor_init (GimpHistogramEditor *editor)
|
||||||
|
|
||||||
const gchar *gimp_histogram_editor_labels[] =
|
const gchar *gimp_histogram_editor_labels[] =
|
||||||
{
|
{
|
||||||
N_("Mean:"),
|
N_("Mean: "),
|
||||||
N_("Std dev:"),
|
N_("Std dev: "),
|
||||||
N_("Median:"),
|
N_("Median: "),
|
||||||
N_("Pixels:"),
|
N_("Pixels: "),
|
||||||
N_("Count:"),
|
N_("Count: "),
|
||||||
N_("Percentile:")
|
N_("Percentile: ")
|
||||||
};
|
};
|
||||||
|
|
||||||
editor->box = gimp_histogram_box_new ();
|
editor->box = gimp_histogram_box_new ();
|
||||||
|
@ -221,6 +221,30 @@ gimp_histogram_editor_init (GimpHistogramEditor *editor)
|
||||||
gtk_grid_attach (GTK_GRID (grid), label, x + 1, y, 1, 1);
|
gtk_grid_attach (GTK_GRID (grid), label, x + 1, y, 1, 1);
|
||||||
gtk_widget_show (label);
|
gtk_widget_show (label);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
editor->toggle = gtk_check_button_new_with_label (_("Compute unique colors:"));
|
||||||
|
gimp_label_set_attributes (GTK_LABEL (gtk_bin_get_child (GTK_BIN (editor->toggle))),
|
||||||
|
PANGO_ATTR_SCALE, PANGO_SCALE_SMALL,
|
||||||
|
-1);
|
||||||
|
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (editor->toggle), FALSE);
|
||||||
|
g_signal_connect_swapped (editor->toggle, "toggled",
|
||||||
|
G_CALLBACK (gimp_histogram_editor_info_update),
|
||||||
|
editor);
|
||||||
|
gtk_widget_set_margin_start (gtk_bin_get_child (GTK_BIN (editor->toggle)), 6);
|
||||||
|
gtk_widget_set_halign (editor->toggle, GTK_ALIGN_END);
|
||||||
|
gtk_grid_attach (GTK_GRID (grid), editor->toggle, 0, 3, 1, 1);
|
||||||
|
gtk_widget_show (editor->toggle);
|
||||||
|
|
||||||
|
editor->labels[6] = label = g_object_new (GTK_TYPE_LABEL,
|
||||||
|
"xalign", 0.0,
|
||||||
|
"yalign", 0.5,
|
||||||
|
"width-chars", 9,
|
||||||
|
NULL);
|
||||||
|
gimp_label_set_attributes (GTK_LABEL (label),
|
||||||
|
PANGO_ATTR_SCALE, PANGO_SCALE_SMALL,
|
||||||
|
-1);
|
||||||
|
gtk_grid_attach (GTK_GRID (grid), label, 1, 3, 1, 1);
|
||||||
|
gtk_widget_show (label);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -767,12 +791,23 @@ gimp_histogram_editor_info_update (GimpHistogramEditor *editor)
|
||||||
(100.0 * count / pixels) :
|
(100.0 * count / pixels) :
|
||||||
0.0));
|
0.0));
|
||||||
gtk_label_set_text (GTK_LABEL (editor->labels[5]), text);
|
gtk_label_set_text (GTK_LABEL (editor->labels[5]), text);
|
||||||
|
|
||||||
|
if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (editor->toggle)))
|
||||||
|
{
|
||||||
|
g_snprintf (text, sizeof (text), "%d",
|
||||||
|
gimp_histogram_unique_colors (editor->drawable));
|
||||||
|
gtk_label_set_text (GTK_LABEL (editor->labels[6]), text);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gtk_label_set_text (GTK_LABEL (editor->labels[6]), "n/a");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
gint i;
|
gint i;
|
||||||
|
|
||||||
for (i = 0; i < 6; i++)
|
for (i = 0; i < 7; i++)
|
||||||
gtk_label_set_text (GTK_LABEL (editor->labels[i]), NULL);
|
gtk_label_set_text (GTK_LABEL (editor->labels[i]), NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,7 +51,8 @@ struct _GimpHistogramEditor
|
||||||
|
|
||||||
GtkWidget *menu;
|
GtkWidget *menu;
|
||||||
GtkWidget *box;
|
GtkWidget *box;
|
||||||
GtkWidget *labels[6];
|
GtkWidget *labels[7];
|
||||||
|
GtkWidget *toggle;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GimpHistogramEditorClass
|
struct _GimpHistogramEditorClass
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue