Issue #12614: Successive layer effects should use a higher bit-depth as intermediary format.

While it's normal to be limited to the storage precision at drawable
level, we want to have as high precision as possible during processing.

Two pieces of code were problematic in this regard:

1. GimpApplicator had a "gegl:convert-format" node which was converting
   back to storage format after every effect. Instead only set this node
   after the last effect.
2. "gimp:mask-components" operation was working with the input format.
   Let's change this to work with the higher precision when comparing
   input and aux format (typically when aux was the output of a previous
   filter, now that we didn't convert format back to storage precision,
   the aux precision may be bigger).
This commit is contained in:
Jehan 2025-01-12 21:43:34 +01:00
parent bd4530e580
commit 2c066afff9
2 changed files with 41 additions and 12 deletions

View File

@ -51,6 +51,7 @@
#include "gimpidtable.h"
#include "gimpimage.h"
#include "gimplayer.h"
#include "gimplist.h"
#include "gimpprogress.h"
@ -1522,17 +1523,37 @@ gimp_drawable_filter_sync_affect (GimpDrawableFilter *filter)
static void
gimp_drawable_filter_sync_format (GimpDrawableFilter *filter)
{
const Babl *format;
const Babl *format = NULL;
GimpContainer *filters;
if (filter->add_alpha &&
(gimp_drawable_supports_alpha (filter->drawable) ||
filter->override_constraints))
filters = gimp_drawable_get_filters (filter->drawable);
g_return_if_fail (GIMP_LIST (filters)->queue->head != NULL);
if (filter == GIMP_LIST (filters)->queue->head->data)
{
format = gimp_drawable_get_format_with_alpha (filter->drawable);
}
else
{
format = gimp_drawable_get_format (filter->drawable);
/* We only want to convert back to the source format at the very
* end, and keep an as-high-bit-depth as possible format during
* multi-filter processing.
*/
GimpDrawableFilter *next_filter = NULL;
if (GIMP_LIST (filters)->queue->head->next)
next_filter = GIMP_LIST (filters)->queue->head->next->data;
if (filter->add_alpha &&
(gimp_drawable_supports_alpha (filter->drawable) ||
filter->override_constraints))
{
format = gimp_drawable_get_format_with_alpha (filter->drawable);
}
else
{
format = gimp_drawable_get_format (filter->drawable);
}
if (next_filter)
gimp_drawable_filter_sync_format (next_filter);
}
gimp_applicator_set_output_format (filter->applicator, format);
@ -1625,10 +1646,10 @@ gimp_drawable_filter_add_filter (GimpDrawableFilter *filter)
gimp_drawable_filter_sync_opacity (filter);
gimp_drawable_filter_sync_mode (filter);
gimp_drawable_filter_sync_affect (filter);
gimp_drawable_filter_sync_format (filter);
gimp_drawable_add_filter (filter->drawable,
GIMP_FILTER (filter));
gimp_drawable_filter_sync_format (filter);
gimp_drawable_update_bounding_box (filter->drawable);

View File

@ -370,9 +370,17 @@ gimp_operation_mask_components_prepare (GeglOperation *operation)
{
GimpOperationMaskComponents *self = GIMP_OPERATION_MASK_COMPONENTS (operation);
const Babl *format;
const Babl *aux_format;
format = gimp_operation_mask_components_get_format (
gegl_operation_get_source_format (operation, "input"));
format = gimp_operation_mask_components_get_format (gegl_operation_get_source_format (operation, "input"));
aux_format = gimp_operation_mask_components_get_format (gegl_operation_get_source_format (operation, "aux"));
if (babl_format_get_bytes_per_pixel (aux_format) / babl_format_get_n_components (aux_format) >
babl_format_get_bytes_per_pixel (format) / babl_format_get_n_components (format))
/* Use the higher bit-depth format as possible for processing and
* output.
*/
format = aux_format;
gegl_operation_set_format (operation, "input", format);
gegl_operation_set_format (operation, "aux", format);