app: fixup commit be1496a91e implementing unique color count.

- Improve the hash: doing the value computation in guint64, we'd
  wrap-around the max guint64, which mostly means that we'd drop all
  high bits! Therefore the hash doesn't depend at all on the most
  significant bits. Instead let's do our computation in double and
  convert to guint in the end. I am not 100% sure if it is that much
  better, to be fair (thinking in term of color: the old hash function
  depended on the least significant color channels; I do wonder if it
  could not make collisions more frequent but I'm not sure). The
  wrap-around hash function should be fairly distributed too, but then
  maybe we should just use guint directly in this case.
- The computation of unique colors was leaking all the GBytes but the
  last! First we must use g_hash_table_new_full() to set a free function
  for inserted keys, then we must free every non-inserted key ourselves.
- The "n/a" string should be localized (it's English acronym).
- Also display this "n/a" in italic to make it clearly different from
  computed numbers.
This commit is contained in:
Jehan 2025-06-15 17:01:55 +02:00
parent 22a14d6248
commit cc21e6d70b
2 changed files with 20 additions and 14 deletions

View file

@ -239,22 +239,22 @@ hash_color_bytes (gpointer *key)
GBytes *bytes = (GBytes *) key;
gsize size;
const guint8 *data;
guint64 max_value = 0;
guint64 value = 0;
gdouble max_value = 0.0;
gdouble value = 0.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;
value = value * 256.0 + data[i];
max_value = max_value * 256.0 + 255.0;
}
if (max_value == 0)
return 0;
hash = (guint) ((value * (guint64) G_MAXUINT) / max_value);
hash = (guint) (value * G_MAXUINT / max_value);
return hash;
}
@ -1285,7 +1285,6 @@ gimp_histogram_unique_colors (GimpDrawable *drawable)
guint bpp;
GeglBufferIterator *iter;
GHashTable *hash_table;
GBytes *key = NULL;
guint uniques = 0;
g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), 0);
@ -1298,8 +1297,10 @@ gimp_histogram_unique_colors (GimpDrawable *drawable)
GEGL_ACCESS_READ, GEGL_ABYSS_NONE, 1);
hash_table = g_hash_table_new ((GHashFunc) hash_color_bytes,
(GEqualFunc) color_bytes_equal);
hash_table = g_hash_table_new_full ((GHashFunc) hash_color_bytes,
(GEqualFunc) color_bytes_equal,
(GDestroyNotify) g_bytes_unref,
NULL);
while (gegl_buffer_iterator_next (iter))
{
@ -1308,21 +1309,22 @@ gimp_histogram_unique_colors (GimpDrawable *drawable)
while (length--)
{
key = g_bytes_new (data, bpp);
GBytes *key = g_bytes_new (data, bpp);
if (! g_hash_table_lookup (hash_table, key))
if (! g_hash_table_lookup_extended (hash_table, key, NULL, NULL))
{
g_hash_table_insert (hash_table, key, key);
g_hash_table_insert (hash_table, key, NULL);
key = NULL;
uniques++;
}
g_bytes_unref (key);
data += bpp;
}
}
g_hash_table_destroy (hash_table);
g_bytes_unref (key);
return uniques;
}

View file

@ -800,7 +800,11 @@ gimp_histogram_editor_info_update (GimpHistogramEditor *editor)
}
else
{
gtk_label_set_text (GTK_LABEL (editor->labels[6]), "n/a");
gchar *markup = g_strdup_printf ("<i>%s</i>", _("n/a"));
gtk_label_set_markup (GTK_LABEL (editor->labels[6]), markup);
g_free (markup);
}
}
else