1
1
mirror of https://gitlab.gnome.org/GNOME/gimp.git synced 2025-10-06 01:12:40 +02:00

app, libgimp, pdb: new gimp_palette_set_colormap() PDB procedure.

This commit is contained in:
Jehan
2024-09-21 20:45:09 +02:00
parent f66c9c1996
commit 6a35118a8f
10 changed files with 347 additions and 62 deletions

View File

@@ -175,6 +175,7 @@ gimp_data_class_init (GimpDataClass *klass)
g_object_class_install_property (object_class, PROP_IMAGE,
g_param_spec_object ("image", NULL, NULL,
GIMP_TYPE_IMAGE,
G_PARAM_EXPLICIT_NOTIFY |
GIMP_PARAM_READWRITE));
g_object_class_install_property (object_class, PROP_WRITABLE,
@@ -992,6 +993,8 @@ gimp_data_set_image (GimpData *data,
private->writable = writable ? TRUE : FALSE;
private->deletable = deletable ? TRUE : FALSE;
g_object_notify (G_OBJECT (data), "image");
}
GimpImage *

View File

@@ -88,7 +88,7 @@ gimp_image_colormap_init (GimpImage *image)
palette_id = g_strdup_printf ("gimp-indexed-image-palette-%d",
gimp_image_get_id (image));
private->palette = GIMP_PALETTE (gimp_palette_new (NULL, palette_name));
private->palette = GIMP_PALETTE (gimp_palette_new (NULL, palette_name));
gimp_image_colormap_update_formats (image);
@@ -254,8 +254,6 @@ _gimp_image_get_colormap (GimpImage *image,
gint *n_colors)
{
GimpImagePrivate *private;
const Babl *space;
const Babl *format;
g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);
@@ -264,10 +262,9 @@ _gimp_image_get_colormap (GimpImage *image,
if (private->palette == NULL)
return NULL;
space = gimp_image_get_layer_space (image);
format = gimp_babl_format (GIMP_RGB, private->precision, FALSE, space);
g_return_val_if_fail (private->palette->format != NULL, NULL);
return gimp_palette_get_colormap (private->palette, format, n_colors);
return gimp_palette_get_colormap (private->palette, private->palette->format, n_colors);
}
void
@@ -277,12 +274,8 @@ _gimp_image_set_colormap (GimpImage *image,
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));
g_return_if_fail (colormap != NULL || n_colors == 0);
@@ -290,31 +283,14 @@ _gimp_image_set_colormap (GimpImage *image,
private = GIMP_IMAGE_GET_PRIVATE (image);
if (push_undo)
gimp_image_undo_push_image_colormap (image, C_("undo-type", "Set Colormap"));
if (!private->palette)
if (private->palette == NULL)
gimp_image_colormap_init (image);
gimp_data_freeze (GIMP_DATA (private->palette));
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++)
{
gegl_color_set_pixel (color, format, &colormap[i * bpp]);
gimp_image_colormap_set_palette_entry (image, color, i);
}
g_object_unref (color);
gimp_palette_set_colormap (private->palette, format, colormap, n_colors, push_undo);
gimp_image_colormap_changed (image, -1);
gimp_data_thaw (GIMP_DATA (private->palette));
}
void

View File

