app: correct usage of babl formats

GIMP was doing evil hacks lying to GEGL about it's pixels being in a linear
color space when they are not. This causes incorrect rendering, makes gaussian
blur misbehave etc.

The legacy projection modes should be implemented using the same 2.2 gamma
formats that are correct to specify for sRGB data. (for proper color
management in higher bitdepths; icc backend babl formats should be used.)

For the old image modes correct babl formats are:

R'G'B'A u8  -  8 bit RGB with 2.2 gamma (sRGB) with linear alpha component
R'G'B' u8   -  8 bit RGB with 2.2 gamma (sRGB)
Y'A u8      -  8 bit Grayscale with 2.2 gamma with linear alpha component
Y' u8       -  8 bit Grayscale with 2.2 gamma

Y u8        -  8 bit linear data, used for masks/channels
A u8        -  8 bit linear alpha

-----------------------------------------------

RGBA float  -     32bit floating point linear light RGB
RaGaBaA float  -  32bit floating point linear light RGB, premultiplied alpha
                  to be used for processing that needs to scale by the alpha,
                  (blurs, resampling etc)
R'G'B'A float  -  32bit floating point sRGB with gamma, to be used where
                  the result depends on being closer to perceptual when
                  processing, can be used a cheaper alternative to CIE Lab
                  based modes.

-----------------------------------------------

The legacy layer modes should use the formats with gamma 2.2 only for loading
and rendering legacy XCF files correctly, in the brave new world compositing
should most likely be done in linear light with "RGBA float" and even better
"RaGaBaA float" like GEGL does for porter duff and other compositing modes.

The ability to chose the legacy layer modes should probably be hidden from the
user unless an old .xcf has been opened.
This commit is contained in:
Øyvind Kolås 2012-03-27 21:31:47 +01:00 committed by Michael Natterer
parent 2c0fde88f2
commit ee97c1f4ff
18 changed files with 75 additions and 115 deletions

View file

