From f78a0629507cfdb47671ad57185d2f4998015487 Mon Sep 17 00:00:00 2001 From: Jehan Date: Wed, 29 Oct 2025 20:13:17 +0100 Subject: [PATCH] app, pdb: fix gimp_drawable_get_thumbnail() on high-bit depth drawable. This bug had several causes: * gimp_drawable_get_thumbnail_data() is pretty crappy as it just returns dimensions and bpp. You get no real format information. * When using it to create a GdkPixbuf, which seems like the most common usage, only sRGB (with or without alpha) in 8-bit is supported by GdkPixbuf. So I'm just making sure that private _gimp_drawable_thumbnail() PDB proc is only returning 8-bit sRGB(A) data. For thumbnailing, this is probably fine anyway. Fixes when calling gimp_drawable_get_thumbnail() on an item from a high-bit depth image: > LibGimp-CRITICAL **: 20:12:21.028: file ../../../../../../../dev/src/gimp/libgimp/gimppixbuf.c: line 112 (_gimp_pixbuf_from_data): should not be reached --- app/pdb/drawable-cmds.c | 40 ++++++++++++++++++++++++++++++----- pdb/groups/drawable.pdb | 46 ++++++++++++++++++++++++++++++++++------- 2 files changed, 73 insertions(+), 13 deletions(-) diff --git a/app/pdb/drawable-cmds.c b/app/pdb/drawable-cmds.c index 67f86bf8d4..a702feba1a 100644 --- a/app/pdb/drawable-cmds.c +++ b/app/pdb/drawable-cmds.c @@ -988,11 +988,41 @@ drawable_thumbnail_invoker (GimpProcedure *procedure, if (buf) { - actual_width = gimp_temp_buf_get_width (buf); - actual_height = gimp_temp_buf_get_height (buf); - bpp = babl_format_get_bytes_per_pixel (gimp_temp_buf_get_format (buf)); - thumbnail_data = g_bytes_new (gimp_temp_buf_get_data (buf), - gimp_temp_buf_get_data_size (buf)); + const Babl *format = gimp_temp_buf_get_format (buf); + const Babl *rgb_format = babl_format ("R'G'B' u8"); + const Babl *rgba_format = babl_format ("R'G'B'A u8"); + const Babl *fish = NULL; + + if (babl_format_has_alpha (format) && format != rgba_format) + { + fish = babl_fish (format, rgba_format); + format = rgba_format; + } + else if (! babl_format_has_alpha (format) && format != rgb_format) + { + fish = babl_fish (format, rgb_format); + format = rgb_format; + } + + actual_width = gimp_temp_buf_get_width (buf); + actual_height = gimp_temp_buf_get_height (buf); + bpp = babl_format_get_bytes_per_pixel (format); + if (fish) + { + guchar *data; + gint data_size = bpp * actual_width * actual_height; + + data = g_malloc (data_size); + babl_process (fish, gimp_temp_buf_get_data (buf), data, actual_width * actual_height); + + thumbnail_data = g_bytes_new (data, data_size); + g_free (data); + } + else + { + thumbnail_data = g_bytes_new (gimp_temp_buf_get_data (buf), + gimp_temp_buf_get_data_size (buf)); + } gimp_temp_buf_unref (buf); } diff --git a/pdb/groups/drawable.pdb b/pdb/groups/drawable.pdb index bfbc2a166a..f71921d6fd 100644 --- a/pdb/groups/drawable.pdb +++ b/pdb/groups/drawable.pdb @@ -959,9 +959,9 @@ HELP desc => 'The previews height' }, { name => 'bpp', type => 'int32', desc => 'The previews bpp' }, - { name => 'thumbnail_data', type => 'bytes', - desc => 'The thumbnail data', } - ); + { name => 'thumbnail_data', type => 'bytes', + desc => 'The thumbnail data', } + ); %invoke = ( code => <<'CODE' @@ -991,11 +991,41 @@ HELP if (buf) { - actual_width = gimp_temp_buf_get_width (buf); - actual_height = gimp_temp_buf_get_height (buf); - bpp = babl_format_get_bytes_per_pixel (gimp_temp_buf_get_format (buf)); - thumbnail_data = g_bytes_new (gimp_temp_buf_get_data (buf), - gimp_temp_buf_get_data_size (buf)); + const Babl *format = gimp_temp_buf_get_format (buf); + const Babl *rgb_format = babl_format ("R'G'B' u8"); + const Babl *rgba_format = babl_format ("R'G'B'A u8"); + const Babl *fish = NULL; + + if (babl_format_has_alpha (format) && format != rgba_format) + { + fish = babl_fish (format, rgba_format); + format = rgba_format; + } + else if (! babl_format_has_alpha (format) && format != rgb_format) + { + fish = babl_fish (format, rgb_format); + format = rgb_format; + } + + actual_width = gimp_temp_buf_get_width (buf); + actual_height = gimp_temp_buf_get_height (buf); + bpp = babl_format_get_bytes_per_pixel (format); + if (fish) + { + guchar *data; + gint data_size = bpp * actual_width * actual_height; + + data = g_malloc (data_size); + babl_process (fish, gimp_temp_buf_get_data (buf), data, actual_width * actual_height); + + thumbnail_data = g_bytes_new (data, data_size); + g_free (data); + } + else + { + thumbnail_data = g_bytes_new (gimp_temp_buf_get_data (buf), + gimp_temp_buf_get_data_size (buf)); + } gimp_temp_buf_unref (buf); }