Bug 750874 - Displayed colors look clipped after profile conversion...

but they aren't clipped

Add gimp_display_shell_profile_can_convert_to_u8() which returns
whether the lcms transform can safely write directly into an u8 buffer
without destroying out-of-gammut pixel values, which we assume is the
case for all integer formats. If the function returns FALSE, always
convert via the R'G'B'A float filter_buffer.

Also connect to the image's "precision-changed" signal and update the
profile transform when it's emitted.
This commit is contained in:
Michael Natterer 2015-06-13 00:27:21 +02:00
parent 86e88b9b40
commit c876e281b1
4 changed files with 69 additions and 13 deletions

View File

@ -117,6 +117,8 @@ static void gimp_display_shell_sample_point_move_handler (GimpImage *i
GimpDisplayShell *shell); GimpDisplayShell *shell);
static void gimp_display_shell_invalidate_preview_handler (GimpImage *image, static void gimp_display_shell_invalidate_preview_handler (GimpImage *image,
GimpDisplayShell *shell); GimpDisplayShell *shell);
static void gimp_display_shell_precision_changed_handler (GimpImage *image,
GimpDisplayShell *shell);
static void gimp_display_shell_profile_changed_handler (GimpColorManaged *image, static void gimp_display_shell_profile_changed_handler (GimpColorManaged *image,
GimpDisplayShell *shell); GimpDisplayShell *shell);
static void gimp_display_shell_saved_handler (GimpImage *image, static void gimp_display_shell_saved_handler (GimpImage *image,
@ -251,9 +253,15 @@ gimp_display_shell_connect (GimpDisplayShell *shell)
g_signal_connect (image, "invalidate-preview", g_signal_connect (image, "invalidate-preview",
G_CALLBACK (gimp_display_shell_invalidate_preview_handler), G_CALLBACK (gimp_display_shell_invalidate_preview_handler),
shell); shell);
g_signal_connect (image, "precision-changed",
G_CALLBACK (gimp_display_shell_precision_changed_handler),
shell);
g_signal_connect (image, "profile-changed", g_signal_connect (image, "profile-changed",
G_CALLBACK (gimp_display_shell_profile_changed_handler), G_CALLBACK (gimp_display_shell_profile_changed_handler),
shell); shell);
g_signal_connect (image, "precision-changed",
G_CALLBACK (gimp_display_shell_precision_changed_handler),
shell);
g_signal_connect (image, "saved", g_signal_connect (image, "saved",
G_CALLBACK (gimp_display_shell_saved_handler), G_CALLBACK (gimp_display_shell_saved_handler),
shell); shell);
@ -453,6 +461,9 @@ gimp_display_shell_disconnect (GimpDisplayShell *shell)
g_signal_handlers_disconnect_by_func (image, g_signal_handlers_disconnect_by_func (image,
gimp_display_shell_profile_changed_handler, gimp_display_shell_profile_changed_handler,
shell); shell);
g_signal_handlers_disconnect_by_func (image,
gimp_display_shell_precision_changed_handler,
shell);
g_signal_handlers_disconnect_by_func (image, g_signal_handlers_disconnect_by_func (image,
gimp_display_shell_invalidate_preview_handler, gimp_display_shell_invalidate_preview_handler,
shell); shell);
@ -790,6 +801,13 @@ gimp_display_shell_invalidate_preview_handler (GimpImage *image,
gimp_display_shell_icon_update (shell); gimp_display_shell_icon_update (shell);
} }
static void
gimp_display_shell_precision_changed_handler (GimpImage *image,
GimpDisplayShell *shell)
{
gimp_display_shell_profile_update (shell);
}
static void static void
gimp_display_shell_profile_changed_handler (GimpColorManaged *image, gimp_display_shell_profile_changed_handler (GimpColorManaged *image,
GimpDisplayShell *shell) GimpDisplayShell *shell)
@ -797,7 +815,6 @@ gimp_display_shell_profile_changed_handler (GimpColorManaged *image,
gimp_color_managed_profile_changed (GIMP_COLOR_MANAGED (shell)); gimp_color_managed_profile_changed (GIMP_COLOR_MANAGED (shell));
} }
static void static void
gimp_display_shell_saved_handler (GimpImage *image, gimp_display_shell_saved_handler (GimpImage *image,
GFile *file, GFile *file,

View File

@ -34,6 +34,7 @@
#include "gegl/gimp-babl.h" #include "gegl/gimp-babl.h"
#include "core/gimpimage.h"
#include "core/gimppickable.h" #include "core/gimppickable.h"
#include "gimpdisplay.h" #include "gimpdisplay.h"
@ -92,10 +93,15 @@ gimp_display_shell_profile_update (GimpDisplayShell *shell)
gimp_image_get_precision (image), gimp_image_get_precision (image),
TRUE); TRUE);
if (gimp_display_shell_has_filter (shell)) if (gimp_display_shell_has_filter (shell) ||
! gimp_display_shell_profile_can_convert_to_u8 (shell))
{
dest_format = shell->filter_format; dest_format = shell->filter_format;
}
else else
{
dest_format = babl_format ("R'G'B'A u8"); dest_format = babl_format ("R'G'B'A u8");
}
g_printerr ("src_format: %s\n", babl_get_name (src_format)); g_printerr ("src_format: %s\n", babl_get_name (src_format));
g_printerr ("dest_format: %s\n", babl_get_name (dest_format)); g_printerr ("dest_format: %s\n", babl_get_name (dest_format));
@ -130,6 +136,30 @@ gimp_display_shell_profile_update (GimpDisplayShell *shell)
} }
} }
gboolean
gimp_display_shell_profile_can_convert_to_u8 (GimpDisplayShell *shell)
{
GimpImage *image;
image = gimp_display_get_image (shell->display);
if (image)
{
switch (gimp_image_get_component_type (image))
{
case GIMP_COMPONENT_TYPE_U8:
case GIMP_COMPONENT_TYPE_U16:
case GIMP_COMPONENT_TYPE_U32:
return TRUE;
default:
break;
}
}
return FALSE;
}
void void
gimp_display_shell_profile_convert_buffer (GimpDisplayShell *shell, gimp_display_shell_profile_convert_buffer (GimpDisplayShell *shell,
GeglBuffer *src_buffer, GeglBuffer *src_buffer,

View File

@ -22,6 +22,8 @@
void gimp_display_shell_profile_dispose (GimpDisplayShell *shell); void gimp_display_shell_profile_dispose (GimpDisplayShell *shell);
void gimp_display_shell_profile_update (GimpDisplayShell *shell); void gimp_display_shell_profile_update (GimpDisplayShell *shell);
gboolean gimp_display_shell_profile_can_convert_to_u8 (GimpDisplayShell *shell);
void gimp_display_shell_profile_convert_buffer (GimpDisplayShell *shell, void gimp_display_shell_profile_convert_buffer (GimpDisplayShell *shell,
GeglBuffer *src_buffer, GeglBuffer *src_buffer,
GeglRectangle *src_area, GeglRectangle *src_area,

View File

@ -163,13 +163,17 @@ gimp_display_shell_render (GimpDisplayShell *shell,
if (shell->profile_transform || if (shell->profile_transform ||
gimp_display_shell_has_filter (shell)) gimp_display_shell_has_filter (shell))
{ {
gboolean can_convert_to_u8;
/* if there is a profile transform or a display filter, we need /* if there is a profile transform or a display filter, we need
* to use temp buffers * to use temp buffers
*/ */
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
*/ */
if (gimp_display_shell_has_filter (shell) && if ((gimp_display_shell_has_filter (shell) || ! can_convert_to_u8) &&
! shell->filter_buffer) ! shell->filter_buffer)
{ {
gint w = GIMP_DISPLAY_RENDER_BUF_WIDTH * GIMP_DISPLAY_RENDER_MAX_SCALE; gint w = GIMP_DISPLAY_RENDER_BUF_WIDTH * GIMP_DISPLAY_RENDER_MAX_SCALE;
@ -213,7 +217,7 @@ gimp_display_shell_render (GimpDisplayShell *shell,
GEGL_BLIT_CACHE); GEGL_BLIT_CACHE);
#endif #endif
if (gimp_display_shell_has_filter (shell)) if (gimp_display_shell_has_filter (shell) || ! can_convert_to_u8)
{ {
/* if there are filters, convert the pixels from the /* if there are filters, convert the pixels from the
* profile_buffer to the filter_buffer * profile_buffer to the filter_buffer
@ -277,7 +281,10 @@ gimp_display_shell_render (GimpDisplayShell *shell,
GEGL_RECTANGLE (0, 0, GEGL_RECTANGLE (0, 0,
scaled_width, scaled_width,
scaled_height)); scaled_height));
}
if (gimp_display_shell_has_filter (shell) || ! can_convert_to_u8)
{
/* finally, copy the filter buffer to the cairo-ARGB32 buffer /* finally, copy the filter buffer to the cairo-ARGB32 buffer
*/ */
gegl_buffer_get (shell->filter_buffer, gegl_buffer_get (shell->filter_buffer,