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-parallel.h"
|
||||
#include "gimpasync.h"
|
||||
#include "gimpdrawable.h"
|
||||
#include "gimphistogram.h"
|
||||
#include "gimpwaitable.h"
|
||||
|
||||
|
@ -119,6 +120,9 @@ static void gimp_histogram_calculate_area (const GeglRectangle
|
|||
CalculateData *data);
|
||||
static void gimp_histogram_calculate_async_callback (GimpAsync *async,
|
||||
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)
|
||||
|
@ -229,6 +233,49 @@ gimp_histogram_get_memsize (GimpObject *object,
|
|||
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 */
|
||||
|
||||
GimpHistogram *
|
||||
|
@ -1230,3 +1277,52 @@ gimp_histogram_calculate_async_callback (GimpAsync *async,
|
|||
|
||||
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);
|
||||
gboolean gimp_histogram_has_channel (GimpHistogram *histogram,
|
||||
GimpHistogramChannel channel);
|
||||
guint gimp_histogram_unique_colors (GimpDrawable *drawable);
|
||||
|
||||
|
||||
#endif /* __GIMP_HISTOGRAM_H__ */
|
||||
|
|
|
@ -132,12 +132,12 @@ gimp_histogram_editor_init (GimpHistogramEditor *editor)
|
|||
|
||||
const gchar *gimp_histogram_editor_labels[] =
|
||||
{
|
||||
N_("Mean:"),
|
||||
N_("Std dev:"),
|
||||
N_("Median:"),
|
||||
N_("Pixels:"),
|
||||
N_("Count:"),
|
||||
N_("Percentile:")
|
||||
N_("Mean: "),
|
||||
N_("Std dev: "),
|
||||
N_("Median: "),
|
||||
N_("Pixels: "),
|
||||
N_("Count: "),
|
||||
N_("Percentile: ")
|
||||
};
|
||||
|
||||
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_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
|
||||
|
@ -767,12 +791,23 @@ gimp_histogram_editor_info_update (GimpHistogramEditor *editor)
|
|||
(100.0 * count / pixels) :
|
||||
0.0));
|
||||
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
|
||||
{
|
||||
gint i;
|
||||
|
||||
for (i = 0; i < 6; i++)
|
||||
for (i = 0; i < 7; i++)
|
||||
gtk_label_set_text (GTK_LABEL (editor->labels[i]), NULL);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,7 +51,8 @@ struct _GimpHistogramEditor
|
|||
|
||||
GtkWidget *menu;
|
||||
GtkWidget *box;
|
||||
GtkWidget *labels[6];
|
||||
GtkWidget *labels[7];
|
||||
GtkWidget *toggle;
|
||||
};
|
||||
|
||||
struct _GimpHistogramEditorClass
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue