Skip to content

Commit

Permalink
app: apply display filters in sRGB, not monitor profile
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
ell-gh committed Nov 3, 2017
1 parent 22a28a2 commit 9cd8e7f
Show file tree
Hide file tree
Showing 3 changed files with 133 additions and 53 deletions.
54 changes: 45 additions & 9 deletions app/display/gimpdisplayshell-profile.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ gimp_display_shell_profile_update (GimpDisplayShell *shell)
GimpImage *image;
GimpColorProfile *src_profile;
const Babl *src_format;
GimpColorProfile *filter_profile;
const Babl *filter_format;
const Babl *dest_format;

gimp_display_shell_profile_free (shell);
Expand All @@ -103,8 +105,18 @@ gimp_display_shell_profile_update (GimpDisplayShell *shell)

src_format = gimp_projectable_get_format (GIMP_PROJECTABLE (image));

if (gimp_display_shell_has_filter (shell) ||
! gimp_display_shell_profile_can_convert_to_u8 (shell))
if (gimp_display_shell_has_filter (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;
}
Expand All @@ -114,22 +126,38 @@ gimp_display_shell_profile_update (GimpDisplayShell *shell)
}

#if 0
g_printerr ("src_profile: %s\n"
"src_format: %s\n"
"dest_format: %s\n",
g_printerr ("src_profile: %s\n"
"src_format: %s\n"
"filter_profile: %s\n"
"filter_format: %s\n"
"dest_format: %s\n",
gimp_color_profile_get_label (src_profile),
babl_get_name (src_format),
gimp_color_profile_get_label (filter_profile),
babl_get_name (filter_format),
babl_get_name (dest_format));
#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 =
gimp_widget_get_color_transform (gtk_widget_get_toplevel (GTK_WIDGET (shell)),
gimp_display_shell_get_color_config (shell),
src_profile,
src_format,
filter_profile,
filter_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 h = GIMP_DISPLAY_RENDER_BUF_HEIGHT * GIMP_DISPLAY_RENDER_MAX_SCALE;
Expand Down Expand Up @@ -157,7 +185,14 @@ gimp_display_shell_profile_can_convert_to_u8 (GimpDisplayShell *shell)

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:
#if 0
Expand All @@ -184,6 +219,7 @@ static void
gimp_display_shell_profile_free (GimpDisplayShell *shell)
{
g_clear_object (&shell->profile_transform);
g_clear_object (&shell->filter_transform);
g_clear_object (&shell->profile_buffer);
shell->profile_data = NULL;
shell->profile_stride = 0;
Expand Down
121 changes: 82 additions & 39 deletions app/display/gimpdisplayshell-render.c
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,8 @@ gimp_display_shell_render (GimpDisplayShell *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) &&
! shell->filter_buffer)
Expand All @@ -194,10 +195,10 @@ gimp_display_shell_render (GimpDisplayShell *shell,
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
* pixels into the profile_buffer
/* if there are no filters, or there is a filter transform,
* load the projection pixels into the profile_buffer
*/
#ifndef USE_NODE_BLIT
gegl_buffer_get (buffer,
Expand All @@ -216,42 +217,10 @@ gimp_display_shell_render (GimpDisplayShell *shell,
shell->profile_data, shell->profile_stride,
GEGL_BLIT_CACHE);
#endif

if (gimp_display_shell_has_filter (shell) || ! can_convert_to_u8)
{
/* if there are filters, convert the pixels from the
* profile_buffer to the filter_buffer
*/
gimp_color_transform_process_buffer (shell->profile_transform,
shell->profile_buffer,
GEGL_RECTANGLE (0, 0,
scaled_width,
scaled_height),
shell->filter_buffer,
GEGL_RECTANGLE (0, 0,
scaled_width,
scaled_height));
}
else
{
/* otherwise, convert the profile_buffer directly into
* the cairo_buffer
*/
gimp_color_transform_process_buffer (shell->profile_transform,
shell->profile_buffer,
GEGL_RECTANGLE (0, 0,
scaled_width,
scaled_height),
cairo_buffer,
GEGL_RECTANGLE (0, 0,
scaled_width,
scaled_height));
}
}
else
{
/* otherwise, load the projection pixels directly into the
* filter_buffer
/* otherwise, load the pixels directly into the filter_buffer
*/
#ifndef USE_NODE_BLIT
gegl_buffer_get (buffer,
Expand All @@ -272,10 +241,32 @@ gimp_display_shell_render (GimpDisplayShell *shell,
#endif
}

/* 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,
Expand All @@ -293,10 +284,62 @@ gimp_display_shell_render (GimpDisplayShell *shell,
g_object_unref (filter_buffer);
}

/* if there is a profile transform...
*/
if (shell->profile_transform)
{
if (gimp_display_shell_has_filter (shell))
{
/* if we have filters, convert the pixels in 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,
shell->profile_buffer,
GEGL_RECTANGLE (0, 0,
scaled_width,
scaled_height),
shell->filter_buffer,
GEGL_RECTANGLE (0, 0,
scaled_width,
scaled_height));
}
else
{
/* otherwise, convert the profile_buffer directly into
* the cairo_buffer
*/
gimp_color_transform_process_buffer (shell->profile_transform,
shell->profile_buffer,
GEGL_RECTANGLE (0, 0,
scaled_width,
scaled_height),
cairo_buffer,
GEGL_RECTANGLE (0, 0,
scaled_width,
scaled_height));
}
}

/* finally, copy the filter buffer to the cairo-ARGB32 buffer,
* if necessary
*/
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_RECTANGLE (0, 0,
scaled_width,
Expand Down
11 changes: 6 additions & 5 deletions app/display/gimpdisplayshell.h
Original file line number Diff line number Diff line change
Expand Up @@ -157,13 +157,14 @@ struct _GimpDisplayShell
guchar *profile_data; /* profile_buffer's pixels */
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;

const Babl *filter_format; /* filter_buffer's format */
GeglBuffer *filter_buffer; /* buffer for display filters */
guchar *filter_data; /* filter_buffer's pixels */
gint filter_stride; /* filter_buffer's stride */
GimpColorTransform *filter_transform;
const Babl *filter_format; /* filter_buffer's format */
GeglBuffer *filter_buffer; /* buffer for display filters */
guchar *filter_data; /* filter_buffer's pixels */
gint filter_stride; /* filter_buffer's stride */

GimpDisplayXfer *xfer; /* manages image buffer transfers */
cairo_surface_t *mask_surface; /* buffer for rendering the mask */
Expand Down

0 comments on commit 9cd8e7f

Please sign in to comment.