Commit 21dfb8bd authored by Michael Natterer's avatar Michael Natterer 😴
Browse files

app/libgimp: enable plug-ins on high precision images

Add gimp_plugin_enable_precision() in libgimp which switches the
plug-in to deal with the drawables' real precision, call it from the
libgimp GeglBuffer and Babl format APIs. If it's not enabled, let the
core's plug-in convert the tiles to legacy formats when sending them
over the wire.
parent 85ee13dd
......@@ -33,6 +33,7 @@
#include "core/gimpimage.h"
#include "core/gimpparamspecs.h"
#include "core/gimptempbuf.h"
#include "gegl/gimp-babl.h"
#include "gegl/gimp-gegl-utils.h"
#include "plug-in/gimpplugin-cleanup.h"
#include "plug-in/gimpplugin.h"
......@@ -46,6 +47,35 @@
#include "gimp-intl.h"
static GValueArray *
drawable_get_format_invoker (GimpProcedure *procedure,
Gimp *gimp,
GimpContext *context,
GimpProgress *progress,
const GValueArray *args,
GError **error)
{
gboolean success = TRUE;
GValueArray *return_vals;
GimpDrawable *drawable;
gchar *format = NULL;
drawable = gimp_value_get_drawable (&args->values[0], gimp);
if (success)
{
format = g_strdup (babl_get_name (gimp_drawable_get_format (drawable)));
}
return_vals = gimp_procedure_get_return_values (procedure, success,
error ? *error : NULL);
if (success)
g_value_take_string (&return_vals->values[1], format);
return return_vals;
}
static GValueArray *
drawable_type_invoker (GimpProcedure *procedure,
Gimp *gimp,
......@@ -239,7 +269,18 @@ drawable_bpp_invoker (GimpProcedure *procedure,
if (success)
{
bpp = gimp_drawable_bytes (drawable);
const Babl *format = gimp_drawable_get_format (drawable);
if (! gimp->plug_in_manager->current_plug_in ||
! gimp_plug_in_precision_enabled (gimp->plug_in_manager->current_plug_in))
{
if (! gimp_drawable_is_indexed (drawable) /* XXX fixme */)
format = gimp_babl_format (gimp_babl_format_get_base_type (format),
GIMP_PRECISION_U8,
babl_format_has_alpha (format));
}
bpp = babl_format_get_bytes_per_pixel (format);
}
return_vals = gimp_procedure_get_return_values (procedure, success,
......@@ -888,6 +929,36 @@ register_drawable_procs (GimpPDB *pdb)
{
GimpProcedure *procedure;
/*
* gimp-drawable-get-format
*/
procedure = gimp_procedure_new (drawable_get_format_invoker);
gimp_object_set_static_name (GIMP_OBJECT (procedure),
"gimp-drawable-get-format");
gimp_procedure_set_static_strings (procedure,
"gimp-drawable-get-format",
"Returns the drawable's Babl format",
"This procedure returns the drawable's Babl format.",
"Michael Natterer <mitch@gimp.org>",
"Michael Natterer",
"2012",
NULL);
gimp_procedure_add_argument (procedure,
gimp_param_spec_drawable_id ("drawable",
"drawable",
"The drawable",
pdb->gimp, FALSE,
GIMP_PARAM_READWRITE));
gimp_procedure_add_return_value (procedure,
gimp_param_spec_string ("format",
"format",
"The drawable's Babl format",
FALSE, FALSE, FALSE,
NULL,
GIMP_PARAM_READWRITE));
gimp_pdb_register_procedure (pdb, procedure);
g_object_unref (procedure);
/*
* gimp-drawable-type
*/
......@@ -1079,7 +1150,7 @@ register_drawable_procs (GimpPDB *pdb)
gimp_procedure_set_static_strings (procedure,
"gimp-drawable-bpp",
"Returns the bytes per pixel.",
"This procedure returns the number of bytes per pixel (or the number of channels) for the specified drawable.",
"This procedure returns the number of bytes per pixel, which corresponds to the number of components unless 'gimp-plugin-enable-precision' was called.",
"Spencer Kimball & Peter Mattis",
"Spencer Kimball & Peter Mattis",
"1995-1996",
......
......@@ -28,7 +28,7 @@
#include "internal-procs.h"
/* 667 procedures registered total */
/* 670 procedures registered total */
void
internal_procs_init (GimpPDB *pdb)
......
......@@ -340,6 +340,62 @@ plugin_get_pdb_error_handler_invoker (GimpProcedure *procedure,
return return_vals;
}
static GValueArray *
plugin_enable_precision_invoker (GimpProcedure *procedure,
Gimp *gimp,
GimpContext *context,
GimpProgress *progress,
const GValueArray *args,
GError **error)
{
gboolean success = TRUE;
GimpPlugIn *plug_in = gimp->plug_in_manager->current_plug_in;
if (plug_in)
{
gimp_plug_in_enable_precision (plug_in);
}
else
{
success = FALSE;
}
return gimp_procedure_get_return_values (procedure, success,
error ? *error : NULL);
}
static GValueArray *
plugin_precision_enabled_invoker (GimpProcedure *procedure,
Gimp *gimp,
GimpContext *context,
GimpProgress *progress,
const GValueArray *args,
GError **error)
{
gboolean success = TRUE;
GValueArray *return_vals;
gboolean enabled = FALSE;
GimpPlugIn *plug_in = gimp->plug_in_manager->current_plug_in;
if (plug_in)
{
enabled = gimp_plug_in_precision_enabled (plug_in);
}
else
{
success = FALSE;
}
return_vals = gimp_procedure_get_return_values (procedure, success,
error ? *error : NULL);
if (success)
g_value_set_boolean (&return_vals->values[1], enabled);
return return_vals;
}
void
register_plug_in_procs (GimpPDB *pdb)
{
......@@ -648,4 +704,44 @@ register_plug_in_procs (GimpPDB *pdb)
GIMP_PARAM_READWRITE));
gimp_pdb_register_procedure (pdb, procedure);
g_object_unref (procedure);
/*
* gimp-plugin-enable-precision
*/
procedure = gimp_procedure_new (plugin_enable_precision_invoker);
gimp_object_set_static_name (GIMP_OBJECT (procedure),
"gimp-plugin-enable-precision");
gimp_procedure_set_static_strings (procedure,
"gimp-plugin-enable-precision",
"Switches this plug-in to using the real bit depth of drawables.",
"Switches this plug-in to using the real bit depth of drawables. This setting can only be enabled, and not disabled again during the lifetime of the plug-in. Using 'gimp-drawable-get-buffer', 'gimp-drawable-get-shadow-buffer' or 'gimp-drawable-get-format' will automatically call this function.",
"Michael Natterer <mitch@gimp.org>",
"Michael Natterer",
"2012",
NULL);
gimp_pdb_register_procedure (pdb, procedure);
g_object_unref (procedure);
/*
* gimp-plugin-precision-enabled
*/
procedure = gimp_procedure_new (plugin_precision_enabled_invoker);
gimp_object_set_static_name (GIMP_OBJECT (procedure),
"gimp-plugin-precision-enabled");
gimp_procedure_set_static_strings (procedure,
"gimp-plugin-precision-enabled",
"Whether this plug-in is using the real bit depth of drawables.",
"Returns whether this plug-in is using the real bit depth of drawables, which can be more than 8 bits per channel.",
"Michael Natterer <mitch@gimp.org>",
"Michael Natterer",
"2012",
NULL);
gimp_procedure_add_return_value (procedure,
g_param_spec_boolean ("enabled",
"enabled",
"Whether precision is enabled",
FALSE,
GIMP_PARAM_READWRITE));
gimp_pdb_register_procedure (pdb, procedure);
g_object_unref (procedure);
}
......@@ -29,6 +29,7 @@
#include "plug-in-types.h"
#include "gegl/gimp-babl.h"
#include "gegl/gimp-gegl-tile-compat.h"
#include "core/gimp.h"
......@@ -310,9 +311,16 @@ gimp_plug_in_handle_tile_put (GimpPlugIn *plug_in,
return;
}
/* XXX use an appropriate format here */
format = gegl_buffer_get_format (buffer);
if (! gimp_plug_in_precision_enabled (plug_in) &&
! gimp_drawable_is_indexed (drawable) /* XXX fixme */)
{
format = gimp_babl_format (gimp_babl_format_get_base_type (format),
GIMP_PRECISION_U8,
babl_format_has_alpha (format));
}
if (tile_data.use_shm)
{
gegl_buffer_set (buffer, &tile_rect, 0, format,
......@@ -402,9 +410,16 @@ gimp_plug_in_handle_tile_get (GimpPlugIn *plug_in,
return;
}
/* XXX use an appropriate format here */
format = gegl_buffer_get_format (buffer);
if (! gimp_plug_in_precision_enabled (plug_in) &&
! gimp_drawable_is_indexed (drawable) /* XXX fixme */)
{
format = gimp_babl_format (gimp_babl_format_get_base_type (format),
GIMP_PRECISION_U8,
babl_format_has_alpha (format));
}
tile_size = (babl_format_get_bytes_per_pixel (format) *
tile_rect.width * tile_rect.height);
......
......@@ -1032,3 +1032,19 @@ gimp_plug_in_remove_temp_proc (GimpPlugIn *plug_in,
gimp_plug_in_manager_remove_temp_proc (plug_in->manager, proc);
g_object_unref (proc);
}
void
gimp_plug_in_enable_precision (GimpPlugIn *plug_in)
{
g_return_if_fail (GIMP_IS_PLUG_IN (plug_in));
plug_in->precision = TRUE;
}
gboolean
gimp_plug_in_precision_enabled (GimpPlugIn *plug_in)
{
g_return_val_if_fail (GIMP_IS_PLUG_IN (plug_in), FALSE);
return plug_in->precision;
}
......@@ -47,6 +47,7 @@ struct _GimpPlugIn
GimpPlugInCallMode call_mode; /* QUERY, INIT or RUN */
guint open : 1; /* Is the plug-in open? */
guint hup : 1; /* Did we receive a G_IO_HUP */
guint precision : 1; /* True drawable precision enabled */
GPid pid; /* Plug-in's process id */
GIOChannel *my_read; /* App's read and write channels */
......@@ -119,5 +120,8 @@ void gimp_plug_in_set_error_handler (GimpPlugIn *plug_in,
GimpPDBErrorHandler
gimp_plug_in_get_error_handler (GimpPlugIn *plug_in);
void gimp_plug_in_enable_precision (GimpPlugIn *plug_in);
gboolean gimp_plug_in_precision_enabled (GimpPlugIn *plug_in);
#endif /* __GIMP_PLUG_IN_H__ */
......@@ -667,11 +667,13 @@ EXPORTS
gimp_pixel_rgns_register
gimp_pixel_rgns_register2
gimp_plugin_domain_register
gimp_plugin_enable_precision
gimp_plugin_get_pdb_error_handler
gimp_plugin_help_register
gimp_plugin_icon_register
gimp_plugin_menu_branch_register
gimp_plugin_menu_register
gimp_plugin_precision_enabled
gimp_plugin_set_pdb_error_handler
gimp_posterize
gimp_procedural_db_dump
......
......@@ -315,7 +315,6 @@ void gimp_destroy_paramdefs (GimpParamDef *paramdefs,
*/
const gchar * gimp_get_pdb_error (void);
/* Return various constants given by the GIMP core at plug-in config time.
*/
guint gimp_tile_width (void) G_GNUC_CONST;
......
......@@ -668,6 +668,8 @@ gimp_drawable_get_buffer (gint32 drawable_ID)
{
GimpDrawable *drawable;
gimp_plugin_enable_precision ();
drawable = gimp_drawable_get (drawable_ID);
if (drawable)
......@@ -705,6 +707,8 @@ gimp_drawable_get_shadow_buffer (gint32 drawable_ID)
{
GimpDrawable *drawable;
gimp_plugin_enable_precision ();
drawable = gimp_drawable_get (drawable_ID);
if (drawable)
......@@ -735,38 +739,42 @@ gimp_drawable_get_shadow_buffer (gint32 drawable_ID)
const Babl *
gimp_drawable_get_format (gint32 drawable_ID)
{
switch (gimp_drawable_type (drawable_ID))
const Babl *format = NULL;
gchar *format_str = _gimp_drawable_get_format (drawable_ID);
if (format_str)
{
case GIMP_RGB_IMAGE: return babl_format ("R'G'B' u8");
case GIMP_RGBA_IMAGE: return babl_format ("R'G'B'A u8");
case GIMP_GRAY_IMAGE: return babl_format ("Y' u8");
case GIMP_GRAYA_IMAGE: return babl_format ("Y'A u8");
case GIMP_INDEXED_IMAGE:
case GIMP_INDEXEDA_IMAGE:
{
gint32 image_ID = gimp_item_get_image (drawable_ID);
const Babl *pala;
const Babl *pal;
guchar *cmap;
gint n_cols;
gimp_plugin_enable_precision ();
cmap = gimp_image_get_colormap (image_ID, &n_cols);
if (gimp_drawable_is_indexed (drawable_ID))
{
gint32 image_ID = gimp_item_get_image (drawable_ID);
const Babl *palette;
const Babl *palette_alpha;
guchar *colormap;
gint n_colors;
babl_new_palette (NULL, &pal, &pala);
babl_palette_set_palette (pal, babl_format ("R'G'B' u8"),
cmap, n_cols);
colormap = gimp_image_get_colormap (image_ID, &n_colors);
g_free (cmap);
babl_new_palette (format_str, &palette, &palette_alpha);
babl_palette_set_palette (palette,
babl_format ("R'G'B' u8"),
colormap, n_colors);
if (gimp_drawable_type (drawable_ID) == GIMP_INDEXEDA_IMAGE)
return pala;
g_free (colormap);
return pal;
}
if (gimp_drawable_has_alpha (drawable_ID))
format = palette;
else
format = palette_alpha;
}
else
{
format = babl_format (format_str);
}
default:
g_warn_if_reached ();
g_free (format_str);
}
return NULL;
return format;
}
......@@ -39,6 +39,38 @@
**/
/**
* _gimp_drawable_get_format:
* @drawable_ID: The drawable.
*
* Returns the drawable's Babl format
*
* This procedure returns the drawable's Babl format.
*
* Returns: The drawable's Babl format.
*
* Since: GIMP 2.10
**/
gchar *
_gimp_drawable_get_format (gint32 drawable_ID)
{
GimpParam *return_vals;
gint nreturn_vals;
gchar *format = NULL;
return_vals = gimp_run_procedure ("gimp-drawable-get-format",
&nreturn_vals,
GIMP_PDB_DRAWABLE, drawable_ID,
GIMP_PDB_END);
if (return_vals[0].data.d_status == GIMP_PDB_SUCCESS)
format = g_strdup (return_vals[1].data.d_string);
gimp_destroy_params (return_vals, nreturn_vals);
return format;
}
/**
* gimp_drawable_type:
* @drawable_ID: The drawable.
......@@ -233,8 +265,9 @@ gimp_drawable_is_indexed (gint32 drawable_ID)
*
* Returns the bytes per pixel.
*
* This procedure returns the number of bytes per pixel (or the number
* of channels) for the specified drawable.
* This procedure returns the number of bytes per pixel, which
* corresponds to the number of components unless
* gimp_plugin_enable_precision() was called.
*
* Returns: Bytes per pixel.
**/
......
......@@ -32,6 +32,7 @@ G_BEGIN_DECLS
/* For information look into the C source or the html documentation */
G_GNUC_INTERNAL gchar* _gimp_drawable_get_format (gint32 drawable_ID);
GimpImageType gimp_drawable_type (gint32 drawable_ID);
GimpImageType gimp_drawable_type_with_alpha (gint32 drawable_ID);
gboolean gimp_drawable_has_alpha (gint32 drawable_ID);
......
......@@ -291,3 +291,67 @@ gimp_plugin_get_pdb_error_handler (void)
return handler;
}
/**
* gimp_plugin_enable_precision:
*
* Switches this plug-in to using the real bit depth of drawables.
*
* Switches this plug-in to using the real bit depth of drawables. This
* setting can only be enabled, and not disabled again during the
* lifetime of the plug-in. Using gimp_drawable_get_buffer(),
* gimp_drawable_get_shadow_buffer() or gimp_drawable_get_format() will
* automatically call this function.
*
* Returns: TRUE on success.
*
* Since: GIMP 2.10
**/
gboolean
gimp_plugin_enable_precision (void)
{
GimpParam *return_vals;
gint nreturn_vals;
gboolean success = TRUE;
return_vals = gimp_run_procedure ("gimp-plugin-enable-precision",
&nreturn_vals,
GIMP_PDB_END);
success = return_vals[0].data.d_status == GIMP_PDB_SUCCESS;
gimp_destroy_params (return_vals, nreturn_vals);
return success;
}
/**
* gimp_plugin_precision_enabled:
*
* Whether this plug-in is using the real bit depth of drawables.
*
* Returns whether this plug-in is using the real bit depth of
* drawables, which can be more than 8 bits per channel.
*
* Returns: Whether precision is enabled.
*
* Since: GIMP 2.10
**/
gboolean
gimp_plugin_precision_enabled (void)
{
GimpParam *return_vals;
gint nreturn_vals;
gboolean enabled = FALSE;
return_vals = gimp_run_procedure ("gimp-plugin-precision-enabled",
&nreturn_vals,
GIMP_PDB_END);
if (return_vals[0].data.d_status == GIMP_PDB_SUCCESS)
enabled = return_vals[1].data.d_int32;
gimp_destroy_params (return_vals, nreturn_vals);
return enabled;
}
......@@ -46,6 +46,8 @@ G_GNUC_INTERNAL gboolean _gimp_plugin_icon_register (const gchar
const guint8 *icon_data);
gboolean gimp_plugin_set_pdb_error_handler (GimpPDBErrorHandler handler);
GimpPDBErrorHandler gimp_plugin_get_pdb_error_handler (void);
gboolean gimp_plugin_enable_precision (void);
gboolean gimp_plugin_precision_enabled (void);
G_END_DECLS
......
......@@ -264,6 +264,31 @@ CODE
);
}
sub drawable_get_format {
$blurb = "Returns the drawable's Babl format";
$help = "This procedure returns the drawable's Babl format.";
&mitch_pdb_misc('2012', '2.10');
@inargs = (
{ name => 'drawable', type => 'drawable',
desc => 'The drawable' }
);
@outargs = (
{ name => 'format', type => 'string', wrap => 1,
desc => "The drawable's Babl format" }
);
%invoke = (
code => <<'CODE'
{
format = g_strdup (babl_get_name (gimp_drawable_get_format (drawable)));
}
CODE
);
}
sub drawable_type {
$blurb = "Returns the drawable's type.";
$help = "This procedure returns the drawable's type.";
......@@ -446,8 +471,8 @@ sub drawable_bpp {
$blurb = 'Returns the bytes per pixel.';
$help = <<'HELP';
This procedure returns the number of bytes per pixel (or the number of
channels) for the specified drawable.
This procedure returns the number of bytes per pixel, which corresponds to
the number of components unless gimp_plugin_enable_precision() was called.
HELP
&std_pdb_misc;
......@@ -465,7 +490,18 @@ HELP
%invoke = (
code => <<'CODE'
{
bpp = gimp_drawable_bytes (drawable);
const Babl *format = gimp_drawable_get_format (drawable);
if (! gimp->plug_in_manager->current_plug_in ||
! gimp_plug_in_precision_enabled (gimp->plug_in_manager->current_plug_in))
{
if (! gimp_drawable_is_indexed (drawable) /* XXX fixme */)
format = gimp_babl_format (gimp_babl_format_get_base_type (format),
GIMP_PRECISION_U8,
babl_format_has_alpha (format));
}
bpp = babl_format_get_bytes_per_pixel (format);
}
CODE
);
......@@ -907,6 +943,7 @@ CODE
@headers = qw("config/gimpcoreconfig.h"
"gegl/gimp-babl.h"