From 4a30f431fd032a4281f27bf41a4137e4616df043 Mon Sep 17 00:00:00 2001 From: Jehan Date: Sat, 9 Dec 2023 16:53:44 +0900 Subject: [PATCH] app: work with a GimpPalette rather than a colormap. We historically have both the colormap and palette concept in core GIMP, though they are actually kinda the same concept, except that with "colormap" we work with an array of raw data and it's a lot less color-aware. It is still much more efficient in some specific cases, such as when converting the image (we can then convert the whole palette as a single buffer, because the image palette is space-restricted anyway), when storing undo data or when storing/loading in XCF. But for all the rest, let's use gimp_image_get_colormap_palette() and work with the GimpPalette API. --- app/actions/colormap-actions.c | 3 +- app/actions/colormap-commands.c | 3 +- app/core/gimpdrawable.c | 12 ---- app/core/gimpdrawable.h | 2 - app/core/gimpimage-colormap.c | 82 ++++++++++++++++------------ app/core/gimpimage-colormap.h | 7 ++- app/core/gimpimage-convert-indexed.c | 6 +- app/core/gimpimageundo.c | 11 ++-- app/gimpcore.def | 7 +-- app/pdb/image-cmds.c | 14 ++--- app/widgets/gimpcolordialog.c | 2 +- app/widgets/gimpcolormapselection.c | 28 ++++++---- app/widgets/gimpimagepropview.c | 15 +++-- app/xcf/xcf-load.c | 2 +- app/xcf/xcf-save.c | 6 +- pdb/groups/image.pdb | 14 ++--- 16 files changed, 111 insertions(+), 103 deletions(-) diff --git a/app/actions/colormap-actions.c b/app/actions/colormap-actions.c index ad8655a3cc..da03377bde 100644 --- a/app/actions/colormap-actions.c +++ b/app/actions/colormap-actions.c @@ -28,6 +28,7 @@ #include "core/gimpdrawable.h" #include "core/gimpimage.h" #include "core/gimpimage-colormap.h" +#include "core/gimppalette.h" #include "widgets/gimpactiongroup.h" #include "widgets/gimpcolormapeditor.h" @@ -134,7 +135,7 @@ colormap_actions_update (GimpActionGroup *group, { GList *drawables = gimp_image_get_selected_drawables (image); - num_colors = gimp_image_get_colormap_size (image); + num_colors = gimp_palette_get_n_colors (gimp_image_get_colormap_palette ((image))); if (g_list_length (drawables) == 1) drawable_indexed = gimp_drawable_is_indexed (drawables->data); diff --git a/app/actions/colormap-commands.c b/app/actions/colormap-commands.c index c7741c01b1..4fd15097af 100644 --- a/app/actions/colormap-commands.c +++ b/app/actions/colormap-commands.c @@ -26,6 +26,7 @@ #include "core/gimpcontext.h" #include "core/gimpimage.h" #include "core/gimpimage-colormap.h" +#include "core/gimppalette.h" #include "widgets/gimpcolormapeditor.h" #include "widgets/gimpcolormapselection.h" @@ -69,7 +70,7 @@ colormap_add_color_cmd_callback (GimpAction *action, background = (gboolean) g_variant_get_int32 (value); - if (gimp_image_get_colormap_size (image) < 256) + if (gimp_palette_get_n_colors (gimp_image_get_colormap_palette ((image))) < 256) { GeglColor *color; diff --git a/app/core/gimpdrawable.c b/app/core/gimpdrawable.c index 9e7498708f..374d5b56f1 100644 --- a/app/core/gimpdrawable.c +++ b/app/core/gimpdrawable.c @@ -1997,18 +1997,6 @@ gimp_drawable_get_component_index (GimpDrawable *drawable, return -1; } -guchar * -gimp_drawable_get_colormap (GimpDrawable *drawable) -{ - GimpImage *image; - - g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL); - - image = gimp_item_get_image (GIMP_ITEM (drawable)); - - return image ? gimp_image_get_colormap (image) : NULL; -} - void gimp_drawable_start_paint (GimpDrawable *drawable) { diff --git a/app/core/gimpdrawable.h b/app/core/gimpdrawable.h index 7a8b5351ad..0bb4595fc7 100644 --- a/app/core/gimpdrawable.h +++ b/app/core/gimpdrawable.h @@ -230,8 +230,6 @@ const Babl * gimp_drawable_get_component_format (GimpDrawable *drawable, gint gimp_drawable_get_component_index (GimpDrawable *drawable, GimpChannelType channel); -guchar * gimp_drawable_get_colormap (GimpDrawable *drawable); - void gimp_drawable_start_paint (GimpDrawable *drawable); gboolean gimp_drawable_end_paint (GimpDrawable *drawable); gboolean gimp_drawable_flush_paint (GimpDrawable *drawable); diff --git a/app/core/gimpimage-colormap.c b/app/core/gimpimage-colormap.c index 5561fbda24..93f229b31a 100644 --- a/app/core/gimpimage-colormap.c +++ b/app/core/gimpimage-colormap.c @@ -167,8 +167,7 @@ gimp_image_colormap_update_formats (GimpImage *image) guchar *colormap; gint n_colors; - colormap = gimp_image_get_colormap (image); - n_colors = gimp_image_get_colormap_size (image); + colormap = _gimp_image_get_colormap (image, &n_colors); babl_palette_set_palette (private->babl_palette_rgb, gimp_babl_format (GIMP_RGB, @@ -251,11 +250,14 @@ gimp_image_set_colormap_palette (GimpImage *image, } guchar * -gimp_image_get_colormap (GimpImage *image) +_gimp_image_get_colormap (GimpImage *image, + gint *n_colors) { GimpImagePrivate *private; guchar *colormap = NULL; - gint n_colors, i; + const Babl *space; + const Babl *format; + gint bpp; g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); private = GIMP_IMAGE_GET_PRIVATE (image); @@ -263,46 +265,39 @@ gimp_image_get_colormap (GimpImage *image) if (private->palette == NULL) return NULL; - n_colors = gimp_palette_get_n_colors (private->palette); + space = gimp_image_get_layer_space (image); + format = gimp_babl_format (GIMP_RGB, private->precision, FALSE, space); + bpp = babl_format_get_bytes_per_pixel (format); - if (n_colors > 0) + *n_colors = gimp_palette_get_n_colors (private->palette); + + if (*n_colors > 0) { colormap = g_new0 (guchar, GIMP_IMAGE_COLORMAP_SIZE); - for (i = 0; i < n_colors; i++) + for (gint i = 0; i < *n_colors; i++) { GimpPaletteEntry *entry = gimp_palette_get_entry (private->palette, i); - /* TODO: what should be the format of the colormap? */ - gegl_color_get_pixel (entry->color, babl_format ("R'G'B' u8"), &colormap[i * 3]); + gegl_color_get_pixel (entry->color, format, &colormap[i * bpp]); } } return colormap; } -gint -gimp_image_get_colormap_size (GimpImage *image) -{ - GimpImagePrivate *private; - - g_return_val_if_fail (GIMP_IS_IMAGE (image), 0); - private = GIMP_IMAGE_GET_PRIVATE (image); - - if (private->palette == NULL) - return 0; - - return gimp_palette_get_n_colors (private->palette); -} - void -gimp_image_set_colormap (GimpImage *image, - const guchar *colormap, - gint n_colors, - gboolean push_undo) +_gimp_image_set_colormap (GimpImage *image, + const guchar *colormap, + gint n_colors, + gboolean push_undo) { GimpImagePrivate *private; GimpPaletteEntry *entry; + const Babl *space; + const Babl *format; + GeglColor *color; + gint bpp; gint i; g_return_if_fail (GIMP_IS_IMAGE (image)); @@ -322,14 +317,17 @@ gimp_image_set_colormap (GimpImage *image, while ((entry = gimp_palette_get_entry (private->palette, 0))) gimp_palette_delete_entry (private->palette, entry); + space = gimp_image_get_layer_space (image); + format = gimp_babl_format (GIMP_RGB, private->precision, FALSE, space); + bpp = babl_format_get_bytes_per_pixel (format); + + color = gegl_color_new (NULL); for (i = 0; i < n_colors; i++) { - GeglColor *color = gegl_color_new (NULL); - - gegl_color_set_pixel (color, babl_format ("R'G'B' u8"), &colormap[i * 3]); + gegl_color_set_pixel (color, format, &colormap[i * bpp]); gimp_image_colormap_set_palette_entry (image, color, i); - g_object_unref (color); } + g_object_unref (color); gimp_image_colormap_changed (image, -1); gimp_data_thaw (GIMP_DATA (private->palette)); @@ -528,19 +526,31 @@ gimp_image_colormap_set_palette_entry (GimpImage *image, GeglColor *color, gint index) { - GimpImagePrivate *private = GIMP_IMAGE_GET_PRIVATE (image); - GeglColor *black = gegl_color_new ("black"); + GimpImagePrivate *private = GIMP_IMAGE_GET_PRIVATE (image); + GeglColor *new_color = gegl_color_new ("black"); + const Babl *space; + const Babl *format; + guint8 rgb[3]; gchar name[64]; g_return_if_fail (GEGL_IS_COLOR (color)); + /* Adding black entries if needed. */ while (gimp_palette_get_n_colors (private->palette) <= index) - gimp_palette_add_entry (private->palette, index, name, black); + gimp_palette_add_entry (private->palette, index, name, new_color); g_snprintf (name, sizeof (name), "#%d", index); - gimp_palette_set_entry (private->palette, index, name, color); - g_object_unref (black); + space = gimp_image_get_layer_space (image); + format = gimp_babl_format (GIMP_RGB, private->precision, FALSE, space); + + /* For image colormap, we force the color to be in the target format (which at + * time of writing is only "R'G'B' u8" for the target space). + */ + gegl_color_get_pixel (color, format, rgb); + gegl_color_set_pixel (new_color, format, rgb); + gimp_palette_set_entry (private->palette, index, name, new_color); + g_object_unref (new_color); } static void diff --git a/app/core/gimpimage-colormap.h b/app/core/gimpimage-colormap.h index 284976c671..47f995b1a3 100644 --- a/app/core/gimpimage-colormap.h +++ b/app/core/gimpimage-colormap.h @@ -36,9 +36,10 @@ void gimp_image_set_colormap_palette (GimpImage *image, GimpPalette *palette, gboolean push_undo); -guchar * gimp_image_get_colormap (GimpImage *image); -gint gimp_image_get_colormap_size (GimpImage *image); -void gimp_image_set_colormap (GimpImage *image, +/* Only internally */ +guchar * _gimp_image_get_colormap (GimpImage *image, + gint *n_colors); +void _gimp_image_set_colormap (GimpImage *image, const guchar *colormap, gint n_colors, gboolean push_undo); diff --git a/app/core/gimpimage-convert-indexed.c b/app/core/gimpimage-convert-indexed.c index 9af6bb186d..38cb33b9e1 100644 --- a/app/core/gimpimage-convert-indexed.c +++ b/app/core/gimpimage-convert-indexed.c @@ -973,8 +973,8 @@ gimp_image_convert_indexed (GimpImage *image, colormap[j++] = quantobj->cmap[i].blue; } - gimp_image_set_colormap (image, colormap, - quantobj->actual_number_of_colors, TRUE); + _gimp_image_set_colormap (image, colormap, + quantobj->actual_number_of_colors, TRUE); } /* when converting from GRAY, always convert to the new type's @@ -1071,7 +1071,7 @@ gimp_image_convert_indexed (GimpImage *image, colormap[j] = new_palette[j]; j++; } - gimp_image_set_colormap (image, colormap, num_entries, TRUE); + _gimp_image_set_colormap (image, colormap, num_entries, TRUE); } /* When converting from GRAY, set the new profile. diff --git a/app/core/gimpimageundo.c b/app/core/gimpimageundo.c index c0b1048f12..d03f7ed5fa 100644 --- a/app/core/gimpimageundo.c +++ b/app/core/gimpimageundo.c @@ -182,8 +182,7 @@ gimp_image_undo_constructed (GObject *object) break; case GIMP_UNDO_IMAGE_COLORMAP: - image_undo->num_colors = gimp_image_get_colormap_size (image); - image_undo->colormap = gimp_image_get_colormap (image); + image_undo->colormap = _gimp_image_get_colormap (image, &image_undo->num_colors); break; case GIMP_UNDO_IMAGE_HIDDEN_PROFILE: @@ -452,13 +451,11 @@ gimp_image_undo_pop (GimpUndo *undo, guchar *colormap; gint num_colors; - num_colors = gimp_image_get_colormap_size (image); - colormap = gimp_image_get_colormap (image); + colormap = _gimp_image_get_colormap (image, &num_colors); if (image_undo->colormap) - gimp_image_set_colormap (image, - image_undo->colormap, image_undo->num_colors, - FALSE); + _gimp_image_set_colormap (image, image_undo->colormap, + image_undo->num_colors, FALSE); else gimp_image_unset_colormap (image, FALSE); diff --git a/app/gimpcore.def b/app/gimpcore.def index 234bd0d48a..ac37d1a983 100644 --- a/app/gimpcore.def +++ b/app/gimpcore.def @@ -1,4 +1,7 @@ EXPORTS + _gimp_image_get_colormap + _gimp_image_get_colormap_size + _gimp_image_set_colormap _gimp_unit_get_abbreviation _gimp_unit_get_deletion_flag _gimp_unit_get_digits @@ -287,9 +290,7 @@ EXPORTS gimp_image_get_active_vectors gimp_image_get_by_ID gimp_image_get_channels - gimp_image_get_colormap gimp_image_get_colormap_entry - gimp_image_get_colormap_size gimp_image_get_component_active gimp_image_get_component_index gimp_image_get_component_visible @@ -352,7 +353,6 @@ EXPORTS gimp_image_set_active_channel gimp_image_set_active_layer gimp_image_set_active_vectors - gimp_image_set_colormap gimp_image_set_colormap_entry gimp_image_set_component_active gimp_image_set_component_visible @@ -716,7 +716,6 @@ gimp_scan_convert_stroke gimp_array_free gimp_array_new -gimp_drawable_get_colormap gimp_drawable_get_tiles gimp_drawable_id_get_type gimp_float_array_get_type diff --git a/app/pdb/image-cmds.c b/app/pdb/image-cmds.c index acc2695bce..4506c31cdf 100644 --- a/app/pdb/image-cmds.c +++ b/app/pdb/image-cmds.c @@ -1528,10 +1528,10 @@ image_get_colormap_invoker (GimpProcedure *procedure, if (success) { guchar *colormap_data; + gint n_colors; - colormap_data = gimp_image_get_colormap (image); - colormap = g_bytes_new_take (colormap_data, - 3 * gimp_image_get_colormap_size (image)); + colormap_data = _gimp_image_get_colormap (image, &n_colors); + colormap = g_bytes_new_take (colormap_data, 3 * n_colors); } return_vals = gimp_procedure_get_return_values (procedure, success, @@ -1560,10 +1560,10 @@ image_set_colormap_invoker (GimpProcedure *procedure, if (success) { - gimp_image_set_colormap (image, - g_bytes_get_data (colormap, NULL), - g_bytes_get_size (colormap) / 3, - TRUE); + _gimp_image_set_colormap (image, + g_bytes_get_data (colormap, NULL), + g_bytes_get_size (colormap) / 3, + TRUE); } return gimp_procedure_get_return_values (procedure, success, diff --git a/app/widgets/gimpcolordialog.c b/app/widgets/gimpcolordialog.c index 2a580828ee..4aa4558738 100644 --- a/app/widgets/gimpcolordialog.c +++ b/app/widgets/gimpcolordialog.c @@ -620,7 +620,7 @@ gimp_color_dialog_colormap_add_activate (GimpColorDialog *dialog) GimpViewableDialog *viewable_dialog = GIMP_VIEWABLE_DIALOG (dialog); if (dialog->active_image && - gimp_image_get_colormap_size (dialog->active_image) < 256 && + gimp_palette_get_n_colors (gimp_image_get_colormap_palette (dialog->active_image)) < 256 && viewable_dialog->context) { GimpContext *user_context = viewable_dialog->context->gimp->user_context; diff --git a/app/widgets/gimpcolormapselection.c b/app/widgets/gimpcolormapselection.c index 9adde694ef..bdae46fd06 100644 --- a/app/widgets/gimpcolormapselection.c +++ b/app/widgets/gimpcolormapselection.c @@ -390,10 +390,10 @@ gimp_colormap_selection_get_index (GimpColormapSelection *selection, if (! gimp_color_is_perceptually_identical (temp, search)) { - gint n_colors = gimp_image_get_colormap_size (image); - gint i; + gint n_colors; - for (i = 0; i < n_colors; i++) + n_colors = gimp_palette_get_n_colors (gimp_image_get_colormap_palette (image)); + for (gint i = 0; i < n_colors; i++) { temp = gimp_image_get_colormap_entry (image, i); @@ -425,7 +425,7 @@ gimp_colormap_selection_set_index (GimpColormapSelection *selection, if (! HAVE_COLORMAP (image)) return FALSE; - size = gimp_image_get_colormap_size (image); + size = gimp_palette_get_n_colors (gimp_image_get_colormap_palette (image)); if (size < 1) return FALSE; @@ -463,6 +463,7 @@ gint gimp_colormap_selection_max_index (GimpColormapSelection *selection) { GimpImage *image; + gint n_colors; g_return_val_if_fail (GIMP_IS_COLORMAP_SELECTION (selection), -1); @@ -471,7 +472,9 @@ gimp_colormap_selection_max_index (GimpColormapSelection *selection) if (! HAVE_COLORMAP (image)) return -1; - return MAX (0, gimp_image_get_colormap_size (image) - 1); + n_colors = gimp_palette_get_n_colors (gimp_image_get_colormap_palette (image)); + + return MAX (0, n_colors - 1); } GimpPaletteEntry * @@ -571,10 +574,13 @@ gimp_colormap_selection_preview_draw (GtkWidget *widget, static void gimp_colormap_selection_update_entries (GimpColormapSelection *selection) { - GimpImage *image = gimp_context_get_image (selection->context); + GimpImage *image = gimp_context_get_image (selection->context); + gint n_colors = 0; - if (! HAVE_COLORMAP (image) || - ! gimp_image_get_colormap_size (image)) + if (gimp_image_get_colormap_palette (image)) + n_colors = gimp_palette_get_n_colors (gimp_image_get_colormap_palette (image)); + + if (! HAVE_COLORMAP (image) || ! n_colors) { gtk_widget_set_sensitive (selection->index_spinbutton, FALSE); gtk_widget_set_sensitive (selection->color_entry, FALSE); @@ -821,13 +827,15 @@ gimp_colormap_selection_set_palette (GimpColormapSelection *selection) if (palette) { + gint n_colors; + + n_colors = gimp_palette_get_n_colors (palette); g_signal_connect_swapped (palette, "dirty", G_CALLBACK (gtk_widget_queue_draw), selection); gimp_view_set_viewable (GIMP_VIEW (selection->view), GIMP_VIEWABLE (palette)); - gtk_adjustment_set_upper (selection->index_adjustment, - gimp_image_get_colormap_size (selection->active_image) - 1); + gtk_adjustment_set_upper (selection->index_adjustment, n_colors - 1); } } } diff --git a/app/widgets/gimpimagepropview.c b/app/widgets/gimpimagepropview.c index 5ad3cb6060..d448bd0deb 100644 --- a/app/widgets/gimpimagepropview.c +++ b/app/widgets/gimpimagepropview.c @@ -35,6 +35,7 @@ #include "core/gimpimage.h" #include "core/gimpimage-colormap.h" #include "core/gimpimage-undo.h" +#include "core/gimppalette.h" #include "core/gimpundostack.h" #include "core/gimp-utils.h" @@ -479,11 +480,15 @@ gimp_image_prop_view_update (GimpImagePropView *view) gimp_color_profile_get_label (profile)); break; case GIMP_INDEXED: - g_snprintf (buf, sizeof (buf), - ngettext ("Indexed color (monochrome)", - "Indexed color (%d colors)", - gimp_image_get_colormap_size (image)), - gimp_image_get_colormap_size (image)); + { + gint n_colors; + + n_colors = gimp_palette_get_n_colors (gimp_image_get_colormap_palette (image)); + g_snprintf (buf, sizeof (buf), + ngettext ("Indexed color (monochrome)", + "Indexed color (%d colors)", + n_colors), n_colors); + } break; } diff --git a/app/xcf/xcf-load.c b/app/xcf/xcf-load.c index 8edddce092..4a28f6138c 100644 --- a/app/xcf/xcf-load.c +++ b/app/xcf/xcf-load.c @@ -1178,7 +1178,7 @@ xcf_load_image_props (XcfInfo *info, * an image state that is impossible. */ if (gimp_image_get_base_type (image) == GIMP_INDEXED) - gimp_image_set_colormap (image, cmap, n_colors, FALSE); + _gimp_image_set_colormap (image, cmap, n_colors, FALSE); GIMP_LOG (XCF, "prop colormap n_colors=%d", n_colors); } diff --git a/app/xcf/xcf-save.c b/app/xcf/xcf-save.c index 367b9e5b30..ea9a44daeb 100644 --- a/app/xcf/xcf-save.c +++ b/app/xcf/xcf-save.c @@ -487,10 +487,10 @@ xcf_save_image_props (XcfInfo *info, /* check and see if we should save the colormap property */ if (gimp_image_get_colormap_palette (image)) { - guint8 *colormap = gimp_image_get_colormap (image); + gint n_colors; + guint8 *colormap = _gimp_image_get_colormap (image, &n_colors); xcf_check_error (xcf_save_prop (info, image, PROP_COLORMAP, error, - gimp_image_get_colormap_size (image), - colormap), ;); + n_colors, colormap), ;); g_free (colormap); } diff --git a/pdb/groups/image.pdb b/pdb/groups/image.pdb index 896aaa1687..015043338a 100644 --- a/pdb/groups/image.pdb +++ b/pdb/groups/image.pdb @@ -1521,10 +1521,10 @@ HELP code => <<'CODE' { guchar *colormap_data; + gint n_colors; - colormap_data = gimp_image_get_colormap (image); - colormap = g_bytes_new_take (colormap_data, - 3 * gimp_image_get_colormap_size (image)); + colormap_data = _gimp_image_get_colormap (image, &n_colors); + colormap = g_bytes_new_take (colormap_data, 3 * n_colors); } CODE ); @@ -1555,10 +1555,10 @@ HELP headers => [ qw("core/gimpimage-colormap.h") ], code => <<'CODE' { - gimp_image_set_colormap (image, - g_bytes_get_data (colormap, NULL), - g_bytes_get_size (colormap) / 3, - TRUE); + _gimp_image_set_colormap (image, + g_bytes_get_data (colormap, NULL), + g_bytes_get_size (colormap) / 3, + TRUE); } CODE );