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.
This commit is contained in:
Michael Natterer 2012-04-24 21:45:35 +02:00
parent 85ee13dd7d
commit 21dfb8bd9f
15 changed files with 454 additions and 39 deletions

View File

@ -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",

View File

@ -28,7 +28,7 @@
#include "internal-procs.h"
/* 667 procedures registered total */
/* 670 procedures registered total */
void
internal_procs_init (GimpPDB *pdb)

View File

@ -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);
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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__ */

View File

@ -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

View File

@ -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;

View File

@ -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;
}

View File

@ -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.
**/

View File

@ -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);

View File

@ -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;
}

View File

@ -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

View File

@ -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"
"gegl/gimp-gegl-utils.h"
"core/gimp.h"
"core/gimpdrawable-offset.h"
@ -914,7 +951,8 @@ CODE
"gimppdb-utils.h"
"gimp-intl.h");
@procs = qw(drawable_type
@procs = qw(drawable_get_format
drawable_type
drawable_type_with_alpha
drawable_has_alpha
drawable_is_rgb

View File

@ -353,6 +353,70 @@ CODE
);
}
sub plugin_enable_precision {
$blurb = "Switches this plug-in to using the real bit depth of drawables.";
$help = <<HELP;
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.
HELP
&mitch_pdb_misc('2012', '2.10');
%invoke = (
code => <<'CODE'
{
GimpPlugIn *plug_in = gimp->plug_in_manager->current_plug_in;
if (plug_in)
{
gimp_plug_in_enable_precision (plug_in);
}
else
{
success = FALSE;
}
}
CODE
);
}
sub plugin_precision_enabled {
$blurb = "Whether this plug-in is using the real bit depth of drawables.";
$help = <<HELP;
Returns whether this plug-in is using the real bit depth of drawables,
which can be more than 8 bits per channel.
HELP
&mitch_pdb_misc('2012', '2.10');
@outargs = (
{ name => 'enabled', type => 'boolean',
desc => "Whether precision is enabled" }
);
%invoke = (
code => <<'CODE'
{
GimpPlugIn *plug_in = gimp->plug_in_manager->current_plug_in;
if (plug_in)
{
enabled = gimp_plug_in_precision_enabled (plug_in);
}
else
{
success = FALSE;
}
}
CODE
);
}
@headers = qw(<string.h>
<stdlib.h>
"libgimpbase/gimpbase.h"
@ -371,9 +435,11 @@ CODE
plugin_menu_branch_register
plugin_icon_register
plugin_set_pdb_error_handler
plugin_get_pdb_error_handler);
plugin_get_pdb_error_handler
plugin_enable_precision
plugin_precision_enabled);
%exports = (app => [@procs], lib => [@procs[1,2,3,4,5,6,7]]);
%exports = (app => [@procs], lib => [@procs[1,2,3,4,5,6,7,8,9]]);
$desc = 'Plug-in';
$doc_title = 'gimpplugin';