@@ -28,6 +28,8 @@
#include "core-types.h"
#include "gegl/gimp-babl.h"
#include "gimp-memsize.h"
#include "gimpimage.h"
#include "gimpimage-undo-push.h"
@@ -51,41 +53,47 @@ enum
/* local function prototypes */
static void gimp_palette_tagged_iface_init (GimpTaggedInterface *iface);
static void gimp_palette_tagged_iface_init (GimpTaggedInterface *iface);
static void gimp_palette_finalize (GObject *object);
static void gimp_palette_finalize (GObject *object);
static gint64 gimp_palette_get_memsize (GimpObject *object,
gint64 *gui_size);
static gint64 gimp_palette_get_memsize (GimpObject *object,
gint64 *gui_size);
static void gimp_palette_get_preview_size (GimpViewable *viewable,
gint size,
gboolean popup,
gboolean dot_for_dot,
gint *width,
gint *height);
static gboolean gimp_palette_get_popup_size (GimpViewable *viewable,
gint width,
gint height,
gboolean dot_for_dot,
gint *popup_width,
gint *popup_height);
static GimpTempBuf * gimp_palette_get_new_preview (GimpViewable *viewable,
GimpContext *context,
gint width,
gint height);
static gchar * gimp_palette_get_description (GimpViewable *viewable,
gchar **tooltip);
static const gchar * gimp_palette_get_extension (GimpData *data);
static void gimp_palette_copy (GimpData *data,
GimpData *src_data);
static void gimp_palette_real_entry_changed (GimpPalette *palette,
gint index);
static void gimp_palette_get_preview_size (GimpViewable *viewable,
gint size,
gboolean popup,
gboolean dot_for_dot,
gint *width,
gint *height);
static gboolean gimp_palette_get_popup_size (GimpViewable *viewable,
gint width,
gint height,
gboolean dot_for_dot,
gint *popup_width,
gint *popup_height);
static GimpTempBuf * gimp_palette_get_new_preview (GimpViewable *viewable,
GimpContext *context,
gint width,
gint height);
static gchar * gimp_palette_get_description (GimpViewable *viewable,
gchar **tooltip);
static const gchar * gimp_palette_get_extension (GimpData *data);
static void gimp_palette_copy (GimpData *data,
GimpData *src_data);
static void gimp_palette_real_entry_changed (GimpPalette *palette,
gint index);
static void gimp_palette_entry_free (GimpPaletteEntry *entry);
static gint64 gimp_palette_entry_get_memsize (GimpPaletteEntry *entry,
gint64 *gui_size);
static gchar * gimp_palette_get_checksum (GimpTagged *tagged);
static void gimp_palette_entry_free (GimpPaletteEntry *entry);
static gint64 gimp_palette_entry_get_memsize (GimpPaletteEntry *entry,
gint64 *gui_size);
static gchar * gimp_palette_get_checksum (GimpTagged *tagged);
static void gimp_palette_image_space_updated (GimpImage *image,
GimpPalette *palette);
static void gimp_palette_notify_image (GimpPalette *palette,
const GParamSpec *unused,
gpointer unused_user_data);
G_DEFINE_TYPE_WITH_CODE (GimpPalette, gimp_palette, GIMP_TYPE_DATA,
@@ -141,6 +149,12 @@ gimp_palette_init (GimpPalette *palette)
palette->colors = NULL;
palette->n_colors = 0;
palette->n_columns = 0;
palette->image = NULL;
palette->format = NULL;
g_signal_connect (palette, "notify::image",
G_CALLBACK (gimp_palette_notify_image),
NULL);
}
static void
@@ -155,6 +169,8 @@ gimp_palette_finalize (GObject *object)
palette->colors = NULL;
}
g_clear_weak_pointer (&palette->image);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
@@ -401,6 +417,58 @@ gimp_palette_get_checksum (GimpTagged *tagged)
return checksum_string;
}
static void
gimp_palette_image_space_updated (GimpImage *image,
GimpPalette *palette)
{
const Babl *space;
const Babl *format;
space = gimp_image_get_layer_space (image);
format = gimp_babl_format (GIMP_RGB, gimp_image_get_precision (image), FALSE, space);
gimp_palette_restrict_format (palette, format);
}
static void
gimp_palette_notify_image (GimpPalette *palette,
const GParamSpec *unused,
gpointer unused_user_data)
{
GimpImage *image = gimp_data_get_image (GIMP_DATA (palette));
if (palette->image == image)
return;
if (palette->image)
g_signal_handlers_disconnect_by_func (palette->image,
G_CALLBACK (gimp_palette_image_space_updated),
palette);
g_set_weak_pointer (&palette->image, image);
if (image)
{
/* Note: I only connect to "precision-changed", and not
* "profile-changed" changes which is handled in
* gimp_image_convert_profile_colormap() with additional bpc
* argument.
* In current implementation of indexed images,
* "precision-changed" should not happen because it is always
* 8-bit non-linear.
*/
g_signal_connect_object (image,
"precision-changed",
G_CALLBACK (gimp_palette_image_space_updated),
palette, 0);
gimp_palette_image_space_updated (image, palette);
}
else
{
gimp_palette_restrict_format (palette, NULL);
}
}
/* public functions */
@@ -799,6 +867,53 @@ gimp_palette_get_colormap (GimpPalette *palette,
return colormap;
}
void
gimp_palette_set_colormap (GimpPalette *palette,
const Babl *format,
const guchar *colormap,
gint n_colors,
gboolean push_undo_if_image)
{
GimpPaletteEntry *entry;
GeglColor *color;
gchar name[64];
gint bpp;
gint i;
g_return_if_fail (GIMP_IS_PALETTE (palette));
g_return_if_fail (format != NULL);
g_return_if_fail (n_colors > 0);
if (push_undo_if_image && gimp_data_get_image (GIMP_DATA (palette)))
gimp_image_undo_push_image_colormap (gimp_data_get_image (GIMP_DATA (palette)),
C_("undo-type", "Set Colormap"));
if (gimp_data_get_image (GIMP_DATA (palette)))
n_colors = MIN (n_colors, 256);
gimp_data_freeze (GIMP_DATA (palette));
while ((entry = gimp_palette_get_entry (palette, 0)))
gimp_palette_delete_entry (palette, entry);
bpp = babl_format_get_bytes_per_pixel (format);
color = gegl_color_new (NULL);
for (i = 0; i < n_colors; i++)
{
gegl_color_set_pixel (color, format, &colormap[i * bpp]);
g_snprintf (name, sizeof (name), "#%d", i);
gimp_palette_add_entry (palette, i, name, color);
}
g_object_unref (color);
gimp_data_thaw (GIMP_DATA (palette));
if (! gimp_data_is_frozen (GIMP_DATA (palette)))
for (gint i = 0; i < n_colors; i++)
g_signal_emit (palette, signals[ENTRY_CHANGED], 0, i);
}
/* private functions */

