1999-10-04 02:54:54 +08:00
|
|
|
/* LIBGIMP - The GIMP Library
|
|
|
|
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
|
|
|
|
*
|
2024-05-07 02:38:12 +08:00
|
|
|
* gimpexportoptions.c
|
|
|
|
* Copyright (C) 2024 Alx Sa.
|
2000-02-26 11:41:06 +08:00
|
|
|
*
|
2009-01-18 06:28:01 +08:00
|
|
|
* This library is free software: you can redistribute it and/or
|
1999-11-18 05:13:50 +08:00
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
1999-10-04 02:54:54 +08:00
|
|
|
* License as published by the Free Software Foundation; either
|
2009-01-18 06:28:01 +08:00
|
|
|
* version 3 of the License, or (at your option) any later version.
|
1999-10-04 02:54:54 +08:00
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
2024-05-07 02:38:12 +08:00
|
|
|
* Lesser General Public License for more details.
|
1999-10-04 02:54:54 +08:00
|
|
|
*
|
1999-11-18 05:13:50 +08:00
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
2009-01-18 06:28:01 +08:00
|
|
|
* License along with this library. If not, see
|
2018-07-12 05:27:07 +08:00
|
|
|
* <https://www.gnu.org/licenses/>.
|
2003-11-06 23:27:05 +08:00
|
|
|
*/
|
2000-06-01 05:16:11 +08:00
|
|
|
|
1999-11-14 10:08:07 +08:00
|
|
|
#include "config.h"
|
1999-10-04 02:54:54 +08:00
|
|
|
|
|
|
|
#include "gimp.h"
|
2000-01-27 09:54:52 +08:00
|
|
|
|
2024-05-07 02:38:12 +08:00
|
|
|
#include "gimpexportoptions.h"
|
1999-10-04 02:54:54 +08:00
|
|
|
|
2024-05-07 02:38:12 +08:00
|
|
|
#include "libgimp-intl.h"
|
2000-06-01 05:16:11 +08:00
|
|
|
|
2010-07-07 17:48:10 +08:00
|
|
|
|
2024-05-07 02:38:12 +08:00
|
|
|
/* export helper functions */
|
2010-07-07 17:48:10 +08:00
|
|
|
|
2020-04-14 17:46:17 +08:00
|
|
|
typedef void (* ExportFunc) (GimpImage *image,
|
|
|
|
GList **drawables);
|
2000-11-18 08:25:42 +08:00
|
|
|
|
1999-10-04 02:54:54 +08:00
|
|
|
/* the export action structure */
|
2003-11-06 23:27:05 +08:00
|
|
|
typedef struct
|
1999-10-04 02:54:54 +08:00
|
|
|
{
|
2008-09-11 19:49:13 +08:00
|
|
|
ExportFunc default_action;
|
|
|
|
ExportFunc alt_action;
|
|
|
|
const gchar *reason;
|
|
|
|
const gchar *possibilities[2];
|
|
|
|
gint choice;
|
1999-10-04 02:54:54 +08:00
|
|
|
} ExportAction;
|
|
|
|
|
|
|
|
|
|
|
|
/* the functions that do the actual export */
|
1999-10-24 21:26:30 +08:00
|
|
|
|
1999-10-04 02:54:54 +08:00
|
|
|
static void
|
2020-04-14 17:46:17 +08:00
|
|
|
export_merge (GimpImage *image,
|
|
|
|
GList **drawables)
|
1999-10-04 02:54:54 +08:00
|
|
|
{
|
2019-08-14 17:08:42 +08:00
|
|
|
GList *layers;
|
|
|
|
GList *iter;
|
2000-02-09 01:04:19 +08:00
|
|
|
gint32 nvisible = 0;
|
1999-10-24 21:26:30 +08:00
|
|
|
|
2019-08-27 19:26:27 +08:00
|
|
|
layers = gimp_image_list_layers (image);
|
|
|
|
|
|
|
|
for (iter = layers; iter; iter = g_list_next (iter))
|
2000-02-09 01:04:19 +08:00
|
|
|
{
|
2019-08-14 17:08:42 +08:00
|
|
|
if (gimp_item_get_visible (GIMP_ITEM (iter->data)))
|
2006-04-12 18:53:28 +08:00
|
|
|
nvisible++;
|
2000-02-09 01:04:19 +08:00
|
|
|
}
|
|
|
|
|
2001-10-25 01:34:44 +08:00
|
|
|
if (nvisible <= 1)
|
|
|
|
{
|
2020-06-28 00:11:40 +08:00
|
|
|
GimpLayer *transp;
|
|
|
|
GimpImageType layer_type;
|
2019-08-13 22:16:08 +08:00
|
|
|
|
2017-08-20 21:06:26 +08:00
|
|
|
/* if there is only one (or zero) visible layer, add a new
|
|
|
|
* transparent layer that has the same size as the canvas. The
|
|
|
|
* merge that follows will ensure that the offset, opacity and
|
|
|
|
* size are correct
|
|
|
|
*/
|
2021-04-06 06:47:07 +08:00
|
|
|
switch (gimp_image_get_base_type (image))
|
2020-06-28 00:11:40 +08:00
|
|
|
{
|
|
|
|
case GIMP_RGB:
|
|
|
|
layer_type = GIMP_RGBA_IMAGE;
|
|
|
|
break;
|
|
|
|
case GIMP_GRAY:
|
|
|
|
layer_type = GIMP_GRAYA_IMAGE;
|
|
|
|
break;
|
|
|
|
case GIMP_INDEXED:
|
|
|
|
layer_type = GIMP_INDEXEDA_IMAGE;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
/* In case we add a new type in future. */
|
|
|
|
g_return_if_reached ();
|
|
|
|
}
|
2019-08-11 23:12:20 +08:00
|
|
|
transp = gimp_layer_new (image, "-",
|
2021-04-06 06:47:07 +08:00
|
|
|
gimp_image_get_width (image),
|
|
|
|
gimp_image_get_height (image),
|
2020-06-28 00:11:40 +08:00
|
|
|
layer_type,
|
2017-08-20 21:06:26 +08:00
|
|
|
100.0, GIMP_LAYER_MODE_NORMAL);
|
2019-08-13 22:16:08 +08:00
|
|
|
gimp_image_insert_layer (image, transp, NULL, 1);
|
2019-08-11 23:12:20 +08:00
|
|
|
gimp_selection_none (image);
|
2019-08-13 22:16:08 +08:00
|
|
|
gimp_drawable_edit_clear (GIMP_DRAWABLE (transp));
|
2001-10-25 01:34:44 +08:00
|
|
|
nvisible++;
|
|
|
|
}
|
2000-02-09 01:04:19 +08:00
|
|
|
|
|
|
|
if (nvisible > 1)
|
|
|
|
{
|
2019-08-13 22:16:08 +08:00
|
|
|
GimpLayer *merged;
|
|
|
|
|
2019-08-11 23:12:20 +08:00
|
|
|
merged = gimp_image_merge_visible_layers (image, GIMP_CLIP_TO_IMAGE);
|
2000-02-09 01:04:19 +08:00
|
|
|
|
2020-04-14 17:46:17 +08:00
|
|
|
g_return_if_fail (merged != NULL);
|
|
|
|
|
|
|
|
*drawables = g_list_prepend (NULL, merged);
|
2003-11-06 23:27:05 +08:00
|
|
|
|
2019-08-15 18:12:25 +08:00
|
|
|
g_list_free (layers);
|
2019-08-27 19:26:27 +08:00
|
|
|
|
|
|
|
layers = gimp_image_list_layers (image);
|
2003-05-27 01:30:15 +08:00
|
|
|
|
|
|
|
/* make sure that the merged drawable matches the image size */
|
2021-04-06 20:28:40 +08:00
|
|
|
if (gimp_drawable_get_width (GIMP_DRAWABLE (merged)) !=
|
2021-04-06 06:47:07 +08:00
|
|
|
gimp_image_get_width (image) ||
|
2021-04-06 20:28:40 +08:00
|
|
|
gimp_drawable_get_height (GIMP_DRAWABLE (merged)) !=
|
2021-04-06 06:47:07 +08:00
|
|
|
gimp_image_get_height (image))
|
2003-05-27 01:30:15 +08:00
|
|
|
{
|
|
|
|
gint off_x, off_y;
|
|
|
|
|
2021-04-06 20:28:40 +08:00
|
|
|
gimp_drawable_get_offsets (GIMP_DRAWABLE (merged), &off_x, &off_y);
|
2003-05-27 01:30:15 +08:00
|
|
|
gimp_layer_resize (merged,
|
2021-04-06 06:47:07 +08:00
|
|
|
gimp_image_get_width (image),
|
|
|
|
gimp_image_get_height (image),
|
2003-05-27 01:30:15 +08:00
|
|
|
off_x, off_y);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-11-06 23:27:05 +08:00
|
|
|
/* remove any remaining (invisible) layers */
|
2019-08-14 17:08:42 +08:00
|
|
|
for (iter = layers; iter; iter = iter->next)
|
1999-10-24 21:26:30 +08:00
|
|
|
{
|
2020-06-28 00:11:40 +08:00
|
|
|
if (! g_list_find (*drawables, iter->data))
|
2019-08-14 17:08:42 +08:00
|
|
|
gimp_image_remove_layer (image, iter->data);
|
1999-10-24 21:26:30 +08:00
|
|
|
}
|
2019-08-27 19:26:27 +08:00
|
|
|
|
2019-08-15 18:12:25 +08:00
|
|
|
g_list_free (layers);
|
1999-10-04 02:54:54 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2020-04-14 17:46:17 +08:00
|
|
|
export_flatten (GimpImage *image,
|
|
|
|
GList **drawables)
|
2003-11-06 23:27:05 +08:00
|
|
|
{
|
2019-08-13 22:16:08 +08:00
|
|
|
GimpLayer *flattened;
|
2003-11-06 23:27:05 +08:00
|
|
|
|
2019-08-11 23:12:20 +08:00
|
|
|
flattened = gimp_image_flatten (image);
|
2000-02-09 01:04:19 +08:00
|
|
|
|
2019-08-13 22:16:08 +08:00
|
|
|
if (flattened != NULL)
|
2020-04-14 17:46:17 +08:00
|
|
|
*drawables = g_list_prepend (NULL, flattened);
|
1999-10-04 02:54:54 +08:00
|
|
|
}
|
|
|
|
|
app: a few fixups to MR !958 (initial non-destructive editing).
- Do not leak allocated return value of gegl_node_to_xml_full().
- When merging layer effects, use gimp_drawable_filter_commit(), making
sure we use the exact same code path as when applying layer effects
destructively from the start. This also ensures that filters are
properly removed from the filter stack (unlike
gimp_drawable_merge_filter()), which was the reason why the rendering
was wrong (hence getting the buffer without effects first, then
reapplying it after was only a workaround to an actual bug).
- When removing a filter, verify the object still exists before doing
anything with it. If this was the last reference, we don't want to
call functions on this object. In gimp_drawable_filter_commit(), we
set up a weak pointer. In gimp_drawable_filter_remove_filter() itself,
we save the pointer to the filter's drawable before actual removal (as
we don't want to dereference a freed object later on).
- export_merge_layer_effects() should merge filters recursively through
layer groups.
- clean up the XCF code:
* No need to wrap the effect pointers list into 2 zero offset. Only
have one zero offset to indicate the list end.
* Add the layer effect mask in the effect structure (not in the layer
structure), similar as for layer masks.
* Effect name and icon made as main data in the structure, not as
properties.
2024-01-03 00:12:35 +08:00
|
|
|
static void
|
|
|
|
export_merge_layer_effects_rec (GList *layers)
|
|
|
|
{
|
|
|
|
GList *iter;
|
|
|
|
|
|
|
|
for (iter = layers; iter; iter = g_list_next (iter))
|
|
|
|
if (gimp_item_is_group (iter->data))
|
|
|
|
{
|
|
|
|
GList *children = gimp_item_list_children (iter->data);
|
|
|
|
|
|
|
|
export_merge_layer_effects_rec (children);
|
|
|
|
|
|
|
|
g_list_free (children);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gimp_drawable_merge_filters (GIMP_DRAWABLE (iter->data));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-19 22:54:21 +08:00
|
|
|
static void
|
|
|
|
export_merge_layer_effects (GimpImage *image,
|
|
|
|
GList **drawables)
|
|
|
|
{
|
app: a few fixups to MR !958 (initial non-destructive editing).
- Do not leak allocated return value of gegl_node_to_xml_full().
- When merging layer effects, use gimp_drawable_filter_commit(), making
sure we use the exact same code path as when applying layer effects
destructively from the start. This also ensures that filters are
properly removed from the filter stack (unlike
gimp_drawable_merge_filter()), which was the reason why the rendering
was wrong (hence getting the buffer without effects first, then
reapplying it after was only a workaround to an actual bug).
- When removing a filter, verify the object still exists before doing
anything with it. If this was the last reference, we don't want to
call functions on this object. In gimp_drawable_filter_commit(), we
set up a weak pointer. In gimp_drawable_filter_remove_filter() itself,
we save the pointer to the filter's drawable before actual removal (as
we don't want to dereference a freed object later on).
- export_merge_layer_effects() should merge filters recursively through
layer groups.
- clean up the XCF code:
* No need to wrap the effect pointers list into 2 zero offset. Only
have one zero offset to indicate the list end.
* Add the layer effect mask in the effect structure (not in the layer
structure), similar as for layer masks.
* Effect name and icon made as main data in the structure, not as
properties.
2024-01-03 00:12:35 +08:00
|
|
|
GList *layers;
|
2023-06-19 22:54:21 +08:00
|
|
|
|
|
|
|
layers = gimp_image_list_layers (image);
|
app: a few fixups to MR !958 (initial non-destructive editing).
- Do not leak allocated return value of gegl_node_to_xml_full().
- When merging layer effects, use gimp_drawable_filter_commit(), making
sure we use the exact same code path as when applying layer effects
destructively from the start. This also ensures that filters are
properly removed from the filter stack (unlike
gimp_drawable_merge_filter()), which was the reason why the rendering
was wrong (hence getting the buffer without effects first, then
reapplying it after was only a workaround to an actual bug).
- When removing a filter, verify the object still exists before doing
anything with it. If this was the last reference, we don't want to
call functions on this object. In gimp_drawable_filter_commit(), we
set up a weak pointer. In gimp_drawable_filter_remove_filter() itself,
we save the pointer to the filter's drawable before actual removal (as
we don't want to dereference a freed object later on).
- export_merge_layer_effects() should merge filters recursively through
layer groups.
- clean up the XCF code:
* No need to wrap the effect pointers list into 2 zero offset. Only
have one zero offset to indicate the list end.
* Add the layer effect mask in the effect structure (not in the layer
structure), similar as for layer masks.
* Effect name and icon made as main data in the structure, not as
properties.
2024-01-03 00:12:35 +08:00
|
|
|
export_merge_layer_effects_rec (layers);
|
2023-06-19 22:54:21 +08:00
|
|
|
g_list_free (layers);
|
|
|
|
}
|
|
|
|
|
2019-06-28 19:20:44 +08:00
|
|
|
static void
|
2020-04-14 17:46:17 +08:00
|
|
|
export_remove_alpha (GimpImage *image,
|
|
|
|
GList **drawables)
|
2019-06-28 19:20:44 +08:00
|
|
|
{
|
2019-08-14 17:08:42 +08:00
|
|
|
GList *layers;
|
|
|
|
GList *iter;
|
2019-06-28 19:20:44 +08:00
|
|
|
|
2019-08-27 19:26:27 +08:00
|
|
|
layers = gimp_image_list_layers (image);
|
2019-06-28 19:20:44 +08:00
|
|
|
|
2019-08-14 17:08:42 +08:00
|
|
|
for (iter = layers; iter; iter = iter->next)
|
2019-06-28 19:20:44 +08:00
|
|
|
{
|
2019-08-14 17:08:42 +08:00
|
|
|
if (gimp_drawable_has_alpha (GIMP_DRAWABLE (iter->data)))
|
|
|
|
gimp_layer_flatten (iter->data);
|
2019-06-28 19:20:44 +08:00
|
|
|
}
|
|
|
|
|
2019-08-15 18:12:25 +08:00
|
|
|
g_list_free (layers);
|
2019-06-28 19:20:44 +08:00
|
|
|
}
|
|
|
|
|
2003-11-16 00:51:20 +08:00
|
|
|
static void
|
2020-04-14 17:46:17 +08:00
|
|
|
export_apply_masks (GimpImage *image,
|
|
|
|
GList **drawables)
|
2003-11-16 00:51:20 +08:00
|
|
|
{
|
2019-08-14 17:08:42 +08:00
|
|
|
GList *layers;
|
|
|
|
GList *iter;
|
2003-11-16 00:51:20 +08:00
|
|
|
|
2019-08-27 19:26:27 +08:00
|
|
|
layers = gimp_image_list_layers (image);
|
2003-11-16 00:51:20 +08:00
|
|
|
|
2019-08-14 17:08:42 +08:00
|
|
|
for (iter = layers; iter; iter = iter->next)
|
2003-11-16 00:51:20 +08:00
|
|
|
{
|
2019-08-14 04:54:37 +08:00
|
|
|
GimpLayerMask *mask;
|
2019-08-13 22:16:08 +08:00
|
|
|
|
2019-08-14 17:08:42 +08:00
|
|
|
mask = gimp_layer_get_mask (iter->data);
|
2019-09-07 15:24:51 +08:00
|
|
|
|
2019-08-14 04:54:37 +08:00
|
|
|
if (mask)
|
2019-09-07 15:24:51 +08:00
|
|
|
{
|
|
|
|
/* we can't apply the mask directly to a layer group, so merge it
|
|
|
|
* first
|
|
|
|
*/
|
|
|
|
if (gimp_item_is_group (iter->data))
|
app, libgimp, pdb, plug-ins: new GimpGroupLayer class in libgimp.
Also:
- renaming gimp_layer_group_new() to gimp_group_layer_new() in order to keep the
same name as in core code (i.e. GimpGroupLayer, not GimpLayerGroup).
- renaming gimp_image_merge_layer_group() to gimp_group_layer_merge()
- new functions: gimp_procedure_add_group_layer_argument(),
gimp_procedure_add_group_layer_aux_argument() and
gimp_procedure_add_group_layer_return_value().
This can be tested, e.g. in Python with these calls:
```py
i = Gimp.get_images()[0]
g = Gimp.GroupLayer.new(i, "hello")
i.insert_layer(g, None, 1)
g2 = Gimp.GroupLayer.new(i, "world")
i.insert_layer(g2, g, 1)
g.merge()
```
This was work started long ago, stored in an old stash which I finally
finish now! :-)
2024-07-06 23:24:11 +08:00
|
|
|
iter->data = gimp_group_layer_merge (iter->data);
|
2019-09-07 15:24:51 +08:00
|
|
|
|
|
|
|
gimp_layer_remove_mask (iter->data, GIMP_MASK_APPLY);
|
|
|
|
}
|
2003-11-16 00:51:20 +08:00
|
|
|
}
|
|
|
|
|
2019-08-15 18:12:25 +08:00
|
|
|
g_list_free (layers);
|
2003-11-16 00:51:20 +08:00
|
|
|
}
|
|
|
|
|
1999-10-04 02:54:54 +08:00
|
|
|
static void
|
2020-04-14 17:46:17 +08:00
|
|
|
export_convert_rgb (GimpImage *image,
|
|
|
|
GList **drawables)
|
2003-11-06 23:27:05 +08:00
|
|
|
{
|
2019-08-11 23:12:20 +08:00
|
|
|
gimp_image_convert_rgb (image);
|
1999-10-04 02:54:54 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2020-04-14 17:46:17 +08:00
|
|
|
export_convert_grayscale (GimpImage *image,
|
|
|
|
GList **drawables)
|
2003-11-06 23:27:05 +08:00
|
|
|
{
|
2019-08-11 23:12:20 +08:00
|
|
|
gimp_image_convert_grayscale (image);
|
1999-10-04 02:54:54 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2020-04-14 17:46:17 +08:00
|
|
|
export_convert_indexed (GimpImage *image,
|
|
|
|
GList **drawables)
|
2003-11-06 23:27:05 +08:00
|
|
|
{
|
2020-04-14 17:46:17 +08:00
|
|
|
GList *layers;
|
|
|
|
GList *iter;
|
|
|
|
gboolean has_alpha = FALSE;
|
2003-11-06 23:27:05 +08:00
|
|
|
|
1999-10-04 02:54:54 +08:00
|
|
|
/* check alpha */
|
2019-08-27 19:26:27 +08:00
|
|
|
layers = gimp_image_list_layers (image);
|
|
|
|
|
2020-04-14 17:46:17 +08:00
|
|
|
for (iter = *drawables; iter; iter = iter->next)
|
|
|
|
{
|
|
|
|
if (gimp_drawable_has_alpha (iter->data))
|
|
|
|
{
|
|
|
|
has_alpha = TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (layers || has_alpha)
|
2019-08-11 23:12:20 +08:00
|
|
|
gimp_image_convert_indexed (image,
|
2017-02-27 03:55:00 +08:00
|
|
|
GIMP_CONVERT_DITHER_NONE,
|
|
|
|
GIMP_CONVERT_PALETTE_GENERATE,
|
|
|
|
255, FALSE, FALSE, "");
|
1999-10-04 02:54:54 +08:00
|
|
|
else
|
2019-08-11 23:12:20 +08:00
|
|
|
gimp_image_convert_indexed (image,
|
2017-02-27 03:55:00 +08:00
|
|
|
GIMP_CONVERT_DITHER_NONE,
|
|
|
|
GIMP_CONVERT_PALETTE_GENERATE,
|
|
|
|
256, FALSE, FALSE, "");
|
2019-08-15 18:12:25 +08:00
|
|
|
g_list_free (layers);
|
2003-11-16 00:51:20 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2020-04-14 17:46:17 +08:00
|
|
|
export_convert_bitmap (GimpImage *image,
|
|
|
|
GList **drawables)
|
2003-11-16 00:51:20 +08:00
|
|
|
{
|
2021-04-06 06:47:07 +08:00
|
|
|
if (gimp_image_get_base_type (image) == GIMP_INDEXED)
|
2019-08-11 23:12:20 +08:00
|
|
|
gimp_image_convert_rgb (image);
|
2003-11-16 00:51:20 +08:00
|
|
|
|
2019-08-11 23:12:20 +08:00
|
|
|
gimp_image_convert_indexed (image,
|
2017-02-27 03:55:00 +08:00
|
|
|
GIMP_CONVERT_DITHER_FS,
|
|
|
|
GIMP_CONVERT_PALETTE_GENERATE,
|
|
|
|
2, FALSE, FALSE, "");
|
1999-10-04 02:54:54 +08:00
|
|
|
}
|
|
|
|
|
1999-10-09 08:11:50 +08:00
|
|
|
static void
|
2020-04-14 17:46:17 +08:00
|
|
|
export_add_alpha (GimpImage *image,
|
|
|
|
GList **drawables)
|
2003-11-06 23:27:05 +08:00
|
|
|
{
|
2019-08-14 17:08:42 +08:00
|
|
|
GList *layers;
|
|
|
|
GList *iter;
|
1999-10-09 08:11:50 +08:00
|
|
|
|
2019-08-27 19:26:27 +08:00
|
|
|
layers = gimp_image_list_layers (image);
|
|
|
|
|
2019-08-14 17:08:42 +08:00
|
|
|
for (iter = layers; iter; iter = iter->next)
|
1999-10-09 08:11:50 +08:00
|
|
|
{
|
2019-08-14 17:08:42 +08:00
|
|
|
if (! gimp_drawable_has_alpha (GIMP_DRAWABLE (iter->data)))
|
|
|
|
gimp_layer_add_alpha (GIMP_LAYER (iter->data));
|
1999-10-09 08:11:50 +08:00
|
|
|
}
|
2019-08-27 19:26:27 +08:00
|
|
|
|
2019-08-15 18:12:25 +08:00
|
|
|
g_list_free (layers);
|
1999-10-09 08:11:50 +08:00
|
|
|
}
|
|
|
|
|
2020-06-25 22:50:21 +08:00
|
|
|
static void
|
|
|
|
export_crop_image (GimpImage *image,
|
|
|
|
GList **drawables)
|
|
|
|
{
|
|
|
|
gimp_image_crop (image,
|
2021-04-06 06:47:07 +08:00
|
|
|
gimp_image_get_width (image),
|
|
|
|
gimp_image_get_height (image),
|
2020-06-25 22:50:21 +08:00
|
|
|
0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
export_resize_image (GimpImage *image,
|
|
|
|
GList **drawables)
|
|
|
|
{
|
|
|
|
gimp_image_resize_to_layers (image);
|
|
|
|
}
|
|
|
|
|
2008-11-25 16:20:56 +08:00
|
|
|
static void
|
2020-04-14 17:46:17 +08:00
|
|
|
export_void (GimpImage *image,
|
|
|
|
GList **drawables)
|
2008-11-25 16:20:56 +08:00
|
|
|
{
|
|
|
|
/* do nothing */
|
|
|
|
}
|
|
|
|
|
1999-10-24 21:26:30 +08:00
|
|
|
|
1999-10-04 02:54:54 +08:00
|
|
|
/* a set of predefined actions */
|
|
|
|
|
|
|
|
static ExportAction export_action_merge =
|
|
|
|
{
|
|
|
|
export_merge,
|
|
|
|
NULL,
|
2007-03-06 05:31:04 +08:00
|
|
|
N_("%s plug-in can't handle layers"),
|
2000-01-11 23:48:00 +08:00
|
|
|
{ N_("Merge Visible Layers"), NULL },
|
1999-10-04 02:54:54 +08:00
|
|
|
0
|
|
|
|
};
|
|
|
|
|
2001-10-25 01:34:44 +08:00
|
|
|
static ExportAction export_action_merge_single =
|
|
|
|
{
|
|
|
|
export_merge,
|
|
|
|
NULL,
|
2007-03-06 05:31:04 +08:00
|
|
|
N_("%s plug-in can't handle layer offsets, size or opacity"),
|
2001-10-25 01:34:44 +08:00
|
|
|
{ N_("Merge Visible Layers"), NULL },
|
|
|
|
0
|
|
|
|
};
|
|
|
|
|
1999-10-04 02:54:54 +08:00
|
|
|
static ExportAction export_action_animate_or_merge =
|
|
|
|
{
|
2000-07-09 23:47:11 +08:00
|
|
|
NULL,
|
2016-09-04 23:10:57 +08:00
|
|
|
export_merge,
|
2007-03-06 05:31:04 +08:00
|
|
|
N_("%s plug-in can only handle layers as animation frames"),
|
2016-09-04 23:10:57 +08:00
|
|
|
{ N_("Save as Animation"), N_("Merge Visible Layers") },
|
1999-10-04 02:54:54 +08:00
|
|
|
0
|
|
|
|
};
|
|
|
|
|
2000-04-08 04:04:00 +08:00
|
|
|
static ExportAction export_action_animate_or_flatten =
|
|
|
|
{
|
2000-07-09 23:47:11 +08:00
|
|
|
NULL,
|
2016-09-04 23:10:57 +08:00
|
|
|
export_flatten,
|
2007-03-06 05:31:04 +08:00
|
|
|
N_("%s plug-in can only handle layers as animation frames"),
|
2016-09-04 23:10:57 +08:00
|
|
|
{ N_("Save as Animation"), N_("Flatten Image") },
|
2000-04-08 04:04:00 +08:00
|
|
|
0
|
|
|
|
};
|
|
|
|
|
2006-03-09 19:12:55 +08:00
|
|
|
static ExportAction export_action_merge_or_flatten =
|
2000-06-26 07:18:56 +08:00
|
|
|
{
|
|
|
|
export_flatten,
|
2006-03-09 19:12:55 +08:00
|
|
|
export_merge,
|
2007-03-06 05:31:04 +08:00
|
|
|
N_("%s plug-in can't handle layers"),
|
2006-03-09 19:12:55 +08:00
|
|
|
{ N_("Flatten Image"), N_("Merge Visible Layers") },
|
|
|
|
1
|
2000-06-26 07:18:56 +08:00
|
|
|
};
|
|
|
|
|
1999-10-04 02:54:54 +08:00
|
|
|
static ExportAction export_action_flatten =
|
|
|
|
{
|
2000-04-08 04:04:00 +08:00
|
|
|
export_flatten,
|
1999-10-04 02:54:54 +08:00
|
|
|
NULL,
|
2007-03-06 05:31:04 +08:00
|
|
|
N_("%s plug-in can't handle transparency"),
|
1999-10-04 02:54:54 +08:00
|
|
|
{ N_("Flatten Image"), NULL },
|
|
|
|
0
|
|
|
|
};
|
|
|
|
|
2023-06-19 22:54:21 +08:00
|
|
|
static ExportAction export_action_merge_layer_effects =
|
|
|
|
{
|
|
|
|
export_merge_layer_effects,
|
|
|
|
NULL,
|
|
|
|
N_("%s plug-in can't handle layer effects"),
|
|
|
|
{ N_("Merge Layer Effects"), NULL },
|
|
|
|
0
|
|
|
|
};
|
|
|
|
|
2019-06-28 19:20:44 +08:00
|
|
|
static ExportAction export_action_remove_alpha =
|
|
|
|
{
|
|
|
|
export_remove_alpha,
|
|
|
|
NULL,
|
|
|
|
N_("%s plug-in can't handle transparent layers"),
|
|
|
|
{ N_("Flatten Image"), NULL },
|
|
|
|
0
|
|
|
|
};
|
|
|
|
|
2003-11-16 00:51:20 +08:00
|
|
|
static ExportAction export_action_apply_masks =
|
|
|
|
{
|
|
|
|
export_apply_masks,
|
|
|
|
NULL,
|
2007-03-06 05:31:04 +08:00
|
|
|
N_("%s plug-in can't handle layer masks"),
|
2003-11-16 00:51:20 +08:00
|
|
|
{ N_("Apply Layer Masks"), NULL },
|
|
|
|
0
|
|
|
|
};
|
|
|
|
|
1999-10-04 02:54:54 +08:00
|
|
|
static ExportAction export_action_convert_rgb =
|
|
|
|
{
|
2000-04-08 04:04:00 +08:00
|
|
|
export_convert_rgb,
|
1999-10-04 02:54:54 +08:00
|
|
|
NULL,
|
2007-03-06 05:31:04 +08:00
|
|
|
N_("%s plug-in can only handle RGB images"),
|
1999-10-04 02:54:54 +08:00
|
|
|
{ N_("Convert to RGB"), NULL },
|
|
|
|
0
|
|
|
|
};
|
|
|
|
|
|
|
|
static ExportAction export_action_convert_grayscale =
|
|
|
|
{
|
2000-04-08 04:04:00 +08:00
|
|
|
export_convert_grayscale,
|
1999-10-04 02:54:54 +08:00
|
|
|
NULL,
|
2007-03-06 05:31:04 +08:00
|
|
|
N_("%s plug-in can only handle grayscale images"),
|
2000-01-11 23:48:00 +08:00
|
|
|
{ N_("Convert to Grayscale"), NULL },
|
1999-10-04 02:54:54 +08:00
|
|
|
0
|
|
|
|
};
|
|
|
|
|
|
|
|
static ExportAction export_action_convert_indexed =
|
|
|
|
{
|
2000-04-08 04:04:00 +08:00
|
|
|
export_convert_indexed,
|
1999-10-04 02:54:54 +08:00
|
|
|
NULL,
|
2007-03-06 05:31:04 +08:00
|
|
|
N_("%s plug-in can only handle indexed images"),
|
2000-06-28 06:02:27 +08:00
|
|
|
{ N_("Convert to Indexed using default settings\n"
|
2000-01-11 23:48:00 +08:00
|
|
|
"(Do it manually to tune the result)"), NULL },
|
1999-10-04 02:54:54 +08:00
|
|
|
0
|
|
|
|
};
|
|
|
|
|
2003-11-16 00:51:20 +08:00
|
|
|
static ExportAction export_action_convert_bitmap =
|
|
|
|
{
|
|
|
|
export_convert_bitmap,
|
|
|
|
NULL,
|
2007-03-06 05:31:04 +08:00
|
|
|
N_("%s plug-in can only handle bitmap (two color) indexed images"),
|
2003-11-16 00:51:20 +08:00
|
|
|
{ N_("Convert to Indexed using bitmap default settings\n"
|
|
|
|
"(Do it manually to tune the result)"), NULL },
|
|
|
|
0
|
|
|
|
};
|
|
|
|
|
1999-10-04 02:54:54 +08:00
|
|
|
static ExportAction export_action_convert_rgb_or_grayscale =
|
|
|
|
{
|
2000-04-08 04:04:00 +08:00
|
|
|
export_convert_rgb,
|
|
|
|
export_convert_grayscale,
|
2007-03-06 05:31:04 +08:00
|
|
|
N_("%s plug-in can only handle RGB or grayscale images"),
|
2000-01-11 23:48:00 +08:00
|
|
|
{ N_("Convert to RGB"), N_("Convert to Grayscale")},
|
1999-10-04 02:54:54 +08:00
|
|
|
0
|
|
|
|
};
|
|
|
|
|
|
|
|
static ExportAction export_action_convert_rgb_or_indexed =
|
|
|
|
{
|
2000-04-08 04:04:00 +08:00
|
|
|
export_convert_rgb,
|
|
|
|
export_convert_indexed,
|
2016-11-06 22:53:27 +08:00
|
|
|
N_("%s plug-in can only handle RGB or indexed images"),
|
2000-06-28 06:02:27 +08:00
|
|
|
{ N_("Convert to RGB"), N_("Convert to Indexed using default settings\n"
|
2006-04-12 18:53:28 +08:00
|
|
|
"(Do it manually to tune the result)")},
|
1999-10-04 02:54:54 +08:00
|
|
|
0
|
|
|
|
};
|
|
|
|
|
|
|
|
static ExportAction export_action_convert_indexed_or_grayscale =
|
|
|
|
{
|
2000-04-08 04:04:00 +08:00
|
|
|
export_convert_indexed,
|
|
|
|
export_convert_grayscale,
|
2007-03-06 05:31:04 +08:00
|
|
|
N_("%s plug-in can only handle grayscale or indexed images"),
|
2000-06-28 06:02:27 +08:00
|
|
|
{ N_("Convert to Indexed using default settings\n"
|
2003-11-06 23:27:05 +08:00
|
|
|
"(Do it manually to tune the result)"),
|
2000-01-11 23:48:00 +08:00
|
|
|
N_("Convert to Grayscale") },
|
1999-10-04 02:54:54 +08:00
|
|
|
0
|
|
|
|
};
|
|
|
|
|
1999-10-09 08:11:50 +08:00
|
|
|
static ExportAction export_action_add_alpha =
|
|
|
|
{
|
2000-04-08 04:04:00 +08:00
|
|
|
export_add_alpha,
|
1999-10-09 08:11:50 +08:00
|
|
|
NULL,
|
2007-03-06 05:31:04 +08:00
|
|
|
N_("%s plug-in needs an alpha channel"),
|
2000-01-11 23:48:00 +08:00
|
|
|
{ N_("Add Alpha Channel"), NULL},
|
1999-10-09 08:11:50 +08:00
|
|
|
0
|
|
|
|
};
|
1999-10-04 02:54:54 +08:00
|
|
|
|
2020-06-25 22:50:21 +08:00
|
|
|
static ExportAction export_action_crop_or_resize =
|
|
|
|
{
|
|
|
|
export_crop_image,
|
|
|
|
export_resize_image,
|
|
|
|
N_("%s plug-in needs to crop the layers to the image bounds"),
|
|
|
|
{ N_("Crop Layers"), N_("Resize Image to Layers")},
|
|
|
|
0
|
|
|
|
};
|
|
|
|
|
1999-10-24 21:26:30 +08:00
|
|
|
|
2008-11-25 16:20:56 +08:00
|
|
|
static ExportFunc
|
|
|
|
export_action_get_func (const ExportAction *action)
|
|
|
|
{
|
|
|
|
if (action->choice == 0 && action->default_action)
|
2016-09-04 23:10:57 +08:00
|
|
|
{
|
|
|
|
return action->default_action;
|
|
|
|
}
|
2008-11-25 16:20:56 +08:00
|
|
|
|
|
|
|
if (action->choice == 1 && action->alt_action)
|
2016-09-04 23:10:57 +08:00
|
|
|
{
|
|
|
|
return action->alt_action;
|
|
|
|
}
|
2008-11-25 16:20:56 +08:00
|
|
|
|
|
|
|
return export_void;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
export_action_perform (const ExportAction *action,
|
2019-08-11 23:12:20 +08:00
|
|
|
GimpImage *image,
|
2020-04-14 17:46:17 +08:00
|
|
|
GList **drawables)
|
2008-11-25 16:20:56 +08:00
|
|
|
{
|
2020-04-14 17:46:17 +08:00
|
|
|
export_action_get_func (action) (image, drawables);
|
2008-11-25 16:20:56 +08:00
|
|
|
}
|
|
|
|
|
2000-02-05 02:55:32 +08:00
|
|
|
/**
|
2024-05-07 02:38:12 +08:00
|
|
|
* gimp_export_options_get_image:
|
app, libgimp*, pdb, plug-ins: review and enhance MR !1549.
- Fix annotations for gimp_export_options_get_image() to make it
actually introspectable with the GimpImage being both input and
output. Even though the logic doesn't change much (the input image may
be overriden or not), it doesn't matter for introspection because
images are handled centrally by libgimp and therefore must not be
freed. Actually deleting the image from the central list of images
though remains a manual action depending on code logic, not some
automatic action to be handled by binding engines.
- Add G_GNUC_WARN_UNUSED_RESULT to gimp_export_options_get_image()
because ignoring the returned value is rarely a good idea (as you
usually want to delete the image).
- Remove gimp_export_options_new(): we don't need this constructor
because at this point, the best is to tell plug-in developers to just
pass NULL everywhere. This leaves us free to create a more useful
default constructor if needed, in the future. Main description for
GimpExportOptions has also been updated to say this.
- Add a data_destroy callback for the user data passed in
gimp_export_procedure_set_capabilities().
- Fixing annotations of 'export_options' object from pdb/pdb.pl: input
args would actually be (nullable) and would not transfer ownership
(calling code must still free the object). Return value's ownership on
the other hand is fully transfered.
- Add C and Python unit testing for GimpExportOptions and
gimp_export_options_get_image() in particular.
- Fix or improve various details.
Note that I have also considered for a long time changing the signature
of gimp_export_options_get_image() to return a boolean indicating
whether `image` had been replaced (hence needed deletion) or not. This
also meant getting rid of the GimpExportReturn enum. Right now it would
work because there are no third case, but I was considering the future
possibility that for instance we got some impossible conversion for some
future capability. I'm not sure it would ever happen; and for sure, this
is not desirable because it implies an export failure a bit late in the
workflow. But just in case, let's keep the enum return value. It does
not even make the using code that much more complicated (well just a
value comparison instead of a simple boolean test).
2024-08-17 21:06:27 +08:00
|
|
|
* @options: (transfer none): The #GimpExportOptions object.
|
|
|
|
* @image: (inout) (transfer none): the image.
|
2000-02-05 02:55:32 +08:00
|
|
|
*
|
app, libgimp*, pdb, plug-ins: review and enhance MR !1549.
- Fix annotations for gimp_export_options_get_image() to make it
actually introspectable with the GimpImage being both input and
output. Even though the logic doesn't change much (the input image may
be overriden or not), it doesn't matter for introspection because
images are handled centrally by libgimp and therefore must not be
freed. Actually deleting the image from the central list of images
though remains a manual action depending on code logic, not some
automatic action to be handled by binding engines.
- Add G_GNUC_WARN_UNUSED_RESULT to gimp_export_options_get_image()
because ignoring the returned value is rarely a good idea (as you
usually want to delete the image).
- Remove gimp_export_options_new(): we don't need this constructor
because at this point, the best is to tell plug-in developers to just
pass NULL everywhere. This leaves us free to create a more useful
default constructor if needed, in the future. Main description for
GimpExportOptions has also been updated to say this.
- Add a data_destroy callback for the user data passed in
gimp_export_procedure_set_capabilities().
- Fixing annotations of 'export_options' object from pdb/pdb.pl: input
args would actually be (nullable) and would not transfer ownership
(calling code must still free the object). Return value's ownership on
the other hand is fully transfered.
- Add C and Python unit testing for GimpExportOptions and
gimp_export_options_get_image() in particular.
- Fix or improve various details.
Note that I have also considered for a long time changing the signature
of gimp_export_options_get_image() to return a boolean indicating
whether `image` had been replaced (hence needed deletion) or not. This
also meant getting rid of the GimpExportReturn enum. Right now it would
work because there are no third case, but I was considering the future
possibility that for instance we got some impossible conversion for some
future capability. I'm not sure it would ever happen; and for sure, this
is not desirable because it implies an export failure a bit late in the
workflow. But just in case, let's keep the enum return value. It does
not even make the using code that much more complicated (well just a
value comparison instead of a simple boolean test).
2024-08-17 21:06:27 +08:00
|
|
|
* Takes an image to be exported, possibly creating a temporary copy
|
|
|
|
* modified according to export settings in @options (such as the
|
|
|
|
* capabilities of the export format).
|
2000-02-05 02:55:32 +08:00
|
|
|
*
|
app, libgimp*, pdb, plug-ins: review and enhance MR !1549.
- Fix annotations for gimp_export_options_get_image() to make it
actually introspectable with the GimpImage being both input and
output. Even though the logic doesn't change much (the input image may
be overriden or not), it doesn't matter for introspection because
images are handled centrally by libgimp and therefore must not be
freed. Actually deleting the image from the central list of images
though remains a manual action depending on code logic, not some
automatic action to be handled by binding engines.
- Add G_GNUC_WARN_UNUSED_RESULT to gimp_export_options_get_image()
because ignoring the returned value is rarely a good idea (as you
usually want to delete the image).
- Remove gimp_export_options_new(): we don't need this constructor
because at this point, the best is to tell plug-in developers to just
pass NULL everywhere. This leaves us free to create a more useful
default constructor if needed, in the future. Main description for
GimpExportOptions has also been updated to say this.
- Add a data_destroy callback for the user data passed in
gimp_export_procedure_set_capabilities().
- Fixing annotations of 'export_options' object from pdb/pdb.pl: input
args would actually be (nullable) and would not transfer ownership
(calling code must still free the object). Return value's ownership on
the other hand is fully transfered.
- Add C and Python unit testing for GimpExportOptions and
gimp_export_options_get_image() in particular.
- Fix or improve various details.
Note that I have also considered for a long time changing the signature
of gimp_export_options_get_image() to return a boolean indicating
whether `image` had been replaced (hence needed deletion) or not. This
also meant getting rid of the GimpExportReturn enum. Right now it would
work because there are no third case, but I was considering the future
possibility that for instance we got some impossible conversion for some
future capability. I'm not sure it would ever happen; and for sure, this
is not desirable because it implies an export failure a bit late in the
workflow. But just in case, let's keep the enum return value. It does
not even make the using code that much more complicated (well just a
value comparison instead of a simple boolean test).
2024-08-17 21:06:27 +08:00
|
|
|
* If necessary, a copy is created, converted and modified, @image
|
|
|
|
* changed to point to the new image and the procedure returns
|
2024-08-19 22:16:31 +08:00
|
|
|
* [enum@Gimp.ExportReturn.EXPORT].
|
app, libgimp*, pdb, plug-ins: review and enhance MR !1549.
- Fix annotations for gimp_export_options_get_image() to make it
actually introspectable with the GimpImage being both input and
output. Even though the logic doesn't change much (the input image may
be overriden or not), it doesn't matter for introspection because
images are handled centrally by libgimp and therefore must not be
freed. Actually deleting the image from the central list of images
though remains a manual action depending on code logic, not some
automatic action to be handled by binding engines.
- Add G_GNUC_WARN_UNUSED_RESULT to gimp_export_options_get_image()
because ignoring the returned value is rarely a good idea (as you
usually want to delete the image).
- Remove gimp_export_options_new(): we don't need this constructor
because at this point, the best is to tell plug-in developers to just
pass NULL everywhere. This leaves us free to create a more useful
default constructor if needed, in the future. Main description for
GimpExportOptions has also been updated to say this.
- Add a data_destroy callback for the user data passed in
gimp_export_procedure_set_capabilities().
- Fixing annotations of 'export_options' object from pdb/pdb.pl: input
args would actually be (nullable) and would not transfer ownership
(calling code must still free the object). Return value's ownership on
the other hand is fully transfered.
- Add C and Python unit testing for GimpExportOptions and
gimp_export_options_get_image() in particular.
- Fix or improve various details.
Note that I have also considered for a long time changing the signature
of gimp_export_options_get_image() to return a boolean indicating
whether `image` had been replaced (hence needed deletion) or not. This
also meant getting rid of the GimpExportReturn enum. Right now it would
work because there are no third case, but I was considering the future
possibility that for instance we got some impossible conversion for some
future capability. I'm not sure it would ever happen; and for sure, this
is not desirable because it implies an export failure a bit late in the
workflow. But just in case, let's keep the enum return value. It does
not even make the using code that much more complicated (well just a
value comparison instead of a simple boolean test).
2024-08-17 21:06:27 +08:00
|
|
|
* In this case, you must take care of deleting the created image using
|
|
|
|
* [method@Image.delete] once the image has been exported, unless you
|
|
|
|
* were planning to display it with [ctor@Display.new], or you will leak
|
|
|
|
* memory.
|
|
|
|
*
|
2024-08-19 22:16:31 +08:00
|
|
|
* If [enum@Gimp.ExportReturn.IGNORE] is returned, then @image is still the
|
app, libgimp*, pdb, plug-ins: review and enhance MR !1549.
- Fix annotations for gimp_export_options_get_image() to make it
actually introspectable with the GimpImage being both input and
output. Even though the logic doesn't change much (the input image may
be overriden or not), it doesn't matter for introspection because
images are handled centrally by libgimp and therefore must not be
freed. Actually deleting the image from the central list of images
though remains a manual action depending on code logic, not some
automatic action to be handled by binding engines.
- Add G_GNUC_WARN_UNUSED_RESULT to gimp_export_options_get_image()
because ignoring the returned value is rarely a good idea (as you
usually want to delete the image).
- Remove gimp_export_options_new(): we don't need this constructor
because at this point, the best is to tell plug-in developers to just
pass NULL everywhere. This leaves us free to create a more useful
default constructor if needed, in the future. Main description for
GimpExportOptions has also been updated to say this.
- Add a data_destroy callback for the user data passed in
gimp_export_procedure_set_capabilities().
- Fixing annotations of 'export_options' object from pdb/pdb.pl: input
args would actually be (nullable) and would not transfer ownership
(calling code must still free the object). Return value's ownership on
the other hand is fully transfered.
- Add C and Python unit testing for GimpExportOptions and
gimp_export_options_get_image() in particular.
- Fix or improve various details.
Note that I have also considered for a long time changing the signature
of gimp_export_options_get_image() to return a boolean indicating
whether `image` had been replaced (hence needed deletion) or not. This
also meant getting rid of the GimpExportReturn enum. Right now it would
work because there are no third case, but I was considering the future
possibility that for instance we got some impossible conversion for some
future capability. I'm not sure it would ever happen; and for sure, this
is not desirable because it implies an export failure a bit late in the
workflow. But just in case, let's keep the enum return value. It does
not even make the using code that much more complicated (well just a
value comparison instead of a simple boolean test).
2024-08-17 21:06:27 +08:00
|
|
|
* original image. You should neither modify it, nor should you delete
|
|
|
|
* it in the end. If you wish to temporarily modify the image before
|
|
|
|
* export anyway, call [method@Image.duplicate] when
|
2024-08-19 22:16:31 +08:00
|
|
|
* [enum@Gimp.ExportReturn.IGNORE] was returned.
|
app, libgimp*, pdb, plug-ins: review and enhance MR !1549.
- Fix annotations for gimp_export_options_get_image() to make it
actually introspectable with the GimpImage being both input and
output. Even though the logic doesn't change much (the input image may
be overriden or not), it doesn't matter for introspection because
images are handled centrally by libgimp and therefore must not be
freed. Actually deleting the image from the central list of images
though remains a manual action depending on code logic, not some
automatic action to be handled by binding engines.
- Add G_GNUC_WARN_UNUSED_RESULT to gimp_export_options_get_image()
because ignoring the returned value is rarely a good idea (as you
usually want to delete the image).
- Remove gimp_export_options_new(): we don't need this constructor
because at this point, the best is to tell plug-in developers to just
pass NULL everywhere. This leaves us free to create a more useful
default constructor if needed, in the future. Main description for
GimpExportOptions has also been updated to say this.
- Add a data_destroy callback for the user data passed in
gimp_export_procedure_set_capabilities().
- Fixing annotations of 'export_options' object from pdb/pdb.pl: input
args would actually be (nullable) and would not transfer ownership
(calling code must still free the object). Return value's ownership on
the other hand is fully transfered.
- Add C and Python unit testing for GimpExportOptions and
gimp_export_options_get_image() in particular.
- Fix or improve various details.
Note that I have also considered for a long time changing the signature
of gimp_export_options_get_image() to return a boolean indicating
whether `image` had been replaced (hence needed deletion) or not. This
also meant getting rid of the GimpExportReturn enum. Right now it would
work because there are no third case, but I was considering the future
possibility that for instance we got some impossible conversion for some
future capability. I'm not sure it would ever happen; and for sure, this
is not desirable because it implies an export failure a bit late in the
workflow. But just in case, let's keep the enum return value. It does
not even make the using code that much more complicated (well just a
value comparison instead of a simple boolean test).
2024-08-17 21:06:27 +08:00
|
|
|
*
|
|
|
|
* Returns: An enum of #GimpExportReturn.
|
2024-05-07 02:38:12 +08:00
|
|
|
*
|
|
|
|
* Since: 3.0
|
2000-11-18 08:25:42 +08:00
|
|
|
**/
|
2003-11-06 23:27:05 +08:00
|
|
|
GimpExportReturn
|
app, libgimp*, pdb, plug-ins: review and enhance MR !1549.
- Fix annotations for gimp_export_options_get_image() to make it
actually introspectable with the GimpImage being both input and
output. Even though the logic doesn't change much (the input image may
be overriden or not), it doesn't matter for introspection because
images are handled centrally by libgimp and therefore must not be
freed. Actually deleting the image from the central list of images
though remains a manual action depending on code logic, not some
automatic action to be handled by binding engines.
- Add G_GNUC_WARN_UNUSED_RESULT to gimp_export_options_get_image()
because ignoring the returned value is rarely a good idea (as you
usually want to delete the image).
- Remove gimp_export_options_new(): we don't need this constructor
because at this point, the best is to tell plug-in developers to just
pass NULL everywhere. This leaves us free to create a more useful
default constructor if needed, in the future. Main description for
GimpExportOptions has also been updated to say this.
- Add a data_destroy callback for the user data passed in
gimp_export_procedure_set_capabilities().
- Fixing annotations of 'export_options' object from pdb/pdb.pl: input
args would actually be (nullable) and would not transfer ownership
(calling code must still free the object). Return value's ownership on
the other hand is fully transfered.
- Add C and Python unit testing for GimpExportOptions and
gimp_export_options_get_image() in particular.
- Fix or improve various details.
Note that I have also considered for a long time changing the signature
of gimp_export_options_get_image() to return a boolean indicating
whether `image` had been replaced (hence needed deletion) or not. This
also meant getting rid of the GimpExportReturn enum. Right now it would
work because there are no third case, but I was considering the future
possibility that for instance we got some impossible conversion for some
future capability. I'm not sure it would ever happen; and for sure, this
is not desirable because it implies an export failure a bit late in the
workflow. But just in case, let's keep the enum return value. It does
not even make the using code that much more complicated (well just a
value comparison instead of a simple boolean test).
2024-08-17 21:06:27 +08:00
|
|
|
gimp_export_options_get_image (GimpExportOptions *options,
|
|
|
|
GimpImage **image)
|
2024-05-07 02:38:12 +08:00
|
|
|
{
|
|
|
|
GSList *actions = NULL;
|
|
|
|
GimpImageBaseType type;
|
|
|
|
GList *layers;
|
|
|
|
gint n_layers;
|
|
|
|
GList *iter;
|
|
|
|
GimpExportCapabilities capabilities = 0;
|
|
|
|
gboolean added_flatten = FALSE;
|
|
|
|
gboolean has_layer_masks = FALSE;
|
|
|
|
gboolean background_has_alpha = TRUE;
|
|
|
|
GimpExportReturn retval = GIMP_EXPORT_IGNORE;
|
1999-10-04 02:54:54 +08:00
|
|
|
|
app, libgimp*, pdb, plug-ins: review and enhance MR !1549.
- Fix annotations for gimp_export_options_get_image() to make it
actually introspectable with the GimpImage being both input and
output. Even though the logic doesn't change much (the input image may
be overriden or not), it doesn't matter for introspection because
images are handled centrally by libgimp and therefore must not be
freed. Actually deleting the image from the central list of images
though remains a manual action depending on code logic, not some
automatic action to be handled by binding engines.
- Add G_GNUC_WARN_UNUSED_RESULT to gimp_export_options_get_image()
because ignoring the returned value is rarely a good idea (as you
usually want to delete the image).
- Remove gimp_export_options_new(): we don't need this constructor
because at this point, the best is to tell plug-in developers to just
pass NULL everywhere. This leaves us free to create a more useful
default constructor if needed, in the future. Main description for
GimpExportOptions has also been updated to say this.
- Add a data_destroy callback for the user data passed in
gimp_export_procedure_set_capabilities().
- Fixing annotations of 'export_options' object from pdb/pdb.pl: input
args would actually be (nullable) and would not transfer ownership
(calling code must still free the object). Return value's ownership on
the other hand is fully transfered.
- Add C and Python unit testing for GimpExportOptions and
gimp_export_options_get_image() in particular.
- Fix or improve various details.
Note that I have also considered for a long time changing the signature
of gimp_export_options_get_image() to return a boolean indicating
whether `image` had been replaced (hence needed deletion) or not. This
also meant getting rid of the GimpExportReturn enum. Right now it would
work because there are no third case, but I was considering the future
possibility that for instance we got some impossible conversion for some
future capability. I'm not sure it would ever happen; and for sure, this
is not desirable because it implies an export failure a bit late in the
workflow. But just in case, let's keep the enum return value. It does
not even make the using code that much more complicated (well just a
value comparison instead of a simple boolean test).
2024-08-17 21:06:27 +08:00
|
|
|
g_return_val_if_fail (image && gimp_image_is_valid (*image), GIMP_EXPORT_IGNORE);
|
|
|
|
g_return_val_if_fail (GIMP_IS_EXPORT_OPTIONS (options), GIMP_EXPORT_IGNORE);
|
2024-05-07 02:38:12 +08:00
|
|
|
|
|
|
|
/* Get capabilities from ExportOptions */
|
|
|
|
g_object_get (options, "capabilities", &capabilities, NULL);
|
1999-10-04 02:54:54 +08:00
|
|
|
|
app, libgimp*, pdb, plug-ins: review and enhance MR !1549.
- Fix annotations for gimp_export_options_get_image() to make it
actually introspectable with the GimpImage being both input and
output. Even though the logic doesn't change much (the input image may
be overriden or not), it doesn't matter for introspection because
images are handled centrally by libgimp and therefore must not be
freed. Actually deleting the image from the central list of images
though remains a manual action depending on code logic, not some
automatic action to be handled by binding engines.
- Add G_GNUC_WARN_UNUSED_RESULT to gimp_export_options_get_image()
because ignoring the returned value is rarely a good idea (as you
usually want to delete the image).
- Remove gimp_export_options_new(): we don't need this constructor
because at this point, the best is to tell plug-in developers to just
pass NULL everywhere. This leaves us free to create a more useful
default constructor if needed, in the future. Main description for
GimpExportOptions has also been updated to say this.
- Add a data_destroy callback for the user data passed in
gimp_export_procedure_set_capabilities().
- Fixing annotations of 'export_options' object from pdb/pdb.pl: input
args would actually be (nullable) and would not transfer ownership
(calling code must still free the object). Return value's ownership on
the other hand is fully transfered.
- Add C and Python unit testing for GimpExportOptions and
gimp_export_options_get_image() in particular.
- Fix or improve various details.
Note that I have also considered for a long time changing the signature
of gimp_export_options_get_image() to return a boolean indicating
whether `image` had been replaced (hence needed deletion) or not. This
also meant getting rid of the GimpExportReturn enum. Right now it would
work because there are no third case, but I was considering the future
possibility that for instance we got some impossible conversion for some
future capability. I'm not sure it would ever happen; and for sure, this
is not desirable because it implies an export failure a bit late in the
workflow. But just in case, let's keep the enum return value. It does
not even make the using code that much more complicated (well just a
value comparison instead of a simple boolean test).
2024-08-17 21:06:27 +08:00
|
|
|
g_return_val_if_fail (capabilities & (GIMP_EXPORT_CAN_HANDLE_RGB |
|
|
|
|
GIMP_EXPORT_CAN_HANDLE_GRAY |
|
|
|
|
GIMP_EXPORT_CAN_HANDLE_INDEXED |
|
|
|
|
GIMP_EXPORT_CAN_HANDLE_BITMAP),
|
|
|
|
GIMP_EXPORT_IGNORE);
|
|
|
|
|
|
|
|
|
1999-10-09 08:11:50 +08:00
|
|
|
/* do some sanity checks */
|
2000-08-24 22:17:34 +08:00
|
|
|
if (capabilities & GIMP_EXPORT_NEEDS_ALPHA)
|
2003-11-08 01:13:45 +08:00
|
|
|
capabilities |= GIMP_EXPORT_CAN_HANDLE_ALPHA;
|
2003-11-16 00:51:20 +08:00
|
|
|
|
2000-08-24 22:17:34 +08:00
|
|
|
if (capabilities & GIMP_EXPORT_CAN_HANDLE_LAYERS_AS_ANIMATION)
|
|
|
|
capabilities |= GIMP_EXPORT_CAN_HANDLE_LAYERS;
|
1999-10-09 08:11:50 +08:00
|
|
|
|
2003-11-16 00:51:20 +08:00
|
|
|
if (capabilities & GIMP_EXPORT_CAN_HANDLE_LAYER_MASKS)
|
|
|
|
capabilities |= GIMP_EXPORT_CAN_HANDLE_LAYERS;
|
|
|
|
|
2023-06-19 22:54:21 +08:00
|
|
|
/* Merge down layer effects for non-project file formats */
|
|
|
|
if (! (capabilities & GIMP_EXPORT_CAN_HANDLE_LAYER_EFFECTS))
|
|
|
|
actions = g_slist_prepend (actions, &export_action_merge_layer_effects);
|
2003-11-16 00:51:20 +08:00
|
|
|
|
|
|
|
/* check alpha and layer masks */
|
2024-04-30 21:50:24 +08:00
|
|
|
layers = gimp_image_list_layers (*image);
|
|
|
|
n_layers = g_list_length (layers);
|
|
|
|
|
|
|
|
if (n_layers < 1)
|
|
|
|
{
|
|
|
|
g_list_free (layers);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2003-11-16 00:51:20 +08:00
|
|
|
|
2019-08-14 17:08:42 +08:00
|
|
|
for (iter = layers; iter; iter = iter->next)
|
1999-10-04 02:54:54 +08:00
|
|
|
{
|
2019-08-14 17:08:42 +08:00
|
|
|
GimpLayer *layer = GIMP_LAYER (iter->data);
|
2019-08-13 22:16:08 +08:00
|
|
|
|
|
|
|
if (gimp_drawable_has_alpha (GIMP_DRAWABLE (layer)))
|
2006-04-12 18:53:28 +08:00
|
|
|
{
|
|
|
|
if (! (capabilities & GIMP_EXPORT_CAN_HANDLE_ALPHA))
|
|
|
|
{
|
2019-06-28 19:20:44 +08:00
|
|
|
if (! (capabilities & GIMP_EXPORT_CAN_HANDLE_LAYERS))
|
|
|
|
{
|
|
|
|
actions = g_slist_prepend (actions, &export_action_flatten);
|
|
|
|
added_flatten = TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
actions = g_slist_prepend (actions, &export_action_remove_alpha);
|
|
|
|
break;
|
|
|
|
}
|
2006-04-12 18:53:28 +08:00
|
|
|
}
|
|
|
|
}
|
2003-11-06 23:27:05 +08:00
|
|
|
else
|
2006-04-12 18:53:28 +08:00
|
|
|
{
|
2003-11-16 00:51:20 +08:00
|
|
|
/* If this is the last layer, it's visible and has no alpha
|
|
|
|
* channel, then the image has a "flat" background
|
|
|
|
*/
|
2019-08-14 17:08:42 +08:00
|
|
|
if (iter->next == NULL && gimp_item_get_visible (GIMP_ITEM (layer)))
|
2006-04-12 18:53:28 +08:00
|
|
|
background_has_alpha = FALSE;
|
|
|
|
|
|
|
|
if (capabilities & GIMP_EXPORT_NEEDS_ALPHA)
|
|
|
|
{
|
|
|
|
actions = g_slist_prepend (actions, &export_action_add_alpha);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
1999-10-04 02:54:54 +08:00
|
|
|
}
|
|
|
|
|
2003-11-16 00:51:20 +08:00
|
|
|
if (! added_flatten)
|
2001-10-25 01:34:44 +08:00
|
|
|
{
|
2019-08-14 17:08:42 +08:00
|
|
|
for (iter = layers; iter; iter = iter->next)
|
2003-11-16 00:51:20 +08:00
|
|
|
{
|
2019-08-15 18:12:25 +08:00
|
|
|
if (gimp_layer_get_mask (iter->data))
|
2003-11-16 00:51:20 +08:00
|
|
|
has_layer_masks = TRUE;
|
|
|
|
}
|
2001-10-25 01:34:44 +08:00
|
|
|
}
|
2003-11-16 00:51:20 +08:00
|
|
|
|
|
|
|
if (! added_flatten)
|
1999-10-04 02:54:54 +08:00
|
|
|
{
|
2019-08-14 17:08:42 +08:00
|
|
|
GimpLayer *layer = GIMP_LAYER (layers->data);
|
|
|
|
GList *children;
|
2013-11-10 08:54:45 +08:00
|
|
|
|
2019-08-27 19:26:27 +08:00
|
|
|
children = gimp_item_list_children (GIMP_ITEM (layer));
|
2013-11-10 08:54:45 +08:00
|
|
|
|
2020-06-25 22:50:21 +08:00
|
|
|
if ((capabilities & GIMP_EXPORT_CAN_HANDLE_LAYERS) &&
|
|
|
|
(capabilities & GIMP_EXPORT_NEEDS_CROP))
|
|
|
|
{
|
|
|
|
GeglRectangle image_bounds;
|
|
|
|
gboolean needs_crop = FALSE;
|
|
|
|
|
|
|
|
image_bounds.x = 0;
|
|
|
|
image_bounds.y = 0;
|
2021-04-06 06:47:07 +08:00
|
|
|
image_bounds.width = gimp_image_get_width (*image);
|
|
|
|
image_bounds.height = gimp_image_get_height (*image);
|
2020-06-25 22:50:21 +08:00
|
|
|
|
|
|
|
for (iter = layers; iter; iter = iter->next)
|
|
|
|
{
|
|
|
|
GimpDrawable *drawable = iter->data;
|
|
|
|
GeglRectangle layer_bounds;
|
|
|
|
|
2021-04-06 20:28:40 +08:00
|
|
|
gimp_drawable_get_offsets (drawable,
|
2020-06-25 22:50:21 +08:00
|
|
|
&layer_bounds.x, &layer_bounds.y);
|
|
|
|
|
2021-04-06 20:28:40 +08:00
|
|
|
layer_bounds.width = gimp_drawable_get_width (drawable);
|
|
|
|
layer_bounds.height = gimp_drawable_get_height (drawable);
|
2020-06-25 22:50:21 +08:00
|
|
|
|
|
|
|
if (! gegl_rectangle_contains (&image_bounds, &layer_bounds))
|
|
|
|
{
|
|
|
|
needs_crop = TRUE;
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (needs_crop)
|
|
|
|
{
|
|
|
|
actions = g_slist_prepend (actions,
|
|
|
|
&export_action_crop_or_resize);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-11-16 00:51:20 +08:00
|
|
|
/* check if layer size != canvas size, opacity != 100%, or offsets != 0 */
|
2019-08-14 17:08:42 +08:00
|
|
|
if (g_list_length (layers) == 1 &&
|
2013-11-10 08:54:45 +08:00
|
|
|
! children &&
|
2003-11-16 00:51:20 +08:00
|
|
|
! (capabilities & GIMP_EXPORT_CAN_HANDLE_LAYERS))
|
|
|
|
{
|
2024-04-30 21:50:24 +08:00
|
|
|
GimpDrawable *drawable = layers->data;
|
2020-04-14 17:46:17 +08:00
|
|
|
gint offset_x;
|
|
|
|
gint offset_y;
|
2003-11-16 00:51:20 +08:00
|
|
|
|
2021-04-06 20:28:40 +08:00
|
|
|
gimp_drawable_get_offsets (drawable, &offset_x, &offset_y);
|
2003-11-16 00:51:20 +08:00
|
|
|
|
2020-04-14 17:46:17 +08:00
|
|
|
if ((gimp_layer_get_opacity (GIMP_LAYER (drawable)) < 100.0) ||
|
2021-04-06 06:47:07 +08:00
|
|
|
(gimp_image_get_width (*image) !=
|
2021-04-06 20:28:40 +08:00
|
|
|
gimp_drawable_get_width (drawable)) ||
|
2021-04-06 06:47:07 +08:00
|
|
|
(gimp_image_get_height (*image) !=
|
2021-04-06 20:28:40 +08:00
|
|
|
gimp_drawable_get_height (drawable)) ||
|
2003-11-16 00:51:20 +08:00
|
|
|
offset_x || offset_y)
|
|
|
|
{
|
|
|
|
if (capabilities & GIMP_EXPORT_CAN_HANDLE_ALPHA)
|
|
|
|
{
|
|
|
|
actions = g_slist_prepend (actions,
|
|
|
|
&export_action_merge_single);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
actions = g_slist_prepend (actions,
|
|
|
|
&export_action_flatten);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* check multiple layers */
|
2019-08-14 17:08:42 +08:00
|
|
|
else if (layers && layers->next != NULL)
|
2003-11-16 00:51:20 +08:00
|
|
|
{
|
|
|
|
if (capabilities & GIMP_EXPORT_CAN_HANDLE_LAYERS_AS_ANIMATION)
|
|
|
|
{
|
2006-03-09 19:12:55 +08:00
|
|
|
if (background_has_alpha ||
|
|
|
|
capabilities & GIMP_EXPORT_NEEDS_ALPHA)
|
2003-11-16 00:51:20 +08:00
|
|
|
actions = g_slist_prepend (actions,
|
|
|
|
&export_action_animate_or_merge);
|
|
|
|
else
|
|
|
|
actions = g_slist_prepend (actions,
|
|
|
|
&export_action_animate_or_flatten);
|
|
|
|
}
|
|
|
|
else if (! (capabilities & GIMP_EXPORT_CAN_HANDLE_LAYERS))
|
|
|
|
{
|
2006-03-09 19:12:55 +08:00
|
|
|
if (capabilities & GIMP_EXPORT_NEEDS_ALPHA)
|
2003-11-16 00:51:20 +08:00
|
|
|
actions = g_slist_prepend (actions,
|
|
|
|
&export_action_merge);
|
|
|
|
else
|
|
|
|
actions = g_slist_prepend (actions,
|
2006-03-09 19:12:55 +08:00
|
|
|
&export_action_merge_or_flatten);
|
2003-11-16 00:51:20 +08:00
|
|
|
}
|
|
|
|
}
|
2013-11-10 08:54:45 +08:00
|
|
|
/* check for a single toplevel layer group */
|
|
|
|
else if (children)
|
|
|
|
{
|
|
|
|
if (! (capabilities & GIMP_EXPORT_CAN_HANDLE_LAYERS))
|
|
|
|
{
|
|
|
|
if (capabilities & GIMP_EXPORT_NEEDS_ALPHA)
|
|
|
|
actions = g_slist_prepend (actions,
|
|
|
|
&export_action_merge);
|
|
|
|
else
|
|
|
|
actions = g_slist_prepend (actions,
|
|
|
|
&export_action_merge_or_flatten);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-15 18:12:25 +08:00
|
|
|
g_list_free (children);
|
2003-11-16 00:51:20 +08:00
|
|
|
|
|
|
|
/* check layer masks */
|
|
|
|
if (has_layer_masks &&
|
|
|
|
! (capabilities & GIMP_EXPORT_CAN_HANDLE_LAYER_MASKS))
|
|
|
|
actions = g_slist_prepend (actions, &export_action_apply_masks);
|
1999-10-04 02:54:54 +08:00
|
|
|
}
|
|
|
|
|
2019-08-15 18:12:25 +08:00
|
|
|
g_list_free (layers);
|
2013-11-10 08:54:45 +08:00
|
|
|
|
2003-11-06 23:27:05 +08:00
|
|
|
/* check the image type */
|
2021-04-06 06:47:07 +08:00
|
|
|
type = gimp_image_get_base_type (*image);
|
1999-10-04 02:54:54 +08:00
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
case GIMP_RGB:
|
2003-11-16 00:51:20 +08:00
|
|
|
if (! (capabilities & GIMP_EXPORT_CAN_HANDLE_RGB))
|
2006-04-12 18:53:28 +08:00
|
|
|
{
|
|
|
|
if ((capabilities & GIMP_EXPORT_CAN_HANDLE_INDEXED) &&
|
2002-09-17 20:40:13 +08:00
|
|
|
(capabilities & GIMP_EXPORT_CAN_HANDLE_GRAY))
|
2006-04-12 18:53:28 +08:00
|
|
|
actions = g_slist_prepend (actions,
|
2002-09-17 20:40:13 +08:00
|
|
|
&export_action_convert_indexed_or_grayscale);
|
2006-04-12 18:53:28 +08:00
|
|
|
else if (capabilities & GIMP_EXPORT_CAN_HANDLE_INDEXED)
|
|
|
|
actions = g_slist_prepend (actions,
|
2002-09-17 20:40:13 +08:00
|
|
|
&export_action_convert_indexed);
|
2006-04-12 18:53:28 +08:00
|
|
|
else if (capabilities & GIMP_EXPORT_CAN_HANDLE_GRAY)
|
|
|
|
actions = g_slist_prepend (actions,
|
2002-09-17 20:40:13 +08:00
|
|
|
&export_action_convert_grayscale);
|
2006-04-12 18:53:28 +08:00
|
|
|
else if (capabilities & GIMP_EXPORT_CAN_HANDLE_BITMAP)
|
|
|
|
actions = g_slist_prepend (actions,
|
2003-11-16 00:51:20 +08:00
|
|
|
&export_action_convert_bitmap);
|
2006-04-12 18:53:28 +08:00
|
|
|
}
|
1999-10-04 02:54:54 +08:00
|
|
|
break;
|
2003-11-16 00:51:20 +08:00
|
|
|
|
1999-10-04 02:54:54 +08:00
|
|
|
case GIMP_GRAY:
|
2003-11-16 00:51:20 +08:00
|
|
|
if (! (capabilities & GIMP_EXPORT_CAN_HANDLE_GRAY))
|
2006-04-12 18:53:28 +08:00
|
|
|
{
|
|
|
|
if ((capabilities & GIMP_EXPORT_CAN_HANDLE_RGB) &&
|
2002-09-17 20:40:13 +08:00
|
|
|
(capabilities & GIMP_EXPORT_CAN_HANDLE_INDEXED))
|
2006-04-12 18:53:28 +08:00
|
|
|
actions = g_slist_prepend (actions,
|
2002-09-17 20:40:13 +08:00
|
|
|
&export_action_convert_rgb_or_indexed);
|
2006-04-12 18:53:28 +08:00
|
|
|
else if (capabilities & GIMP_EXPORT_CAN_HANDLE_RGB)
|
|
|
|
actions = g_slist_prepend (actions,
|
2002-09-17 20:40:13 +08:00
|
|
|
&export_action_convert_rgb);
|
2006-04-12 18:53:28 +08:00
|
|
|
else if (capabilities & GIMP_EXPORT_CAN_HANDLE_INDEXED)
|
|
|
|
actions = g_slist_prepend (actions,
|
2002-09-17 20:40:13 +08:00
|
|
|
&export_action_convert_indexed);
|
2006-04-12 18:53:28 +08:00
|
|
|
else if (capabilities & GIMP_EXPORT_CAN_HANDLE_BITMAP)
|
|
|
|
actions = g_slist_prepend (actions,
|
2003-11-16 00:51:20 +08:00
|
|
|
&export_action_convert_bitmap);
|
2006-04-12 18:53:28 +08:00
|
|
|
}
|
1999-10-04 02:54:54 +08:00
|
|
|
break;
|
2003-11-16 00:51:20 +08:00
|
|
|
|
1999-10-04 02:54:54 +08:00
|
|
|
case GIMP_INDEXED:
|
2003-11-16 00:51:20 +08:00
|
|
|
if (! (capabilities & GIMP_EXPORT_CAN_HANDLE_INDEXED))
|
|
|
|
{
|
|
|
|
if ((capabilities & GIMP_EXPORT_CAN_HANDLE_RGB) &&
|
2002-09-17 20:40:13 +08:00
|
|
|
(capabilities & GIMP_EXPORT_CAN_HANDLE_GRAY))
|
2003-11-16 00:51:20 +08:00
|
|
|
actions = g_slist_prepend (actions,
|
2002-09-17 20:40:13 +08:00
|
|
|
&export_action_convert_rgb_or_grayscale);
|
2003-11-16 00:51:20 +08:00
|
|
|
else if (capabilities & GIMP_EXPORT_CAN_HANDLE_RGB)
|
|
|
|
actions = g_slist_prepend (actions,
|
2002-09-17 20:40:13 +08:00
|
|
|
&export_action_convert_rgb);
|
2003-11-16 00:51:20 +08:00
|
|
|
else if (capabilities & GIMP_EXPORT_CAN_HANDLE_GRAY)
|
|
|
|
actions = g_slist_prepend (actions,
|
2002-09-17 20:40:13 +08:00
|
|
|
&export_action_convert_grayscale);
|
2006-04-12 18:53:28 +08:00
|
|
|
else if (capabilities & GIMP_EXPORT_CAN_HANDLE_BITMAP)
|
2003-11-16 00:51:20 +08:00
|
|
|
{
|
|
|
|
gint n_colors;
|
|
|
|
|
2023-05-24 05:37:46 +08:00
|
|
|
g_free (gimp_image_get_colormap (*image, NULL, &n_colors));
|
2003-11-16 00:51:20 +08:00
|
|
|
|
|
|
|
if (n_colors > 2)
|
|
|
|
actions = g_slist_prepend (actions,
|
|
|
|
&export_action_convert_bitmap);
|
|
|
|
}
|
|
|
|
}
|
1999-10-04 02:54:54 +08:00
|
|
|
break;
|
|
|
|
}
|
2003-11-06 23:27:05 +08:00
|
|
|
|
1999-10-04 02:54:54 +08:00
|
|
|
if (actions)
|
1999-10-22 03:35:35 +08:00
|
|
|
{
|
|
|
|
actions = g_slist_reverse (actions);
|
2006-06-27 14:41:38 +08:00
|
|
|
|
libgimp: clean out the "interactive" intermediate dialog which was hidden…
… since forever anyway!
GIMP used to have a second export dialog, a generically generated one, appearing
either before or after (depending on when gimp_export_image() was called) the
custom export dialog implemented by the plug-in code. This has been hidden deep
in code since forever (since version 2.8.0 in fact, I believe) and only kept
hidden behind an environment variable "GIMP_INTERACTIVE_EXPORT". I don't think
we'll ever revive this, so let's clean up.
In fact, not one, but in worst case even 2 more dialogs were hidden behind this
variable! The first dialog (confirm_save_dialog()) was a confirmation when the
selected drawable was a layer mask or a channel (and not a layer). Most export
code don't even seem to care about the selected drawables anymore anyway (cf.
issue #7370), except with gimp_file_save() non-interactively (issue #8855),
which is a real mess of inconsistency anyway.
The second dialog (export_dialog()) was listing the various actions to do on a
copy of the image to help the plug-in (e.g. merge layers/flatten image, etc.)
and possibly give choices to some of these actions. Though there is definitely
no reason to request this kind of thing anymore, especially for a short-lasting
image copy, the list of action could still be interesting in the future, not as
information of what is going to be done, but as information of the kind of data
loss of the exported format. I could imagine we want to be able to reuse such
information for generating types of data loss per format in the export dialog,
in particular in the context of my long-term export workflow refactoring (from
which resizing before export such as #2531 are part of, but the whole
refactoring project is much wider).
In the whole discussion of #5858, there will be the question on whether we don't
want plug-ins to be directly given a "ready-to-use" image depending on
capabilities they advertized in create_procedure().
2024-04-21 06:16:27 +08:00
|
|
|
retval = GIMP_EXPORT_EXPORT;
|
1999-10-22 03:35:35 +08:00
|
|
|
}
|
1999-10-04 14:36:38 +08:00
|
|
|
else
|
2003-11-06 23:27:05 +08:00
|
|
|
{
|
|
|
|
retval = GIMP_EXPORT_IGNORE;
|
|
|
|
}
|
1999-10-04 02:54:54 +08:00
|
|
|
|
2003-11-06 23:27:05 +08:00
|
|
|
if (retval == GIMP_EXPORT_EXPORT)
|
1999-10-04 02:54:54 +08:00
|
|
|
{
|
2008-11-25 16:20:56 +08:00
|
|
|
GSList *list;
|
2020-04-14 17:46:17 +08:00
|
|
|
GList *drawables_in;
|
|
|
|
GList *drawables_out;
|
2008-11-25 16:20:56 +08:00
|
|
|
|
2019-08-11 23:12:20 +08:00
|
|
|
*image = gimp_image_duplicate (*image);
|
2020-04-14 17:46:17 +08:00
|
|
|
drawables_in = gimp_image_list_selected_layers (*image);
|
|
|
|
drawables_out = drawables_in;
|
2003-11-06 23:27:05 +08:00
|
|
|
|
2019-08-11 23:12:20 +08:00
|
|
|
gimp_image_undo_disable (*image);
|
2003-11-06 23:27:05 +08:00
|
|
|
|
1999-10-04 02:54:54 +08:00
|
|
|
for (list = actions; list; list = list->next)
|
2006-04-12 18:53:28 +08:00
|
|
|
{
|
2020-04-14 17:46:17 +08:00
|
|
|
export_action_perform (list->data, *image, &drawables_out);
|
|
|
|
|
|
|
|
if (drawables_in != drawables_out)
|
|
|
|
{
|
|
|
|
g_list_free (drawables_in);
|
|
|
|
drawables_in = drawables_out;
|
|
|
|
}
|
2006-04-12 18:53:28 +08:00
|
|
|
}
|
2020-04-14 17:46:17 +08:00
|
|
|
|
|
|
|
g_list_free (drawables_out);
|
1999-10-04 02:54:54 +08:00
|
|
|
}
|
2003-11-06 23:27:05 +08:00
|
|
|
|
1999-10-24 21:26:30 +08:00
|
|
|
g_slist_free (actions);
|
1999-10-04 02:54:54 +08:00
|
|
|
|
2003-11-06 23:27:05 +08:00
|
|
|
return retval;
|
1999-10-04 02:54:54 +08:00
|
|
|
}
|