@ -233,7 +233,7 @@ gimp_brush_clipboard_buffer_changed (Gimp *gimp,
/* copy the color channels into the brush's pixmap */
dest_buffer =
gegl_buffer_linear_new_from_data (temp_buf_get_data (brush->pixmap),
babl_format ("RGB u8"),
babl_format ("R'G'B' u8"),
&rect,
width * brush->pixmap->bytes,
NULL, NULL);

View file

@ -205,8 +205,7 @@ gimp_buffer_get_new_preview (GimpViewable *viewable,
NULL,
MIN ((gdouble) width / (gdouble) gimp_buffer_get_width (buffer),
(gdouble) height / (gdouble) gimp_buffer_get_height (buffer)),
gimp_bpp_to_babl_format (gimp_buffer_get_bytes (buffer),
TRUE),
gimp_bpp_to_babl_format (gimp_buffer_get_bytes (buffer)),
temp_buf_get_data (preview),
width * gimp_buffer_get_bytes (buffer),
GEGL_ABYSS_NONE);

View file

@ -1689,13 +1689,13 @@ gimp_drawable_type (const GimpDrawable *drawable)
format = drawable->private->format;
if (format == babl_format ("Y u8"))
if (format == babl_format ("Y' u8"))
return GIMP_GRAY_IMAGE;
else if (format == babl_format ("YA u8"))
else if (format == babl_format ("Y'A u8"))
return GIMP_GRAYA_IMAGE;
else if (format == babl_format ("RGB u8"))
else if (format == babl_format ("R'G'B' u8"))
return GIMP_RGB_IMAGE;
else if (format == babl_format ("RGBA u8"))
else if (format == babl_format ("R'G'B'A u8"))
return GIMP_RGBA_IMAGE;
else
{

View file

@ -1181,11 +1181,11 @@ gimp_image_real_colormap_changed (GimpImage *image,
if (private->colormap)
{
babl_palette_set_palette (private->babl_palette_rgb,
babl_format ("RGB u8"),
babl_format ("R'G'B' u8"),
private->colormap,
private->n_colors);
babl_palette_set_palette (private->babl_palette_rgba,
babl_format ("RGB u8"),
babl_format ("R'G'B' u8"),
private->colormap,
private->n_colors);
}
@ -1492,10 +1492,10 @@ gimp_image_get_format (const GimpImage *image,
switch (type)
{
case GIMP_RGB_IMAGE: return babl_format ("RGB u8");
case GIMP_RGBA_IMAGE: return babl_format ("RGBA u8");
case GIMP_GRAY_IMAGE: return babl_format ("Y u8");
case GIMP_GRAYA_IMAGE: return babl_format ("YA u8");
case GIMP_RGB_IMAGE: return babl_format ("R'G'B' u8");
case GIMP_RGBA_IMAGE: return babl_format ("R'G'B'A u8");
case GIMP_GRAY_IMAGE: return babl_format ("Y' u8");
case GIMP_GRAYA_IMAGE: return babl_format ("Y'A u8");
case GIMP_INDEXED_IMAGE: return gimp_image_colormap_get_rgb_format (image);
case GIMP_INDEXEDA_IMAGE: return gimp_image_colormap_get_rgba_format (image);
}
@ -1514,9 +1514,9 @@ gimp_image_get_format_with_alpha (const GimpImage *image,
switch (type)
{
case GIMP_RGB_IMAGE:
case GIMP_RGBA_IMAGE: return babl_format ("RGBA u8");
case GIMP_RGBA_IMAGE: return babl_format ("R'G'B'A u8");
case GIMP_GRAY_IMAGE:
case GIMP_GRAYA_IMAGE: return babl_format ("YA u8");
case GIMP_GRAYA_IMAGE: return babl_format ("Y'A u8");
case GIMP_INDEXED_IMAGE:
case GIMP_INDEXEDA_IMAGE: return gimp_image_colormap_get_rgba_format (image);
}
@ -1535,9 +1535,9 @@ gimp_image_get_format_without_alpha (const GimpImage *image,
switch (type)
{
case GIMP_RGB_IMAGE:
case GIMP_RGBA_IMAGE: return babl_format ("RGB u8");
case GIMP_RGBA_IMAGE: return babl_format ("R'G'B' u8");
case GIMP_GRAY_IMAGE:
case GIMP_GRAYA_IMAGE: return babl_format ("Y u8");
case GIMP_GRAYA_IMAGE: return babl_format ("Y' u8");
case GIMP_INDEXED_IMAGE:
case GIMP_INDEXEDA_IMAGE: return gimp_image_colormap_get_rgb_format (image);
}
@ -2054,11 +2054,11 @@ gimp_image_get_component_format (const GimpImage *image,
switch (channel)
{
case GIMP_RED_CHANNEL: return babl_format ("R u8");
case GIMP_GREEN_CHANNEL: return babl_format ("G u8");
case GIMP_BLUE_CHANNEL: return babl_format ("B u8");
case GIMP_GRAY_CHANNEL: return babl_format ("Y u8");
case GIMP_INDEXED_CHANNEL: return babl_format ("Y u8");
case GIMP_RED_CHANNEL: return babl_format ("R' u8");
case GIMP_GREEN_CHANNEL: return babl_format ("G' u8");
case GIMP_BLUE_CHANNEL: return babl_format ("B' u8");
case GIMP_GRAY_CHANNEL: return babl_format ("Y' u8");
case GIMP_INDEXED_CHANNEL: return babl_format ("Y' u8"); /* XXX: seems wrong */
case GIMP_ALPHA_CHANNEL: return babl_format ("A u8");
}
@ -2729,7 +2729,7 @@ gimp_image_transform_rgb (const GimpImage *dest_image,
gimp_rgba_get_uchar (rgb, &col[0], &col[1], &col[2], &col[3]);
babl_process (babl_fish (babl_format ("RGBA u8"), dest_format),
babl_process (babl_fish (babl_format ("R'G'B'A u8"), dest_format),
col, color, 1);
}
@ -2747,7 +2747,7 @@ gimp_image_transform_temp_buf (const GimpImage *dest_image,
g_return_val_if_fail (temp_buf != NULL, NULL);
g_return_val_if_fail (new_buf != NULL, NULL);
buf_format = gimp_bpp_to_babl_format (temp_buf->bytes, TRUE);
buf_format = gimp_bpp_to_babl_format (temp_buf->bytes);
ret_format = gimp_image_get_format (dest_image, dest_type);
/* If the pattern doesn't match the image in terms of color type,

View file

@ -278,7 +278,7 @@ gimp_pattern_create_buffer (const GimpPattern *pattern)
bytes = pattern->mask->bytes;
return gegl_buffer_linear_new_from_data (temp_buf_get_data (pattern->mask),
gimp_bpp_to_babl_format (bytes, TRUE),
gimp_bpp_to_babl_format (bytes),
GIMP_GEGL_RECT(0,0,width,height),
width * bytes,
NULL, NULL);

View file

@ -201,7 +201,7 @@ gimp_pattern_clipboard_buffer_changed (Gimp *gimp,
gegl_buffer_get (gimp_buffer_get_buffer (buffer),
GIMP_GEGL_RECT (0,0,width,height), 1.0,
gimp_bpp_to_babl_format (bytes, TRUE),
gimp_bpp_to_babl_format (bytes),
temp_buf_get_data (pattern->mask),
width * gimp_buffer_get_bytes (buffer),
GEGL_ABYSS_NONE);

View file

@ -307,10 +307,10 @@ gimp_projection_get_format (GimpPickable *pickable)
{
case GIMP_RGB:
case GIMP_INDEXED:
return babl_format ("RGBA u8");
return babl_format ("R'G'B'A u8");
case GIMP_GRAY:
return babl_format ("YA u8");
return babl_format ("Y'A u8");
}
g_assert_not_reached ();

View file

@ -691,9 +691,9 @@ gimp_selection_extract (GimpSelection *selection,
{
if (add_alpha ||
GIMP_IMAGE_TYPE_HAS_ALPHA (gimp_pickable_get_image_type (pickable)))
format = babl_format ("RGBA u8");
format = babl_format ("R'G'B'A u8");
else
format = babl_format ("RGB u8");
format = babl_format ("R'G'B' u8");
}
break;

View file

@ -36,7 +36,6 @@
/**
* gimp_bpp_to_babl_format:
* @bpp: bytes per pixel
* @linear: whether the pixels are linear or gamma-corrected.
*
* Return the Babl format to use for a given number of bytes per pixel.
* This function assumes that the data is 8bit.
@ -44,38 +43,20 @@
* Return value: the Babl format to use
**/
const Babl *
gimp_bpp_to_babl_format (guint bpp,
gboolean linear)
gimp_bpp_to_babl_format (guint bpp)
{
g_return_val_if_fail (bpp > 0 && bpp <= 4, NULL);
if (linear)
switch (bpp)
{
switch (bpp)
{
case 1:
return babl_format ("Y u8");
case 2:
return babl_format ("YA u8");
case 3:
return babl_format ("RGB u8");
case 4:
return babl_format ("RGBA u8");
}
}
else
{
switch (bpp)
{
case 1:
return babl_format ("Y' u8");
case 2:
return babl_format ("Y'A u8");
case 3:
return babl_format ("R'G'B' u8");
case 4:
return babl_format ("R'G'B'A u8");
}
case 1:
return babl_format ("Y' u8");
case 2:
return babl_format ("Y'A u8");
case 3:
return babl_format ("R'G'B' u8");
case 4:
return babl_format ("R'G'B'A u8");
}
return NULL;
@ -84,7 +65,6 @@ gimp_bpp_to_babl_format (guint bpp,
/**
* gimp_bpp_to_babl_format_with_alpha:
* @bpp: bytes per pixel
* @linear: whether the pixels are linear or gamma-corrected.
*
* Return the Babl format to use for a given number of bytes per pixel.
* This function assumes that the data is 8bit.
@ -92,34 +72,18 @@ gimp_bpp_to_babl_format (guint bpp,
* Return value: the Babl format to use
**/
const Babl *
gimp_bpp_to_babl_format_with_alpha (guint bpp,
gboolean linear)
gimp_bpp_to_babl_format_with_alpha (guint bpp)
{
g_return_val_if_fail (bpp > 0 && bpp <= 4, NULL);
if (linear)
switch (bpp)
{
switch (bpp)
{
case 1:
case 2:
return babl_format ("YA u8");
case 3:
case 4:
return babl_format ("RGBA u8");
}
}
else
{
switch (bpp)
{
case 1:
case 2:
return babl_format ("Y'A u8");
case 3:
case 4:
return babl_format ("R'G'B'A u8");
}
case 1:
case 2:
return babl_format ("Y'A u8");
case 3:
case 4:
return babl_format ("R'G'B'A u8");
}
return NULL;
@ -157,8 +121,7 @@ gimp_pixbuf_create_buffer (GdkPixbuf *pixbuf)
channels = gdk_pixbuf_get_n_channels (pixbuf);
return gegl_buffer_linear_new_from_data (gdk_pixbuf_get_pixels (pixbuf),
gimp_bpp_to_babl_format (channels,
TRUE),
gimp_bpp_to_babl_format (channels),
GIMP_GEGL_RECT (0,0,width,height),
rowstride,
(GDestroyNotify) g_object_unref,

View file

@ -25,10 +25,8 @@
#include <gdk-pixbuf/gdk-pixbuf.h> /* temp hack */
const Babl * gimp_bpp_to_babl_format (guint bpp,
gboolean linear) G_GNUC_CONST;
const Babl * gimp_bpp_to_babl_format_with_alpha (guint bpp,
gboolean linear) G_GNUC_CONST;
const Babl * gimp_bpp_to_babl_format (guint bpp) G_GNUC_CONST;
const Babl * gimp_bpp_to_babl_format_with_alpha (guint bpp) G_GNUC_CONST;
const gchar * gimp_interpolation_to_gegl_filter (GimpInterpolationType interpolation) G_GNUC_CONST;

View file

@ -102,23 +102,23 @@ gimp_gegl_init (Gimp *gimp)
G_CALLBACK (gimp_gegl_notify_tile_cache_size),
NULL);
babl_format_new ("name", "R u8",
babl_model ("RGBA"),
babl_format_new ("name", "R' u8",
babl_model ("R'G'B'A"),
babl_type ("u8"),
babl_component ("R"),
NULL);
babl_format_new ("name", "G u8",
babl_model ("RGBA"),
babl_format_new ("name", "G' u8",
babl_model ("R'G'B'A"),
babl_type ("u8"),
babl_component ("G"),
NULL);
babl_format_new ("name", "B u8",
babl_model ("RGBA"),
babl_format_new ("name", "B' u8",
babl_model ("R'G'B'A"),
babl_type ("u8"),
babl_component ("B"),
NULL);
babl_format_new ("name", "A u8",
babl_model ("RGBA"),
babl_format_new ("name", "A' u8",
babl_model ("R'G'B'A"),
babl_type ("u8"),
babl_component ("A"),
NULL);

View file

@ -203,9 +203,9 @@ gimp_operation_point_layer_mode_prepare (GeglOperation *operation)
const Babl *format;
if (self->premultiplied)
format = babl_format ("RaGaBaA float");
format = babl_format ("R'aG'aB'aA float");
else
format = babl_format ("RGBA float");
format = babl_format ("R'G'B'A float");
gegl_operation_set_format (operation, "input", format);
gegl_operation_set_format (operation, "output", format);
@ -221,10 +221,10 @@ gimp_operation_point_layer_mode_get_new_color_lchab (GimpLayerModeEffects blend
float in_lchab[3];
float lay_lchab[3];
float new_lchab[3];
const Babl *ragabaa_to_lchab = babl_fish (babl_format ("RaGaBaA float"),
const Babl *ragabaa_to_lchab = babl_fish (babl_format ("R'aG'aB'aA float"),
babl_format ("CIE LCH(ab) float"));
const Babl *lchab_to_ragabaa = babl_fish (babl_format ("CIE LCH(ab) float"),
babl_format ("RaGaBaA float"));
babl_format ("R'aG'aB'aA float"));
babl_process (ragabaa_to_lchab, (void*)in, (void*)in_lchab, 1);
babl_process (ragabaa_to_lchab, (void*)lay, (void*)lay_lchab, 1);

View file

@ -133,9 +133,9 @@ gimp_operation_set_alpha_set_property (GObject *object,
static void
gimp_operation_set_alpha_prepare (GeglOperation *operation)
{
gegl_operation_set_format (operation, "input", babl_format ("RGBA float"));
gegl_operation_set_format (operation, "input", babl_format ("R'G'B'A float"));
gegl_operation_set_format (operation, "aux", babl_format ("Y float"));
gegl_operation_set_format (operation, "output", babl_format ("RGBA float"));
gegl_operation_set_format (operation, "output", babl_format ("R'G'B'A float"));
}
static gboolean

View file

@ -378,14 +378,14 @@ gimp_tile_backend_tile_manager_new (TileManager *tm,
g_return_val_if_fail (format == NULL ||
babl_format_get_bytes_per_pixel (format) ==
babl_format_get_bytes_per_pixel (gimp_bpp_to_babl_format (bpp, TRUE)),
babl_format_get_bytes_per_pixel (gimp_bpp_to_babl_format (bpp)),
NULL);
if (tm->validate_proc)
mul = 1;
if (! format)
format = gimp_bpp_to_babl_format (bpp, TRUE);
format = gimp_bpp_to_babl_format (bpp);
ret = g_object_new (GIMP_TYPE_TILE_BACKEND_TILE_MANAGER,
"tile-width", TILE_WIDTH * mul,

View file

@ -1627,7 +1627,7 @@ gimp_brush_core_paint_line_pixmap_mask (GimpImage *dest,
guchar *l = line_buf;
gint i;
fish = babl_fish (gimp_bpp_to_babl_format_with_alpha (pixmap_mask->bytes, TRUE),
fish = babl_fish (gimp_bpp_to_babl_format_with_alpha (pixmap_mask->bytes),
gimp_drawable_get_format_with_alpha (drawable));
/* put the source pixmap's pixels, plus the mask's alpha, into
@ -1655,7 +1655,7 @@ gimp_brush_core_paint_line_pixmap_mask (GimpImage *dest,
guchar *l = line_buf;
gint i;
fish = babl_fish (gimp_bpp_to_babl_format (pixmap_mask->bytes, TRUE),
fish = babl_fish (gimp_bpp_to_babl_format (pixmap_mask->bytes),
gimp_drawable_get_format_with_alpha (drawable));
/* put the source pixmap's pixels, into one line, so we can use

View file

@ -207,7 +207,7 @@ gimp_clone_motion (GimpSourceCore *source_core,
PixelRegion destPR;
gpointer pr;
fish = babl_fish (gimp_bpp_to_babl_format (pattern->mask->bytes, TRUE),
fish = babl_fish (gimp_bpp_to_babl_format (pattern->mask->bytes),
gimp_drawable_get_format_with_alpha (drawable));
pixel_region_init_temp_buf (&destPR, paint_area,

View file

@ -682,7 +682,7 @@ gimp_text_layer_render_layout (GimpTextLayer *layer,
buffer = gimp_drawable_get_buffer (drawable);
format = gimp_drawable_get_format (drawable);
fish = babl_fish (babl_format ("RGBA u8"), format);
fish = babl_fish (babl_format ("R'G'B'A u8"), format);
bytes = babl_format_get_bytes_per_pixel (format);
iter = gegl_buffer_iterator_new (buffer, NULL, 0, format,

View file

@ -50,10 +50,10 @@ static const Babl *get_format (gint32 drawable_ID)
{
switch (gimp_drawable_type (drawable_ID))
{
case GIMP_RGB_IMAGE: return babl_format ("RGB u8");
case GIMP_RGBA_IMAGE: return babl_format ("RGBA u8");
case GIMP_GRAY_IMAGE: return babl_format ("Y u8");
case GIMP_GRAYA_IMAGE: return babl_format ("YA u8");
case GIMP_RGB_IMAGE: return babl_format ("R'G'B' u8");
case GIMP_RGBA_IMAGE: return babl_format ("R'G'B'A u8");
case GIMP_GRAY_IMAGE: return babl_format ("Y' u8");
case GIMP_GRAYA_IMAGE: return babl_format ("Y'A u8");
case GIMP_INDEXED_IMAGE:
case GIMP_INDEXEDA_IMAGE:
{
@ -62,7 +62,7 @@ static const Babl *get_format (gint32 drawable_ID)
gint ncols;
guchar *cmap = gimp_image_get_colormap (image_ID, &ncols);
babl_new_palette (NULL, &pal, &pala);
babl_palette_set_palette (pal, babl_format ("RGB u8"),
babl_palette_set_palette (pal, babl_format ("R'G'B' u8"),
cmap, ncols);
g_free (cmap);
if (gimp_drawable_type (drawable_ID) == GIMP_INDEXEDA_IMAGE)