View File

@@ -43,6 +43,13 @@ struct _GimpPalette
{
GimpData parent_instance;
/* When set to an image, we store the image we connect to, so that we
* can correctly disconnect if parent GimpData's image changes (so the
* GimpPalette and GimpData's images may be unsynced for a tiny span of
* time).
*/
GimpImage *image;
/* Palette colors can be restricted to a given format. If NULL, then the
* palette can be a mix of color models and color spaces.
*/
@@ -114,6 +121,11 @@ GimpPaletteEntry * gimp_palette_find_entry (GimpPalette *palette,
guchar * gimp_palette_get_colormap (GimpPalette *palette,
const Babl *format,
gint *n_colors);
void gimp_palette_set_colormap (GimpPalette *palette,
const Babl *format,
const guchar *colormap,
gint n_colors,
gboolean push_undo_if_image);
#endif /* __GIMP_PALETTE_H__ */

View File

@@ -30,7 +30,7 @@
#include "internal-procs.h"
/* 779 procedures registered total */
/* 780 procedures registered total */
void
internal_procs_init (GimpPDB *pdb)

View File

@@ -492,6 +492,49 @@ palette_get_colormap_invoker (GimpProcedure *procedure,
return return_vals;
}
static GimpValueArray *
palette_set_colormap_invoker (GimpProcedure *procedure,
Gimp *gimp,
GimpContext *context,
GimpProgress *progress,
const GimpValueArray *args,
GError **error)
{
gboolean success = TRUE;
GimpPalette *palette;
const Babl *format;
GBytes *colormap;
palette = g_value_get_object (gimp_value_array_index (args, 0));
format = g_value_get_boxed (gimp_value_array_index (args, 1));
colormap = g_value_get_boxed (gimp_value_array_index (args, 2));
if (success)
{
gint bpp;
bpp = babl_format_get_bytes_per_pixel (format);
if (g_bytes_get_size (colormap) % bpp == 0)
{
const guchar *data;
gsize n_bytes;
gint n_colors;
data = g_bytes_get_data (colormap, &n_bytes),
n_colors = n_bytes / bpp;
gimp_palette_set_colormap (palette, format, (guchar *) data, n_colors, TRUE);
}
else
{
success = FALSE;
}
}
return gimp_procedure_get_return_values (procedure, success,
error ? *error : NULL);
}
void
register_palette_procs (GimpPDB *pdb)
{
@@ -961,4 +1004,42 @@ register_palette_procs (GimpPDB *pdb)
GIMP_PARAM_READWRITE));
gimp_pdb_register_procedure (pdb, procedure);
g_object_unref (procedure);
/*
* gimp-palette-set-colormap
*/
procedure = gimp_procedure_new (palette_set_colormap_invoker);
gimp_object_set_static_name (GIMP_OBJECT (procedure),
"gimp-palette-set-colormap");
gimp_procedure_set_static_help (procedure,
"Sets the entries in the image's colormap.",
"This procedure sets the entries in the specified palette in one go. The number of entries depens on the size of @colormap and the bytes-per-pixel size of @format.\n"
"The procedure will fail if the size of @colormap is not an exact multiple of the number of bytes per pixel of @format.",
NULL);
gimp_procedure_set_static_attribution (procedure,
"Jehan",
"Jehan",
"2024");
gimp_procedure_add_argument (procedure,
gimp_param_spec_palette ("palette",
"palette",
"The palette",
FALSE,
NULL,
FALSE,
GIMP_PARAM_READWRITE));
gimp_procedure_add_argument (procedure,
g_param_spec_boxed ("format",
"format",
"The desired color format",
GIMP_TYPE_BABL_FORMAT,
GIMP_PARAM_READWRITE));
gimp_procedure_add_argument (procedure,
g_param_spec_boxed ("colormap",
"colormap",
"The new colormap values",
G_TYPE_BYTES,
GIMP_PARAM_READWRITE));
gimp_pdb_register_procedure (pdb, procedure);
g_object_unref (procedure);
}

