mirror of https://github.com/GNOME/gimp.git
app: apply display filters in sRGB, not monitor profile
When we have display filters, break the color profile transform in two: first, convert from the image profile to sRGB, then apply the filters, then convert from sRGB to the monitor profile.
This commit is contained in:
parent
22a28a23cc
commit
9cd8e7f9c6
|
@ -87,6 +87,8 @@ gimp_display_shell_profile_update (GimpDisplayShell *shell)
|
||||||
GimpImage *image;
|
GimpImage *image;
|
||||||
GimpColorProfile *src_profile;
|
GimpColorProfile *src_profile;
|
||||||
const Babl *src_format;
|
const Babl *src_format;
|
||||||
|
GimpColorProfile *filter_profile;
|
||||||
|
const Babl *filter_format;
|
||||||
const Babl *dest_format;
|
const Babl *dest_format;
|
||||||
|
|
||||||
gimp_display_shell_profile_free (shell);
|
gimp_display_shell_profile_free (shell);
|
||||||
|
@ -103,8 +105,18 @@ gimp_display_shell_profile_update (GimpDisplayShell *shell)
|
||||||
|
|
||||||
src_format = gimp_projectable_get_format (GIMP_PROJECTABLE (image));
|
src_format = gimp_projectable_get_format (GIMP_PROJECTABLE (image));
|
||||||
|
|
||||||
if (gimp_display_shell_has_filter (shell) ||
|
if (gimp_display_shell_has_filter (shell))
|
||||||
! gimp_display_shell_profile_can_convert_to_u8 (shell))
|
{
|
||||||
|
filter_format = shell->filter_format;
|
||||||
|
filter_profile = gimp_babl_format_get_color_profile (filter_format);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
filter_format = src_format;
|
||||||
|
filter_profile = src_profile;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! gimp_display_shell_profile_can_convert_to_u8 (shell))
|
||||||
{
|
{
|
||||||
dest_format = shell->filter_format;
|
dest_format = shell->filter_format;
|
||||||
}
|
}
|
||||||
|
@ -114,22 +126,38 @@ gimp_display_shell_profile_update (GimpDisplayShell *shell)
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
g_printerr ("src_profile: %s\n"
|
g_printerr ("src_profile: %s\n"
|
||||||
"src_format: %s\n"
|
"src_format: %s\n"
|
||||||
"dest_format: %s\n",
|
"filter_profile: %s\n"
|
||||||
|
"filter_format: %s\n"
|
||||||
|
"dest_format: %s\n",
|
||||||
gimp_color_profile_get_label (src_profile),
|
gimp_color_profile_get_label (src_profile),
|
||||||
babl_get_name (src_format),
|
babl_get_name (src_format),
|
||||||
|
gimp_color_profile_get_label (filter_profile),
|
||||||
|
babl_get_name (filter_format),
|
||||||
babl_get_name (dest_format));
|
babl_get_name (dest_format));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (! gimp_color_transform_can_gegl_copy (src_profile, filter_profile))
|
||||||
|
{
|
||||||
|
shell->filter_transform =
|
||||||
|
gimp_color_transform_new (src_profile,
|
||||||
|
src_format,
|
||||||
|
filter_profile,
|
||||||
|
filter_format,
|
||||||
|
GIMP_COLOR_RENDERING_INTENT_RELATIVE_COLORIMETRIC,
|
||||||
|
GIMP_COLOR_TRANSFORM_FLAGS_BLACK_POINT_COMPENSATION |
|
||||||
|
GIMP_COLOR_TRANSFORM_FLAGS_NOOPTIMIZE);
|
||||||
|
}
|
||||||
|
|
||||||
shell->profile_transform =
|
shell->profile_transform =
|
||||||
gimp_widget_get_color_transform (gtk_widget_get_toplevel (GTK_WIDGET (shell)),
|
gimp_widget_get_color_transform (gtk_widget_get_toplevel (GTK_WIDGET (shell)),
|
||||||
gimp_display_shell_get_color_config (shell),
|
gimp_display_shell_get_color_config (shell),
|
||||||
src_profile,
|
filter_profile,
|
||||||
src_format,
|
filter_format,
|
||||||
dest_format);
|
dest_format);
|
||||||
|
|
||||||
if (shell->profile_transform)
|
if (shell->filter_transform || shell->profile_transform)
|
||||||
{
|
{
|
||||||
gint w = GIMP_DISPLAY_RENDER_BUF_WIDTH * GIMP_DISPLAY_RENDER_MAX_SCALE;
|
gint w = GIMP_DISPLAY_RENDER_BUF_WIDTH * GIMP_DISPLAY_RENDER_MAX_SCALE;
|
||||||
gint h = GIMP_DISPLAY_RENDER_BUF_HEIGHT * GIMP_DISPLAY_RENDER_MAX_SCALE;
|
gint h = GIMP_DISPLAY_RENDER_BUF_HEIGHT * GIMP_DISPLAY_RENDER_MAX_SCALE;
|
||||||
|
@ -157,7 +185,14 @@ gimp_display_shell_profile_can_convert_to_u8 (GimpDisplayShell *shell)
|
||||||
|
|
||||||
if (image)
|
if (image)
|
||||||
{
|
{
|
||||||
switch (gimp_image_get_component_type (image))
|
GimpComponentType component_type;
|
||||||
|
|
||||||
|
if (! gimp_display_shell_has_filter (shell))
|
||||||
|
component_type = gimp_image_get_component_type (image);
|
||||||
|
else
|
||||||
|
component_type = gimp_babl_format_get_component_type (shell->filter_format);
|
||||||
|
|
||||||
|
switch (component_type)
|
||||||
{
|
{
|
||||||
case GIMP_COMPONENT_TYPE_U8:
|
case GIMP_COMPONENT_TYPE_U8:
|
||||||
#if 0
|
#if 0
|
||||||
|
@ -184,6 +219,7 @@ static void
|
||||||
gimp_display_shell_profile_free (GimpDisplayShell *shell)
|
gimp_display_shell_profile_free (GimpDisplayShell *shell)
|
||||||
{
|
{
|
||||||
g_clear_object (&shell->profile_transform);
|
g_clear_object (&shell->profile_transform);
|
||||||
|
g_clear_object (&shell->filter_transform);
|
||||||
g_clear_object (&shell->profile_buffer);
|
g_clear_object (&shell->profile_buffer);
|
||||||
shell->profile_data = NULL;
|
shell->profile_data = NULL;
|
||||||
shell->profile_stride = 0;
|
shell->profile_stride = 0;
|
||||||
|
|
|
@ -171,7 +171,8 @@ gimp_display_shell_render (GimpDisplayShell *shell,
|
||||||
|
|
||||||
can_convert_to_u8 = gimp_display_shell_profile_can_convert_to_u8 (shell);
|
can_convert_to_u8 = gimp_display_shell_profile_can_convert_to_u8 (shell);
|
||||||
|
|
||||||
/* create the filter buffer if we have filters
|
/* create the filter buffer if we have filters, or can't convert
|
||||||
|
* to u8 directly
|
||||||
*/
|
*/
|
||||||
if ((gimp_display_shell_has_filter (shell) || ! can_convert_to_u8) &&
|
if ((gimp_display_shell_has_filter (shell) || ! can_convert_to_u8) &&
|
||||||
! shell->filter_buffer)
|
! shell->filter_buffer)
|
||||||
|
@ -194,10 +195,10 @@ gimp_display_shell_render (GimpDisplayShell *shell,
|
||||||
shell->filter_data);
|
shell->filter_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shell->profile_transform)
|
if (! gimp_display_shell_has_filter (shell) || shell->filter_transform)
|
||||||
{
|
{
|
||||||
/* if there is a profile transform, load the projection
|
/* if there are no filters, or there is a filter transform,
|
||||||
* pixels into the profile_buffer
|
* load the projection pixels into the profile_buffer
|
||||||
*/
|
*/
|
||||||
#ifndef USE_NODE_BLIT
|
#ifndef USE_NODE_BLIT
|
||||||
gegl_buffer_get (buffer,
|
gegl_buffer_get (buffer,
|
||||||
|
@ -216,11 +217,96 @@ gimp_display_shell_render (GimpDisplayShell *shell,
|
||||||
shell->profile_data, shell->profile_stride,
|
shell->profile_data, shell->profile_stride,
|
||||||
GEGL_BLIT_CACHE);
|
GEGL_BLIT_CACHE);
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* otherwise, load the pixels directly into the filter_buffer
|
||||||
|
*/
|
||||||
|
#ifndef USE_NODE_BLIT
|
||||||
|
gegl_buffer_get (buffer,
|
||||||
|
GEGL_RECTANGLE (scaled_x, scaled_y,
|
||||||
|
scaled_width, scaled_height),
|
||||||
|
buffer_scale,
|
||||||
|
shell->filter_format,
|
||||||
|
shell->filter_data, shell->filter_stride,
|
||||||
|
GEGL_ABYSS_CLAMP);
|
||||||
|
#else
|
||||||
|
gegl_node_blit (node,
|
||||||
|
buffer_scale,
|
||||||
|
GEGL_RECTANGLE (scaled_x, scaled_y,
|
||||||
|
scaled_width, scaled_height),
|
||||||
|
shell->filter_format,
|
||||||
|
shell->filter_data, shell->filter_stride,
|
||||||
|
GEGL_BLIT_CACHE);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
if (gimp_display_shell_has_filter (shell) || ! can_convert_to_u8)
|
/* if there is a filter transform, convert the pixels from
|
||||||
|
* the profile_buffer to the filter_buffer
|
||||||
|
*/
|
||||||
|
if (shell->filter_transform)
|
||||||
|
{
|
||||||
|
gimp_color_transform_process_buffer (shell->filter_transform,
|
||||||
|
shell->profile_buffer,
|
||||||
|
GEGL_RECTANGLE (0, 0,
|
||||||
|
scaled_width,
|
||||||
|
scaled_height),
|
||||||
|
shell->filter_buffer,
|
||||||
|
GEGL_RECTANGLE (0, 0,
|
||||||
|
scaled_width,
|
||||||
|
scaled_height));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if there are filters, apply them
|
||||||
|
*/
|
||||||
|
if (gimp_display_shell_has_filter (shell))
|
||||||
|
{
|
||||||
|
GeglBuffer *filter_buffer;
|
||||||
|
|
||||||
|
/* shift the filter_buffer so that the area passed to
|
||||||
|
* the filters is the real render area, allowing for
|
||||||
|
* position-dependent filters
|
||||||
|
*/
|
||||||
|
filter_buffer = g_object_new (GEGL_TYPE_BUFFER,
|
||||||
|
"source", shell->filter_buffer,
|
||||||
|
"shift-x", -scaled_x,
|
||||||
|
"shift-y", -scaled_y,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
/* convert the filter_buffer in place
|
||||||
|
*/
|
||||||
|
gimp_color_display_stack_convert_buffer (shell->filter_stack,
|
||||||
|
filter_buffer,
|
||||||
|
GEGL_RECTANGLE (scaled_x, scaled_y,
|
||||||
|
scaled_width,
|
||||||
|
scaled_height));
|
||||||
|
|
||||||
|
g_object_unref (filter_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if there is a profile transform...
|
||||||
|
*/
|
||||||
|
if (shell->profile_transform)
|
||||||
|
{
|
||||||
|
if (gimp_display_shell_has_filter (shell))
|
||||||
{
|
{
|
||||||
/* if there are filters, convert the pixels from the
|
/* if we have filters, convert the pixels in the filter_buffer
|
||||||
* profile_buffer to the filter_buffer
|
* in-place
|
||||||
|
*/
|
||||||
|
gimp_color_transform_process_buffer (shell->profile_transform,
|
||||||
|
shell->filter_buffer,
|
||||||
|
GEGL_RECTANGLE (0, 0,
|
||||||
|
scaled_width,
|
||||||
|
scaled_height),
|
||||||
|
shell->filter_buffer,
|
||||||
|
GEGL_RECTANGLE (0, 0,
|
||||||
|
scaled_width,
|
||||||
|
scaled_height));
|
||||||
|
}
|
||||||
|
else if (! can_convert_to_u8)
|
||||||
|
{
|
||||||
|
/* otherwise, if we can't convert to u8 directly, convert
|
||||||
|
* the pixels from the profile_buffer to the filter_buffer
|
||||||
*/
|
*/
|
||||||
gimp_color_transform_process_buffer (shell->profile_transform,
|
gimp_color_transform_process_buffer (shell->profile_transform,
|
||||||
shell->profile_buffer,
|
shell->profile_buffer,
|
||||||
|
@ -248,55 +334,12 @@ gimp_display_shell_render (GimpDisplayShell *shell,
|
||||||
scaled_height));
|
scaled_height));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
/* otherwise, load the projection pixels directly into the
|
|
||||||
* filter_buffer
|
|
||||||
*/
|
|
||||||
#ifndef USE_NODE_BLIT
|
|
||||||
gegl_buffer_get (buffer,
|
|
||||||
GEGL_RECTANGLE (scaled_x, scaled_y,
|
|
||||||
scaled_width, scaled_height),
|
|
||||||
buffer_scale,
|
|
||||||
shell->filter_format,
|
|
||||||
shell->filter_data, shell->filter_stride,
|
|
||||||
GEGL_ABYSS_CLAMP);
|
|
||||||
#else
|
|
||||||
gegl_node_blit (node,
|
|
||||||
buffer_scale,
|
|
||||||
GEGL_RECTANGLE (scaled_x, scaled_y,
|
|
||||||
scaled_width, scaled_height),
|
|
||||||
shell->filter_format,
|
|
||||||
shell->filter_data, shell->filter_stride,
|
|
||||||
GEGL_BLIT_CACHE);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gimp_display_shell_has_filter (shell))
|
|
||||||
{
|
|
||||||
GeglBuffer *filter_buffer;
|
|
||||||
|
|
||||||
filter_buffer = g_object_new (GEGL_TYPE_BUFFER,
|
|
||||||
"source", shell->filter_buffer,
|
|
||||||
"shift-x", -scaled_x,
|
|
||||||
"shift-y", -scaled_y,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
/* convert the filter_buffer in place
|
|
||||||
*/
|
|
||||||
gimp_color_display_stack_convert_buffer (shell->filter_stack,
|
|
||||||
filter_buffer,
|
|
||||||
GEGL_RECTANGLE (scaled_x, scaled_y,
|
|
||||||
scaled_width,
|
|
||||||
scaled_height));
|
|
||||||
|
|
||||||
g_object_unref (filter_buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/* finally, copy the filter buffer to the cairo-ARGB32 buffer,
|
||||||
|
* if necessary
|
||||||
|
*/
|
||||||
if (gimp_display_shell_has_filter (shell) || ! can_convert_to_u8)
|
if (gimp_display_shell_has_filter (shell) || ! can_convert_to_u8)
|
||||||
{
|
{
|
||||||
/* finally, copy the filter buffer to the cairo-ARGB32 buffer
|
|
||||||
*/
|
|
||||||
gegl_buffer_get (shell->filter_buffer,
|
gegl_buffer_get (shell->filter_buffer,
|
||||||
GEGL_RECTANGLE (0, 0,
|
GEGL_RECTANGLE (0, 0,
|
||||||
scaled_width,
|
scaled_width,
|
||||||
|
|
|
@ -157,13 +157,14 @@ struct _GimpDisplayShell
|
||||||
guchar *profile_data; /* profile_buffer's pixels */
|
guchar *profile_data; /* profile_buffer's pixels */
|
||||||
gint profile_stride; /* profile_buffer's stride */
|
gint profile_stride; /* profile_buffer's stride */
|
||||||
|
|
||||||
GimpColorDisplayStack *filter_stack; /* color display conversion stuff */
|
GimpColorDisplayStack *filter_stack; /* color display conversion stuff */
|
||||||
guint filter_idle_id;
|
guint filter_idle_id;
|
||||||
|
|
||||||
const Babl *filter_format; /* filter_buffer's format */
|
GimpColorTransform *filter_transform;
|
||||||
GeglBuffer *filter_buffer; /* buffer for display filters */
|
const Babl *filter_format; /* filter_buffer's format */
|
||||||
guchar *filter_data; /* filter_buffer's pixels */
|
GeglBuffer *filter_buffer; /* buffer for display filters */
|
||||||
gint filter_stride; /* filter_buffer's stride */
|
guchar *filter_data; /* filter_buffer's pixels */
|
||||||
|
gint filter_stride; /* filter_buffer's stride */
|
||||||
|
|
||||||
GimpDisplayXfer *xfer; /* manages image buffer transfers */
|
GimpDisplayXfer *xfer; /* manages image buffer transfers */
|
||||||
cairo_surface_t *mask_surface; /* buffer for rendering the mask */
|
cairo_surface_t *mask_surface; /* buffer for rendering the mask */
|
||||||
|
|
Loading…
Reference in New Issue