Issue #5313: consistent "file-pat-save-internal" procedure with…

… multiple drawables as parameter.

Previous commit 7bb892f3 was "making it work" by making the API
inconsistent and also only using the first drawable, which is making the
logics meaningless.

Instead accept multiple drawables, and export only the selected drawable
(when alone) or the merged-down image containing only the selected
drawables (when many).

Note that in current implementation, this is not useful from GUI calls
because the fully merged image is always exported when run interactively
or with last vals (i.e. from the GUI) because gimp_export_image()
flattens the image. So this change would only work when called
non-interactively from other plug-ins. In such a case, multi-layer
images do no longer return an error and whatever items are selected
would change the export result.

See also #7370 for a discussion about how to handle the selected items
during export (because currently the `drawables` parameter of
GimpSaveProcedure's run function is clearly a mostly bogus parameter).
This commit is contained in:
Jehan 2021-10-14 23:48:36 +02:00
parent d47fc1372d
commit 6905b0bbef
3 changed files with 90 additions and 51 deletions

View File

@ -28,12 +28,16 @@
#include "gegl/gimp-babl.h" #include "gegl/gimp-babl.h"
#include "core/gimp.h" #include "core/gimp.h"
#include "core/gimpcontainer.h"
#include "core/gimpdrawable.h" #include "core/gimpdrawable.h"
#include "core/gimpimage.h" #include "core/gimpimage.h"
#include "core/gimpimage-new.h"
#include "core/gimpimage-resize.h"
#include "core/gimplayer-new.h" #include "core/gimplayer-new.h"
#include "core/gimpparamspecs.h" #include "core/gimpparamspecs.h"
#include "core/gimppattern.h" #include "core/gimppattern.h"
#include "core/gimppattern-load.h" #include "core/gimppattern-load.h"
#include "core/gimppickable.h"
#include "core/gimptempbuf.h" #include "core/gimptempbuf.h"
#include "pdb/gimpprocedure.h" #include "pdb/gimpprocedure.h"
@ -45,11 +49,13 @@
/* local function prototypes */ /* local function prototypes */
static GimpImage * file_pat_pattern_to_image (Gimp *gimp, static GimpImage * file_pat_pattern_to_image (Gimp *gimp,
GimpPattern *pattern); GimpPattern *pattern);
static GimpPattern * file_pat_image_to_pattern (GimpImage *image, static GimpPattern * file_pat_image_to_pattern (GimpImage *image,
GimpDrawable *drawable, GimpContext *context,
const gchar *name); gint n_drawables,
GimpDrawable **drawables,
const gchar *name);
/* public functions */ /* public functions */
@ -116,22 +122,24 @@ file_pat_save_invoker (GimpProcedure *procedure,
const GimpValueArray *args, const GimpValueArray *args,
GError **error) GError **error)
{ {
GimpValueArray *return_vals; GimpValueArray *return_vals;
GimpImage *image; GimpImage *image;
GimpDrawable *drawable; GimpPattern *pattern;
GimpPattern *pattern; const gchar *name;
const gchar *name; GFile *file;
GFile *file; GimpDrawable **drawables;
gboolean success; gint n_drawables;
gboolean success;
gimp_set_busy (gimp); gimp_set_busy (gimp);
image = g_value_get_object (gimp_value_array_index (args, 1)); image = g_value_get_object (gimp_value_array_index (args, 1));
drawable = g_value_get_object (gimp_value_array_index (args, 2)); n_drawables = g_value_get_int (gimp_value_array_index (args, 2));
file = g_value_get_object (gimp_value_array_index (args, 3)); drawables = (GimpDrawable **) gimp_value_get_object_array (gimp_value_array_index (args, 3));
name = g_value_get_string (gimp_value_array_index (args, 4)); file = g_value_get_object (gimp_value_array_index (args, 4));
name = g_value_get_string (gimp_value_array_index (args, 5));
pattern = file_pat_image_to_pattern (image, drawable, name); pattern = file_pat_image_to_pattern (image, context, n_drawables, drawables, name);
gimp_data_set_file (GIMP_DATA (pattern), file, TRUE, TRUE); gimp_data_set_file (GIMP_DATA (pattern), file, TRUE, TRUE);
@ -235,24 +243,50 @@ file_pat_pattern_to_image (Gimp *gimp,
} }
static GimpPattern * static GimpPattern *
file_pat_image_to_pattern (GimpImage *image, file_pat_image_to_pattern (GimpImage *image,
GimpDrawable *drawable, GimpContext *context,
const gchar *name) gint n_drawables,
GimpDrawable **drawables,
const gchar *name)
{ {
GimpPattern *pattern; GimpPattern *pattern;
GimpImage *subimage = NULL;
const Babl *format; const Babl *format;
gint width; gint width;
gint height; gint height;
format = gimp_babl_format (gimp_drawable_is_gray (drawable) ? g_return_val_if_fail (n_drawables > 0, NULL);
if (n_drawables > 1)
{
GList *drawable_list = NULL;
for (gint i = 0; i < n_drawables; i++)
drawable_list = g_list_prepend (drawable_list, drawables[i]);
subimage = gimp_image_new_from_drawables (image->gimp, drawable_list, FALSE);
g_list_free (drawable_list);
gimp_container_remove (image->gimp->images, GIMP_OBJECT (subimage));
gimp_image_resize_to_layers (subimage, context,
NULL, NULL, NULL, NULL, NULL);
width = gimp_image_get_width (subimage);
height = gimp_image_get_width (subimage);
gimp_pickable_flush (GIMP_PICKABLE (subimage));
}
else
{
width = gimp_item_get_width (GIMP_ITEM (drawables[0]));
height = gimp_item_get_height (GIMP_ITEM (drawables[0]));
}
format = gimp_babl_format (gimp_drawable_is_gray (drawables[0]) ?
GIMP_GRAY : GIMP_RGB, GIMP_GRAY : GIMP_RGB,
GIMP_PRECISION_U8_NON_LINEAR, GIMP_PRECISION_U8_NON_LINEAR,
gimp_drawable_has_alpha (drawable), (subimage && gimp_image_has_alpha (subimage)) ||
gimp_drawable_has_alpha (drawables[0]),
NULL); NULL);
width = gimp_item_get_width (GIMP_ITEM (drawable));
height = gimp_item_get_height (GIMP_ITEM (drawable));
pattern = g_object_new (GIMP_TYPE_PATTERN, pattern = g_object_new (GIMP_TYPE_PATTERN,
"name", name, "name", name,
"mime-type", "image/x-gimp-pat", "mime-type", "image/x-gimp-pat",
@ -260,10 +294,13 @@ file_pat_image_to_pattern (GimpImage *image,
pattern->mask = gimp_temp_buf_new (width, height, format); pattern->mask = gimp_temp_buf_new (width, height, format);
gegl_buffer_get (gimp_drawable_get_buffer (drawable), gegl_buffer_get (subimage != NULL ? gimp_pickable_get_buffer (GIMP_PICKABLE (subimage)) :
gimp_drawable_get_buffer (drawables[0]),
GEGL_RECTANGLE (0, 0, width, height), 1.0, GEGL_RECTANGLE (0, 0, width, height), 1.0,
format, gimp_temp_buf_get_data (pattern->mask), format, gimp_temp_buf_get_data (pattern->mask),
GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE); GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
g_clear_object (&subimage);
return pattern; return pattern;
} }

View File

@ -429,12 +429,17 @@ file_data_init (Gimp *gimp)
FALSE, FALSE,
GIMP_PARAM_READWRITE)); GIMP_PARAM_READWRITE));
gimp_procedure_add_argument (procedure, gimp_procedure_add_argument (procedure,
gimp_param_spec_drawable ("drawable", g_param_spec_int ("n-drawables",
"Drawable", "Num drawables",
"Active drawable " "Number of drawables",
"of input image", 1, G_MAXINT, 1,
FALSE, GIMP_PARAM_READWRITE));
GIMP_PARAM_READWRITE)); gimp_procedure_add_argument (procedure,
gimp_param_spec_object_array ("drawables",
"Drawables",
"Selected drawables",
GIMP_TYPE_DRAWABLE,
GIMP_PARAM_READWRITE | GIMP_PARAM_NO_VALIDATE));
gimp_procedure_add_argument (procedure, gimp_procedure_add_argument (procedure,
g_param_spec_object ("file", g_param_spec_object ("file",
"File", "File",

View File

@ -200,16 +200,6 @@ pat_save (GimpProcedure *procedure,
break; break;
} }
if (n_drawables != 1)
{
g_set_error (&error, G_FILE_ERROR, 0,
_("PAT format does not support multiple layers."));
return gimp_procedure_new_return_values (procedure,
GIMP_PDB_CALLING_ERROR,
error);
}
if (run_mode == GIMP_RUN_INTERACTIVE) if (run_mode == GIMP_RUN_INTERACTIVE)
{ {
if (! save_dialog (procedure, G_OBJECT (config))) if (! save_dialog (procedure, G_OBJECT (config)))
@ -219,20 +209,27 @@ pat_save (GimpProcedure *procedure,
if (status == GIMP_PDB_SUCCESS) if (status == GIMP_PDB_SUCCESS)
{ {
GimpValueArray *save_retvals; GimpValueArray *save_retvals;
GimpValueArray *args;
g_object_get (config, g_object_get (config,
"description", &description, "description", &description,
NULL); NULL);
save_retvals = args = gimp_value_array_new_from_types (NULL,
gimp_pdb_run_procedure (gimp_get_pdb (), GIMP_TYPE_RUN_MODE, GIMP_RUN_NONINTERACTIVE,
"file-pat-save-internal", GIMP_TYPE_IMAGE, image,
GIMP_TYPE_RUN_MODE, GIMP_RUN_NONINTERACTIVE, G_TYPE_INT, n_drawables,
GIMP_TYPE_IMAGE, image, GIMP_TYPE_OBJECT_ARRAY, NULL,
GIMP_TYPE_DRAWABLE, drawables[0], G_TYPE_FILE, file,
G_TYPE_FILE, file, G_TYPE_STRING, description,
G_TYPE_STRING, description, G_TYPE_NONE);
G_TYPE_NONE); gimp_value_set_object_array (gimp_value_array_index (args, 3),
GIMP_TYPE_ITEM, (GObject **) drawables, n_drawables);
save_retvals = gimp_pdb_run_procedure_array (gimp_get_pdb (),
"file-pat-save-internal",
args);
gimp_value_array_unref (args);
if (GIMP_VALUES_GET_ENUM (save_retvals, 0) != GIMP_PDB_SUCCESS) if (GIMP_VALUES_GET_ENUM (save_retvals, 0) != GIMP_PDB_SUCCESS)
{ {