View File

@@ -674,6 +674,7 @@ EXPORTS
gimp_palette_get_columns
gimp_palette_get_type
gimp_palette_new
gimp_palette_set_colormap
gimp_palette_set_columns
gimp_palettes_close_popup
gimp_palettes_get_list

View File

@@ -578,3 +578,48 @@ gimp_palette_get_colormap (GimpPalette *palette,
return colormap;
}
/**
* gimp_palette_set_colormap:
* @palette: The palette.
* @format: The desired color format.
* @colormap: The new colormap values.
*
* Sets the entries in the image's colormap.
*
* This procedure sets the entries in the specified palette in one go.
* The number of entries depens on the size of @colormap and the
* bytes-per-pixel size of @format.
* The procedure will fail if the size of @colormap is not an exact
* multiple of the number of bytes per pixel of @format.
*
* Returns: TRUE on success.
*
* Since: 3.0
**/
gboolean
gimp_palette_set_colormap (GimpPalette *palette,
const Babl *format,
GBytes *colormap)
{
GimpValueArray *args;
GimpValueArray *return_vals;
gboolean success = TRUE;
args = gimp_value_array_new_from_types (NULL,
GIMP_TYPE_PALETTE, palette,
GIMP_TYPE_BABL_FORMAT, format,
G_TYPE_BYTES, colormap,
G_TYPE_NONE);
return_vals = _gimp_pdb_run_procedure_array (gimp_get_pdb (),
"gimp-palette-set-colormap",
args);
gimp_value_array_unref (args);
success = GIMP_VALUES_GET_ENUM (return_vals, 0) == GIMP_PDB_SUCCESS;
gimp_value_array_unref (return_vals);
return success;
}

View File

@@ -59,6 +59,9 @@ gboolean gimp_palette_entry_set_name (GimpPalette *palette,
GBytes* gimp_palette_get_colormap (GimpPalette *palette,
const Babl *format,
gint *num_colors);
gboolean gimp_palette_set_colormap (GimpPalette *palette,
const Babl *format,
GBytes *colormap);
G_END_DECLS

View File

@@ -475,6 +475,55 @@ CODE
);
}
sub palette_set_colormap {
$blurb = "Sets the entries in the image's colormap.";
$help = <<'HELP';
This procedure sets the entries in the specified palette in one go. The number
of entries depens on the size of @colormap and the bytes-per-pixel size of @format.
The procedure will fail if the size of @colormap is not an exact
multiple of the number of bytes per pixel of @format.
HELP
&jehan_pdb_misc('2024', '3.0');
@inargs = (
{ name => 'palette', type => 'palette',
desc => 'The palette' },
{ name => 'format', type => 'format',
desc => 'The desired color format' },
{ name => 'colormap', type => 'bytes',
desc => 'The new colormap values' }
);
%invoke = (
headers => [ qw("core/gimpimage-colormap.h") ],
code => <<'CODE'
{
gint bpp;
bpp = babl_format_get_bytes_per_pixel (format);
if (g_bytes_get_size (colormap) % bpp == 0)
{
const guchar *data;
gsize n_bytes;
gint n_colors;
data = g_bytes_get_data (colormap, &n_bytes),
n_colors = n_bytes / bpp;
gimp_palette_set_colormap (palette, format, (guchar *) data, n_colors, TRUE);
}
else
{
success = FALSE;
}
}
CODE
);
}
@headers = qw(<string.h>
"core/gimp.h"
"core/gimpcontext.h"
@@ -491,7 +540,7 @@ CODE
palette_add_entry palette_delete_entry
palette_entry_get_color palette_entry_set_color
palette_entry_get_name palette_entry_set_name
palette_get_colormap);
palette_get_colormap palette_set_colormap);
%exports = (app => [@procs], lib => [@procs]);