From cc21e6d70b70ece8cdcff965e7e8e08c25b60b77 Mon Sep 17 00:00:00 2001 From: Jehan Date: Sun, 15 Jun 2025 17:01:55 +0200 Subject: [PATCH] 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. --- app/core/gimphistogram.c | 28 +++++++++++++++------------- app/widgets/gimphistogrameditor.c | 6 +++++- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/app/core/gimphistogram.c b/app/core/gimphistogram.c index 730484d037..21b6afb03a 100644 --- a/app/core/gimphistogram.c +++ b/app/core/gimphistogram.c @@ -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; -} \ No newline at end of file +} diff --git a/app/widgets/gimphistogrameditor.c b/app/widgets/gimphistogrameditor.c index 09462bc672..82b425a7f2 100644 --- a/app/widgets/gimphistogrameditor.c +++ b/app/widgets/gimphistogrameditor.c @@ -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 ("%s", _("n/a")); + + gtk_label_set_markup (GTK_LABEL (editor->labels[6]), markup); + + g_free (markup); } } else