summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2018-10-18 10:31:45 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2018-10-18 10:31:56 +0000
commitacebdb8da801ef89d50097d326e107fef3e270f1 (patch)
tree9176f57cbc1d1476c95d26bae17d70f3f3a80744
parentReleasing progress-linux version 0.1.56-1~dschinn1. (diff)
downloadbabl-acebdb8da801ef89d50097d326e107fef3e270f1.zip
babl-acebdb8da801ef89d50097d326e107fef3e270f1.tar.xz
Merging upstream version 0.1.58.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
-rw-r--r--INSTALL10
-rw-r--r--Makefile.in2
-rw-r--r--NEWS8
-rw-r--r--README572
-rw-r--r--babl/babl-conversion.c17
-rw-r--r--babl/babl-fish-path.c9
-rw-r--r--babl/babl-fish-reference.c776
-rw-r--r--babl/babl-fish.c6
-rw-r--r--babl/babl-icc.c59
-rw-r--r--babl/babl-internal.c3
-rw-r--r--babl/babl-internal.h2
-rw-r--r--babl/babl-matrix.h27
-rw-r--r--babl/babl-memory.c9
-rw-r--r--babl/babl-version.h2
-rw-r--r--babl/babl.h11
-rw-r--r--babl/base/babl-base.c2
-rw-r--r--babl/base/babl-base.h1
-rw-r--r--babl/base/model-gray.c783
-rw-r--r--babl/base/model-rgb.c613
-rw-r--r--babl/base/type-float.c32
-rw-r--r--babl/base/type-half.c183
-rw-r--r--babl/base/type-u15.c101
-rw-r--r--babl/base/type-u16.c99
-rw-r--r--babl/base/type-u32.c100
-rw-r--r--babl/base/type-u8.c128
-rw-r--r--babl/base/util.h3
-rwxr-xr-xconfigure30
-rw-r--r--configure.ac2
-rw-r--r--docs/index-static.html.in28
-rw-r--r--extensions/CIE.c996
-rw-r--r--extensions/cairo.c49
-rw-r--r--extensions/double.c19
-rw-r--r--extensions/fast-float.c62
-rw-r--r--extensions/float.c48
-rw-r--r--extensions/gegl-fixups.c32
-rw-r--r--extensions/gggl-lies.c14
-rw-r--r--extensions/gggl-table-lies.c11
-rw-r--r--extensions/gggl-table.c13
-rw-r--r--extensions/gggl.c37
-rw-r--r--extensions/sse2-float.c42
-rw-r--r--extensions/two-table.c33
-rw-r--r--tools/babl_fish_path_fitness.c174
42 files changed, 4532 insertions, 616 deletions
diff --git a/INSTALL b/INSTALL
index 66e28ba..72bb7f5 100644
--- a/INSTALL
+++ b/INSTALL
@@ -1,5 +1,5 @@
-babl 0.1.56
+babl 0.1.58
Dynamic; any to any, pixel format conversion library.
@@ -12,10 +12,10 @@ From a released version the following is the expected method of
installation (or a variation on this theme):
------------------------------------------------------------
- foo$ wget ftp://ftp.gtk.org/pub/babl/0.1/babl-0.1.56.tar.bz2
- foo$ tar jxf babl-0.1.56.tar.gz
- foo$ cd babl-0.1.56
- foo/babl-0.1.56$ ./configure && make && sudo make install
+ foo$ wget ftp://ftp.gtk.org/pub/babl/0.1/babl-0.1.58.tar.bz2
+ foo$ tar jxf babl-0.1.58.tar.gz
+ foo$ cd babl-0.1.58
+ foo/babl-0.1.58$ ./configure && make && sudo make install
------------------------------------------------------------
diff --git a/Makefile.in b/Makefile.in
index 1322778..2b3f208 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -195,7 +195,7 @@ DIST_SUBDIRS = babl extensions tests tools docs
am__DIST_COMMON = $(srcdir)/INSTALL.in $(srcdir)/Makefile.in \
$(srcdir)/babl.pc.in $(srcdir)/config.h.in AUTHORS COPYING \
INSTALL NEWS README TODO compile config.guess config.sub \
- install-sh ltmain.sh missing
+ depcomp install-sh ltmain.sh missing
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
distdir = $(PACKAGE)-$(VERSION)
top_distdir = $(distdir)
diff --git a/NEWS b/NEWS
index a7d93e1..0d1eac9 100644
--- a/NEWS
+++ b/NEWS
@@ -3,6 +3,14 @@ The NEWS file in the babl source tree is the source location for
the news section both in the README and the webpage.
-->
+2018-10-05 babl-0.1.58 </dt><dd>
+Preserve color of transparent pixels in conversion to premultiplied alpha,
+Added single precision code-paths for faster fallback/reference conversions.
+New BABL_ICC_INTENT_PERFORMANCE bitflag for combining with intent as bitflags,
+use of matrix+trc when relative colorimetric CLUT is present. New color model
+and formats, CIE xyY.
+
+ </dd><dt>
2018-08-14 babl-0.1.56 </dt><dd>
Improvements to the caching of profiled conversion chains between invocations
by ignoring unknown bits in cache file and remember which conversions yielded
diff --git a/README b/README
index 5e2a456..3954c2c 100644
--- a/README
+++ b/README
@@ -1,4 +1,4 @@
-Babl-0.1.56
+Babl-0.1.58
Contents
@@ -63,6 +63,12 @@ babl release. If there are significant improvements to babl when a GEGL
release is done a babl release is most often put out just prior to the
GEGL release.
+2018-10-05 babl-0.1.58
+ Preserve color of transparent pixels in conversion to premultiplied
+ alpha, Added single precision code-paths for faster fallback/
+ reference conversions. New BABL_ICC_INTENT_PERFORMANCE bitflag for
+ combining with intent as bitflags, use of matrix+trc when relative
+ colorimetric CLUT is present. New color model and formats, CIE xyY.
2018-08-14 babl-0.1.56
Improvements to the caching of profiled conversion chains between
invocations by ignoring unknown bits in cache file and remember
@@ -256,9 +262,9 @@ data being sRGB defines the conversion to and from gray-scale as well
as the gamma - or Transfer Response Curve, TRC, used for converting
between linear and non-linear variants of the data.
-There is also a babl API call for creating a format for a specific
-space. babl_format_with_space("R'G'B' u16", babl_space ("Rec2020"))
-creates a 16 bit integer format for the Rec2020 color space. Babl knows
+babl has API for creating a format for a specific space:
+babl_format_with_space("R'G'B' u16", babl_space ("Rec2020")) creates a
+16 bit integer format for the Rec2020 color space. Babl knows
internally about "sRGB", "Rec2020", "Adobe", "Apple" and "ProPhoto"
spaces, as they are defined with constants on their wikipedia pages.
@@ -269,12 +275,10 @@ babl_format_get_space.
The conversions babl does with ICC profiles are according to what is
known as the relative-colorimetric intent, monitor profiles containing
-both the matrices used by babl and 3d CLUTs (color look up tables) most
-often also do relative-colorimetric transfer for the "perceptual"
+both the matrices used by babl and 3d CLUTs (color look up tables)
+sometimes also do relative-colorimetric transfer for the "perceptual"
intent CLUTs, but with a more flexible and possibly higher accuracy
-conversions. If babl adds support for loading and using CLUTs it will
-be thus the perceptual intent will by babl be considered a different
-albeit more accurate relative-colorimetric RGB space.
+conversions.
Vocabulary
@@ -288,26 +292,26 @@ bits
bytes
8
-u15
+float
bits
- 16
+ 32
bytes
- 2
+ 4
-half
+u15
bits
16
bytes
2
-float
+half
bits
- 32
+ 16
bytes
- 4
+ 2
u8
@@ -572,6 +576,23 @@ components
CIE Z
A
+CIE xyY
+
+components
+
+ CIE x
+ CIE y
+ CIE Y
+
+CIE xyY alpha
+
+components
+
+ CIE x
+ CIE y
+ CIE Y
+ A
+
HCYA
components
@@ -657,6 +678,43 @@ components
magenta
yellow
+camayakaA
+
+components
+
+ ca
+ ma
+ ya
+ ka
+ A
+
+cmykA
+
+components
+
+ cyan
+ magenta
+ yellow
+ key
+ A
+
+cmyk
+
+components
+
+ cyan
+ magenta
+ yellow
+ key
+
+cmy
+
+components
+
+ cyan
+ magenta
+ yellow
+
Pixel formats
RGBA double
@@ -1011,6 +1069,18 @@ components
u15 G'
u15 B'
+R'G'B' float
+
+bytes/pixel
+ 12
+model
+ R'G'B'
+components
+
+ float R'
+ float G'
+ float B'
+
R'G'B'A u15
bytes/pixel
@@ -1113,6 +1183,19 @@ components
u32 B'a
u32 A
+R'aG'aB'aA float
+
+bytes/pixel
+ 16
+model
+ R'aG'aB'aA
+components
+
+ float R'a
+ float G'a
+ float B'a
+ float A
+
R~G~B~ u32
bytes/pixel
@@ -1151,6 +1234,57 @@ components
u32 B~a
u32 A
+RaGaBaA float
+
+bytes/pixel
+ 16
+model
+ RaGaBaA
+components
+
+ float Ra
+ float Ga
+ float Ba
+ float A
+
+R'G'B'A float
+
+bytes/pixel
+ 16
+model
+ R'G'B'A
+components
+
+ float R'
+ float G'
+ float B'
+ float A
+
+R~G~B~A float
+
+bytes/pixel
+ 16
+model
+ R~G~B~A
+components
+
+ float R~
+ float G~
+ float B~
+ float A
+
+R~G~B~ float
+
+bytes/pixel
+ 12
+model
+ R~G~B~
+components
+
+ float R~
+ float G~
+ float B~
+
Y double
bytes/pixel
@@ -1428,118 +1562,15 @@ components
u32 Y'
-Y'CbCr double
-
-bytes/pixel
- 24
-model
- Y'CbCr
-components
-
- double Y'
- double Cb
- double Cr
-
-Y'CbCrA double
-
-bytes/pixel
- 32
-model
- Y'CbCrA
-components
-
- double Y'
- double Cb
- double Cr
- double A
-
-Y'CbCr u8
-
-bytes/pixel
- 3
-model
- Y'CbCr
-components
-
- u8-luma Y'
- u8-chroma Cb
- u8-chroma Cr
-
-R'aG'aB'aA float
-
-bytes/pixel
- 16
-model
- R'aG'aB'aA
-components
-
- float R'a
- float G'a
- float B'a
- float A
-
-R~aG~aB~aA float
-
-bytes/pixel
- 16
-model
- R~aG~aB~aA
-components
-
- float R~a
- float G~a
- float B~a
- float A
-
-R'G'B'A float
-
-bytes/pixel
- 16
-model
- R'G'B'A
-components
-
- float R'
- float G'
- float B'
- float A
-
-R~G~B~A float
-
-bytes/pixel
- 16
-model
- R~G~B~A
-components
-
- float R~
- float G~
- float B~
- float A
-
-R'G'B' float
-
-bytes/pixel
- 12
-model
- R'G'B'
-components
-
- float R'
- float G'
- float B'
-
-R~G~B~ float
+Y float
bytes/pixel
- 12
+ 4
model
- R~G~B~
+ Y
components
- float R~
- float G~
- float B~
+ float Y
Y' float
@@ -1561,6 +1592,17 @@ components
float Y~
+YA float
+
+bytes/pixel
+ 8
+model
+ YA
+components
+
+ float Y
+ float A
+
Y'A float
bytes/pixel
@@ -1583,6 +1625,17 @@ components
float Y~
float A
+YaA float
+
+bytes/pixel
+ 8
+model
+ YaA
+components
+
+ float Ya
+ float A
+
Y'aA float
bytes/pixel
@@ -1594,50 +1647,55 @@ components
float Y'a
float A
-RaGaBaA float
+Y'CbCr double
bytes/pixel
- 16
+ 24
model
- RaGaBaA
+ Y'CbCr
components
- float Ra
- float Ga
- float Ba
- float A
+ double Y'
+ double Cb
+ double Cr
-YA float
+Y'CbCrA double
bytes/pixel
- 8
+ 32
model
- YA
+ Y'CbCrA
components
- float Y
- float A
+ double Y'
+ double Cb
+ double Cr
+ double A
-YaA float
+Y'CbCr u8
bytes/pixel
- 8
+ 3
model
- YaA
+ Y'CbCr
components
- float Ya
- float A
+ u8-luma Y'
+ u8-chroma Cb
+ u8-chroma Cr
-Y float
+R~aG~aB~aA float
bytes/pixel
- 4
+ 16
model
- Y
+ R~aG~aB~aA
components
- float Y
+ float R~a
+ float G~a
+ float B~a
+ float A
Y~ half
@@ -2129,6 +2187,31 @@ components
double CIE Z
double A
+CIE xyY double
+
+bytes/pixel
+ 24
+model
+ CIE xyY
+components
+
+ double CIE x
+ double CIE y
+ double CIE Y
+
+CIE xyY alpha double
+
+bytes/pixel
+ 32
+model
+ CIE xyY alpha
+components
+
+ double CIE x
+ double CIE y
+ double CIE Y
+ double A
+
CIE Lab float
bytes/pixel
@@ -2179,6 +2262,31 @@ components
float CIE b
float A
+CIE LCH(ab) float
+
+bytes/pixel
+ 12
+model
+ CIE LCH(ab)
+components
+
+ float CIE L
+ float CIE C(ab)
+ float CIE H(ab)
+
+CIE LCH(ab) alpha float
+
+bytes/pixel
+ 16
+model
+ CIE LCH(ab) alpha
+components
+
+ float CIE L
+ float CIE C(ab)
+ float CIE H(ab)
+ float A
+
CIE L float
bytes/pixel
@@ -2224,29 +2332,29 @@ components
CIE u16 ab CIE a
CIE u16 ab CIE b
-CIE LCH(ab) float
+CIE xyY float
bytes/pixel
12
model
- CIE LCH(ab)
+ CIE xyY
components
- float CIE L
- float CIE C(ab)
- float CIE H(ab)
+ float CIE x
+ float CIE y
+ float CIE Y
-CIE LCH(ab) alpha float
+CIE xyY alpha float
bytes/pixel
16
model
- CIE LCH(ab) alpha
+ CIE xyY alpha
components
- float CIE L
- float CIE C(ab)
- float CIE H(ab)
+ float CIE x
+ float CIE y
+ float CIE Y
float A
HCYA double
@@ -2561,6 +2669,139 @@ components
u8 yellow
u8 key
+camayakaA double
+
+bytes/pixel
+ 40
+model
+ camayakaA
+components
+
+ double ca
+ double ma
+ double ya
+ double ka
+ double A
+
+cmykA double
+
+bytes/pixel
+ 40
+model
+ cmykA
+components
+
+ double cyan
+ double magenta
+ double yellow
+ double key
+ double A
+
+cmyk double
+
+bytes/pixel
+ 32
+model
+ cmyk
+components
+
+ double cyan
+ double magenta
+ double yellow
+ double key
+
+cmy double
+
+bytes/pixel
+ 24
+model
+ cmy
+components
+
+ double cyan
+ double magenta
+ double yellow
+
+camayakaA float
+
+bytes/pixel
+ 20
+model
+ camayakaA
+components
+
+ float ca
+ float ma
+ float ya
+ float ka
+ float A
+
+cmykA float
+
+bytes/pixel
+ 20
+model
+ cmykA
+components
+
+ float cyan
+ float magenta
+ float yellow
+ float key
+ float A
+
+cmyk float
+
+bytes/pixel
+ 16
+model
+ cmyk
+components
+
+ float cyan
+ float magenta
+ float yellow
+ float key
+
+cmy float
+
+bytes/pixel
+ 12
+model
+ cmy
+components
+
+ float cyan
+ float magenta
+ float yellow
+
+cmyk u8
+
+bytes/pixel
+ 4
+model
+ cmyk
+components
+
+ u8 cyan
+ u8 magenta
+ u8 yellow
+ u8 key
+
+cmykA u8
+
+bytes/pixel
+ 5
+model
+ cmykA
+components
+
+ u8 cyan
+ u8 magenta
+ u8 yellow
+ u8 key
+ u8 A
+
Environment
Through the environment variable BABL_TOLERANCE you can control a speed
@@ -2598,6 +2839,27 @@ babl-dist-root
└──docs Documentation/webpage for babl (the document you are reading
originated there.
+Pre-multiplied alpha
+
+babl stores color information in transparent pre-multiplied or
+associated alpha pixels in floating point formats. With floating point
+pixel formats standard way of handling alpha maintains color
+information very near fully transparent pixels - by introducing a
+limit: BABL_ALPHA_FLOOR which is 1/65536.0, and treating all alphas
+beteen zero and this value as this value we maintain color information
+while the discrepancy in behavior gets concealed by quantization in
+16bit and 8bit formats.
+
+For images that already are in a premultiplied format on import, this
+change has no impact on its use for pre-multiplied arithmetic, meaning
+that superluminous colors are still supported, it also opens up to GEGL
+more widely expect premultiplied data in more operations which will
+become a speedup when more filters want to integrate in the layer
+processing pipeline.
+
+There is a post on patreon with further details about details of the
+implementation.
+
TODO
• Support for conversions between formats that have higher
@@ -2692,4 +2954,4 @@ Ell
Félix Piédallu
Initial meson build
-/babl-0.1.56
+/babl-0.1.58
diff --git a/babl/babl-conversion.c b/babl/babl-conversion.c
index 136d91f..1127c00 100644
--- a/babl/babl-conversion.c
+++ b/babl/babl-conversion.c
@@ -493,10 +493,19 @@ babl_conversion_error (BablConversion *conversion)
babl_process (fish_rgba_to_source,
test, source, test_pixels);
- ticks_start = babl_ticks ();
- babl_process (babl_fish_simple (conversion),
- source, destination, test_pixels);
- ticks_end = babl_ticks ();
+ if (BABL(conversion)->class_type == BABL_CONVERSION_LINEAR)
+ {
+ ticks_start = babl_ticks ();
+ babl_process (babl_fish_simple (conversion),
+ source, destination, test_pixels);
+ ticks_end = babl_ticks ();
+ }
+ else
+ {
+ /* we could still measure it, but for the paths we only really consider
+ * the linear ones anyways */
+ ticks_end = 1000;
+ }
babl_process (fish_reference,
source, ref_destination, test_pixels);
diff --git a/babl/babl-fish-path.c b/babl/babl-fish-path.c
index 2e87268..c3a2289 100644
--- a/babl/babl-fish-path.c
+++ b/babl/babl-fish-path.c
@@ -599,11 +599,13 @@ babl_fish_path2 (const Babl *source,
{
get_conversion_path (&pc, (Babl *) source, 0, max_path_length () + 1, tolerance);
+#if 0
if (babl->fish_path.conversion_list->count)
{
fprintf (stderr, "babl is using a rather long chain, room exists for optimization here\n");
babl_list_each (babl->fish_path.conversion_list, show_item, NULL);
}
+#endif
}
/* third attempt,. at path length + 2 */
@@ -611,11 +613,13 @@ babl_fish_path2 (const Babl *source,
max_path_length () + 2 <= BABL_HARD_MAX_PATH_LENGTH)
{
get_conversion_path (&pc, (Babl *) source, 0, max_path_length () + 2, tolerance);
+#if 0
if (babl->fish_path.conversion_list->count)
{
fprintf (stderr, "babl is using very long chain, should be optimized\n");
babl_list_each (babl->fish_path.conversion_list, show_item, NULL);
}
+#endif
}
babl_in_fish_path--;
@@ -627,7 +631,10 @@ babl_fish_path2 (const Babl *source,
babl_free (babl);
babl_mutex_unlock (babl_format_mutex);
- _babl_fish_missing_fast_path_warning (source, destination);
+ /* it is legitimate for reference paths to be faster than long chains
+ of paths, thus it is time to retire this warning. XXX: remove it fully
+
+ _babl_fish_missing_fast_path_warning (source, destination); */
return NULL;
}
diff --git a/babl/babl-fish-reference.c b/babl/babl-fish-reference.c
index 27040ae..6d1aa84 100644
--- a/babl/babl-fish-reference.c
+++ b/babl/babl-fish-reference.c
@@ -97,6 +97,9 @@ create_name (const Babl *source,
#endif
+/* need an internal version that only ever does double,
+ * for use in path evaluation? and perhaps even self evaluation of float code path?
+ */
Babl *
babl_fish_reference (const Babl *source,
const Babl *destination)
@@ -368,6 +371,7 @@ process_to_n_component (const Babl *babl,
double_buf = babl_malloc (sizeof (double) * n * components);
memset (double_buf, 0,sizeof (double) * n * components);
+ /* a single precision path could be added here*/
{
ncomponent_convert_to_double (
(BablFormat *) BABL (babl->fish.source),
@@ -388,56 +392,642 @@ process_to_n_component (const Babl *babl,
return 0;
}
+static int compatible_components (const BablFormat *a,
+ const BablFormat *b)
+{
+ int i;
+ if (a->components != b->components)
+ return 0;
+ for (i = 0; i < a->components; i++)
+ if (a->component[i] != b->component[i])
+ return 0;
+ return 1;
+}
+
+static void
+ncomponent_convert_to_float (BablFormat *source_fmt,
+ char *source_buf,
+ char *source_float_buf,
+ int n)
+{
+ BablImage *src_img;
+ BablImage *dst_img;
+
+ src_img = (BablImage *) babl_image_new (
+ babl_component_from_id (BABL_GRAY_LINEAR), NULL, 1, 0, NULL);
+ dst_img = (BablImage *) babl_image_new (
+ babl_component_from_id (BABL_GRAY_LINEAR), NULL, 1, 0, NULL);
+
+ dst_img->type[0] = (BablType *) babl_type_from_id (BABL_FLOAT);
+ dst_img->pitch[0] = (dst_img->type[0]->bits / 8);
+ dst_img->stride[0] = 0;
+
+ src_img->data[0] = source_buf;
+ src_img->type[0] = source_fmt->type[0];
+ src_img->pitch[0] = source_fmt->type[0]->bits / 8;
+ src_img->stride[0] = 0;
+
+ dst_img->data[0] = source_float_buf;
+
+ babl_conversion_process (
+ assert_conversion_find (src_img->type[0], dst_img->type[0]),
+ (void*)src_img, (void*)dst_img,
+ n * source_fmt->components);
+ babl_free (src_img);
+ babl_free (dst_img);
+}
+
+static void
+ncomponent_convert_from_float (BablFormat *destination_fmt,
+ char *destination_float_buf,
+ char *destination_buf,
+ int n)
+{
+ BablImage *src_img;
+ BablImage *dst_img;
+
+ src_img = (BablImage *) babl_image_new (
+ babl_component_from_id (BABL_GRAY_LINEAR), NULL, 1, 0, NULL);
+ dst_img = (BablImage *) babl_image_new (
+ babl_component_from_id (BABL_GRAY_LINEAR), NULL, 1, 0, NULL);
+
+ src_img->type[0] = (BablType *) babl_type_from_id (BABL_FLOAT);
+ src_img->pitch[0] = (src_img->type[0]->bits / 8);
+ src_img->stride[0] = 0;
+
+ dst_img->data[0] = destination_buf;
+ dst_img->type[0] = (BablType *) babl_type_from_id (BABL_FLOAT);
+ dst_img->pitch[0] = destination_fmt->type[0]->bits/8;
+ dst_img->stride[0] = 0;
+
+ dst_img->type[0] = destination_fmt->type[0];
+ src_img->data[0] = destination_float_buf;
+
+ babl_conversion_process (
+ assert_conversion_find (src_img->type[0], dst_img->type[0]),
+ (void*)src_img, (void*)dst_img,
+ n * destination_fmt->components);
+
+ dst_img->data[0] += dst_img->type[0]->bits / 8;
+ babl_free (src_img);
+ babl_free (dst_img);
+}
+
+static void
+convert_to_float (BablFormat *source_fmt,
+ const char *source_buf,
+ char *float_buf,
+ int n)
+{
+ int i;
+
+ BablImage *src_img;
+ BablImage *dst_img;
+
+ src_img = (BablImage *) babl_image_new (
+ babl_component_from_id (BABL_GRAY_LINEAR), NULL, 1, 0, NULL);
+ dst_img = (BablImage *) babl_image_new (
+ babl_component_from_id (BABL_GRAY_LINEAR), NULL, 1, 0, NULL);
+
+ dst_img->type[0] = (BablType *) babl_type_from_id (BABL_FLOAT);
+ dst_img->pitch[0] =
+ (dst_img->type[0]->bits / 8) * source_fmt->model->components;
+ dst_img->stride[0] = 0;
+
+ src_img->type[0] = (BablType *) babl_type_from_id (BABL_FLOAT);
+ src_img->pitch[0] = source_fmt->bytes_per_pixel;
+ src_img->stride[0] = 0;
+
+ {
+ /* i is dest position */
+ for (i = 0; i < source_fmt->model->components; i++)
+ {
+ int j;
+ int found = 0;
+
+ dst_img->data[0] =
+ float_buf + (dst_img->type[0]->bits / 8) * i;
+
+ src_img->data[0] = (char *)source_buf;
+
+ /* j is source position */
+ for (j = 0; j < source_fmt->components; j++)
+ {
+ src_img->type[0] = source_fmt->type[j];
+
+ if (source_fmt->component[j] ==
+ source_fmt->model->component[i])
+ {
+ babl_conversion_process (assert_conversion_find (src_img->type[0], dst_img->type[0]),
+ (void*)src_img, (void*)dst_img, n);
+ found = 1;
+ break;
+ }
+
+ src_img->data[0] += src_img->type[0]->bits / 8;
+ }
+
+ if (!found)
+ {
+ char *dst_ptr = dst_img->data[0];
+ float value;
+
+ value = source_fmt->model->component[i]->instance.id == BABL_ALPHA ? 1.0 : 0.0;
+
+ for (j = 0; j < n; j++)
+ {
+ float *dst_component = (float *) dst_ptr;
+
+ *dst_component = value;
+ dst_ptr += dst_img->pitch[0];
+ }
+ }
+ }
+ }
+ babl_free (src_img);
+ babl_free (dst_img);
+}
+
+
+static void
+convert_from_float (BablFormat *destination_fmt,
+ char *destination_float_buf,
+ char *destination_buf,
+ int n)
+{
+ int i;
+
+ BablImage *src_img;
+ BablImage *dst_img;
+
+ src_img = (BablImage *) babl_image_new (
+ babl_component_from_id (BABL_GRAY_LINEAR), NULL, 1, 0, NULL);
+ dst_img = (BablImage *) babl_image_new (
+ babl_component_from_id (BABL_GRAY_LINEAR), NULL, 1, 0, NULL);
+
+ src_img->type[0] = (BablType *) babl_type_from_id (BABL_FLOAT);
+ src_img->pitch[0] = (src_img->type[0]->bits / 8) * destination_fmt->model->components;
+ src_img->stride[0] = 0;
+
+ dst_img->data[0] = destination_buf;
+ dst_img->type[0] = (BablType *) babl_type_from_id (BABL_FLOAT);
+ dst_img->pitch[0] = destination_fmt->bytes_per_pixel;
+ dst_img->stride[0] = 0;
+
+ for (i = 0; i < destination_fmt->components; i++)
+ {
+ int j;
+
+ dst_img->type[0] = destination_fmt->type[i];
+
+ for (j = 0; j < destination_fmt->model->components; j++)
+ {
+ if (destination_fmt->component[i] ==
+ destination_fmt->model->component[j])
+ {
+ src_img->data[0] =
+ destination_float_buf + (src_img->type[0]->bits / 8) * j;
+
+ babl_conversion_process (assert_conversion_find (src_img->type[0],
+ dst_img->type[0]),
+ (void*)src_img, (void*)dst_img, n);
+ break;
+ }
+ }
+
+ dst_img->data[0] += dst_img->type[0]->bits / 8;
+ }
+ babl_free (src_img);
+ babl_free (dst_img);
+}
+
+
+
static void
process_same_model (const Babl *babl,
const char *source,
char *destination,
long n)
{
- void *double_buf;
+ const void *type_float = babl_type_from_id (BABL_FLOAT);
#define MAX(a, b) ((a) > (b) ? (a) : (b))
- double_buf = babl_malloc (sizeof (double) * n *
+
+
+ if ((babl->fish.source->format.type[0]->bits < 32 ||
+ babl->fish.source->format.type[0] == type_float) &&
+ (babl->fish.destination->format.type[0]->bits < 32 ||
+ babl->fish.destination->format.type[0] == type_float))
+ {
+ void *float_buf = babl_malloc (sizeof (float) * n *
+ MAX (BABL (babl->fish.source)->format.model->components,
+ BABL (babl->fish.source)->format.components));
+ if (compatible_components ((void*)babl->fish.source,
+ (void*)babl->fish.destination))
+ {
+ ncomponent_convert_to_float (
+ (BablFormat *) BABL (babl->fish.source),
+ (char *) source,
+ float_buf,
+ n);
+ ncomponent_convert_from_float (
+ (BablFormat *) BABL (babl->fish.destination),
+ float_buf,
+ (char *) destination,
+ n);
+ }
+ else
+ {
+ convert_to_float (
+ (BablFormat *) BABL (babl->fish.source),
+ (char *) source,
+ float_buf,
+ n);
+
+ convert_from_float (
+ (BablFormat *) BABL (babl->fish.destination),
+ float_buf,
+ (char *) destination,
+ n);
+ }
+ babl_free (float_buf);
+ }
+ else
+ {
+ void *double_buf = babl_malloc (sizeof (double) * n *
MAX (BABL (babl->fish.source)->format.model->components,
BABL (babl->fish.source)->format.components));
#undef MAX
+ if (compatible_components ((void*)babl->fish.source,
+ (void*)babl->fish.destination))
+ {
+ ncomponent_convert_to_double (
+ (BablFormat *) BABL (babl->fish.source),
+ (char *) source,
+ double_buf,
+ n);
+ ncomponent_convert_from_double (
+ (BablFormat *) BABL (babl->fish.destination),
+ double_buf,
+ (char *) destination,
+ n);
+ }
+ else
+ {
+ convert_to_double (
+ (BablFormat *) BABL (babl->fish.source),
+ (char *) source,
+ double_buf,
+ n);
+
+ convert_from_double (
+ (BablFormat *) BABL (babl->fish.destination),
+ double_buf,
+ (char *) destination,
+ n);
+ }
+ babl_free (double_buf);
+ }
+}
- if ((BABL (babl->fish.source)->format.components ==
- BABL (babl->fish.destination)->format.components)
- && (BABL (babl->fish.source)->format.model->components !=
- BABL (babl->fish.source)->format.components))
+
+static void
+babl_fish_reference_process_double (const Babl *babl,
+ const char *source,
+ char *destination,
+ long n,
+ void *data)
+{
+ Babl *source_image = NULL;
+ Babl *rgba_image = NULL;
+ Babl *destination_image = NULL;
+ void *source_double_buf_alloc = NULL;
+ void *source_double_buf;
+ void *rgba_double_buf_alloc = NULL;
+ void *rgba_double_buf;
+ void *destination_double_buf_alloc = NULL;
+ void *destination_double_buf;
+ const void *type_double = babl_type_from_id (BABL_DOUBLE);
+
+ if (babl->fish.source->format.type[0] == type_double &&
+ BABL(babl->fish.source)->format.components ==
+ BABL(babl->fish.source)->format.model->components && 0)
{
- ncomponent_convert_to_double (
+ source_double_buf = (void*)source;
+ source_image = babl_image_from_linear (
+ source_double_buf, BABL (BABL ((babl->fish.source))->format.model));
+ }
+ else
+ {
+ source_double_buf_alloc = babl_malloc (sizeof (double) * n *
+ BABL (babl->fish.source)->format.model->components);
+
+ source_double_buf = source_double_buf_alloc;
+ source_image = babl_image_from_linear (
+ source_double_buf, BABL (BABL ((babl->fish.source))->format.model));
+ convert_to_double (
(BablFormat *) BABL (babl->fish.source),
- (char *) source,
- double_buf,
+ source,
+ source_double_buf,
n
);
+ }
- ncomponent_convert_from_double (
- (BablFormat *) BABL (babl->fish.destination),
- double_buf,
- (char *) destination,
- n
- );
+ if (babl_model_is ((void*)babl->fish.source->format.model, "RGBA"))
+ {
+ rgba_double_buf = source_double_buf;
+ rgba_image = babl_image_from_linear (
+ rgba_double_buf,
+ (void*)babl->fish.source->format.model);
}
- else
+ else
{
- convert_to_double (
+ Babl *conv =
+ assert_conversion_find (
+ BABL (babl->fish.source)->format.model,
+
+ babl_remodel_with_space (babl_model_from_id (BABL_RGBA),
+ BABL (BABL ((babl->fish.source))->format.space)));
+
+ rgba_double_buf_alloc = babl_malloc (sizeof (double) * n * 4);
+ rgba_double_buf = rgba_double_buf_alloc;
+
+ rgba_image = babl_image_from_linear (
+ rgba_double_buf, babl_remodel_with_space (babl_model_from_id (BABL_RGBA),
+ BABL (BABL ((babl->fish.source))->format.space)) );
+
+ if (conv->class_type == BABL_CONVERSION_PLANAR)
+ {
+ babl_conversion_process (
+ conv,
+ (void*)source_image, (void*)rgba_image,
+ n);
+ }
+ else if (conv->class_type == BABL_CONVERSION_LINEAR)
+ {
+ babl_conversion_process (
+ conv,
+ source_double_buf, rgba_double_buf,
+ n);
+ }
+ else babl_fatal ("oops");
+ }
+
+ if (((babl->fish.source)->format.space !=
+ ((babl->fish.destination)->format.space)))
+ {
+ double matrix[9];
+ double *rgba = rgba_double_buf;
+ babl_matrix_mul_matrix (
+ (babl->fish.destination)->format.space->space.XYZtoRGB,
+ (babl->fish.source)->format.space->space.RGBtoXYZ,
+ matrix);
+
+ babl_matrix_mul_vector_buf4 (matrix, rgba, rgba, n);
+ }
+
+ {
+ const Babl *destination_rgba_format =
+ babl_remodel_with_space (babl_model_from_id (BABL_RGBA),
+ BABL (BABL ((babl->fish.destination))->format.space));
+
+ if(BABL (babl->fish.destination)->format.model == (void*)destination_rgba_format)
+ {
+ destination_double_buf = rgba_double_buf;
+ }
+ else
+ {
+ Babl *conv =
+ assert_conversion_find (destination_rgba_format,
+ BABL (babl->fish.destination)->format.model);
+
+ destination_double_buf_alloc = babl_malloc (sizeof (double) * n *
+ BABL (babl->fish.destination)->format.model->components);
+ destination_double_buf = destination_double_buf_alloc;
+
+ if (conv->class_type == BABL_CONVERSION_PLANAR)
+ {
+ destination_image = babl_image_from_linear (
+ destination_double_buf, BABL (BABL ((babl->fish.destination))->format.model));
+
+
+ babl_conversion_process (
+ conv,
+ (void*)rgba_image, (void*)destination_image,
+ n);
+ }
+ else if (conv->class_type == BABL_CONVERSION_LINEAR)
+ {
+ babl_conversion_process (
+ conv,
+ rgba_double_buf, destination_double_buf,
+ n);
+ }
+ else babl_fatal ("oops");
+ }
+ }
+
+ convert_from_double (
+ (BablFormat *) BABL (babl->fish.destination),
+ destination_double_buf,
+ destination,
+ n
+ );
+
+ if (destination_double_buf_alloc)
+ babl_free (destination_double_buf_alloc);
+ if (rgba_double_buf_alloc)
+ babl_free (rgba_double_buf_alloc);
+ if (source_double_buf_alloc)
+ babl_free (source_double_buf_alloc);
+ if (source_image)
+ babl_free (source_image);
+ if (rgba_image)
+ babl_free (rgba_image);
+ if (destination_image)
+ babl_free (destination_image);
+}
+
+static void
+babl_fish_reference_process_float (const Babl *babl,
+ const char *source,
+ char *destination,
+ long n,
+ void *data)
+{
+ const void *type_float = babl_type_from_id (BABL_FLOAT);
+ Babl *source_image = NULL;
+ Babl *rgba_image = NULL;
+ Babl *destination_image = NULL;
+ void *source_float_buf_alloc = NULL;
+ void *source_float_buf;
+ void *rgba_float_buf_alloc = NULL;
+ void *rgba_float_buf;
+ void *destination_float_buf_alloc = NULL;
+ void *destination_float_buf;
+ const Babl *destination_float_format;
+ Babl *conv_to_rgba;
+ Babl *conv_from_rgba;
+ char dst_name[256];
+
+ {
+ char src_name[256];
+ sprintf (src_name, "%s float", babl_get_name((void*)babl->fish.source->format.model));
+ conv_to_rgba =
+ babl_conversion_find (
+ babl_format_with_space (src_name,
+ BABL (BABL ((babl->fish.source))->format.space)),
+ babl_format_with_space ("RGBA float",
+ BABL (BABL ((babl->fish.source))->format.space)));
+ }
+ {
+ sprintf (dst_name, "%s float", babl_get_name((void*)babl->fish.destination->format.model));
+ conv_from_rgba =
+ babl_conversion_find (
+ babl_format_with_space ("RGBA float",
+ BABL (BABL ((babl->fish.destination))->format.space)),
+ babl_format_with_space (dst_name,
+ BABL (BABL ((babl->fish.destination))->format.space)));
+ destination_float_format =
+ babl_format_with_space (dst_name,
+ BABL (BABL ((babl->fish.destination))->format.space));
+ }
+
+ if (!conv_to_rgba || !conv_from_rgba)
+ {
+ /* needed float conversions not found, using double code path instead */
+ babl_fish_reference_process_double (babl, source, destination, n, data);
+ return;
+ }
+
+ babl_mutex_lock (babl_reference_mutex);
+ if (babl->fish.source->format.type[0] == type_float &&
+ BABL(babl->fish.source)->format.components ==
+ BABL(babl->fish.source)->format.model->components && 0)
+ {
+ source_float_buf = (void*)source;
+ source_image = babl_image_from_linear (
+ source_float_buf,
+ babl_format_with_model_as_type ((void*)((babl->fish.source))->format.model,
+ type_float));
+ }
+ else
+ {
+ source_float_buf_alloc = babl_malloc (sizeof (float) * n *
+ (BABL (babl->fish.source)->format.model->components));
+
+ source_float_buf = source_float_buf_alloc;
+ source_image = babl_image_from_linear (
+ source_float_buf,
+ babl_format_with_model_as_type (BABL(BABL ((babl->fish.source))->format.model),
+ type_float));
+ convert_to_float (
(BablFormat *) BABL (babl->fish.source),
- (char *) source,
- double_buf,
+ source,
+ source_float_buf,
n
);
+ }
- convert_from_double (
- (BablFormat *) BABL (babl->fish.destination),
- double_buf,
- (char *) destination,
- n
- );
+ if (babl_model_is ((void*)babl->fish.source->format.model, "RGBA") && 0)
+ {
+ rgba_float_buf = source_float_buf;
+ rgba_image = babl_image_from_linear (
+ rgba_float_buf,
+ (void*)babl->fish.source->format.model);
}
- babl_free (double_buf);
+ else
+ {
+ rgba_float_buf_alloc = babl_malloc (sizeof (float) * n * 4);
+ rgba_float_buf = rgba_float_buf_alloc;
+
+ rgba_image = babl_image_from_linear (
+ rgba_float_buf,
+ babl_format_with_space ("RGBA float",
+ BABL (BABL ((babl->fish.source))->format.space)));
+
+
+ if (conv_to_rgba->class_type == BABL_CONVERSION_PLANAR)
+ {
+ babl_conversion_process (
+ conv_to_rgba,
+ (void*)source_image, (void*)rgba_image,
+ n);
+ }
+ else if (conv_to_rgba->class_type == BABL_CONVERSION_LINEAR)
+ {
+ babl_conversion_process (
+ conv_to_rgba,
+ source_float_buf, rgba_float_buf,
+ n);
+ }
+ }
+ babl_mutex_unlock (babl_reference_mutex);
+
+ if (((babl->fish.source)->format.space !=
+ ((babl->fish.destination)->format.space)))
+ {
+ float matrix[9];
+ float *rgba = rgba_float_buf;
+ babl_matrix_mul_matrixf (
+ (babl->fish.destination)->format.space->space.XYZtoRGBf,
+ (babl->fish.source)->format.space->space.RGBtoXYZf,
+ matrix);
+
+ babl_matrix_mul_vectorff_buf4 (matrix, rgba, rgba, n);
+ }
+
+ {
+
+ if(babl_format_with_space ("RGBA float",
+ BABL (BABL ((babl->fish.destination))->format.space)) ==
+ babl_format_with_space (dst_name,
+ BABL (BABL ((babl->fish.destination))->format.space)))
+ {
+ destination_float_buf = rgba_float_buf;
+ }
+ else
+ {
+ destination_float_buf_alloc = babl_malloc (sizeof (float) * n *
+ BABL (babl->fish.destination)->format.model->components);
+ destination_float_buf = destination_float_buf_alloc;
+
+ if (conv_from_rgba->class_type == BABL_CONVERSION_PLANAR)
+ {
+ destination_image = babl_image_from_linear (
+ destination_float_buf, destination_float_format);
+ babl_conversion_process (
+ conv_from_rgba,
+ (void*)rgba_image, (void*)destination_image,
+ n);
+ }
+ else if (conv_from_rgba->class_type == BABL_CONVERSION_LINEAR)
+ {
+ babl_conversion_process (conv_from_rgba, rgba_float_buf,
+ destination_float_buf, n);
+ }
+ }
+ }
+
+ convert_from_float (
+ (BablFormat *) BABL (babl->fish.destination),
+ destination_float_buf,
+ destination,
+ n
+ );
+
+ if (destination_float_buf_alloc)
+ babl_free (destination_float_buf_alloc);
+ if (rgba_float_buf_alloc)
+ babl_free (rgba_float_buf_alloc);
+ if (source_float_buf_alloc)
+ babl_free (source_float_buf_alloc);
+ if (source_image)
+ babl_free (source_image);
+ if (rgba_image)
+ babl_free (rgba_image);
+ if (destination_image)
+ babl_free (destination_image);
}
void
@@ -447,13 +1037,22 @@ babl_fish_reference_process (const Babl *babl,
long n,
void *data)
{
- void *source_double_buf;
- void *rgba_double_buf;
- void *destination_double_buf;
- Babl *source_image;
- Babl *rgba_image;
- Babl *destination_image;
+ static const void *type_float = NULL;
+ static int allow_float_reference = -1;
+
+ if (!type_float) type_float = babl_type_from_id (BABL_FLOAT);
+ /* same format in source/destination */
+ if (BABL (babl->fish.source) == BABL (babl->fish.destination))
+ {
+ if (source == destination)
+ {
+ memcpy (destination, source, n * babl->fish.source->format.bytes_per_pixel);
+ }
+ return;
+ }
+
+ /* same model and space, only convert type */
if ((BABL (babl->fish.source)->format.model ==
BABL (babl->fish.destination)->format.model) &&
(BABL (babl->fish.source)->format.space ==
@@ -464,105 +1063,38 @@ babl_fish_reference_process (const Babl *babl,
return;
}
+ /* we're converting to a n_component format - special case */
if (babl_format_is_format_n (BABL (babl->fish.destination)))
{
process_to_n_component (babl, source, destination, n);
return;
}
- source_double_buf = babl_malloc (sizeof (double) * n *
- BABL (babl->fish.source)->format.model->components);
- rgba_double_buf = babl_malloc (sizeof (double) * n * 4);
- destination_double_buf = babl_malloc (sizeof (double) * n *
- BABL (babl->fish.destination)->format.model->components);
-
- source_image = babl_image_from_linear (
- source_double_buf, BABL (BABL ((babl->fish.source))->format.model));
- rgba_image = babl_image_from_linear (
- rgba_double_buf, babl_remodel_with_space (babl_model_from_id (BABL_RGBA),
- BABL (BABL ((babl->fish.source))->format.space)) );
- destination_image = babl_image_from_linear (
- destination_double_buf, BABL (BABL ((babl->fish.destination))->format.model));
-
- convert_to_double (
- (BablFormat *) BABL (babl->fish.source),
- source,
- source_double_buf,
- n
- );
-
- {
- Babl *conv =
- assert_conversion_find (
- BABL (babl->fish.source)->format.model,
- babl_remodel_with_space (babl_model_from_id (BABL_RGBA),
- BABL (BABL ((babl->fish.source))->format.space))
- );
- if (conv->class_type == BABL_CONVERSION_PLANAR)
- {
- babl_conversion_process (
- conv,
- (void*)source_image, (void*)rgba_image,
- n);
- }
- else if (conv->class_type == BABL_CONVERSION_LINEAR)
- {
- babl_conversion_process (
- conv,
- source_double_buf, rgba_double_buf,
- n);
- }
- else babl_fatal ("oops");
- }
-
- if (((babl->fish.source)->format.space !=
- ((babl->fish.destination)->format.space)))
+ if (allow_float_reference == -1)
+ allow_float_reference = getenv ("BABL_REFERENCE_NOFLOAT") ? 0 : 1;
+
+ /* both source and destination are either single precision float or <32bit component,
+ we then do a similar to the double reference - using the first registered
+ float conversions - note that this makes the first registered float conversion of
+ a given type a reference, and we thus rely on the *first* float conversion regsitered
+ to be correct, this will be the case if the code paths are duplicated and we register
+ either a planar or linear conversion to and from "RGBA float" at the same time as
+ registering conversions for double. When needed conversions do not exist, we defer
+ to the double code paths
+ */
+ if (allow_float_reference &&
+ (babl->fish.source->format.type[0]->bits < 32 ||
+ babl->fish.source->format.type[0] == type_float) &&
+ (babl->fish.destination->format.type[0]->bits < 32 ||
+ babl->fish.destination->format.type[0] == type_float) &&
+ !babl_format_is_palette (babl->fish.source) &&
+ !babl_format_is_palette (babl->fish.destination))
{
- double matrix[9];
- double *rgba = rgba_double_buf;
- babl_matrix_mul_matrix (
- (babl->fish.destination)->format.space->space.XYZtoRGB,
- (babl->fish.source)->format.space->space.RGBtoXYZ,
- matrix);
-
- babl_matrix_mul_vector_buf4 (matrix, rgba, rgba, n);
+ babl_fish_reference_process_float (babl, source, destination, n, data);
}
-
+ else /* double */
{
- Babl *conv =
- assert_conversion_find (
- babl_remodel_with_space (babl_model_from_id (BABL_RGBA),
- BABL (BABL ((babl->fish.destination))->format.space)),
- BABL (babl->fish.destination)->format.model);
- if (conv->class_type == BABL_CONVERSION_PLANAR)
- {
- babl_conversion_process (
- conv,
- (void*)rgba_image, (void*)destination_image,
- n);
- }
- else if (conv->class_type == BABL_CONVERSION_LINEAR)
- {
- babl_conversion_process (
- conv,
- rgba_double_buf, destination_double_buf,
- n);
- }
- else babl_fatal ("oops");
+ babl_fish_reference_process_double (babl, source, destination, n, data);
}
- convert_from_double (
- (BablFormat *) BABL (babl->fish.destination),
- destination_double_buf,
- destination,
- n
- );
-
- babl_free (source_image);
- babl_free (rgba_image);
- babl_free (destination_image);
-
- babl_free (destination_double_buf);
- babl_free (rgba_double_buf);
- babl_free (source_double_buf);
}
diff --git a/babl/babl-fish.c b/babl/babl-fish.c
index a1baa50..65c482e 100644
--- a/babl/babl-fish.c
+++ b/babl/babl-fish.c
@@ -119,7 +119,9 @@ babl_conversion_find (const void *source,
const void *destination)
{
void *data = (void*)destination;
- babl_list_each (BABL (source)->type.from_list, match_conversion, &data);
+
+ if (BABL (source)->type.from_list)
+ babl_list_each (BABL (source)->type.from_list, match_conversion, &data);
if (data != (void*)destination) /* didn't change */
return data;
data = NULL;
@@ -295,8 +297,10 @@ babl_fish (const void *source,
/* the dummy fish was created by the cache, and we need to manually
* show a "missing fast path" warning for it on the first lookup.
*/
+#if 0
_babl_fish_missing_fast_path_warning (ffish.fish_fish->fish.source,
ffish.fish_fish->fish.destination);
+#endif
ffish.fish_fish->fish.data = NULL;
}
diff --git a/babl/babl-icc.c b/babl/babl-icc.c
index 7f38c99..f463e9e 100644
--- a/babl/babl-icc.c
+++ b/babl/babl-icc.c
@@ -734,9 +734,9 @@ babl_space_from_icc (const char *icc_data,
const Babl *trc_blue = NULL;
const char *int_err;
Babl *ret = NULL;
+ int speed_over_accuracy = intent & BABL_ICC_INTENT_PERFORMANCE;
- sign_t profile_class, color_space;
-
+ sign_t profile_class, color_space, pcs;
if (!error) error = &int_err;
*error = NULL;
@@ -745,29 +745,41 @@ babl_space_from_icc (const char *icc_data,
{
*error = "icc profile length inconsistency";
}
-#if 0
- else if (icc_ver_major > 2)
- {
- *error = "only ICC v2 profiles supported";
- }
-#endif
- else
- {
- profile_class = icc_read (sign, 12);
- if (strcmp (profile_class.str, "mntr"))
- *error = "not a monitor-class profile";
else
{
- color_space = icc_read (sign, 16);
- if (strcmp (color_space.str, "RGB "))
- *error = "not defining an RGB space";
+ profile_class = icc_read (sign, 12);
+ if (strcmp (profile_class.str, "mntr"))
+ *error = "not a monitor-class profile";
+ else
+ {
+ color_space = icc_read (sign, 16);
+ if (strcmp (color_space.str, "RGB "))
+ *error = "not defining an RGB space";
+ }
}
+
+ if (!*error)
+ {
+ pcs = icc_read (sign, 20);
+ if (strcmp (pcs.str, "XYZ "))
+ *error = "PCS is not XYZ";
}
- switch (intent)
+ if (!*error)
+ switch (intent & 7) /* enum of intent is in lowest bits */
{
case BABL_ICC_INTENT_RELATIVE_COLORIMETRIC:
/* that is what we do well */
+
+ if (!speed_over_accuracy)
+ {
+ if (icc_tag (state, "A2B0", NULL, NULL) &&
+ icc_tag (state, "B2A0", NULL, NULL))
+ {
+ *error = "use lcms, accuracy desired and cluts are present";
+ }
+ }
+
break;
case BABL_ICC_INTENT_PERCEPTUAL:
/* if there is an A2B0 and B2A0 tags, we do not do what that
@@ -848,6 +860,19 @@ babl_space_from_icc (const char *icc_data,
wY = icc_read (s15f16, offset + 8 + 4);
wZ = icc_read (s15f16, offset + 8 + 4 * 2);
+ /* detect inconsistent Argyll cLUT + matrix profiles */
+ if (icc_tag (state, "A2B0", NULL, NULL) ||
+ icc_tag (state, "B2A0", NULL, NULL))
+ {
+ if (rz > rx)
+ {
+ *error = "Inconsistent ICC profile detected, profile contains both cLUTs and a matrix with swapped primaries, this likely means it is an intentionally inconsistent Argyll profile is in use; this profile is only capable of high accuracy rendering and does not permit acceleration for interactive previews.";
+ fprintf (stderr, "babl ICC warning: %s\n", *error);
+ babl_free (state);
+ return NULL;
+ }
+ }
+
ret = (void*)babl_space_match_trc_matrix (trc_red, trc_green, trc_blue,
rx, ry, rz, gx, gy, gz, bx, by, bz);
if (ret)
diff --git a/babl/babl-internal.c b/babl/babl-internal.c
index 2f3c42e..5609720 100644
--- a/babl/babl-internal.c
+++ b/babl/babl-internal.c
@@ -82,6 +82,7 @@ BablMutex *babl_format_mutex;
#if BABL_DEBUG_MEM
BablMutex *babl_debug_mutex;
#endif
+BablMutex *babl_reference_mutex;
void
babl_internal_init (void)
@@ -89,6 +90,7 @@ babl_internal_init (void)
babl_set_malloc (malloc);
babl_set_free (free);
babl_format_mutex = babl_mutex_new ();
+ babl_reference_mutex = babl_mutex_new ();
#if BABL_DEBUG_MEM
babl_debug_mutex = babl_mutex_new ();
#endif
@@ -98,6 +100,7 @@ void
babl_internal_destroy (void)
{
babl_mutex_destroy (babl_format_mutex);
+ babl_mutex_destroy (babl_reference_mutex);
#if BABL_DEBUG_MEM
babl_mutex_destroy (babl_debug_mutex);
#endif
diff --git a/babl/babl-internal.h b/babl/babl-internal.h
index 0f8a07c..73fe18f 100644
--- a/babl/babl-internal.h
+++ b/babl/babl-internal.h
@@ -30,6 +30,7 @@
#define BABL_MAX_COMPONENTS 32
#define BABL_CONVERSIONS 5
+
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@@ -241,6 +242,7 @@ babl_fatal (const char *format, ...)
extern int babl_hmpf_on_name_lookups;
extern int babl_in_fish_path;
extern BablMutex *babl_format_mutex;
+extern BablMutex *babl_reference_mutex;
#define BABL_DEBUG_MEM 0
#if BABL_DEBUG_MEM
diff --git a/babl/babl-matrix.h b/babl/babl-matrix.h
index 8f331a5..2107b31 100644
--- a/babl/babl-matrix.h
+++ b/babl/babl-matrix.h
@@ -31,6 +31,33 @@ static inline void babl_matrix_mul_matrix (const double *matA_,
}
}
+
+static inline void babl_matrix_mul_matrixf (const float *matA_,
+ const float *matB_,
+ float *out)
+{
+ int i, j;
+ float matA[9];
+ float matB[9];
+ float t1, t2, t3;
+ memcpy (matA, matA_, sizeof (matA));
+ memcpy (matB, matB_, sizeof (matB));
+
+ for (i = 0; i < 3; i++)
+ {
+ t1 = m(matA, i, 0);
+ t2 = m(matA, i, 1);
+ t3 = m(matA, i, 2);
+
+ for (j = 0; j < 3; j ++)
+ {
+ m(out,i,j) = t1 * m(matB, 0, j);
+ m(out,i,j) += t2 * m(matB, 1, j);
+ m(out,i,j) += t3 * m(matB, 2, j);
+ }
+ }
+}
+
static inline void babl_matrix_to_float (const double *in, float *out)
{
int i;
diff --git a/babl/babl-memory.c b/babl/babl-memory.c
index 658c495..5c9214e 100644
--- a/babl/babl-memory.c
+++ b/babl/babl-memory.c
@@ -180,9 +180,12 @@ babl_free (void *ptr,
if (!IS_BAI (ptr))
{
#define IS_BAI(ptr) (BAI (ptr)->signature == signature)
- if (freed)
- babl_fatal ("\nbabl:double free detected\n------------------------");
- babl_fatal ("memory not allocated by babl allocator");
+ if (freed == BAI (ptr)->signature)
+ fprintf (stderr, "\nbabl:double free detected\n");
+ else
+ fprintf (stderr, "\nbabl_free passed unknown pointer, bailing and leaking it\n");
+ return;
+ //assert(0);
}
if (BAI (ptr)->destructor)
diff --git a/babl/babl-version.h b/babl/babl-version.h
index 52203b0..1b4b369 100644
--- a/babl/babl-version.h
+++ b/babl/babl-version.h
@@ -34,7 +34,7 @@
#define BABL_MAJOR_VERSION 0
#define BABL_MINOR_VERSION 1
-#define BABL_MICRO_VERSION 56
+#define BABL_MICRO_VERSION 58
/** Get the version information on the babl library */
void babl_get_version (int *major,
diff --git a/babl/babl.h b/babl/babl.h
index baddd44..5a7ca7e 100644
--- a/babl/babl.h
+++ b/babl/babl.h
@@ -104,7 +104,9 @@ typedef enum {
BABL_ICC_INTENT_PERCEPTUAL = 0,
BABL_ICC_INTENT_RELATIVE_COLORIMETRIC = 1,
BABL_ICC_INTENT_SATURATION = 2,
- BABL_ICC_INTENT_ABSOLUTE_COLORIMETRIC = 3
+ BABL_ICC_INTENT_ABSOLUTE_COLORIMETRIC = 3,
+ BABL_ICC_INTENT_PERFORMANCE = 32
+ // black-point compensation toggle will be added if/when support exist in babl
} BablIccIntent;
/**
@@ -135,6 +137,7 @@ const Babl *babl_space_from_icc (const char *icc_data,
BablIccIntent intent,
const char **error);
+
// XXX : deprecated
const Babl *babl_icc_make_space (const char *icc_data,
int icc_length,
@@ -581,6 +584,12 @@ babl_space_from_rgbxyz_matrix (const char *name,
*/
const char * babl_format_get_encoding (const Babl *babl);
+/* values below this are stored premultiplied with this value,
+ * it can also be used as a generic alpha zero epsilon in GEGL
+ *
+ */
+#define BABL_ALPHA_FLOOR (1/65536.0)
+
#ifdef __cplusplus
}
#endif
diff --git a/babl/base/babl-base.c b/babl/base/babl-base.c
index a25a144..7931cfc 100644
--- a/babl/base/babl-base.c
+++ b/babl/base/babl-base.c
@@ -50,9 +50,9 @@ babl_base_destroy (void)
static void
types (void)
{
+ babl_base_type_float ();
babl_base_type_u15 ();
babl_base_type_half ();
- babl_base_type_float ();
babl_base_type_u8 ();
babl_base_type_u16 ();
babl_base_type_u32 ();
diff --git a/babl/base/babl-base.h b/babl/base/babl-base.h
index 80a5b54..bc67f5c 100644
--- a/babl/base/babl-base.h
+++ b/babl/base/babl-base.h
@@ -19,6 +19,7 @@
#ifndef _BABL_BASE_H
#define _BABL_BASE_H
+
void babl_base_init (void);
void babl_base_destroy (void);
void babl_formats_init (void);
diff --git a/babl/base/model-gray.c b/babl/base/model-gray.c
index 9d3677b..0cae837 100644
--- a/babl/base/model-gray.c
+++ b/babl/base/model-gray.c
@@ -28,6 +28,7 @@ static void components (void);
static void models (void);
static void conversions (void);
static void formats (void);
+static void init_single_precision (void);
void babl_base_model_gray (void)
{
@@ -35,6 +36,7 @@ void babl_base_model_gray (void)
models ();
conversions ();
formats ();
+ init_single_precision ();
}
static void
@@ -425,16 +427,16 @@ gray_alpha_premultiplied_to_rgba (Babl *conversion,
while (n--)
{
double luminance = *(double *) src[0];
- double alpha = *(double *) src[1];
-
- if (alpha > BABL_ALPHA_THRESHOLD)
- {
- luminance = luminance / alpha;
- }
+ double alpha;
+ alpha = *(double *) src[1];
+ if (alpha == 0)
+ luminance = 0;
else
- {
- luminance = 0.0;
- }
+ {
+ luminance = luminance / alpha;
+ if (alpha == BABL_ALPHA_FLOOR || alpha == -BABL_ALPHA_FLOOR)
+ alpha = 0.0;
+ }
*(double *) dst[0] = luminance;
*(double *) dst[1] = luminance;
@@ -469,8 +471,15 @@ rgba_to_gray_alpha_premultiplied (Babl *conversion,
double red = *(double *) src[0];
double green = *(double *) src[1];
double blue = *(double *) src[2];
- double alpha = *(double *) src[3];
double luminance;
+ double alpha = *(double *) src[3];
+ if (alpha <= BABL_ALPHA_FLOOR)
+ {
+ if (alpha >= 0.0f)
+ alpha = BABL_ALPHA_FLOOR;
+ else if (alpha >= -BABL_ALPHA_FLOOR)
+ alpha = -BABL_ALPHA_FLOOR;
+ }
luminance = red * RGB_LUMINANCE_RED +
green * RGB_LUMINANCE_GREEN +
@@ -498,10 +507,16 @@ non_premultiplied_to_premultiplied (Babl *conversion,
while (n--)
{
- double alpha;
int band;
+ double alpha = *(double *) src[src_bands-1];
+ if (alpha < BABL_ALPHA_FLOOR)
+ {
+ if (alpha >= 0.0f)
+ alpha = BABL_ALPHA_FLOOR;
+ else if (alpha >= -BABL_ALPHA_FLOOR)
+ alpha = -BABL_ALPHA_FLOOR;
+ }
- alpha = *(double *) src[src_bands - 1];
for (band = 0; band < src_bands - 1; band++)
{
*(double *) dst[band] = *(double *) src[band] * alpha;
@@ -526,21 +541,19 @@ premultiplied_to_non_premultiplied (Babl *conversion,
while (n--)
{
- double alpha;
int band;
+ double alpha;
+ alpha = *(double *) src[src_bands-1];
- alpha = *(double *) src[src_bands - 1];
for (band = 0; band < src_bands - 1; band++)
{
- if (alpha > BABL_ALPHA_THRESHOLD)
- {
- *(double *) dst[band] = *(double *) src[band] / alpha;
- }
+ if (alpha == 0.0)
+ *(double *) dst[band] = 0;
else
- {
- *(double *) dst[band] = 0.0;
- }
+ *(double *) dst[band] = *(double *) src[band] / alpha;
}
+ if (alpha == BABL_ALPHA_FLOOR || alpha == -BABL_ALPHA_FLOOR)
+ alpha = 0.0;
*(double *) dst[dst_bands - 1] = alpha;
BABL_PLANAR_STEP
@@ -564,10 +577,16 @@ rgba2gray_nonlinear_premultiplied (Babl *conversion,
double red = ((double *) src)[0];
double green = ((double *) src)[1];
double blue = ((double *) src)[2];
- double alpha = ((double *) src)[3];
-
double luminance;
double luma;
+ double alpha = ((double *) src)[3];
+ if (alpha < BABL_ALPHA_FLOOR)
+ {
+ if (alpha >= 0.0f)
+ alpha = BABL_ALPHA_FLOOR;
+ else if (alpha >= -BABL_ALPHA_FLOOR)
+ alpha = -BABL_ALPHA_FLOOR;
+ }
luminance = red * RGB_LUMINANCE_RED +
green * RGB_LUMINANCE_GREEN +
@@ -595,16 +614,19 @@ gray_nonlinear_premultiplied2rgba (Babl *conversion,
while (n--)
{
double luma = ((double *) src)[0];
- double alpha = ((double *) src)[1];
double luminance;
-
- if (alpha > BABL_ALPHA_THRESHOLD)
- luma = luma / alpha;
+ double alpha;
+ alpha = ((double *) src)[1];
+ if (alpha == 0.0)
+ luma = 0.0;
else
- luma = 0.0;
+ luma = luma / alpha;
luminance = babl_trc_to_linear (trc, luma);
+ if (alpha == BABL_ALPHA_FLOOR || alpha == -BABL_ALPHA_FLOOR)
+ alpha = 0.0;
+
((double *) dst)[0] = luminance;
((double *) dst)[1] = luminance;
((double *) dst)[2] = luminance;
@@ -859,3 +881,708 @@ formats (void)
babl_component_from_id (BABL_GRAY_NONLINEAR),
NULL);
}
+
+/********** float versions ***********/
+
+static void
+rgba_to_graya_float (Babl *conversion,
+ char *src,
+ char *dst,
+ long n)
+{
+ const Babl *space = babl_conversion_get_source_space (conversion);
+ float RGB_LUMINANCE_RED = space->space.RGBtoXYZf[3];
+ float RGB_LUMINANCE_GREEN = space->space.RGBtoXYZf[4];
+ float RGB_LUMINANCE_BLUE = space->space.RGBtoXYZf[5];
+
+ while (n--)
+ {
+ float red, green, blue;
+ float luminance, alpha;
+
+ red = ((float *) src)[0];
+ green = ((float *) src)[1];
+ blue = ((float *) src)[2];
+ alpha = ((float *) src)[3];
+
+ luminance = red * RGB_LUMINANCE_RED +
+ green * RGB_LUMINANCE_GREEN +
+ blue * RGB_LUMINANCE_BLUE;
+
+ ((float *) dst)[0] = luminance;
+ ((float *) dst)[1] = alpha;
+
+ src += sizeof (float) * 4;
+ dst += sizeof (float) * 2;
+ }
+}
+
+static void
+rgba_to_gray_float (Babl *conversion,
+ char *src,
+ char *dst,
+ long n)
+{
+ const Babl *space = babl_conversion_get_source_space (conversion);
+ float RGB_LUMINANCE_RED = space->space.RGBtoXYZf[3];
+ float RGB_LUMINANCE_GREEN = space->space.RGBtoXYZf[4];
+ float RGB_LUMINANCE_BLUE = space->space.RGBtoXYZf[5];
+
+ while (n--)
+ {
+ float red, green, blue;
+ float luminance;
+
+ red = ((float *) src)[0];
+ green = ((float *) src)[1];
+ blue = ((float *) src)[2];
+
+ luminance = red * RGB_LUMINANCE_RED +
+ green * RGB_LUMINANCE_GREEN +
+ blue * RGB_LUMINANCE_BLUE;
+
+ ((float *) dst)[0] = luminance;
+
+ src += sizeof (float) * 4;
+ dst += sizeof (float) * 1;
+ }
+}
+
+static void
+rgb_to_gray_nonlinear_float (Babl *conversion,
+ int src_bands,
+ char **src,
+ int *src_pitch,
+ int dst_bands,
+ char **dst,
+ int *dst_pitch,
+ long n)
+{
+ const Babl *space = babl_conversion_get_destination_space (conversion);
+ const Babl *trc = space->space.trc[0];
+ float RGB_LUMINANCE_RED = space->space.RGBtoXYZf[3];
+ float RGB_LUMINANCE_GREEN = space->space.RGBtoXYZf[4];
+ float RGB_LUMINANCE_BLUE = space->space.RGBtoXYZf[5];
+
+ BABL_PLANAR_SANITY
+ while (n--)
+ {
+ float red, green, blue;
+ float luminance, alpha;
+
+ red = *(float *) src[0];
+ green = *(float *) src[1];
+ blue = *(float *) src[2];
+ if (src_bands > 3)
+ alpha = *(float *) src[3];
+ else
+ alpha = 1.0f;
+
+ luminance = red * RGB_LUMINANCE_RED +
+ green * RGB_LUMINANCE_GREEN +
+ blue * RGB_LUMINANCE_BLUE;
+ *(float *) dst[0] = babl_trc_from_linear (trc, luminance);
+
+ if (dst_bands == 2)
+ *(float *) dst[1] = alpha;
+
+ BABL_PLANAR_STEP
+ }
+}
+
+
+static void
+gray_nonlinear_to_rgb_float (Babl *conversion,
+ int src_bands,
+ char **src,
+ int *src_pitch,
+ int dst_bands,
+ char **dst,
+ int *dst_pitch,
+ long n)
+{
+ const Babl *space = babl_conversion_get_source_space (conversion);
+ const Babl *trc = space->space.trc[0];
+
+ BABL_PLANAR_SANITY
+ while (n--)
+ {
+ float luminance;
+ float red, green, blue;
+ float alpha;
+
+ luminance = babl_trc_to_linear (trc, *(float *) src[0]);
+ red = luminance;
+ green = luminance;
+ blue = luminance;
+ if (src_bands > 1)
+ alpha = *(float *) src[1];
+ else
+ alpha = 1.0f;
+
+ *(float *) dst[0] = red;
+ *(float *) dst[1] = green;
+ *(float *) dst[2] = blue;
+
+ if (dst_bands > 3)
+ *(float *) dst[3] = alpha;
+
+ BABL_PLANAR_STEP
+ }
+}
+
+static void
+rgb_to_gray_perceptual_float (Babl *conversion,
+ int src_bands,
+ char **src,
+ int *src_pitch,
+ int dst_bands,
+ char **dst,
+ int *dst_pitch,
+ long n)
+{
+ const Babl *space = babl_conversion_get_destination_space (conversion);
+ const Babl *trc = perceptual_trc;
+ float RGB_LUMINANCE_RED = space->space.RGBtoXYZf[3];
+ float RGB_LUMINANCE_GREEN = space->space.RGBtoXYZf[4];
+ float RGB_LUMINANCE_BLUE = space->space.RGBtoXYZf[5];
+
+ BABL_PLANAR_SANITY
+ while (n--)
+ {
+ float red, green, blue;
+ float luminance, alpha;
+
+ red = *(float *) src[0];
+ green = *(float *) src[1];
+ blue = *(float *) src[2];
+ if (src_bands > 3)
+ alpha = *(float *) src[3];
+ else
+ alpha = 1.0f;
+
+ luminance = red * RGB_LUMINANCE_RED +
+ green * RGB_LUMINANCE_GREEN +
+ blue * RGB_LUMINANCE_BLUE;
+ *(float *) dst[0] = babl_trc_from_linear (trc, luminance);
+
+ if (dst_bands == 2)
+ *(float *) dst[1] = alpha;
+
+ BABL_PLANAR_STEP
+ }
+}
+
+static void
+gray_perceptual_to_rgb_float (Babl *conversion,
+ int src_bands,
+ char **src,
+ int *src_pitch,
+ int dst_bands,
+ char **dst,
+ int *dst_pitch,
+ long n)
+{
+ const Babl *trc = perceptual_trc;
+
+ BABL_PLANAR_SANITY
+ while (n--)
+ {
+ float luminance;
+ float red, green, blue;
+ float alpha;
+
+ luminance = babl_trc_to_linear (trc, *(float *) src[0]);
+ red = luminance;
+ green = luminance;
+ blue = luminance;
+ if (src_bands > 1)
+ alpha = *(float *) src[1];
+ else
+ alpha = 1.0f;
+
+ *(float *) dst[0] = red;
+ *(float *) dst[1] = green;
+ *(float *) dst[2] = blue;
+
+ if (dst_bands > 3)
+ *(float *) dst[3] = alpha;
+
+ BABL_PLANAR_STEP
+ }
+}
+
+
+static void
+graya_to_rgba_float (Babl *conversion,
+ char *src,
+ char *dst,
+ long n)
+{
+ while (n--)
+ {
+ float luminance;
+ float red, green, blue;
+ float alpha;
+
+ luminance = ((float *) src)[0];
+ alpha = ((float *) src)[1];
+ red = luminance;
+ green = luminance;
+ blue = luminance;
+
+ ((float *) dst)[0] = red;
+ ((float *) dst)[1] = green;
+ ((float *) dst)[2] = blue;
+ ((float *) dst)[3] = alpha;
+
+ src += sizeof (float) * 2;
+ dst += sizeof (float) * 4;
+ }
+}
+
+
+static void
+gray_to_rgba_float (Babl *conversion,
+ char *src,
+ char *dst,
+ long n)
+{
+ while (n--)
+ {
+ float luminance;
+ float red, green, blue;
+
+ luminance = ((float *) src)[0];
+ red = luminance;
+ green = luminance;
+ blue = luminance;
+
+ ((float *) dst)[0] = red;
+ ((float *) dst)[1] = green;
+ ((float *) dst)[2] = blue;
+ ((float *) dst)[3] = 1.0;
+
+ src += sizeof (float) * 1;
+ dst += sizeof (float) * 4;
+ }
+}
+
+static void
+gray_alpha_premultiplied_to_rgba_float (Babl *conversion,
+ int src_bands,
+ char **src,
+ int *src_pitch,
+ int dst_bands,
+ char **dst,
+ int *dst_pitch,
+ long n)
+{
+ BABL_PLANAR_SANITY
+ assert (src_bands == 2);
+ assert (dst_bands == 4);
+
+ while (n--)
+ {
+ float luminance = *(float *) src[0];
+ float alpha;
+ alpha = *(float *) src[1];
+ if (alpha == 0)
+ luminance = 0.0f;
+ else
+ {
+ luminance = luminance / alpha;
+ if (alpha == BABL_ALPHA_FLOOR || alpha == -BABL_ALPHA_FLOOR)
+ alpha = 0.0f;
+ }
+
+ *(float *) dst[0] = luminance;
+ *(float *) dst[1] = luminance;
+ *(float *) dst[2] = luminance;
+ *(float *) dst[3] = alpha;
+ BABL_PLANAR_STEP
+ }
+}
+
+
+static void
+rgba_to_gray_alpha_premultiplied_float (Babl *conversion,
+ int src_bands,
+ char **src,
+ int *src_pitch,
+ int dst_bands,
+ char **dst,
+ int *dst_pitch,
+ long n)
+{
+ const Babl *space = babl_conversion_get_source_space (conversion);
+ float RGB_LUMINANCE_RED = space->space.RGBtoXYZf[3];
+ float RGB_LUMINANCE_GREEN = space->space.RGBtoXYZf[4];
+ float RGB_LUMINANCE_BLUE = space->space.RGBtoXYZf[5];
+
+ BABL_PLANAR_SANITY;
+ assert (src_bands == 4);
+ assert (dst_bands == 2);
+
+ while (n--)
+ {
+ float red = *(float *) src[0];
+ float green = *(float *) src[1];
+ float blue = *(float *) src[2];
+ float luminance;
+ float alpha = *(float *) src[3];
+ if (alpha <= BABL_ALPHA_FLOOR)
+ {
+ if (alpha >= 0.0f)
+ alpha = BABL_ALPHA_FLOOR;
+ else if (alpha >= -BABL_ALPHA_FLOOR)
+ alpha = -BABL_ALPHA_FLOOR;
+ }
+
+ luminance = red * RGB_LUMINANCE_RED +
+ green * RGB_LUMINANCE_GREEN +
+ blue * RGB_LUMINANCE_BLUE;
+
+ luminance *= alpha;
+
+ *(float *) dst[0] = luminance;
+ *(float *) dst[1] = alpha;
+ BABL_PLANAR_STEP
+ }
+}
+
+static void
+non_premultiplied_to_premultiplied_float (Babl *conversion,
+ int src_bands,
+ char **src,
+ int *src_pitch,
+ int dst_bands,
+ char **dst,
+ int *dst_pitch,
+ long n)
+{
+ BABL_PLANAR_SANITY
+
+ while (n--)
+ {
+ int band;
+ float alpha = *(float *) src[src_bands-1];
+ if (alpha < BABL_ALPHA_FLOOR)
+ {
+ int non_zero_components = 0;
+ if (alpha >= 0.0f)
+ alpha = BABL_ALPHA_FLOOR;
+ else if (alpha >= -BABL_ALPHA_FLOOR)
+ alpha = -BABL_ALPHA_FLOOR;
+
+ for (band = 0; band < src_bands - 1; band++)
+ {
+ if (*(float *) src[band] != 0.0f)
+ non_zero_components++;
+ }
+ if (non_zero_components)
+ alpha = 0.0f;
+
+ }
+
+ for (band = 0; band < src_bands - 1; band++)
+ {
+ *(float *) dst[band] = *(float *) src[band] * alpha;
+ }
+ *(float *) dst[dst_bands - 1] = alpha;
+
+ BABL_PLANAR_STEP
+ }
+}
+
+static void
+premultiplied_to_non_premultiplied_float (Babl *conversion,
+ int src_bands,
+ char **src,
+ int *src_pitch,
+ int dst_bands,
+ char **dst,
+ int *dst_pitch,
+ long n)
+{
+ BABL_PLANAR_SANITY
+
+ while (n--)
+ {
+ int band;
+ float alpha;
+ alpha = *(float *) src[src_bands-1];
+
+ for (band = 0; band < src_bands - 1; band++)
+ {
+ if (alpha == 0.0f)
+ *(float *) dst[band] = 0.0f;
+ else
+ *(float *) dst[band] = *(float *) src[band] / alpha;
+ }
+ if (alpha == BABL_ALPHA_FLOOR || alpha == -BABL_ALPHA_FLOOR)
+ alpha = 0.0f;
+ *(float *) dst[dst_bands - 1] = alpha;
+
+ BABL_PLANAR_STEP
+ }
+}
+
+static void
+rgba2gray_nonlinear_premultiplied_float (Babl *conversion,
+ char *src,
+ char *dst,
+ long n)
+{
+ const Babl *space = babl_conversion_get_destination_space (conversion);
+ const Babl *trc = space->space.trc[0];
+ float RGB_LUMINANCE_RED = space->space.RGBtoXYZf[3];
+ float RGB_LUMINANCE_GREEN = space->space.RGBtoXYZf[4];
+ float RGB_LUMINANCE_BLUE = space->space.RGBtoXYZf[5];
+
+ while (n--)
+ {
+ float red = ((float *) src)[0];
+ float green = ((float *) src)[1];
+ float blue = ((float *) src)[2];
+ float luminance;
+ float luma;
+ float alpha = ((float *) src)[3];
+ if (alpha < BABL_ALPHA_FLOOR)
+ {
+ if (alpha >= 0.0f)
+ alpha = BABL_ALPHA_FLOOR;
+ else if (alpha >= -BABL_ALPHA_FLOOR)
+ alpha = -BABL_ALPHA_FLOOR;
+ }
+
+ luminance = red * RGB_LUMINANCE_RED +
+ green * RGB_LUMINANCE_GREEN +
+ blue * RGB_LUMINANCE_BLUE;
+ luma = babl_trc_from_linear (trc, luminance);
+
+ ((float *) dst)[0] = luma * alpha;
+ ((float *) dst)[1] = alpha;
+
+ src += 4 * sizeof (float);
+ dst += 2 * sizeof (float);
+ }
+}
+
+static void
+gray_nonlinear_premultiplied2rgba_float (Babl *conversion,
+ char *src,
+ char *dst,
+ long n)
+{
+ const Babl *space = babl_conversion_get_destination_space (conversion);
+ const Babl *trc = space->space.trc[0];
+
+ while (n--)
+ {
+ float luma = ((float *) src)[0];
+ float luminance;
+ float alpha;
+ alpha = ((float *) src)[1];
+ if (alpha == 0.0f)
+ luma = 0.0f;
+ else
+ luma = luma / alpha;
+
+ luminance = babl_trc_to_linear (trc, luma);
+
+ if (alpha == BABL_ALPHA_FLOOR || alpha == -BABL_ALPHA_FLOOR)
+ alpha = 0.0f;
+
+ ((float *) dst)[0] = luminance;
+ ((float *) dst)[1] = luminance;
+ ((float *) dst)[2] = luminance;
+ ((float *) dst)[3] = alpha;
+
+ src += 2 * sizeof (float);
+ dst += 4 * sizeof (float);
+ }
+}
+
+static void init_single_precision (void)
+{
+ babl_format_new (
+ babl_model ("Y"),
+ babl_type_from_id (BABL_FLOAT),
+ babl_component ("Y"),
+ NULL);
+ babl_format_new (
+ babl_model ("Y'"),
+ babl_type_from_id (BABL_FLOAT),
+ babl_component ("Y'"),
+ NULL);
+ babl_format_new (
+ babl_model ("Y~"),
+ babl_type_from_id (BABL_FLOAT),
+ babl_component ("Y~"),
+ NULL);
+
+
+ babl_format_new (
+ babl_model ("YA"),
+ babl_type_from_id (BABL_FLOAT),
+ babl_component ("Y"),
+ babl_component ("A"),
+ NULL);
+ babl_format_new (
+ babl_model ("Y'A"),
+ babl_type_from_id (BABL_FLOAT),
+ babl_component ("Y'"),
+ babl_component ("A"),
+ NULL);
+ babl_format_new (
+ babl_model ("Y~A"),
+ babl_type_from_id (BABL_FLOAT),
+ babl_component ("Y~"),
+ babl_component ("A"),
+ NULL);
+
+
+ babl_format_new (
+ babl_model ("YaA"),
+ babl_type_from_id (BABL_FLOAT),
+ babl_component ("Ya"),
+ babl_component ("A"),
+ NULL);
+ babl_format_new (
+ babl_model ("Y'aA"),
+ babl_type_from_id (BABL_FLOAT),
+ babl_component ("Y'a"),
+ babl_component ("A"),
+ NULL);
+
+ babl_conversion_new (
+ babl_format ("Y' float"),
+ babl_format ("RGBA float"),
+ "planar", gray_nonlinear_to_rgb_float,
+ NULL
+ );
+
+ babl_conversion_new (
+ babl_format ("RGBA float"),
+ babl_format ("Y' float"),
+ "planar", rgb_to_gray_nonlinear_float,
+ NULL
+ );
+
+ babl_conversion_new (
+ babl_format ("Y'A float"),
+ babl_format ("RGBA float"),
+ "planar", gray_nonlinear_to_rgb_float,
+ NULL
+ );
+
+ babl_conversion_new (
+ babl_format ("RGBA float"),
+ babl_format ("Y'A float"),
+ "planar", rgb_to_gray_nonlinear_float,
+ NULL
+ );
+
+
+ babl_conversion_new (
+ babl_format ("Y'aA float"),
+ babl_format ("RGBA float"),
+ "linear", gray_nonlinear_premultiplied2rgba_float,
+ NULL
+ );
+
+ babl_conversion_new (
+ babl_format ("RGBA float"),
+ babl_format ("Y'aA float"),
+ "linear", rgba2gray_nonlinear_premultiplied_float,
+ NULL
+ );
+
+
+
+ babl_conversion_new (
+ babl_format ("Y~ float"),
+ babl_format ("RGBA float"),
+ "planar", gray_perceptual_to_rgb_float,
+ NULL
+ );
+
+ babl_conversion_new (
+ babl_format ("RGBA float"),
+ babl_format ("Y~ float"),
+ "planar", rgb_to_gray_perceptual_float,
+ NULL
+ );
+
+ babl_conversion_new (
+ babl_format ("Y~A float"),
+ babl_format ("RGBA float"),
+ "planar", gray_perceptual_to_rgb_float,
+ NULL
+ );
+
+ babl_conversion_new (
+ babl_format ("RGBA float"),
+ babl_format ("Y~A float"),
+ "planar", rgb_to_gray_perceptual_float,
+ NULL
+ );
+
+
+ babl_conversion_new (
+ babl_format ("Y float"),
+ babl_format ("RGBA float"),
+ "linear", gray_to_rgba_float,
+ NULL
+ );
+
+ babl_conversion_new (
+ babl_format ("YA float"),
+ babl_format ("RGBA float"),
+ "linear", graya_to_rgba_float,
+ NULL
+ );
+
+ babl_conversion_new (
+ babl_format ("RGBA float"),
+ babl_format ("YA float"),
+ "linear", rgba_to_graya_float,
+ NULL
+ );
+
+ babl_conversion_new (
+ babl_format ("RGBA float"),
+ babl_format ("Y float"),
+ "linear", rgba_to_gray_float,
+ NULL
+ );
+
+ babl_conversion_new (
+ babl_format ("YA float"),
+ babl_format ("YaA float"),
+ "planar", non_premultiplied_to_premultiplied_float,
+ NULL
+ );
+
+ babl_conversion_new (
+ babl_format ("YaA float"),
+ babl_format ("YA float"),
+ "planar", premultiplied_to_non_premultiplied_float,
+ NULL
+ );
+
+ babl_conversion_new (
+ babl_format ("YaA float"),
+ babl_format ("RGBA float"),
+ "planar", gray_alpha_premultiplied_to_rgba_float,
+ NULL
+ );
+
+ babl_conversion_new (
+ babl_format ("RGBA float"),
+ babl_format ("YaA float"),
+ "planar", rgba_to_gray_alpha_premultiplied_float,
+ NULL
+ );
+}
diff --git a/babl/base/model-rgb.c b/babl/base/model-rgb.c
index 66e16ab..39c8afb 100644
--- a/babl/base/model-rgb.c
+++ b/babl/base/model-rgb.c
@@ -29,6 +29,7 @@ static void models (void);
static void components (void);
static void conversions (void);
static void formats (void);
+static void init_single_precision (void);
void
babl_base_model_rgb (void)
@@ -37,6 +38,7 @@ babl_base_model_rgb (void)
models ();
conversions ();
formats ();
+ init_single_precision ();
}
static void
@@ -273,6 +275,7 @@ g3_nonlinear_from_linear (Babl *conversion,
}
}
+
static void
g3_nonlinear_to_linear (Babl *conversion,
int src_bands,
@@ -306,6 +309,9 @@ g3_nonlinear_to_linear (Babl *conversion,
}
}
+
+
+
static void
non_premultiplied_to_premultiplied (Babl *conversion,
int src_bands,
@@ -321,10 +327,17 @@ non_premultiplied_to_premultiplied (Babl *conversion,
BABL_PLANAR_SANITY
while (n--)
{
- double alpha;
+ double alpha = *(double *) src[src_bands - 1];
int band;
- alpha = *(double *) src[src_bands - 1];
+ if (alpha < BABL_ALPHA_FLOOR)
+ {
+ if (alpha >= 0.0)
+ alpha = BABL_ALPHA_FLOOR;
+ else if (alpha >= -BABL_ALPHA_FLOOR)
+ alpha = -BABL_ALPHA_FLOOR;
+ }
+
for (band = 0; band < src_bands - 1; band++)
{
*(double *) dst[band] = *(double *) src[band] * alpha;
@@ -335,6 +348,9 @@ non_premultiplied_to_premultiplied (Babl *conversion,
}
}
+
+
+
static void
premultiplied_to_non_premultiplied (Babl *conversion,
int src_bands,
@@ -351,20 +367,21 @@ premultiplied_to_non_premultiplied (Babl *conversion,
while (n--)
{
double alpha;
+ double recip_alpha;
int band;
alpha = *(double *) src[src_bands - 1];
- if (alpha > BABL_ALPHA_THRESHOLD)
- {
- double recip_alpha = 1.0 / alpha;
- for (band = 0; band < src_bands - 1; band++)
- *(double *) dst[band] = *(double *) src[band] * recip_alpha;
- }
+ if (alpha == 0.0)
+ recip_alpha = 0.0;
else
- {
- for (band = 0; band < src_bands - 1; band++)
- *(double *) dst[band] = 0.0;
- }
+ {
+ recip_alpha = 1.0 / alpha;
+ if (alpha == BABL_ALPHA_FLOOR)
+ alpha = 0.0; // making 0 round-trip to zero, causing discontinuity
+ }
+
+ for (band = 0; band < src_bands - 1; band++)
+ *(double *) dst[band] = *(double *) src[band] * recip_alpha;
*(double *) dst[dst_bands - 1] = alpha;
BABL_PLANAR_STEP
@@ -385,6 +402,14 @@ rgba2rgba_nonlinear_premultiplied (Babl *conversion,
while (n--)
{
double alpha = ((double *) src)[3];
+ if (alpha <= BABL_ALPHA_FLOOR)
+ {
+ if (alpha >= 0.0f)
+ alpha = BABL_ALPHA_FLOOR;
+ else if (alpha >= -BABL_ALPHA_FLOOR)
+ alpha = -BABL_ALPHA_FLOOR;
+ }
+
((double *) dst)[0] = babl_trc_from_linear (trc[0], ((double *) src)[0]) * alpha;
((double *) dst)[1] = babl_trc_from_linear (trc[1], ((double *) src)[1]) * alpha;
((double *) dst)[2] = babl_trc_from_linear (trc[2], ((double *) src)[2]) * alpha;
@@ -395,6 +420,8 @@ rgba2rgba_nonlinear_premultiplied (Babl *conversion,
}
+
+
static void
rgba_nonlinear_premultiplied2rgba (Babl *conversion,
char *src,
@@ -407,19 +434,22 @@ rgba_nonlinear_premultiplied2rgba (Babl *conversion,
while (n--)
{
- double alpha = ((double *) src)[3];
- if (alpha > BABL_ALPHA_THRESHOLD)
- {
- ((double *) dst)[0] = babl_trc_to_linear (trc[0], ((double *) src)[0] / alpha);
- ((double *) dst)[1] = babl_trc_to_linear (trc[1], ((double *) src)[1] / alpha);
- ((double *) dst)[2] = babl_trc_to_linear (trc[2], ((double *) src)[2] / alpha);
- }
+ double alpha, reciprocal;
+ alpha = ((double *) src)[3];
+ if (alpha == 0.0)
+ {
+ reciprocal= 0.0f;
+ }
else
- {
- ((double *) dst)[0] = 0.0;
- ((double *) dst)[1] = 0.0;
- ((double *) dst)[2] = 0.0;
- }
+ {
+ reciprocal= 1.0 / alpha;
+ if (alpha == BABL_ALPHA_FLOOR || alpha == -BABL_ALPHA_FLOOR)
+ alpha = 0;
+ }
+
+ ((double *) dst)[0] = babl_trc_to_linear (trc[0], ((double *) src)[0] * reciprocal);
+ ((double *) dst)[1] = babl_trc_to_linear (trc[1], ((double *) src)[1] * reciprocal);
+ ((double *) dst)[2] = babl_trc_to_linear (trc[2], ((double *) src)[2] * reciprocal);
((double *) dst)[3] = alpha;
src += 4 * sizeof (double);
@@ -428,6 +458,8 @@ rgba_nonlinear_premultiplied2rgba (Babl *conversion,
}
+
+
static void
rgba2rgba_nonlinear (Babl *conversion,
char *src,
@@ -548,6 +580,15 @@ rgba2rgba_perceptual_premultiplied (Babl *conversion,
while (n--)
{
double alpha = ((double *) src)[3];
+
+ if (alpha <= BABL_ALPHA_FLOOR)
+ {
+ if (alpha >= 0.0f)
+ alpha = BABL_ALPHA_FLOOR;
+ else if (alpha >= -BABL_ALPHA_FLOOR)
+ alpha = -BABL_ALPHA_FLOOR;
+ }
+
((double *) dst)[0] = babl_trc_from_linear (trc, ((double *) src)[0]) * alpha;
((double *) dst)[1] = babl_trc_from_linear (trc, ((double *) src)[1]) * alpha;
((double *) dst)[2] = babl_trc_from_linear (trc, ((double *) src)[2]) * alpha;
@@ -560,28 +601,30 @@ rgba2rgba_perceptual_premultiplied (Babl *conversion,
static void
rgba_perceptual_premultiplied2rgba (Babl *conversion,
- char *src,
- char *dst,
- long samples)
+ char *src,
+ char *dst,
+ long samples)
{
const Babl *trc = perceptual_trc;
long n = samples;
while (n--)
{
- double alpha = ((double *) src)[3];
- if (alpha > BABL_ALPHA_THRESHOLD)
- {
- ((double *) dst)[0] = babl_trc_to_linear (trc, ((double *) src)[0] / alpha);
- ((double *) dst)[1] = babl_trc_to_linear (trc, ((double *) src)[1] / alpha);
- ((double *) dst)[2] = babl_trc_to_linear (trc, ((double *) src)[2] / alpha);
- }
+ double alpha, reciprocal;
+ alpha = ((double *) src)[3];
+ if (alpha == 0)
+ {
+ reciprocal = 0.0;
+ }
else
- {
- ((double *) dst)[0] = 0.0;
- ((double *) dst)[1] = 0.0;
- ((double *) dst)[2] = 0.0;
- }
+ {
+ reciprocal = 1.0/alpha;
+ if(alpha == BABL_ALPHA_FLOOR || alpha == -BABL_ALPHA_FLOOR)
+ alpha = 0.0;
+ }
+ ((double *) dst)[0] = babl_trc_to_linear (trc, ((double *) src)[0] * reciprocal);
+ ((double *) dst)[1] = babl_trc_to_linear (trc, ((double *) src)[1] * reciprocal);
+ ((double *) dst)[2] = babl_trc_to_linear (trc, ((double *) src)[2] * reciprocal);
((double *) dst)[3] = alpha;
src += 4 * sizeof (double);
@@ -667,7 +710,6 @@ conversions (void)
"planar", non_premultiplied_to_premultiplied,
NULL
);
-
babl_conversion_new (
babl_model_from_id (BABL_RGBA_PREMULTIPLIED),
babl_model_from_id (BABL_RGBA),
@@ -688,6 +730,7 @@ conversions (void)
NULL
);
+
babl_conversion_new (
babl_model_from_id (BABL_RGBA),
babl_model_from_id (BABL_RGBA_NONLINEAR),
@@ -920,6 +963,14 @@ formats (void)
NULL);
babl_format_new (
+ babl_model_from_id (BABL_RGB_NONLINEAR),
+ babl_type ("float"),
+ babl_component_from_id (BABL_RED_NONLINEAR),
+ babl_component_from_id (BABL_GREEN_NONLINEAR),
+ babl_component_from_id (BABL_BLUE_NONLINEAR),
+ NULL);
+
+ babl_format_new (
babl_model_from_id (BABL_RGBA_NONLINEAR),
babl_type ("u15"),
babl_component_from_id (BABL_RED_NONLINEAR),
@@ -990,6 +1041,14 @@ formats (void)
babl_component_from_id (BABL_ALPHA),
NULL);
+ babl_format_new (
+ babl_model_from_id (BABL_RGBA_NONLINEAR_PREMULTIPLIED),
+ babl_type_from_id (BABL_FLOAT),
+ babl_component_from_id (BABL_RED_NONLINEAR_MUL_ALPHA),
+ babl_component_from_id (BABL_GREEN_NONLINEAR_MUL_ALPHA),
+ babl_component_from_id (BABL_BLUE_NONLINEAR_MUL_ALPHA),
+ babl_component_from_id (BABL_ALPHA),
+ NULL);
babl_format_new (
babl_model_from_id (BABL_RGB_PERCEPTUAL),
@@ -1017,6 +1076,7 @@ formats (void)
babl_component_from_id (BABL_ALPHA),
NULL);
+
#ifdef XXXX
babl_format_new (
"id", BABL_RGB565,
@@ -1027,5 +1087,478 @@ formats (void)
);
#endif
+
+
+}
+
+
+static void
+g3_nonlinear_from_linear_float (Babl *conversion,
+ int src_bands,
+ char **src,
+ int *src_pitch,
+ int dst_bands,
+ char **dst,
+ int *dst_pitch,
+ long samples)
+{
+ const Babl *space = babl_conversion_get_destination_space (conversion);
+ const Babl **trc = (void*)space->space.trc;
+
+ long n = samples;
+
+ BABL_PLANAR_SANITY
+ while (n--)
+ {
+ int band;
+ for (band = 0; band < 3; band++)
+ *(float *) dst[band] = babl_trc_from_linear (trc[band], (*(float *) src[band]));
+ for (; band < dst_bands; band++)
+ *(float *) dst[band] = *(float *) src[band];
+
+ BABL_PLANAR_STEP
+ }
+}
+
+
+static void
+g3_nonlinear_to_linear_float (Babl *conversion,
+ int src_bands,
+ char **src,
+ int *src_pitch,
+ int dst_bands,
+ char **dst,
+ int *dst_pitch,
+ long samples)
+{
+ const Babl *space = babl_conversion_get_source_space (conversion);
+ const Babl **trc = (void*)space->space.trc;
+ long n = samples;
+
+ BABL_PLANAR_SANITY
+ while (n--)
+ {
+ int band;
+ for (band = 0; band < 3; band++)
+ {
+ *(float *) dst[band] = babl_trc_to_linear (trc[band], (*(float *) src[band]));
+ }
+ for (; band < dst_bands; band++)
+ {
+ if (band < src_bands)
+ *(float *) dst[band] = *(float *) src[band];
+ else
+ *(float *) dst[band] = 1.0f;
+ }
+ BABL_PLANAR_STEP
+ }
+}
+
+
+static void
+non_premultiplied_to_premultiplied_float (Babl *conversion,
+ int src_bands,
+ char **src,
+ int *src_pitch,
+ int dst_bands,
+ char **dst,
+ int *dst_pitch,
+ long samples)
+{
+ long n = samples;
+
+ BABL_PLANAR_SANITY
+ while (n--)
+ {
+ float alpha = *(float *) src[src_bands - 1];
+ int band;
+
+ if (alpha < BABL_ALPHA_FLOOR)
+ {
+ int non_zero_components = 0;
+ if (alpha >= 0.0f)
+ alpha = BABL_ALPHA_FLOOR;
+ else if (alpha >= -BABL_ALPHA_FLOOR)
+ alpha = -BABL_ALPHA_FLOOR;
+ for (band = 0 ; band< src_bands-1; band++)
+ if (*(float *) src[band] != 0.0f)
+ non_zero_components++;
+ if (non_zero_components == 0)
+ alpha = 0.0f;
+ }
+
+ for (band = 0; band < src_bands - 1; band++)
+ {
+ *(float *) dst[band] = *(float *) src[band] * alpha;
+ }
+ *(float *) dst[dst_bands - 1] = alpha;
+
+ BABL_PLANAR_STEP
+ }
+}
+
+
+static void
+premultiplied_to_non_premultiplied_float (Babl *conversion,
+ int src_bands,
+ char **src,
+ int *src_pitch,
+ int dst_bands,
+ char **dst,
+ int *dst_pitch,
+ long samples)
+{
+ long n = samples;
+
+ BABL_PLANAR_SANITY
+ while (n--)
+ {
+ float alpha;
+ float recip_alpha;
+ int band;
+
+ alpha = *(float *) src[src_bands - 1];
+ if (alpha == 0.0f)
+ recip_alpha = 0.0f;
+ else
+ {
+ recip_alpha = 1.0f / alpha;
+ if (alpha == BABL_ALPHA_FLOOR)
+ alpha = 0.0f; // making 0 round-trip to zero, causing discontinuity
+ }
+
+ for (band = 0; band < src_bands - 1; band++)
+ *(float *) dst[band] = *(float *) src[band] * recip_alpha;
+ *(float *) dst[dst_bands - 1] = alpha;
+
+ BABL_PLANAR_STEP
+ }
+}
+
+
+static void
+rgba2rgba_nonlinear_premultiplied_float (Babl *conversion,
+ char *src,
+ char *dst,
+ long samples)
+{
+ const Babl *space = babl_conversion_get_destination_space (conversion);
+ const Babl **trc = (void*)space->space.trc;
+ long n = samples;
+
+ while (n--)
+ {
+ float alpha = ((float *) src)[3];
+ if (alpha <= BABL_ALPHA_FLOOR)
+ {
+ if (alpha >= 0.0f)
+ alpha = BABL_ALPHA_FLOOR;
+ else if (alpha >= -BABL_ALPHA_FLOOR)
+ alpha = -BABL_ALPHA_FLOOR;
+ if (((float *) src)[0] == 0.0 &&
+ ((float *) src)[1] == 0.0 &&
+ ((float *) src)[2] == 0.0)
+ alpha = 0.0;
+ }
+
+ ((float *) dst)[0] = babl_trc_from_linear (trc[0], ((float *) src)[0]) * alpha;
+ ((float *) dst)[1] = babl_trc_from_linear (trc[1], ((float *) src)[1]) * alpha;
+ ((float *) dst)[2] = babl_trc_from_linear (trc[2], ((float *) src)[2]) * alpha;
+ ((float *) dst)[3] = alpha;
+ src += 4 * sizeof (float);
+ dst += 4 * sizeof (float);
+ }
+}
+
+
+static void
+rgba_nonlinear_premultiplied2rgba_float (Babl *conversion,
+ char *src,
+ char *dst,
+ long samples)
+{
+ const Babl *space = babl_conversion_get_source_space (conversion);
+ const Babl **trc = (void*)space->space.trc;
+ long n = samples;
+
+ while (n--)
+ {
+ float alpha, reciprocal;
+ alpha = ((float *) src)[3];
+ if (alpha == 0.0)
+ {
+ reciprocal= 0.0f;
+ }
+ else
+ {
+ reciprocal= 1.0 / alpha;
+ if (alpha == BABL_ALPHA_FLOOR || alpha == -BABL_ALPHA_FLOOR)
+ alpha = 0;
+ }
+
+ ((float *) dst)[0] = babl_trc_to_linear (trc[0], ((float *) src)[0] * reciprocal);
+ ((float *) dst)[1] = babl_trc_to_linear (trc[1], ((float *) src)[1] * reciprocal);
+ ((float *) dst)[2] = babl_trc_to_linear (trc[2], ((float *) src)[2] * reciprocal);
+ ((float *) dst)[3] = alpha;
+
+ src += 4 * sizeof (float);
+ dst += 4 * sizeof (float);
+ }
+}
+
+
+static void
+rgba2rgba_float (Babl *conversion,
+ char *src,
+ char *dst,
+ long samples)
+{
+ long n = samples;
+
+ while (n--)
+ {
+ ((float *) dst)[0] = ((float *) src)[0];
+ ((float *) dst)[1] = ((float *) src)[1];
+ ((float *) dst)[2] = ((float *) src)[2];
+ ((float *) dst)[3] = ((float *) src)[3];
+ src += 4 * sizeof (float);
+ dst += 4 * sizeof (float);
+ }
}
+
+static void
+rgba2rgba_perceptual_float (Babl *conversion,
+ char *src,
+ char *dst,
+ long samples)
+{
+ const Babl *trc = perceptual_trc;
+ long n = samples;
+
+ while (n--)
+ {
+ float alpha = ((float *) src)[3];
+ ((float *) dst)[0] = babl_trc_from_linear (trc, ((float *) src)[0]);
+ ((float *) dst)[1] = babl_trc_from_linear (trc, ((float *) src)[1]);
+ ((float *) dst)[2] = babl_trc_from_linear (trc, ((float *) src)[2]);
+ ((float *) dst)[3] = alpha;
+ src += 4 * sizeof (float);
+ dst += 4 * sizeof (float);
+ }
+}
+
+static void
+rgba_perceptual2rgba_float (Babl *conversion,
+ char *src,
+ char *dst,
+ long samples)
+{
+ const Babl *trc = perceptual_trc;
+ long n = samples;
+
+ while (n--)
+ {
+ float alpha = ((float *) src)[3];
+ ((float *) dst)[0] = babl_trc_to_linear (trc, ((float *) src)[0]);
+ ((float *) dst)[1] = babl_trc_to_linear (trc, ((float *) src)[1]);
+ ((float *) dst)[2] = babl_trc_to_linear (trc, ((float *) src)[2]);
+ ((float *) dst)[3] = alpha;
+
+ src += 4 * sizeof (float);
+ dst += 4 * sizeof (float);
+ }
+}
+
+
+static void
+g3_perceptual_from_linear_float (Babl *conversion,
+ int src_bands,
+ char **src,
+ int *src_pitch,
+ int dst_bands,
+ char **dst,
+ int *dst_pitch,
+ long samples)
+{
+ const Babl *trc = perceptual_trc;
+
+ long n = samples;
+
+ BABL_PLANAR_SANITY
+ while (n--)
+ {
+ int band;
+ for (band = 0; band < 3; band++)
+ *(float *) dst[band] = babl_trc_from_linear (trc, (*(float *) src[band]));
+ for (; band < dst_bands; band++)
+ *(float *) dst[band] = *(float *) src[band];
+
+ BABL_PLANAR_STEP
+ }
+}
+
+static void
+g3_perceptual_to_linear_float (Babl *conversion,
+ int src_bands,
+ char **src,
+ int *src_pitch,
+ int dst_bands,
+ char **dst,
+ int *dst_pitch,
+ long samples)
+{
+ const Babl *trc = perceptual_trc;
+ long n = samples;
+
+ BABL_PLANAR_SANITY
+ while (n--)
+ {
+ int band;
+ for (band = 0; band < 3; band++)
+ {
+ *(float *) dst[band] = babl_trc_to_linear (trc, (*(float *) src[band]));
+ }
+ for (; band < dst_bands; band++)
+ {
+ if (band < src_bands)
+ *(float *) dst[band] = *(float *) src[band];
+ else
+ *(float *) dst[band] = 1.0;
+ }
+ BABL_PLANAR_STEP
+ }
+}
+
+
+static void init_single_precision (void)
+{
+
+ babl_format_new (
+ babl_model_from_id (BABL_RGBA_PREMULTIPLIED),
+ babl_type_from_id (BABL_FLOAT),
+ babl_component_from_id (BABL_RED_MUL_ALPHA),
+ babl_component_from_id (BABL_GREEN_MUL_ALPHA),
+ babl_component_from_id (BABL_BLUE_MUL_ALPHA),
+ babl_component_from_id (BABL_ALPHA),
+ NULL);
+
+ babl_format_new (
+ babl_model_from_id (BABL_RGBA_NONLINEAR),
+ babl_type_from_id (BABL_FLOAT),
+ babl_component_from_id (BABL_RED_NONLINEAR),
+ babl_component_from_id (BABL_GREEN_NONLINEAR),
+ babl_component_from_id (BABL_BLUE_NONLINEAR),
+ babl_component_from_id (BABL_ALPHA),
+ NULL);
+
+ babl_format_new (
+ babl_model_from_id (BABL_RGBA_PERCEPTUAL),
+ babl_type_from_id (BABL_FLOAT),
+ babl_component_from_id (BABL_RED_PERCEPTUAL),
+ babl_component_from_id (BABL_GREEN_PERCEPTUAL),
+ babl_component_from_id (BABL_BLUE_PERCEPTUAL),
+ babl_component_from_id (BABL_ALPHA),
+ NULL);
+
+ babl_format_new (
+ babl_model_from_id (BABL_RGB_PERCEPTUAL),
+ babl_type_from_id (BABL_FLOAT),
+ babl_component_from_id (BABL_RED_PERCEPTUAL),
+ babl_component_from_id (BABL_GREEN_PERCEPTUAL),
+ babl_component_from_id (BABL_BLUE_PERCEPTUAL),
+ NULL);
+
+
+ babl_conversion_new (
+ babl_format ("RGBA float"),
+ babl_format ("RGBA float"),
+ "linear", rgba2rgba_float,
+ NULL
+ );
+
+ babl_conversion_new (
+ babl_format ("R'G'B' float"),
+ babl_format ("RGBA float"),
+ "planar", g3_nonlinear_to_linear_float,
+ NULL
+ );
+
+ babl_conversion_new (
+ babl_format ("RGBA float"),
+ babl_format ("R'G'B' float"),
+ "planar", g3_nonlinear_from_linear_float,
+ NULL
+ );
+ babl_conversion_new (
+ babl_format ("R'G'B'A float"),
+ babl_format ("RGBA float"),
+ "planar", g3_nonlinear_to_linear_float,
+ NULL
+ );
+
+
+ babl_conversion_new (
+ babl_format ("R~G~B~ float"),
+ babl_format ("RGBA float"),
+ "planar", g3_perceptual_to_linear_float,
+ NULL
+ );
+
+ babl_conversion_new (
+ babl_format ("RGBA float"),
+ babl_format ("R~G~B~ float"),
+ "planar", g3_perceptual_from_linear_float,
+ NULL
+ );
+
+
+
+ babl_conversion_new (
+ babl_format ("RGBA float"),
+ babl_format ("R~G~B~A float"),
+ "linear", rgba2rgba_perceptual_float,
+ NULL
+ );
+ babl_conversion_new (
+ babl_format ("R~G~B~A float"),
+ babl_format ("RGBA float"),
+ "linear", rgba_perceptual2rgba_float,
+ NULL
+ );
+
+ babl_conversion_new (
+ babl_format ("RGBA float"),
+ babl_format ("R'G'B'A float"),
+ "planar", g3_nonlinear_from_linear_float,
+ NULL
+ );
+
+
+ babl_conversion_new (
+ babl_format ("RGBA float"),
+ babl_format ("R'aG'aB'aA float"),
+ "linear", rgba2rgba_nonlinear_premultiplied_float,
+ NULL);
+ babl_conversion_new (
+ babl_format ("R'aG'aB'aA float"),
+ babl_format ("RGBA float"),
+ "linear", rgba_nonlinear_premultiplied2rgba_float,
+ NULL);
+
+
+ babl_conversion_new (
+ babl_format ("RGBA float"),
+ babl_format ("RaGaBaA float"),
+ "planar", non_premultiplied_to_premultiplied_float,
+ NULL
+ );
+ babl_conversion_new (
+ babl_format ("RaGaBaA float"),
+ babl_format ("RGBA float"),
+ "planar", premultiplied_to_non_premultiplied_float,
+ NULL
+ );
+
+
+}
diff --git a/babl/base/type-float.c b/babl/base/type-float.c
index 750d836..4a09f3e 100644
--- a/babl/base/type-float.c
+++ b/babl/base/type-float.c
@@ -57,6 +57,31 @@ convert_float_double (BablConversion *conversion,
}
}
+static long
+convert_float_float (const Babl *babl,
+ char *src,
+ char *dst,
+ int src_pitch,
+ int dst_pitch,
+ long n)
+{
+ if (src_pitch == 32 &&
+ dst_pitch == 32)
+ {
+ memcpy (dst, src, n / 4);
+ return n;
+ }
+
+ while (n--)
+ {
+ (*(float *) dst) = (*(float *) src);
+ dst += dst_pitch;
+ src += src_pitch;
+ }
+ return n;
+}
+
+
void
babl_base_type_float (void)
{
@@ -79,4 +104,11 @@ babl_base_type_float (void)
"plane", convert_double_float,
NULL
);
+
+ babl_conversion_new (
+ babl_type_from_id (BABL_FLOAT),
+ babl_type_from_id (BABL_FLOAT),
+ "plane", convert_float_float,
+ NULL
+ );
}
diff --git a/babl/base/type-half.c b/babl/base/type-half.c
index 93d5e5b..d163300 100644
--- a/babl/base/type-half.c
+++ b/babl/base/type-half.c
@@ -183,6 +183,139 @@ static void halfp2doubles(void *target, void *source, long numel)
}
}
+
+static void
+singles2halfp(uint16_t *hp, const uint32_t *xp, int numel)
+{
+
+ uint16_t hs, he, hm;
+ uint32_t x, xs, xe, xm;
+ int hes;
+
+
+
+ if( hp== NULL || xp== NULL ) { // Nothing to convert (e.g., imag part of pure real)
+ return;
+ }
+
+ while( numel-- ) {
+ x = *xp++;
+ if( (x & 0x7FFFFFFFu) == 0 ) { // Signed zero
+ *hp++ = (uint16_t) (x >> 16); // Return the signed zero
+ } else { // Not zero
+ xs = x & 0x80000000u; // Pick off sign bit
+ xe = x & 0x7F800000u; // Pick off exponent bits
+ xm = x & 0x007FFFFFu; // Pick off mantissa bits
+ if( xe == 0 ) { // Denormal will underflow, return a signed zero
+ *hp++ = (uint16_t) (xs >> 16);
+ } else if( xe == 0x7F800000u ) { // Inf or NaN (all the exponent bits are set)
+ if( xm == 0 ) { // If mantissa is zero ...
+ *hp++ = (uint16_t) ((xs >> 16) | 0x7C00u); // Signed Inf
+ } else {
+ *hp++ = (uint16_t) 0xFE00u; // NaN, only 1st mantissa bit set
+ }
+ } else { // Normalized number
+ hs = (uint16_t) (xs >> 16); // Sign bit
+ hes = ((int)(xe >> 23)) - 127 + 15; // Exponent unbias the single, then bias the halfp
+ if( hes >= 0x1F ) { // Overflow
+ *hp++ = (uint16_t) ((xs >> 16) | 0x7C00u); // Signed Inf
+ } else if( hes <= 0 ) { // Underflow
+ if( (14 - hes) > 24 ) { // Mantissa shifted all the way off & no rounding possibility
+ hm = (uint16_t) 0u; // Set mantissa to zero
+ } else {
+ xm |= 0x00800000u; // Add the hidden leading bit
+ hm = (uint16_t) (xm >> (14 - hes)); // Mantissa
+ if( (xm >> (13 - hes)) & 0x00000001u ) // Check for rounding
+ hm += (uint16_t) 1u; // Round, might overflow into exp bit, but this is OK
+ }
+ *hp++ = (hs | hm); // Combine sign bit and mantissa bits, biased exponent is zero
+ } else {
+ he = (uint16_t) (hes << 10); // Exponent
+ hm = (uint16_t) (xm >> 13); // Mantissa
+ if( xm & 0x00001000u ) // Check for rounding
+ *hp++ = (hs | he | hm) + (uint16_t) 1u; // Round, might overflow to inf, this is OK
+ else
+ *hp++ = (hs | he | hm); // No rounding
+ }
+ }
+ }
+ }
+ return;
+}
+
+
+
+
+
+//-----------------------------------------------------------------------------
+//
+// Routine: halfp2singles
+//
+// Input: source = address of 16-bit data to convert
+// numel = Number of values at that address to convert
+//
+// Output: target = Address of 32-bit floating point data to hold output (numel values)
+//
+//
+// Programmer: James Tursa
+//
+//-----------------------------------------------------------------------------
+
+static void
+halfp2singles(uint32_t *xp, const uint16_t *hp, int numel)
+{
+
+ uint16_t h, hs, he, hm;
+ uint32_t xs, xe, xm;
+ int32_t xes;
+ int e;
+
+
+
+ if( xp == NULL || hp == NULL ) // Nothing to convert (e.g., imag part of pure real)
+ return;
+
+ while( numel-- ) {
+ h = *hp++;
+ if( (h & 0x7FFFu) == 0 ) { // Signed zero
+ *xp++ = ((uint32_t) h) << 16; // Return the signed zero
+ } else { // Not zero
+ hs = h & 0x8000u; // Pick off sign bit
+ he = h & 0x7C00u; // Pick off exponent bits
+ hm = h & 0x03FFu; // Pick off mantissa bits
+ if( he == 0 ) { // Denormal will convert to normalized
+ e = -1; // The following loop figures out how much extra to adjust the exponent
+ do {
+ e++;
+ hm <<= 1;
+ } while( (hm & 0x0400u) == 0 ); // Shift until leading bit overflows into exponent bit
+ xs = ((uint32_t) hs) << 16; // Sign bit
+ xes = ((int32_t) (he >> 10)) - 15 + 127 - e; // Exponent unbias the halfp, then bias the single
+ xe = (uint32_t) (xes << 23); // Exponent
+ xm = ((uint32_t) (hm & 0x03FFu)) << 13; // Mantissa
+ *xp++ = (xs | xe | xm); // Combine sign bit, exponent bits, and mantissa bits
+ } else if( he == 0x7C00u ) { // Inf or NaN (all the exponent bits are set)
+ if( hm == 0 ) { // If mantissa is zero ...
+ *xp++ = (((uint32_t) hs) << 16) | ((uint32_t) 0x7F800000u); // Signed Inf
+ } else {
+ *xp++ = (uint32_t) 0xFFC00000u; // NaN, only 1st mantissa bit set
+ }
+ } else { // Normalized number
+ xs = ((uint32_t) hs) << 16; // Sign bit
+ xes = ((int32_t) (he >> 10)) - 15 + 127; // Exponent unbias the halfp, then bias the single
+ xe = (uint32_t) (xes << 23); // Exponent
+ xm = ((uint32_t) hm) << 13; // Mantissa
+ *xp++ = (xs | xe | xm); // Combine sign bit, exponent bits, and mantissa bits
+ }
+ }
+ }
+ return;
+}
+
+
+
+
+
static void
convert_double_half (BablConversion *conversion,
char *src,
@@ -215,6 +348,42 @@ convert_half_double (BablConversion *conversion,
}
}
+
+static void
+convert_float_half (BablConversion *conversion,
+ char *src,
+ char *dst,
+ int src_pitch,
+ int dst_pitch,
+ long n)
+{
+ while (n--)
+ {
+ singles2halfp ((void*)dst, (void*)src, 1);
+ dst += dst_pitch;
+ src += src_pitch;
+ }
+}
+
+static void
+convert_half_float (BablConversion *conversion,
+ char *src,
+ char *dst,
+ int src_pitch,
+ int dst_pitch,
+ long n)
+{
+ while (n--)
+ {
+ halfp2singles ((void*)dst, (void*)src, 1);
+ dst += dst_pitch;
+ src += src_pitch;
+ }
+}
+
+
+
+
void
babl_base_type_half (void)
{
@@ -237,4 +406,18 @@ babl_base_type_half (void)
"plane", convert_double_half,
NULL
);
+
+ babl_conversion_new (
+ babl_type_from_id (BABL_HALF),
+ babl_type_from_id (BABL_FLOAT),
+ "plane", convert_half_float,
+ NULL
+ );
+
+ babl_conversion_new (
+ babl_type_from_id (BABL_FLOAT),
+ babl_type_from_id (BABL_HALF),
+ "plane", convert_float_half,
+ NULL
+ );
}
diff --git a/babl/base/type-u15.c b/babl/base/type-u15.c
index 1f1efe0..c3216f8 100644
--- a/babl/base/type-u15.c
+++ b/babl/base/type-u15.c
@@ -111,6 +111,92 @@ convert_u15_double_scaled (BablConversion *conversion,
MAKE_CONVERSIONS (u15, 0.0, 1.0, 0, (1<<15))
+
+static inline void
+convert_float_u15_scaled (BablConversion *conversion,
+ float min_val,
+ float max_val,
+ uint16_t min,
+ uint16_t max,
+ char *src,
+ char *dst,
+ int src_pitch,
+ int dst_pitch,
+ long n)
+{
+ while (n--)
+ {
+ float dval = *(float *) src;
+ uint16_t u15val;
+
+ if (dval < min_val)
+ u15val = min;
+ else if (dval > max_val)
+ u15val = max;
+ else
+ u15val = rint ((dval - min_val) / (max_val - min_val) * (max - min) + min);
+
+ *(uint16_t *) dst = u15val;
+ dst += dst_pitch;
+ src += src_pitch;
+ }
+}
+
+static inline void
+convert_u15_float_scaled (BablConversion *conversion,
+ float min_val,
+ float max_val,
+ uint16_t min,
+ uint16_t max,
+ char *src,
+ char *dst,
+ int src_pitch,
+ int dst_pitch,
+ long n)
+{
+ while (n--)
+ {
+ int u15val = *(uint16_t *) src;
+ float dval;
+
+ if (u15val < min)
+ dval = min_val;
+ else if (u15val > max)
+ dval = max_val;
+ else
+ dval = (u15val - min) / (float) (max - min) * (max_val - min_val) + min_val;
+
+ (*(float *) dst) = dval;
+ dst += dst_pitch;
+ src += src_pitch;
+ }
+}
+
+#define MAKE_CONVERSIONS_float(name, min_val, max_val, min, max) \
+ static void \
+ convert_ ## name ## _float (BablConversion *conversion, \
+ void *src, \
+ void *dst, \
+ int src_pitch, \
+ int dst_pitch, \
+ long n) \
+ { \
+ convert_u15_float_scaled (conversion, min_val, max_val, min, max, \
+ src, dst, src_pitch, dst_pitch, n); \
+ } \
+ static void \
+ convert_float_ ## name (BablConversion *conversion, void *src, \
+ void *dst, \
+ int src_pitch, \
+ int dst_pitch, \
+ long n) \
+ { \
+ convert_float_u15_scaled (conversion, min_val, max_val, min, max, \
+ src, dst, src_pitch, dst_pitch, n); \
+ }
+
+MAKE_CONVERSIONS_float (u15, 0.0, 1.0, 0, (1<<15))
+
void
babl_base_type_u15 (void)
{
@@ -133,5 +219,20 @@ babl_base_type_u15 (void)
"plane", convert_double_u15,
NULL
);
+
+ babl_conversion_new (
+ babl_type ("u15"),
+ babl_type_from_id (BABL_FLOAT),
+ "plane", convert_u15_float,
+ NULL
+ );
+
+ babl_conversion_new (
+ babl_type_from_id (BABL_FLOAT),
+ babl_type ("u15"),
+ "plane", convert_float_u15,
+ NULL
+ );
+
babl_hmpf_on_name_lookups++;
}
diff --git a/babl/base/type-u16.c b/babl/base/type-u16.c
index 104bdf4..6841c9b 100644
--- a/babl/base/type-u16.c
+++ b/babl/base/type-u16.c
@@ -110,6 +110,91 @@ convert_u16_double_scaled (BablConversion *conversion,
MAKE_CONVERSIONS (u16, 0.0, 1.0, 0, UINT16_MAX)
+static inline void
+convert_float_u16_scaled (BablConversion *conversion,
+ double min_val,
+ double max_val,
+ uint16_t min,
+ uint16_t max,
+ char *src,
+ char *dst,
+ int src_pitch,
+ int dst_pitch,
+ long n)
+{
+ while (n--)
+ {
+ float dval = *(float *) src;
+ uint16_t u16val;
+
+ if (dval < min_val)
+ u16val = min;
+ else if (dval > max_val)
+ u16val = max;
+ else
+ u16val = rint ((dval - min_val) / (max_val - min_val) * (max - min) + min);
+
+ *(uint16_t *) dst = u16val;
+ dst += dst_pitch;
+ src += src_pitch;
+ }
+}
+
+static inline void
+convert_u16_float_scaled (BablConversion *conversion,
+ double min_val,
+ double max_val,
+ uint16_t min,
+ uint16_t max,
+ char *src,
+ char *dst,
+ int src_pitch,
+ int dst_pitch,
+ long n)
+{
+ while (n--)
+ {
+ int u16val = *(uint16_t *) src;
+ float dval;
+
+ if (u16val < min)
+ dval = min_val;
+ else if (u16val > max)
+ dval = max_val;
+ else
+ dval = (u16val - min) / (float) (max - min) * (max_val - min_val) + min_val;
+
+ (*(float *) dst) = dval;
+ dst += dst_pitch;
+ src += src_pitch;
+ }
+}
+
+#define MAKE_CONVERSIONS_float(name, min_val, max_val, min, max) \
+ static void \
+ convert_ ## name ## _float (BablConversion *c, void *src, \
+ void *dst, \
+ int src_pitch, \
+ int dst_pitch, \
+ long n) \
+ { \
+ convert_u16_float_scaled (c, min_val, max_val, min, max, \
+ src, dst, src_pitch, dst_pitch, n); \
+ } \
+ static void \
+ convert_float_ ## name (BablConversion *c, void *src, \
+ void *dst, \
+ int src_pitch, \
+ int dst_pitch, \
+ long n) \
+ { \
+ convert_float_u16_scaled (c, min_val, max_val, min, max, \
+ src, dst, src_pitch, dst_pitch, n); \
+ }
+
+MAKE_CONVERSIONS_float (u16, 0.0, 1.0, 0, UINT16_MAX)
+
+
void
babl_base_type_u16 (void)
{
@@ -132,4 +217,18 @@ babl_base_type_u16 (void)
"plane", convert_double_u16,
NULL
);
+
+ babl_conversion_new (
+ babl_type_from_id (BABL_U16),
+ babl_type_from_id (BABL_FLOAT),
+ "plane", convert_u16_float,
+ NULL
+ );
+
+ babl_conversion_new (
+ babl_type_from_id (BABL_FLOAT),
+ babl_type_from_id (BABL_U16),
+ "plane", convert_float_u16,
+ NULL
+ );
}
diff --git a/babl/base/type-u32.c b/babl/base/type-u32.c
index 3757925..1af2233 100644
--- a/babl/base/type-u32.c
+++ b/babl/base/type-u32.c
@@ -109,6 +109,92 @@ convert_u32_double_scaled (BablConversion *c,
MAKE_CONVERSIONS (u32, 0.0, 1.0, 0, UINT32_MAX)
+
+static inline void
+convert_float_u32_scaled (BablConversion *c,
+ float min_val,
+ float max_val,
+ uint32_t min,
+ uint32_t max,
+ char *src,
+ char *dst,
+ int src_pitch,
+ int dst_pitch,
+ long n)
+{
+ while (n--)
+ {
+ float dval = *(float *) src;
+ uint32_t u32val;
+
+ if (dval < min_val)
+ u32val = min;
+ else if (dval > max_val)
+ u32val = max;
+ else
+ u32val = rint ((dval - min_val) / (max_val - min_val) * (max - min) + min);
+
+ *(uint32_t *) dst = u32val;
+ dst += dst_pitch;
+ src += src_pitch;
+ }
+}
+
+static inline void
+convert_u32_float_scaled (BablConversion *c,
+ float min_val,
+ float max_val,
+ uint32_t min,
+ uint32_t max,
+ char *src,
+ char *dst,
+ int src_pitch,
+ int dst_pitch,
+ long n)
+{
+ while (n--)
+ {
+ int u32val = *(uint32_t *) src;
+ float dval;
+
+ if (u32val < min)
+ dval = min_val;
+ else if (u32val > max)
+ dval = max_val;
+ else
+ dval = (u32val - min) / (float) (max - min) * (max_val - min_val) + min_val;
+
+ (*(float *) dst) = dval;
+ dst += dst_pitch;
+ src += src_pitch;
+ }
+}
+
+#define MAKE_CONVERSIONS_float(name, min_val, max_val, min, max) \
+ static void \
+ convert_ ## name ## _float (BablConversion *c, void *src, \
+ void *dst, \
+ int src_pitch, \
+ int dst_pitch, \
+ long n) \
+ { \
+ convert_u32_float_scaled (c, min_val, max_val, min, max, \
+ src, dst, src_pitch, dst_pitch, n); \
+ } \
+ static void \
+ convert_float_ ## name (BablConversion *c, void *src, \
+ void *dst, \
+ int src_pitch, \
+ int dst_pitch, \
+ long n) \
+ { \
+ convert_float_u32_scaled (c, min_val, max_val, min, max, \
+ src, dst, src_pitch, dst_pitch, n); \
+ }
+
+MAKE_CONVERSIONS_float(u32, 0.0, 1.0, 0, UINT32_MAX)
+
+
void
babl_base_type_u32 (void)
{
@@ -131,4 +217,18 @@ babl_base_type_u32 (void)
"plane", convert_double_u32,
NULL
);
+
+ babl_conversion_new (
+ babl_type_from_id (BABL_U32),
+ babl_type_from_id (BABL_FLOAT),
+ "plane", convert_u32_float,
+ NULL
+ );
+
+ babl_conversion_new (
+ babl_type_from_id (BABL_FLOAT),
+ babl_type_from_id (BABL_U32),
+ "plane", convert_float_u32,
+ NULL
+ );
}
diff --git a/babl/base/type-u8.c b/babl/base/type-u8.c
index 3d79229..2ad561b 100644
--- a/babl/base/type-u8.c
+++ b/babl/base/type-u8.c
@@ -112,6 +112,95 @@ MAKE_CONVERSIONS (u8, 0.0, 1.0, 0x00, UINT8_MAX)
MAKE_CONVERSIONS (u8_luma, 0.0, 1.0, 16, 235)
MAKE_CONVERSIONS (u8_chroma, -0.5, 0.5, 16, 240)
+
+static inline void
+convert_float_u8_scaled (BablConversion *c,
+ double min_val,
+ double max_val,
+ unsigned char min,
+ unsigned char max,
+ char *src,
+ char *dst,
+ int src_pitch,
+ int dst_pitch,
+ long n)
+{
+ while (n--)
+ {
+ float dval = *(float *) src;
+ unsigned char u8val;
+
+ if (dval < min_val)
+ u8val = min;
+ else if (dval > max_val)
+ u8val = max;
+ else
+ u8val = rint ((dval - min_val) / (max_val - min_val) * (max - min) + min);
+
+ *(unsigned char *) dst = u8val;
+ src += src_pitch;
+ dst += dst_pitch;
+ }
+}
+
+static inline void
+convert_u8_float_scaled (BablConversion *c,
+ double min_val,
+ double max_val,
+ unsigned char min,
+ unsigned char max,
+ char *src,
+ char *dst,
+ int src_pitch,
+ int dst_pitch,
+ long n)
+{
+ while (n--)
+ {
+ int u8val = *(unsigned char *) src;
+ float dval;
+
+ if (u8val < min)
+ dval = min_val;
+ else if (u8val > max)
+ dval = max_val;
+ else
+ dval = (u8val - min) / (float) (max - min) * (max_val - min_val) + min_val;
+
+ (*(float *) dst) = dval;
+
+ dst += dst_pitch;
+ src += src_pitch;
+ }
+}
+
+#define MAKE_CONVERSIONS_float(name, min_val, max_val, min, max) \
+ static void \
+ convert_ ## name ## _float (BablConversion *c, void *src, \
+ void *dst, \
+ int src_pitch, \
+ int dst_pitch, \
+ long n) \
+ { \
+ convert_u8_float_scaled (c, min_val, max_val, min, max, \
+ src, dst, src_pitch, dst_pitch, n); \
+ } \
+ static void \
+ convert_float_ ## name (BablConversion *c, void *src, \
+ void *dst, \
+ int src_pitch, \
+ int dst_pitch, \
+ long n) \
+ { \
+ convert_float_u8_scaled (c, min_val, max_val, min, max, \
+ src, dst, src_pitch, dst_pitch, n); \
+ }
+
+MAKE_CONVERSIONS_float (u8, 0.0, 1.0, 0x00, UINT8_MAX)
+MAKE_CONVERSIONS_float (u8_luma, 0.0, 1.0, 16, 235)
+MAKE_CONVERSIONS_float (u8_chroma, -0.5, 0.5, 16, 240)
+
+
void
babl_base_type_u8 (void)
{
@@ -176,4 +265,43 @@ babl_base_type_u8 (void)
"plane", convert_double_u8_chroma,
NULL
);
+
+
+
+ babl_conversion_new (
+ babl_type_from_id (BABL_U8),
+ babl_type_from_id (BABL_FLOAT),
+ "plane", convert_u8_float,
+ NULL
+ );
+ babl_conversion_new (
+ babl_type_from_id (BABL_FLOAT),
+ babl_type_from_id (BABL_U8),
+ "plane", convert_float_u8,
+ NULL
+ );
+ babl_conversion_new (
+ babl_type_from_id (BABL_U8_LUMA),
+ babl_type_from_id (BABL_FLOAT),
+ "plane", convert_u8_luma_float,
+ NULL
+ );
+ babl_conversion_new (
+ babl_type_from_id (BABL_FLOAT),
+ babl_type_from_id (BABL_U8_LUMA),
+ "plane", convert_float_u8_luma,
+ NULL
+ );
+ babl_conversion_new (
+ babl_type_from_id (BABL_U8_CHROMA),
+ babl_type_from_id (BABL_FLOAT),
+ "plane", convert_u8_chroma_float,
+ NULL
+ );
+ babl_conversion_new (
+ babl_type_from_id (BABL_FLOAT),
+ babl_type_from_id (BABL_U8_CHROMA),
+ "plane", convert_float_u8_chroma,
+ NULL
+ );
}
diff --git a/babl/base/util.h b/babl/base/util.h
index b30c935..b16840e 100644
--- a/babl/base/util.h
+++ b/babl/base/util.h
@@ -24,12 +24,13 @@
#include "pow-24.h"
/* Alpha threshold used in the reference implementation for
- * un-pre-multiplication of color data:
+ * un-pre-multiplication of color data, deprecated in favor of the following
*
* 0.01 / (2^16 - 1)
*/
#define BABL_ALPHA_THRESHOLD 0.000000152590219
+
#define BABL_PLANAR_SANITY \
{ \
assert(src_bands>0); \
diff --git a/configure b/configure
index b4662f7..5376c7b 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for babl 0.1.56.
+# Generated by GNU Autoconf 2.69 for babl 0.1.58.
#
#
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@@ -587,8 +587,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='babl'
PACKAGE_TARNAME='babl'
-PACKAGE_VERSION='0.1.56'
-PACKAGE_STRING='babl 0.1.56'
+PACKAGE_VERSION='0.1.58'
+PACKAGE_STRING='babl 0.1.58'
PACKAGE_BUGREPORT=''
PACKAGE_URL=''
@@ -1383,7 +1383,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures babl 0.1.56 to adapt to many kinds of systems.
+\`configure' configures babl 0.1.58 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1455,7 +1455,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of babl 0.1.56:";;
+ short | recursive ) echo "Configuration of babl 0.1.58:";;
esac
cat <<\_ACEOF
@@ -1576,7 +1576,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-babl configure 0.1.56
+babl configure 0.1.58
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -1941,7 +1941,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by babl $as_me 0.1.56, which was
+It was created by babl $as_me 0.1.58, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -2297,11 +2297,11 @@ ac_config_headers="$ac_config_headers config.h"
BABL_MAJOR_VERSION=0
BABL_MINOR_VERSION=1
-BABL_MICRO_VERSION=56
+BABL_MICRO_VERSION=58
BABL_INTERFACE_AGE=1
-BABL_BINARY_AGE=156
-BABL_VERSION=0.1.56
-BABL_REAL_VERSION=0.1.56
+BABL_BINARY_AGE=158
+BABL_VERSION=0.1.58
+BABL_REAL_VERSION=0.1.58
BABL_API_VERSION=0.1
@@ -2336,7 +2336,7 @@ fi
-BABL_LIBRARY_VERSION="155:1:155"
+BABL_LIBRARY_VERSION="157:1:157"
BABL_CURRENT_MINUS_AGE=0
@@ -2968,7 +2968,7 @@ fi
# Define the identity of the package.
PACKAGE='babl'
- VERSION='0.1.56'
+ VERSION='0.1.58'
# Some tools Automake needs.
@@ -14950,7 +14950,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by babl $as_me 0.1.56, which was
+This file was extended by babl $as_me 0.1.58, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -15016,7 +15016,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-babl config.status 0.1.56
+babl config.status 0.1.58
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
diff --git a/configure.ac b/configure.ac
index 9cef01f..1600957 100644
--- a/configure.ac
+++ b/configure.ac
@@ -14,7 +14,7 @@ AC_PREREQ(2.54)
m4_define([babl_major_version], [0])
m4_define([babl_minor_version], [1])
-m4_define([babl_micro_version], [56])
+m4_define([babl_micro_version], [58])
m4_define([babl_real_version],
[babl_major_version.babl_minor_version.babl_micro_version])
m4_define([babl_version], [babl_real_version])
diff --git a/docs/index-static.html.in b/docs/index-static.html.in
index b0a04bd..be463ad 100644
--- a/docs/index-static.html.in
+++ b/docs/index-static.html.in
@@ -265,7 +265,7 @@ lab_buffer = malloc (pixel_count * 3 * sizeof (float));
non-linear variants of the data.
</p>
- <p>There is also a babl API call for creating a format for a specific space.
+ <p>babl has API for creating a format for a specific space:
<tt>babl_format_with_space("R'G'B' u16", babl_space ("Rec2020"))</tt> creates
a 16 bit integer format for the Rec2020 color space. Babl knows internally
about "sRGB", "Rec2020", "Adobe", "Apple" and "ProPhoto" spaces, as they are
@@ -279,12 +279,10 @@ lab_buffer = malloc (pixel_count * 3 * sizeof (float));
<p>The conversions babl does with ICC profiles are according to what is known
as the relative-colorimetric intent, monitor profiles containing both the
- matrices used by babl and 3d CLUTs (color look up tables) most often also do
+ matrices used by babl and 3d CLUTs (color look up tables) sometimes also do
relative-colorimetric transfer for the "perceptual" intent CLUTs, but with
- a more flexible and possibly higher accuracy conversions. If babl adds support
- for loading and using CLUTs it will be thus the perceptual
- intent will by babl be considered a different albeit more accurate
- relative-colorimetric RGB space.</p>
+ a more flexible and possibly higher accuracy conversions.</p>
+
<a name='Vocabulary'></a>
<h3 style='margin-bottom:0em;'>Vocabulary</h3>
@@ -357,6 +355,24 @@ lab_buffer = malloc (pixel_count * 3 * sizeof (float));
</div>
-->
+ <a name='premultiplied-alpha'></a>
+ <h2>Pre-multiplied alpha</h2>
+
+ <p>babl stores color information in transparent pre-multiplied or associated
+alpha pixels in floating point formats. With floating point pixel formats
+standard way of handling alpha maintains color information very near fully
+transparent pixels - by introducing a limit: BABL_ALPHA_FLOOR which is
+1/65536.0, and treating all alphas beteen zero and this value as this value we
+maintain color information while the discrepancy in behavior gets concealed by
+quantization in 16bit and 8bit formats.
+ </p>
+<p>For images that already are in a premultiplied format on import, this change
+has no impact on its use for pre-multiplied arithmetic, meaning that
+superluminous colors are still supported, it also opens up to GEGL more widely
+expect premultiplied data in more operations which will become a speedup when
+more filters want to integrate in the layer processing pipeline.</p>
+
+<p>There is a <a href='https://www.patreon.com/posts/premultiplied-in-21014115'>post on patreon</a> with further details about details of the implementation.</p>
<a name='TODO'></a>
<!--TODO-->
diff --git a/extensions/CIE.c b/extensions/CIE.c
index b96e124..ed1f739 100644
--- a/extensions/CIE.c
+++ b/extensions/CIE.c
@@ -56,6 +56,9 @@
#define D50_WHITE_REF_Y 1.000000000f
#define D50_WHITE_REF_Z 0.824905400f
+#define NEAR_ZERO 0.0000000001f
+#define D50_WHITE_REF_x 0.345702921222f
+#define D50_WHITE_REF_y 0.358537532290f
static void types (void);
@@ -88,6 +91,9 @@ components (void)
babl_component_new ("CIE X", NULL);
babl_component_new ("CIE Y", NULL);
babl_component_new ("CIE Z", NULL);
+ babl_component_new ("CIE x", NULL);
+ babl_component_new ("CIE y", NULL);
+/* babl_component_new ("CIE z", NULL);*/
}
static void
@@ -137,6 +143,21 @@ models (void)
babl_component ("CIE Z"),
babl_component ("A"),
NULL);
+
+ babl_model_new (
+ "name", "CIE xyY",
+ babl_component ("CIE x"),
+ babl_component ("CIE y"),
+ babl_component ("CIE Y"),
+ NULL);
+
+ babl_model_new (
+ "name", "CIE xyY alpha",
+ babl_component ("CIE x"),
+ babl_component ("CIE y"),
+ babl_component ("CIE Y"),
+ babl_component ("A"),
+ NULL);
}
static void rgbcie_init (void);
@@ -169,6 +190,22 @@ static inline void LAB_to_XYZ (double L,
double *to_Z
);
+static inline void XYZ_to_xyY (double X,
+ double Y,
+ double Z,
+ double *to_x,
+ double *to_y,
+ double *to_Y
+ );
+
+static inline void xyY_to_XYZ (double x,
+ double y,
+ double Y,
+ double *to_X,
+ double *to_Y,
+ double *to_Z
+ );
+
static inline void
XYZ_to_LAB (double X,
double Y,
@@ -216,6 +253,53 @@ LAB_to_XYZ (double L,
*to_Z = zr * D50_WHITE_REF_Z;
}
+
+static inline void
+XYZ_to_xyY (double X,
+ double Y,
+ double Z,
+ double *to_x,
+ double *to_y,
+ double *to_Y)
+{
+ double sum = X + Y + Z;
+ if (sum < NEAR_ZERO)
+ { *to_Y = 0.0;
+ *to_x = D50_WHITE_REF_x;
+ *to_y = D50_WHITE_REF_y;
+ }
+ else
+ {
+ *to_x = X / sum;
+ *to_y = Y / sum;
+ *to_Y = Y;
+ }
+}
+
+static inline void
+xyY_to_XYZ (double x,
+ double y,
+ double Y,
+ double *to_X,
+ double *to_Y,
+ double *to_Z)
+{
+ if ( Y < NEAR_ZERO )
+ { *to_X = 0.0;
+ *to_Y = 0.0;
+ *to_Z = 0.0;
+ }
+ else
+ {
+ *to_X = (x * Y) / y;
+ *to_Y = Y;
+ *to_Z = ((1 - x - y) * Y) / y;
+ }
+}
+
+
+/* rgb <-> XYZ */
+
static void
rgba_to_xyz (const Babl *conversion,char *src,
char *dst,
@@ -282,6 +366,442 @@ xyza_to_rgba (const Babl *conversion,char *src,
}
+/* rgb -> xyY */
+
+static void
+rgba_to_xyY (const Babl *conversion,char *src,
+ char *dst,
+ long n)
+{
+ const Babl *space = babl_conversion_get_source_space (conversion);
+ while (n--)
+ {
+ double XYZ[3], x, y, Y;
+
+ babl_space_to_xyz (space, (double*)src, XYZ);
+ XYZ_to_xyY (XYZ[0], XYZ[1], XYZ[2], &x, &y, &Y);
+
+ ((double *) dst)[0] = x;
+ ((double *) dst)[1] = y;
+ ((double *) dst)[2] = Y;
+
+ src += sizeof (double) * 4;
+ dst += sizeof (double) * 3;
+ }
+}
+
+static void
+rgba_to_xyYa (const Babl *conversion,char *src,
+ char *dst,
+ long n)
+{
+ const Babl *space = babl_conversion_get_source_space (conversion);
+ while (n--)
+ {
+ double alpha = ((double *) src)[3];
+ double XYZ[3], x, y, Y;
+
+ //convert RGB to XYZ
+ babl_space_to_xyz (space, (double*)src, XYZ);
+
+ //convert XYZ to xyY
+ XYZ_to_xyY (XYZ[0], XYZ[1], XYZ[2], &x, &y, &Y);
+
+ ((double *) dst)[0] = x;
+ ((double *) dst)[1] = y;
+ ((double *) dst)[2] = Y;
+ ((double *) dst)[3] = alpha;
+
+ src += sizeof (double) * 4;
+ dst += sizeof (double) * 4;
+ }
+}
+
+static void
+rgbaf_to_xyYaf (const Babl *conversion,
+ float *src,
+ float *dst,
+ long samples)
+{
+ const Babl *space = babl_conversion_get_source_space (conversion);
+ float m_0_0 = space->space.RGBtoXYZf[0] / D50_WHITE_REF_X;
+ float m_0_1 = space->space.RGBtoXYZf[1] / D50_WHITE_REF_X;
+ float m_0_2 = space->space.RGBtoXYZf[2] / D50_WHITE_REF_X;
+ float m_1_0 = space->space.RGBtoXYZf[3] / D50_WHITE_REF_Y;
+ float m_1_1 = space->space.RGBtoXYZf[4] / D50_WHITE_REF_Y;
+ float m_1_2 = space->space.RGBtoXYZf[5] / D50_WHITE_REF_Y;
+ float m_2_0 = space->space.RGBtoXYZf[6] / D50_WHITE_REF_Z;
+ float m_2_1 = space->space.RGBtoXYZf[7] / D50_WHITE_REF_Z;
+ float m_2_2 = space->space.RGBtoXYZf[8] / D50_WHITE_REF_Z;
+ long n = samples;
+
+ while (n--)
+ {
+ float x, y, X, Y, Z, r, g, b, a;
+ r = src[0];
+ g = src[1];
+ b = src[2];
+ a = src[3];
+
+ if ( r < NEAR_ZERO && g < NEAR_ZERO && b < NEAR_ZERO )
+ {
+ Y = 0.0f;
+ x = D50_WHITE_REF_x;
+ y = D50_WHITE_REF_y;
+ }
+ else
+ {
+ X = m_0_0 * r + m_0_1 * g + m_0_2 * b;
+ Y = m_1_0 * r + m_1_1 * g + m_1_2 * b;
+ Z = m_2_0 * r + m_2_1 * g + m_2_2 * b;
+
+ x = X / (X + Y + Z);
+ y = Y / (X + Y + Z);
+ }
+
+ dst[0] = x;
+ dst[1] = y;
+ dst[2] = Y;
+ dst[3] = a;
+
+ src += 4;
+ dst += 4;
+ }
+}
+
+static void
+rgbf_to_xyYf (const Babl *conversion,float *src,
+ float *dst,
+ long samples)
+{
+ const Babl *space = babl_conversion_get_source_space (conversion);
+ float m_0_0 = space->space.RGBtoXYZf[0] / D50_WHITE_REF_X;
+ float m_0_1 = space->space.RGBtoXYZf[1] / D50_WHITE_REF_X;
+ float m_0_2 = space->space.RGBtoXYZf[2] / D50_WHITE_REF_X;
+ float m_1_0 = space->space.RGBtoXYZf[3] / D50_WHITE_REF_Y;
+ float m_1_1 = space->space.RGBtoXYZf[4] / D50_WHITE_REF_Y;
+ float m_1_2 = space->space.RGBtoXYZf[5] / D50_WHITE_REF_Y;
+ float m_2_0 = space->space.RGBtoXYZf[6] / D50_WHITE_REF_Z;
+ float m_2_1 = space->space.RGBtoXYZf[7] / D50_WHITE_REF_Z;
+ float m_2_2 = space->space.RGBtoXYZf[8] / D50_WHITE_REF_Z;
+ long n = samples;
+
+ while (n--)
+ {
+ float x, y, X, Y, Z, r, g, b;
+ r = src[0];
+ g = src[1];
+ b = src[2];
+
+ if ( r < NEAR_ZERO && g < NEAR_ZERO && b < NEAR_ZERO )
+ {
+ Y = 0.0f;
+ x = D50_WHITE_REF_x;
+ y = D50_WHITE_REF_y;
+ }
+ else
+ {
+ X = m_0_0 * r + m_0_1 * g + m_0_2 * b;
+ Y = m_1_0 * r + m_1_1 * g + m_1_2 * b;
+ Z = m_2_0 * r + m_2_1 * g + m_2_2 * b;
+
+ x = X / (X + Y + Z);
+ y = Y / (X + Y + Z);
+ }
+
+ dst[0] = x;
+ dst[1] = y;
+ dst[2] = Y;
+
+ src += 3;
+ dst += 3;
+ }
+}
+
+
+static void
+rgbaf_to_xyYf (const Babl *conversion,
+ float *src,
+ float *dst,
+ long samples)
+{
+ const Babl *space = babl_conversion_get_source_space (conversion);
+ float m_0_0 = space->space.RGBtoXYZf[0] / D50_WHITE_REF_X;
+ float m_0_1 = space->space.RGBtoXYZf[1] / D50_WHITE_REF_X;
+ float m_0_2 = space->space.RGBtoXYZf[2] / D50_WHITE_REF_X;
+ float m_1_0 = space->space.RGBtoXYZf[3] / D50_WHITE_REF_Y;
+ float m_1_1 = space->space.RGBtoXYZf[4] / D50_WHITE_REF_Y;
+ float m_1_2 = space->space.RGBtoXYZf[5] / D50_WHITE_REF_Y;
+ float m_2_0 = space->space.RGBtoXYZf[6] / D50_WHITE_REF_Z;
+ float m_2_1 = space->space.RGBtoXYZf[7] / D50_WHITE_REF_Z;
+ float m_2_2 = space->space.RGBtoXYZf[8] / D50_WHITE_REF_Z;
+ long n = samples;
+
+ while (n--)
+ {
+ float x, y, X, Y, Z, r, g, b;
+ r = src[0];
+ g = src[1];
+ b = src[2];
+
+ if ( r < NEAR_ZERO && g < NEAR_ZERO && b < NEAR_ZERO )
+ {
+ Y = 0.0f;
+ x = D50_WHITE_REF_x;
+ y = D50_WHITE_REF_y;
+ }
+ else
+ {
+ X = m_0_0 * r + m_0_1 * g + m_0_2 * b;
+ Y = m_1_0 * r + m_1_1 * g + m_1_2 * b;
+ Z = m_2_0 * r + m_2_1 * g + m_2_2 * b;
+
+ x = X / (X + Y + Z);
+ y = Y / (X + Y + Z);
+ }
+
+ dst[0] = x;
+ dst[1] = y;
+ dst[2] = Y;
+
+ src += 4;
+ dst += 3;
+ }
+}
+
+
+/* xyY -> rgb */
+
+static void
+xyY_to_rgba (const Babl *conversion,char *src,
+ char *dst,
+ long n)
+{
+ const Babl *space = babl_conversion_get_destination_space (conversion);
+ while (n--)
+ {
+ double x = ((double *) src)[0];
+ double y = ((double *) src)[1];
+ double Y = ((double *) src)[2];
+
+ double R, G, B, X, Z;
+
+ //convert xyY to XYZ
+ xyY_to_XYZ (x, y, Y, &X, &Y, &Z);
+
+ //convert XYZ to RGB
+ {
+ double XYZ[3] = {X,Y,Z};
+ double RGB[3];
+ babl_space_from_xyz (space, XYZ, RGB);
+ R = RGB[0];
+ G = RGB[1];
+ B = RGB[2];
+ }
+
+ ((double *) dst)[0] = R;
+ ((double *) dst)[1] = G;
+ ((double *) dst)[2] = B;
+ ((double *) dst)[3] = 1.0;
+
+ src += sizeof (double) * 3;
+ dst += sizeof (double) * 4;
+ }
+}
+
+
+static void
+xyYa_to_rgba (const Babl *conversion,char *src,
+ char *dst,
+ long n)
+{
+ const Babl *space = babl_conversion_get_destination_space (conversion);
+ while (n--)
+ {
+ double x = ((double *) src)[0];
+ double y = ((double *) src)[1];
+ double Y = ((double *) src)[2];
+ double alpha = ((double *) src)[3];
+
+ double X, Z;
+
+ //convert xyY to XYZ
+ xyY_to_XYZ (x, y, Y, &X, &Y, &Z);
+
+ {
+ //convert XYZ to RGB
+ double XYZ[3] = {X,Y,Z};
+ babl_space_from_xyz (space, XYZ, (double*)dst);
+ }
+ ((double *) dst)[3] = alpha;
+
+ src += sizeof (double) * 4;
+ dst += sizeof (double) * 4;
+ }
+}
+
+
+static void
+xyYf_to_rgbf (const Babl *conversion,float *src,
+ float *dst,
+ long samples)
+{
+ const Babl *space = babl_conversion_get_source_space (conversion);
+ float m_0_0 = space->space.XYZtoRGBf[0] * D50_WHITE_REF_X;
+ float m_0_1 = space->space.XYZtoRGBf[1] * D50_WHITE_REF_Y;
+ float m_0_2 = space->space.XYZtoRGBf[2] * D50_WHITE_REF_Z;
+ float m_1_0 = space->space.XYZtoRGBf[3] * D50_WHITE_REF_X;
+ float m_1_1 = space->space.XYZtoRGBf[4] * D50_WHITE_REF_Y;
+ float m_1_2 = space->space.XYZtoRGBf[5] * D50_WHITE_REF_Z;
+ float m_2_0 = space->space.XYZtoRGBf[6] * D50_WHITE_REF_X;
+ float m_2_1 = space->space.XYZtoRGBf[7] * D50_WHITE_REF_Y;
+ float m_2_2 = space->space.XYZtoRGBf[8] * D50_WHITE_REF_Z;
+ long n = samples;
+
+ while (n--)
+ {
+ float X, Z, r, g, b;
+ float x = src[0];
+ float y = src[1];
+ float Y = src[2];
+
+ if ( Y < NEAR_ZERO )
+ {
+ X = 0.0f;
+ Y = 0.0f;
+ Z = 0.0f;
+ }
+ else
+ {
+ X = (x * Y) / y;
+ Y = Y;
+ Z = ((1 - x - y) * Y) / y;
+ }
+
+ r = m_0_0 * X + m_0_1 * Y + m_0_2 * Z;
+ g = m_1_0 * X + m_1_1 * Y + m_1_2 * Z;
+ b = m_2_0 * X + m_2_1 * Y + m_2_2 * Z;
+
+ dst[0] = r;
+ dst[1] = g;
+ dst[2] = b;
+
+ src += 3;
+ dst += 3;
+ }
+}
+
+
+
+static void
+xyYf_to_rgbaf (const Babl *conversion,
+ float *src,
+ float *dst,
+ long samples)
+{
+ const Babl *space = babl_conversion_get_source_space (conversion);
+ float m_0_0 = space->space.XYZtoRGBf[0] * D50_WHITE_REF_X;
+ float m_0_1 = space->space.XYZtoRGBf[1] * D50_WHITE_REF_Y;
+ float m_0_2 = space->space.XYZtoRGBf[2] * D50_WHITE_REF_Z;
+ float m_1_0 = space->space.XYZtoRGBf[3] * D50_WHITE_REF_X;
+ float m_1_1 = space->space.XYZtoRGBf[4] * D50_WHITE_REF_Y;
+ float m_1_2 = space->space.XYZtoRGBf[5] * D50_WHITE_REF_Z;
+ float m_2_0 = space->space.XYZtoRGBf[6] * D50_WHITE_REF_X;
+ float m_2_1 = space->space.XYZtoRGBf[7] * D50_WHITE_REF_Y;
+ float m_2_2 = space->space.XYZtoRGBf[8] * D50_WHITE_REF_Z;
+ long n = samples;
+
+ while (n--)
+ {
+ float X, Z, r, g, b;
+ float x = src[0];
+ float y = src[1];
+ float Y = src[2];
+
+
+ if ( Y < NEAR_ZERO )
+ {
+ X = 0.0f;
+ Y = 0.0f;
+ Z = 0.0f;
+ }
+ else
+ {
+ X = (x * Y) / y;
+ Y = Y;
+ Z = ((1 - x - y) * Y) / y;
+ }
+
+ r = m_0_0 * X + m_0_1 * Y + m_0_2 * Z;
+ g = m_1_0 * X + m_1_1 * Y + m_1_2 * Z;
+ b = m_2_0 * X + m_2_1 * Y + m_2_2 * Z;
+
+ dst[0] = r;
+ dst[1] = g;
+ dst[2] = b;
+ dst[3] = 1.0f;
+
+ src += 3;
+ dst += 4;
+ }
+}
+
+static void
+xyYaf_to_rgbaf (const Babl *conversion,
+ float *src,
+ float *dst,
+ long samples)
+{
+ const Babl *space = babl_conversion_get_source_space (conversion);
+ float m_0_0 = space->space.XYZtoRGBf[0] * D50_WHITE_REF_X;
+ float m_0_1 = space->space.XYZtoRGBf[1] * D50_WHITE_REF_Y;
+ float m_0_2 = space->space.XYZtoRGBf[2] * D50_WHITE_REF_Z;
+ float m_1_0 = space->space.XYZtoRGBf[3] * D50_WHITE_REF_X;
+ float m_1_1 = space->space.XYZtoRGBf[4] * D50_WHITE_REF_Y;
+ float m_1_2 = space->space.XYZtoRGBf[5] * D50_WHITE_REF_Z;
+ float m_2_0 = space->space.XYZtoRGBf[6] * D50_WHITE_REF_X;
+ float m_2_1 = space->space.XYZtoRGBf[7] * D50_WHITE_REF_Y;
+ float m_2_2 = space->space.XYZtoRGBf[8] * D50_WHITE_REF_Z;
+ long n = samples;
+
+ while (n--)
+ {
+ float X, Z, r, g, b;
+ float x = src[0];
+ float y = src[1];
+ float Y = src[2];
+ float a = src[3];
+
+ if ( Y < NEAR_ZERO )
+ {
+ X = 0.0f;
+ Y = 0.0f;
+ Z = 0.0f;
+ }
+ else
+ {
+ X = (x * Y) / y;
+ Y = Y;
+ Z = ((1 - x - y) * Y) / y;
+ }
+
+ r = m_0_0 * X + m_0_1 * Y + m_0_2 * Z;
+ g = m_1_0 * X + m_1_1 * Y + m_1_2 * Z;
+ b = m_2_0 * X + m_2_1 * Y + m_2_2 * Z;
+
+ dst[0] = r;
+ dst[1] = g;
+ dst[2] = b;
+ dst[3] = a;
+
+ src += 4;
+ dst += 4;
+ }
+}
+
+
+/* rgb <-> LAB */
+
static void
rgba_to_lab (const Babl *conversion,char *src,
char *dst,
@@ -305,7 +825,6 @@ rgba_to_lab (const Babl *conversion,char *src,
}
-
static void
lab_to_rgba (const Babl *conversion,char *src,
char *dst,
@@ -400,6 +919,9 @@ laba_to_rgba (const Babl *conversion,char *src,
}
}
+
+/* rgb <-> LCh */
+
static inline void
CHab_to_ab (double C,
double H,
@@ -879,6 +1401,52 @@ Labf_to_rgbf (const Babl *conversion,float *src,
}
}
+
+static void
+Labf_to_rgbaf (const Babl *conversion,float *src,
+ float *dst,
+ long samples)
+{
+ const Babl *space = babl_conversion_get_source_space (conversion);
+ float m_0_0 = space->space.XYZtoRGBf[0] * D50_WHITE_REF_X;
+ float m_0_1 = space->space.XYZtoRGBf[1] * D50_WHITE_REF_Y;
+ float m_0_2 = space->space.XYZtoRGBf[2] * D50_WHITE_REF_Z;
+ float m_1_0 = space->space.XYZtoRGBf[3] * D50_WHITE_REF_X;
+ float m_1_1 = space->space.XYZtoRGBf[4] * D50_WHITE_REF_Y;
+ float m_1_2 = space->space.XYZtoRGBf[5] * D50_WHITE_REF_Z;
+ float m_2_0 = space->space.XYZtoRGBf[6] * D50_WHITE_REF_X;
+ float m_2_1 = space->space.XYZtoRGBf[7] * D50_WHITE_REF_Y;
+ float m_2_2 = space->space.XYZtoRGBf[8] * D50_WHITE_REF_Z;
+ long n = samples;
+
+ while (n--)
+ {
+ float L = src[0];
+ float A = src[1];
+ float B = src[2];
+
+ float fy = (L + 16.0f) / 116.0f;
+ float fx = fy + A / 500.0f;
+ float fz = fy - B / 200.0f;
+
+ float yr = L > LAB_KAPPA * LAB_EPSILON ? cubef (fy) : L / LAB_KAPPA;
+ float xr = cubef (fx) > LAB_EPSILON ? cubef (fx) : (fx * 116.0f - 16.0f) / LAB_KAPPA;
+ float zr = cubef (fz) > LAB_EPSILON ? cubef (fz) : (fz * 116.0f - 16.0f) / LAB_KAPPA;
+
+ float r = m_0_0 * xr + m_0_1 * yr + m_0_2 * zr;
+ float g = m_1_0 * xr + m_1_1 * yr + m_1_2 * zr;
+ float b = m_2_0 * xr + m_2_1 * yr + m_2_2 * zr;
+
+ dst[0] = r;
+ dst[1] = g;
+ dst[2] = b;
+ dst[3] = 1.0f;
+
+ src += 3;
+ dst += 4;
+ }
+}
+
static void
Labaf_to_rgbaf (const Babl *conversion,float *src,
float *dst,
@@ -1380,6 +1948,8 @@ rgbaf_to_Labaf_sse2 (const Babl *conversion, const float *src, float *dst, long
static void
conversions (void)
{
+ /* babl_model */
+
babl_conversion_new (
babl_model ("RGBA"),
babl_model ("CIE Lab"),
@@ -1398,22 +1968,91 @@ conversions (void)
"linear", rgba_to_laba,
NULL
);
- babl_conversion_new (
+ babl_conversion_new (
babl_model ("CIE Lab alpha"),
babl_model ("RGBA"),
"linear", laba_to_rgba,
NULL
);
babl_conversion_new (
- babl_format ("RGB float"),
- babl_format ("CIE Lab float"),
- "linear", rgbf_to_Labf,
+ babl_model ("RGBA"),
+ babl_model ("CIE LCH(ab)"),
+ "linear", rgba_to_lchab,
NULL
);
babl_conversion_new (
- babl_format ("CIE Lab float"),
+ babl_model ("CIE LCH(ab)"),
+ babl_model ("RGBA"),
+ "linear", lchab_to_rgba,
+ NULL
+ );
+ babl_conversion_new (
+ babl_model ("RGBA"),
+ babl_model ("CIE LCH(ab) alpha"),
+ "linear", rgba_to_lchaba,
+ NULL
+ );
+ babl_conversion_new (
+ babl_model ("CIE LCH(ab) alpha"),
+ babl_model ("RGBA"),
+ "linear", lchaba_to_rgba,
+ NULL
+ );
+ babl_conversion_new (
+ babl_model ("RGBA"),
+ babl_model ("CIE XYZ"),
+ "linear", rgba_to_xyz,
+ NULL
+ );
+ babl_conversion_new (
+ babl_model ("CIE XYZ"),
+ babl_model ("RGBA"),
+ "linear", xyz_to_rgba,
+ NULL
+ );
+ babl_conversion_new (
+ babl_model ("RGBA"),
+ babl_model ("CIE XYZ alpha"),
+ "linear", rgba_to_xyza,
+ NULL
+ );
+ babl_conversion_new (
+ babl_model ("CIE XYZ alpha"),
+ babl_model ("RGBA"),
+ "linear", xyza_to_rgba,
+ NULL
+ );
+ babl_conversion_new (
+ babl_model ("RGBA"),
+ babl_model ("CIE xyY"),
+ "linear", rgba_to_xyY,
+ NULL
+ );
+ babl_conversion_new (
+ babl_model ("CIE xyY"),
+ babl_model ("RGBA"),
+ "linear", xyY_to_rgba,
+ NULL
+ );
+ babl_conversion_new (
+ babl_model ("RGBA"),
+ babl_model ("CIE xyY alpha"),
+ "linear", rgba_to_xyYa,
+ NULL
+ );
+ babl_conversion_new (
+ babl_model ("CIE xyY alpha"),
+ babl_model ("RGBA"),
+ "linear", xyYa_to_rgba,
+ NULL
+ );
+
+ /* babl_format */
+
+ babl_conversion_new (
babl_format ("RGB float"),
- "linear", Labf_to_rgbf,
+ babl_format ("CIE Lab float"),
+ "linear", rgbf_to_Labf,
NULL
);
babl_conversion_new (
@@ -1429,6 +2068,18 @@ conversions (void)
NULL
);
babl_conversion_new (
+ babl_format ("CIE Lab float"),
+ babl_format ("RGB float"),
+ "linear", Labf_to_rgbf,
+ NULL
+ );
+ babl_conversion_new (
+ babl_format ("CIE Lab float"),
+ babl_format ("RGBA float"),
+ "linear", Labf_to_rgbaf,
+ NULL
+ );
+ babl_conversion_new (
babl_format ("CIE Lab alpha float"),
babl_format ("RGBA float"),
"linear", Labaf_to_rgbaf,
@@ -1471,30 +2122,6 @@ conversions (void)
NULL
);
babl_conversion_new (
- babl_model ("RGBA"),
- babl_model ("CIE LCH(ab)"),
- "linear", rgba_to_lchab,
- NULL
- );
- babl_conversion_new (
- babl_model ("CIE LCH(ab)"),
- babl_model ("RGBA"),
- "linear", lchab_to_rgba,
- NULL
- );
- babl_conversion_new (
- babl_model ("RGBA"),
- babl_model ("CIE LCH(ab) alpha"),
- "linear", rgba_to_lchaba,
- NULL
- );
- babl_conversion_new (
- babl_model ("CIE LCH(ab) alpha"),
- babl_model ("RGBA"),
- "linear", lchaba_to_rgba,
- NULL
- );
- babl_conversion_new (
babl_format ("CIE Lab float"),
babl_format ("CIE LCH(ab) float"),
"linear", Labf_to_Lchabf,
@@ -1519,27 +2146,39 @@ conversions (void)
NULL
);
babl_conversion_new (
- babl_model ("RGBA"),
- babl_model ("CIE XYZ"),
- "linear", rgba_to_xyz,
+ babl_format ("RGB float"),
+ babl_format ("CIE xyY float"),
+ "linear", rgbf_to_xyYf,
NULL
);
babl_conversion_new (
- babl_model ("CIE XYZ"),
- babl_model ("RGBA"),
- "linear", xyz_to_rgba,
+ babl_format ("CIE xyY float"),
+ babl_format ("RGB float"),
+ "linear", xyYf_to_rgbf,
NULL
);
babl_conversion_new (
- babl_model ("RGBA"),
- babl_model ("CIE XYZ alpha"),
- "linear", rgba_to_xyza,
+ babl_format ("RGBA float"),
+ babl_format ("CIE xyY float"),
+ "linear", rgbaf_to_xyYf,
NULL
);
babl_conversion_new (
- babl_model ("CIE XYZ alpha"),
- babl_model ("RGBA"),
- "linear", xyza_to_rgba,
+ babl_format ("CIE xyY float"),
+ babl_format ("RGBA float"),
+ "linear", xyYf_to_rgbaf,
+ NULL
+ );
+ babl_conversion_new (
+ babl_format ("RGBA float"),
+ babl_format ("CIE xyY alpha float"),
+ "linear", rgbaf_to_xyYaf,
+ NULL
+ );
+ babl_conversion_new (
+ babl_format ("CIE xyY alpha float"),
+ babl_format ("RGBA float"),
+ "linear", xyYaf_to_rgbaf,
NULL
);
@@ -1624,6 +2263,27 @@ formats (void)
NULL);
babl_format_new (
+ "name", "CIE LCH(ab) float",
+ babl_model ("CIE LCH(ab)"),
+
+ babl_type ("float"),
+ babl_component ("CIE L"),
+ babl_component ("CIE C(ab)"),
+ babl_component ("CIE H(ab)"),
+ NULL);
+
+ babl_format_new (
+ "name", "CIE LCH(ab) alpha float",
+ babl_model ("CIE LCH(ab) alpha"),
+
+ babl_type ("float"),
+ babl_component ("CIE L"),
+ babl_component ("CIE C(ab)"),
+ babl_component ("CIE H(ab)"),
+ babl_component ("A"),
+ NULL);
+
+ babl_format_new (
"name", "CIE L float",
babl_model ("CIE Lab"),
babl_type ("float"),
@@ -1663,23 +2323,23 @@ formats (void)
NULL);
babl_format_new (
- "name", "CIE LCH(ab) float",
- babl_model ("CIE LCH(ab)"),
+ "name", "CIE xyY float",
+ babl_model ("CIE xyY"),
babl_type ("float"),
- babl_component ("CIE L"),
- babl_component ("CIE C(ab)"),
- babl_component ("CIE H(ab)"),
+ babl_component ("CIE x"),
+ babl_component ("CIE y"),
+ babl_component ("CIE Y"),
NULL);
babl_format_new (
- "name", "CIE LCH(ab) alpha float",
- babl_model ("CIE LCH(ab) alpha"),
+ "name", "CIE xyY alpha float",
+ babl_model ("CIE xyY alpha"),
babl_type ("float"),
- babl_component ("CIE L"),
- babl_component ("CIE C(ab)"),
- babl_component ("CIE H(ab)"),
+ babl_component ("CIE x"),
+ babl_component ("CIE y"),
+ babl_component ("CIE Y"),
babl_component ("A"),
NULL);
}
@@ -1779,6 +2439,96 @@ MAKE_CONVERSIONS (u8_ab, -128.0, 127.0, 0x00, 0xff)
#undef MAKE_CONVERSIONS
+static inline void
+convert_float_u8_scaled (const Babl *conversion,
+ float min_val,
+ float max_val,
+ unsigned char min,
+ unsigned char max,
+ char *src,
+ char *dst,
+ int src_pitch,
+ int dst_pitch,
+ long n)
+{
+ while (n--)
+ {
+ float dval = *(float *) src;
+ unsigned char u8val;
+
+ if (dval < min_val)
+ u8val = min;
+ else if (dval > max_val)
+ u8val = max;
+ else
+ u8val = rint ((dval - min_val) / (max_val - min_val) * (max - min) + min);
+
+ *(unsigned char *) dst = u8val;
+ src += src_pitch;
+ dst += dst_pitch;
+ }
+}
+
+static inline void
+convert_u8_float_scaled (const Babl *conversion,
+ float min_val,
+ float max_val,
+ unsigned char min,
+ unsigned char max,
+ char *src,
+ char *dst,
+ int src_pitch,
+ int dst_pitch,
+ long n)
+{
+ while (n--)
+ {
+ int u8val = *(unsigned char *) src;
+ float dval;
+
+ if (u8val < min)
+ dval = min_val;
+ else if (u8val > max)
+ dval = max_val;
+ else
+ dval = (u8val - min) / (float) (max - min) * (max_val - min_val) + min_val;
+
+ (*(float *) dst) = dval;
+
+ dst += dst_pitch;
+ src += src_pitch;
+ }
+}
+
+#define MAKE_CONVERSIONS(name, min_val, max_val, min, max) \
+ static void \
+ convert_ ## name ## _float (const Babl *c, char *src, \
+ char *dst, \
+ int src_pitch, \
+ int dst_pitch, \
+ long n) \
+ { \
+ convert_u8_float_scaled (c, min_val, max_val, min, max, \
+ src, dst, src_pitch, dst_pitch, n); \
+ } \
+ static void \
+ convert_float_ ## name (const Babl *c, char *src, \
+ char *dst, \
+ int src_pitch, \
+ int dst_pitch, \
+ long n) \
+ { \
+ convert_float_u8_scaled (c, min_val, max_val, min, max, \
+ src, dst, src_pitch, dst_pitch, n); \
+ }
+
+/* source ICC.1:2004-10 */
+
+MAKE_CONVERSIONS (u8_l, 0.0, 100.0, 0x00, 0xff)
+MAKE_CONVERSIONS (u8_ab, -128.0, 127.0, 0x00, 0xff)
+
+#undef MAKE_CONVERSIONS
+
static void
types_u8 (void)
{
@@ -1827,6 +2577,32 @@ types_u8 (void)
"plane", convert_double_u8_ab,
NULL
);
+
+ babl_conversion_new (
+ babl_type ("CIE u8 L"),
+ babl_type ("float"),
+ "plane", convert_u8_l_float,
+ NULL
+ );
+ babl_conversion_new (
+ babl_type ("float"),
+ babl_type ("CIE u8 L"),
+ "plane", convert_float_u8_l,
+ NULL
+ );
+
+ babl_conversion_new (
+ babl_type ("CIE u8 ab"),
+ babl_type ("float"),
+ "plane", convert_u8_ab_float,
+ NULL
+ );
+ babl_conversion_new (
+ babl_type ("float"),
+ babl_type ("CIE u8 ab"),
+ "plane", convert_float_u8_ab,
+ NULL
+ );
}
static inline void
@@ -1916,6 +2692,94 @@ MAKE_CONVERSIONS (u16_ab, -128.0, 127.0, 0x00, 0xffff)
#undef MAKE_CONVERSIONS
+
+static inline void
+convert_float_u16_scaled (const Babl *conversion,
+ float min_val,
+ float max_val,
+ unsigned short min,
+ unsigned short max,
+ char *src,
+ char *dst,
+ int src_pitch,
+ int dst_pitch,
+ long n)
+{
+ while (n--)
+ {
+ float dval = *(float *) src;
+ unsigned short u16val;
+
+ if (dval < min_val)
+ u16val = min;
+ else if (dval > max_val)
+ u16val = max;
+ else
+ u16val = rint ((dval - min_val) / (max_val - min_val) * (max - min) + min);
+
+ *(unsigned short *) dst = u16val;
+ dst += dst_pitch;
+ src += src_pitch;
+ }
+}
+
+static inline void
+convert_u16_float_scaled (const Babl *conversion,
+ float min_val,
+ float max_val,
+ unsigned short min,
+ unsigned short max,
+ char *src,
+ char *dst,
+ int src_pitch,
+ int dst_pitch,
+ long n)
+{
+ while (n--)
+ {
+ int u16val = *(unsigned short *) src;
+ float dval;
+
+ if (u16val < min)
+ dval = min_val;
+ else if (u16val > max)
+ dval = max_val;
+ else
+ dval = (u16val - min) / (float) (max - min) * (max_val - min_val) + min_val;
+
+ (*(float *) dst) = dval;
+ dst += dst_pitch;
+ src += src_pitch;
+ }
+}
+
+#define MAKE_CONVERSIONS(name, min_val, max_val, min, max) \
+ static void \
+ convert_ ## name ## _float (const Babl *c, char *src, \
+ char *dst, \
+ int src_pitch, \
+ int dst_pitch, \
+ long n) \
+ { \
+ convert_u16_float_scaled (c, min_val, max_val, min, max, \
+ src, dst, src_pitch, dst_pitch, n); \
+ } \
+ static void \
+ convert_float_ ## name (const Babl *c, char *src, \
+ char *dst, \
+ int src_pitch, \
+ int dst_pitch, \
+ long n) \
+ { \
+ convert_float_u16_scaled (c, min_val, max_val, min, max, \
+ src, dst, src_pitch, dst_pitch, n); \
+ }
+
+MAKE_CONVERSIONS (u16_l, 0.0, 100.0, 0x00, 0xffff)
+MAKE_CONVERSIONS (u16_ab, -128.0, 127.0, 0x00, 0xffff)
+
+#undef MAKE_CONVERSIONS
+
static void
types_u16 (void)
{
@@ -1965,6 +2829,32 @@ types_u16 (void)
"plane", convert_double_u16_ab,
NULL
);
+
+ babl_conversion_new (
+ babl_type ("CIE u16 L"),
+ babl_type ("float"),
+ "plane", convert_u16_l_float,
+ NULL
+ );
+ babl_conversion_new (
+ babl_type ("float"),
+ babl_type ("CIE u16 L"),
+ "plane", convert_float_u16_l,
+ NULL
+ );
+
+ babl_conversion_new (
+ babl_type ("CIE u16 ab"),
+ babl_type ("float"),
+ "plane", convert_u16_ab_float,
+ NULL
+ );
+ babl_conversion_new (
+ babl_type ("float"),
+ babl_type ("CIE u16 ab"),
+ "plane", convert_float_u16_ab,
+ NULL
+ );
}
static void
diff --git a/extensions/cairo.c b/extensions/cairo.c
index 77607c5..059b07d 100644
--- a/extensions/cairo.c
+++ b/extensions/cairo.c
@@ -118,6 +118,49 @@ static void conv_cairo32_rgbA8_premul_le (const Babl *conversion,unsigned char *
}
}
+static void conv_cairo32_rgba8_le (const Babl *conversion,unsigned char *src, unsigned char *dst, long samples)
+{
+ long n = samples;
+ while (n--)
+ {
+ unsigned char blue = *src++;
+ unsigned char green = *src++;
+ unsigned char red = *src++;
+ unsigned char alpha = *src++;
+
+ if (alpha == 0)
+ {
+ *dst++ = 0;
+ *dst++ = 0;
+ *dst++ = 0;
+ *dst++ = 0;
+ }
+ else if (alpha == 255)
+ {
+ *dst++ = red;
+ *dst++ = green;
+ *dst++ = blue;
+ *dst++ = alpha;
+ }
+ else
+ {
+ float falpha = alpha / 255.0;
+ float recip_alpha = 1.0 / falpha;
+ // unsigned int aa = ((255 << 16) + alpha) / falpha + 0.5;
+
+
+ *dst++ = ((red/255.0) * recip_alpha) * 255 + 0.5f;
+ *dst++ = ((green/255.0) * recip_alpha) * 255 + 0.5f;
+ *dst++ = ((blue/255.0) * recip_alpha) * 255 + 0.5f;
+
+// *dst++ = (red * aa + 0x8000) >> 16;
+// *dst++ = (green * aa + 0x8000) >> 16;
+// *dst++ = (blue * aa + 0x8000) >> 16;
+ *dst++ = alpha;
+ }
+ }
+}
+
static void conv_cairo32_rgbAF_premul_le (const Babl *conversion,unsigned char *src, unsigned char *dst_char, long samples)
{
@@ -266,7 +309,8 @@ conv_rgbA_gamma_float_cairo32_le (const Babl *conversion,unsigned char *src,
}
static void
-conv_rgbafloat_cairo32_le (const Babl *conversion,unsigned char *src,
+conv_rgbafloat_cairo32_le (const Babl *conversion,
+ unsigned char *src,
unsigned char *dst,
long samples)
{
@@ -392,6 +436,9 @@ init (void)
babl_conversion_new (f32, babl_format ("R'aG'aB'aA u8"), "linear",
conv_cairo32_rgbA8_premul_le, NULL);
+ babl_conversion_new (f32, babl_format ("R'G'B'A u8"), "linear",
+ conv_cairo32_rgba8_le, NULL);
+
babl_conversion_new (babl_format ("R'aG'aB'aA u8"), f32, "linear",
conv_rgbA8_premul_cairo32_le, NULL);
diff --git a/extensions/double.c b/extensions/double.c
index 87b7e3b..502a466 100644
--- a/extensions/double.c
+++ b/extensions/double.c
@@ -42,10 +42,18 @@ conv_rgbaD_linear_rgbAD_gamma (const Babl *conversion,unsigned char *src,
while (n--)
{
double alpha = fsrc[3];
+ if (alpha <= BABL_ALPHA_FLOOR)
+ {
+ if (alpha >= 0.0f)
+ alpha = BABL_ALPHA_FLOOR;
+ else if (alpha >= -BABL_ALPHA_FLOOR)
+ alpha = -BABL_ALPHA_FLOOR;
+ }
*fdst++ = babl_trc_from_linear (trc[0], *fsrc++) * alpha;
*fdst++ = babl_trc_from_linear (trc[1], *fsrc++) * alpha;
*fdst++ = babl_trc_from_linear (trc[2], *fsrc++) * alpha;
- *fdst++ = *fsrc++;
+ *fdst++ = alpha;
+ fsrc++;
}
}
@@ -65,7 +73,7 @@ conv_rgbAD_linear_rgbAD_gamma (const Babl *conversion,
while (n--)
{
double alpha = fsrc[3];
- if (alpha < BABL_ALPHA_THRESHOLD)
+ if (alpha == 0.0)
{
*fdst++ = 0.0;
*fdst++ = 0.0;
@@ -73,13 +81,6 @@ conv_rgbAD_linear_rgbAD_gamma (const Babl *conversion,
*fdst++ = 0.0;
fsrc+=4;
}
- else if (alpha >= 1.0)
- {
- *fdst++ = babl_trc_from_linear (trc[0], *fsrc++) * alpha;
- *fdst++ = babl_trc_from_linear (trc[1], *fsrc++) * alpha;
- *fdst++ = babl_trc_from_linear (trc[2], *fsrc++) * alpha;
- *fdst++ = *fsrc++;
- }
else
{
double alpha_recip = 1.0 / alpha;
diff --git a/extensions/fast-float.c b/extensions/fast-float.c
index 4162204..5540185 100644
--- a/extensions/fast-float.c
+++ b/extensions/fast-float.c
@@ -307,15 +307,15 @@ conv_rgbaF_linear_rgbAF_gamma (const Babl *conversion,unsigned char *src,
*fdst++ = linear_to_gamma_2_2_lut (blue);
*fdst++ = alpha;
}
- else if (alpha == 0.0)
- {
- *fdst++ = 0.0;
- *fdst++ = 0.0;
- *fdst++ = 0.0;
- *fdst++ = 0.0;
- }
else
{
+ if (alpha < BABL_ALPHA_FLOOR)
+ {
+ if (alpha >= 0.0f)
+ alpha = BABL_ALPHA_FLOOR;
+ else if (alpha >= -BABL_ALPHA_FLOOR)
+ alpha = -BABL_ALPHA_FLOOR;
+ }
*fdst++ = linear_to_gamma_2_2_lut (red) * alpha;
*fdst++ = linear_to_gamma_2_2_lut (green) * alpha;
*fdst++ = linear_to_gamma_2_2_lut (blue) * alpha;
@@ -387,11 +387,6 @@ conv_rgbaF_linear_rgbA8_gamma (const Babl *conversion,unsigned char *src,
*cdst++ = val >= 0xff ? 0xff : val <= 0 ? 0 : val;
*cdst++ = 0xff;
}
- else if (alpha <= 0.0)
- {
- *((uint32_t*)(cdst))=0;
- cdst+=4;
- }
else
{
float balpha = alpha * 0xff;
@@ -471,11 +466,6 @@ conv_rgbaF_linear_rgbA8_gamma_cairo (const Babl *conversion,unsigned char *src,
*cdst++ = val >= 0xff ? 0xff : val <= 0 ? 0 : val;
*cdst++ = 0xff;
}
- else if (alpha <= 0.0)
- {
- *((uint32_t*)(cdst))=0;
- cdst+=4;
- }
else
{
float balpha = alpha * 0xff;
@@ -505,28 +495,22 @@ conv_rgbAF_linear_rgbAF_gamma (const Babl *conversion,unsigned char *src,
float green = *fsrc++;
float blue = *fsrc++;
float alpha = *fsrc++;
- if (alpha < BABL_ALPHA_THRESHOLD)
- {
- *fdst++ = 0.0;
- *fdst++ = 0.0;
- *fdst++ = 0.0;
- *fdst++ = 0.0;
- }
- else if (alpha >= 1.0)
- {
- *fdst++ = linear_to_gamma_2_2_lut (red);
- *fdst++ = linear_to_gamma_2_2_lut (green);
- *fdst++ = linear_to_gamma_2_2_lut (blue);
- *fdst++ = *fsrc++;
- }
- else
- {
- float alpha_recip = 1.0 / alpha;
- *fdst++ = linear_to_gamma_2_2_lut (red * alpha_recip) * alpha;
- *fdst++ = linear_to_gamma_2_2_lut (green * alpha_recip) * alpha;
- *fdst++ = linear_to_gamma_2_2_lut (blue * alpha_recip) * alpha;
- *fdst++ = alpha;
- }
+
+ if (alpha == 1.0)
+ {
+ *fdst++ = linear_to_gamma_2_2_lut (red);
+ *fdst++ = linear_to_gamma_2_2_lut (green);
+ *fdst++ = linear_to_gamma_2_2_lut (blue);
+ *fdst++ = *fsrc++;
+ }
+ else
+ {
+ float alpha_recip = 1.0 / alpha;
+ *fdst++ = linear_to_gamma_2_2_lut (red * alpha_recip) * alpha;
+ *fdst++ = linear_to_gamma_2_2_lut (green * alpha_recip) * alpha;
+ *fdst++ = linear_to_gamma_2_2_lut (blue * alpha_recip) * alpha;
+ *fdst++ = alpha;
+ }
}
}
diff --git a/extensions/float.c b/extensions/float.c
index bce0de7..eaa38f5 100644
--- a/extensions/float.c
+++ b/extensions/float.c
@@ -43,10 +43,18 @@ conv_rgbaF_linear_rgbAF_nonlinear (const Babl *conversion,unsigned char *src,
while (n--)
{
float alpha = fsrc[3];
+ if (alpha < BABL_ALPHA_FLOOR)
+ {
+ if (alpha >= 0.0f)
+ alpha = BABL_ALPHA_FLOOR;
+ else if (alpha >= -BABL_ALPHA_FLOOR)
+ alpha = -BABL_ALPHA_FLOOR;
+ }
*fdst++ = babl_trc_from_linear (trc[0], *fsrc++) * alpha;
*fdst++ = babl_trc_from_linear (trc[1], *fsrc++) * alpha;
*fdst++ = babl_trc_from_linear (trc[2], *fsrc++) * alpha;
- *fdst++ = *fsrc++;
+ *fdst++ = alpha;
+ fsrc++;
}
}
@@ -62,10 +70,18 @@ conv_rgbaF_linear_rgbAF_perceptual (const Babl *conversion,unsigned char *src,
while (n--)
{
float alpha = fsrc[3];
+ if (alpha < BABL_ALPHA_FLOOR)
+ {
+ if (alpha >= 0.0f)
+ alpha = BABL_ALPHA_FLOOR;
+ else if (alpha >= -BABL_ALPHA_FLOOR)
+ alpha = -BABL_ALPHA_FLOOR;
+ }
*fdst++ = babl_trc_from_linear (trc_srgb, *fsrc++) * alpha;
*fdst++ = babl_trc_from_linear (trc_srgb, *fsrc++) * alpha;
*fdst++ = babl_trc_from_linear (trc_srgb, *fsrc++) * alpha;
- *fdst++ = *fsrc++;
+ *fdst++ = alpha;
+ fsrc++;
}
}
@@ -86,7 +102,7 @@ conv_rgbAF_linear_rgbAF_nonlinear (const Babl *conversion,
while (n--)
{
float alpha = fsrc[3];
- if (alpha < BABL_ALPHA_THRESHOLD)
+ if (alpha == 0)
{
*fdst++ = 0.0;
*fdst++ = 0.0;
@@ -94,13 +110,6 @@ conv_rgbAF_linear_rgbAF_nonlinear (const Babl *conversion,
*fdst++ = 0.0;
fsrc+=4;
}
- else if (alpha >= 1.0)
- {
- *fdst++ = babl_trc_from_linear (trc[0], *fsrc++) * alpha;
- *fdst++ = babl_trc_from_linear (trc[1], *fsrc++) * alpha;
- *fdst++ = babl_trc_from_linear (trc[2], *fsrc++) * alpha;
- *fdst++ = *fsrc++;
- }
else
{
float alpha_recip = 1.0 / alpha;
@@ -126,24 +135,17 @@ conv_rgbAF_linear_rgbAF_perceptual (const Babl *conversion,
while (n--)
{
float alpha = fsrc[3];
- if (alpha < BABL_ALPHA_THRESHOLD)
+ if (alpha == 0.0f)
{
- *fdst++ = 0.0;
- *fdst++ = 0.0;
- *fdst++ = 0.0;
- *fdst++ = 0.0;
+ *fdst++ = 0.0f;
+ *fdst++ = 0.0f;
+ *fdst++ = 0.0f;
+ *fdst++ = 0.0f;
fsrc+=4;
}
- else if (alpha >= 1.0)
- {
- *fdst++ = babl_trc_from_linear (trc_srgb, *fsrc++) * alpha;
- *fdst++ = babl_trc_from_linear (trc_srgb, *fsrc++) * alpha;
- *fdst++ = babl_trc_from_linear (trc_srgb, *fsrc++) * alpha;
- *fdst++ = *fsrc++;
- }
else
{
- float alpha_recip = 1.0 / alpha;
+ float alpha_recip = 1.0f / alpha;
*fdst++ = babl_trc_from_linear (trc_srgb, *fsrc++ * alpha_recip) * alpha;
*fdst++ = babl_trc_from_linear (trc_srgb, *fsrc++ * alpha_recip) * alpha;
*fdst++ = babl_trc_from_linear (trc_srgb, *fsrc++ * alpha_recip) * alpha;
diff --git a/extensions/gegl-fixups.c b/extensions/gegl-fixups.c
index d866154..70ef2d3 100644
--- a/extensions/gegl-fixups.c
+++ b/extensions/gegl-fixups.c
@@ -329,15 +329,15 @@ conv_rgbAF_rgb8 (const Babl *conversion,unsigned char *srcc,
while (n--)
{
float alpha = src[3];
- if (alpha < BABL_ALPHA_THRESHOLD)
+ if (alpha == 0.0f)
{
- dst[0] = 0;
- dst[1] = 0;
- dst[2] = 0;
+ dst[0] = 0.0f;
+ dst[1] = 0.0f;
+ dst[2] = 0.0f;
}
else
{
- float alpha_recip = 1.0 / alpha;
+ float alpha_recip = 1.0f / alpha;
dst[0] = table_F_8g[gggl_float_to_index16 (src[0] * alpha_recip)];
dst[1] = table_F_8g[gggl_float_to_index16 (src[1] * alpha_recip)];
dst[2] = table_F_8g[gggl_float_to_index16 (src[2] * alpha_recip)];
@@ -380,6 +380,13 @@ conv_rgbaF_rgbAF (const Babl *conversion,unsigned char *srcc,
while (n--)
{
float alpha = src[3];
+ if (alpha < BABL_ALPHA_FLOOR)
+ {
+ if (alpha >= 0.0f)
+ alpha = BABL_ALPHA_FLOOR;
+ else if (alpha >= -BABL_ALPHA_FLOOR)
+ alpha = -BABL_ALPHA_FLOOR;
+ }
dst[0] = src[0] * alpha;
dst[1] = src[1] * alpha;
dst[2] = src[2] * alpha;
@@ -402,13 +409,16 @@ conv_rgbAF_rgbaF (const Babl *conversion,unsigned char *srcc,
{
float alpha = src[3];
float recip;
- if (alpha < BABL_ALPHA_THRESHOLD)
- recip = 0.0;
+ if (alpha == 0.0f)
+ recip = 0.0f;
else
- recip = 1.0/alpha;
+ recip = 1.0f/alpha;
+
dst[0] = src[0] * recip;
dst[1] = src[1] * recip;
dst[2] = src[2] * recip;
+ if (alpha == BABL_ALPHA_FLOOR || alpha == -BABL_ALPHA_FLOOR)
+ alpha = 0.0f;
dst[3] = alpha;
src += 4;
dst += 4;
@@ -428,13 +438,15 @@ conv_rgbAF_lrgba8 (const Babl *conversion,unsigned char *srcc,
while (n--)
{
float alpha = src[3];
- float recip = (1.0/alpha);
- if (alpha < BABL_ALPHA_THRESHOLD)
+ if (alpha == 0.0f)
{
dst[0] = dst[1] = dst[2] = dst[3] = 0;
}
else
{
+ float recip = (1.0/alpha);
+ if (alpha == BABL_ALPHA_FLOOR || alpha == -BABL_ALPHA_FLOOR)
+ alpha = 0.0f;
dst[0] = table_F_8[gggl_float_to_index16 (src[0] * recip)];
dst[1] = table_F_8[gggl_float_to_index16 (src[1] * recip)];
dst[2] = table_F_8[gggl_float_to_index16 (src[2] * recip)];
diff --git a/extensions/gggl-lies.c b/extensions/gggl-lies.c
index 02b3139..3f33305 100644
--- a/extensions/gggl-lies.c
+++ b/extensions/gggl-lies.c
@@ -151,14 +151,26 @@ conv_D_F (const Babl *conversion,unsigned char *src, unsigned char *dst, long sa
src += 8;
}
}
+
static void
conv_16_8 (const Babl *conversion,unsigned char *src, unsigned char *dst, long samples)
{
long n = samples;
- while (n--)
+ while (n>4)
{
#define div_257(a) ((((a)+128)-(((a)+128)>>8))>>8)
+ ((unsigned char *) dst)[0] = div_257 (((unsigned short *) src)[0]);
+ ((unsigned char *) dst)[1] = div_257 (((unsigned short *) src)[1]);
+ ((unsigned char *) dst)[2] = div_257 (((unsigned short *) src)[2]);
+ ((unsigned char *) dst)[3] = div_257 (((unsigned short *) src)[3]);
+ dst += 4;
+ src += 8;
+ n-=4;
+ }
+
+ while (n--)
+ {
(*(unsigned char *) dst) = div_257 (*(unsigned short *) src);
dst += 1;
src += 2;
diff --git a/extensions/gggl-table-lies.c b/extensions/gggl-table-lies.c
index 5cca68d..e70a45a 100644
--- a/extensions/gggl-table-lies.c
+++ b/extensions/gggl-table-lies.c
@@ -23,15 +23,17 @@
* Copyright 2003, 2004, 2005 Øyvind Kolås <pippin@gimp.org>
*/
-#define _POSIX_C_SOURCE 200112L
+//#define _POSIX_C_SOURCE 200112L
#include "config.h"
#include <math.h>
#include <string.h>
#include "babl.h"
+#include "base/util.h"
#include "extensions/util.h"
+
/*
* Implemented according to information read from:
*
@@ -108,8 +110,8 @@ table_init (void)
}
else
{
- c = lrint (u.f * 255.0);
- s = lrint (u.f * 65535.0);
+ c = u.f * 255 + 0.5f;
+ s = u.f * 65535 + 0.5f;
}
/*fprintf (stderr, "%2.3f=%03i %05i ", f, c, (*hi));
@@ -313,9 +315,8 @@ conv_rgbafloat_linear_cairo32_le (const Babl *conversion,unsigned char *src_char
while (n--)
{
float alpha = src[3] * 255;
-#define BABL_ALPHA_THRESHOLD 0.000000152590219
- if (alpha < BABL_ALPHA_THRESHOLD)
+ if (alpha <= BABL_ALPHA_FLOOR)
{
*(int *)dst = 0;
}
diff --git a/extensions/gggl-table.c b/extensions/gggl-table.c
index 039ef2e..a06a649 100644
--- a/extensions/gggl-table.c
+++ b/extensions/gggl-table.c
@@ -36,17 +36,12 @@
*
* http://www.cinenet.net/~spitzak/conversion/sketches_0265.pdf
*
- * initially ignoring any diffusion, to keep the implementation
- * smaller, and interchangeable with the non optimized version.
- *
* due to ability to be able to relicence gggl under a different
* licence than GPL, I avoided the temptation to look at the
* source files in the same location, in case I was going to
* need this piece of code for projects where GPL compatibility
* was a must.
*
- * TODO: error diffusion,
- * gamma correction (not really,. gamma correction belongs in seperate ops,.
*/
/* lookup tables used in conversion */
@@ -65,7 +60,7 @@ table_init (void)
{
if (table_inited)
return;
-
+
table_8_F_int = (void*)(table_8_F);
table_inited = 1;
@@ -108,8 +103,8 @@ table_init (void)
}
else
{
- c = lrint (u.f * 255.0);
- s = lrint (u.f * 65535.0);
+ c = u.f * 255 + 0.5f;
+ s = u.f * 65535 + 0.5f;
}
/*fprintf (stderr, "%2.3f=%03i %05i ", f, c, (*hi));
@@ -120,7 +115,7 @@ table_init (void)
table_F_16[u.s[1]] = s;
}
}
- /* fix tables to ensure 1:1 conversions back and forth */
+ /* patch tables to ensure 1:1 conversions back and forth */
if (0)
{ /*FIXME: probably not the right way to do it,.. must sit down and scribble on paper */
int i;
diff --git a/extensions/gggl.c b/extensions/gggl.c
index 1b0fed4..2108260 100644
--- a/extensions/gggl.c
+++ b/extensions/gggl.c
@@ -175,25 +175,35 @@ conv_16_8 (const Babl *conversion,unsigned char *src, unsigned char *dst, long s
{
long n = samples;
- while (n--)
+ while (n>4)
{
#define div_257(a) ((((a)+128)-(((a)+128)>>8))>>8)
+ ((unsigned char *) dst)[0] = div_257 (((unsigned short *) src)[0]);
+ ((unsigned char *) dst)[1] = div_257 (((unsigned short *) src)[1]);
+ ((unsigned char *) dst)[2] = div_257 (((unsigned short *) src)[2]);
+ ((unsigned char *) dst)[3] = div_257 (((unsigned short *) src)[3]);
+ dst += 4;
+ src += 8;
+ n-=4;
+ }
+
+ while (n--)
+ {
(*(unsigned char *) dst) = div_257 (*(unsigned short *) src);
- dst += 1;
- src += 2;
+ dst += 1;
+ src += 2;
}
}
-static void
+static inline void
conv_8_16 (const Babl *conversion,unsigned char *src, unsigned char *dst, long samples)
{
long n = samples;
-
while (n--)
{
- (*(unsigned short *) dst) = ((*(unsigned char *) src) << 8) | *src;
- dst += 2;
- src += 1;
+ (*(unsigned short *) dst) = *src << 8 | *src;
+ dst += 2;
+ src += 1;
}
}
@@ -757,10 +767,13 @@ conv_rgbA8_rgba8 (const Babl *conversion,unsigned char *src, unsigned char *dst,
}
else
{
- unsigned int aa = ((255 << 16) + (src[3] >> 1)) / src[3];
- *dst++ = (src[0] * aa + 0x8000) >> 16;
- *dst++ = (src[1] * aa + 0x8000) >> 16;
- *dst++ = (src[2] * aa + 0x8000) >> 16;
+ float alpha = src[3]/255.0;
+ float ralpha = 1.0/alpha;
+ //unsigned aa = ((255 << 16)) / src[3];
+ unsigned aa = ((1 << 10)) * ralpha;
+ *dst++ = (src[0] * aa + .5) / 1024.0 + 0.5;
+ *dst++ = (src[1] * aa +.5) / 1024.0 + 0.5;
+ *dst++ = (src[2] * aa +.5) / 1024.0 + 0.5;
*dst++ = src[3];
}
src += 4;
diff --git a/extensions/sse2-float.c b/extensions/sse2-float.c
index 6e7aaf1..d2bc50b 100644
--- a/extensions/sse2-float.c
+++ b/extensions/sse2-float.c
@@ -51,14 +51,33 @@ conv_rgbaF_linear_rgbAF_linear (const Babl *conversion,const float *src, float *
for ( ; i < n; i += 2)
{
+ float alpha0 = ((float *)s)[3];
+ float alpha1 = ((float *)s)[7];
+
+ if (alpha0 < BABL_ALPHA_FLOOR)
+ {
+ if (alpha0 >= 0.0f)
+ alpha0 = BABL_ALPHA_FLOOR;
+ else
+ alpha0 = -BABL_ALPHA_FLOOR;
+ }
+ if (alpha1 < BABL_ALPHA_FLOOR)
+ {
+ if (alpha1 >= 0.0f)
+ alpha1 = BABL_ALPHA_FLOOR;
+ else
+ alpha1 = -BABL_ALPHA_FLOOR;
+ }
+ {
__v4sf rbaa0, rbaa1;
__v4sf rgba0 = *s++;
__v4sf rgba1 = *s++;
+
/* Expand alpha */
- __v4sf aaaa0 = (__v4sf)_mm_shuffle_epi32((__m128i)rgba0, _MM_SHUFFLE(3, 3, 3, 3));
- __v4sf aaaa1 = (__v4sf)_mm_shuffle_epi32((__m128i)rgba1, _MM_SHUFFLE(3, 3, 3, 3));
+ __v4sf aaaa0 = (__v4sf)_mm_set1_ps(alpha0);
+ __v4sf aaaa1 = (__v4sf)_mm_set1_ps(alpha1);
/* Premultiply */
rgba0 = rgba0 * aaaa0;
@@ -73,6 +92,7 @@ conv_rgbaF_linear_rgbAF_linear (const Babl *conversion,const float *src, float *
*d++ = rgba0;
*d++ = rgba1;
+ }
}
_mm_empty ();
}
@@ -82,7 +102,14 @@ conv_rgbaF_linear_rgbAF_linear (const Babl *conversion,const float *src, float *
remainder = samples - i;
while (remainder--)
{
- const float a = src[3];
+ float a = src[3];
+ if (a <= BABL_ALPHA_FLOOR)
+ {
+ if (a >= 0.0f)
+ a = BABL_ALPHA_FLOOR;
+ else if (a >= -BABL_ALPHA_FLOOR)
+ a = -BABL_ALPHA_FLOOR;
+ }
dst[0] = src[0] * a;
dst[1] = src[1] * a;
dst[2] = src[2] * a;
@@ -112,7 +139,7 @@ conv_rgbAF_linear_rgbaF_linear_shuffle (const Babl *conversion,const float *src,
float alpha0 = ((float *)s)[3];
pre_rgba0 = *s;
- if (alpha0 <= BABL_ALPHA_THRESHOLD_FLOAT)
+ if (alpha0 == 0.0f)
{
/* Zero RGB */
rgba0 = _mm_setzero_ps();
@@ -131,7 +158,10 @@ conv_rgbAF_linear_rgbaF_linear_shuffle (const Babl *conversion,const float *src,
/* Shuffle the original alpha value back in */
rbaa0 = _mm_shuffle_ps(rgba0, pre_rgba0, _MM_SHUFFLE(3, 3, 2, 0));
rgba0 = _mm_shuffle_ps(rgba0, rbaa0, _MM_SHUFFLE(2, 1, 1, 0));
-
+
+ if (alpha0 == BABL_ALPHA_FLOOR || alpha0 == -BABL_ALPHA_FLOOR)
+ ((float *)d)[3] = 0.0f;
+
s++;
*d++ = rgba0;
}
@@ -164,7 +194,7 @@ conv_rgbAF_linear_rgbaF_linear_spin (const Babl *conversion,const float *src, fl
{
long i = 0;
long remainder;
-
+ // XXX : not ported to color preserving premul
if (((uintptr_t)src % 16) + ((uintptr_t)dst % 16) == 0)
{
const long n = samples;
diff --git a/extensions/two-table.c b/extensions/two-table.c
index 3202e69..dae28c8 100644
--- a/extensions/two-table.c
+++ b/extensions/two-table.c
@@ -52,16 +52,9 @@ conv_rgbafloat_linear_cairo24_le (const Babl *conversion,unsigned char *src_char
while (n--)
{
- if (src[3] < BABL_ALPHA_THRESHOLD)
- {
- *(int *)dst = 0;
- }
- else
- {
- dst[0] = conv_float_u8_two_table_map (src[2]);
- dst[1] = conv_float_u8_two_table_map (src[1]);
- dst[2] = conv_float_u8_two_table_map (src[0]);
- }
+ dst[0] = conv_float_u8_two_table_map (src[2]);
+ dst[1] = conv_float_u8_two_table_map (src[1]);
+ dst[2] = conv_float_u8_two_table_map (src[0]);
src += 4;
dst += 4;
}
@@ -96,7 +89,7 @@ conv_rgbafloat_linear_rgbu8_gamma (const Babl *conversion,unsigned char *src_cha
while (n--)
{
- if (src[3] < BABL_ALPHA_THRESHOLD)
+ if (src[3] <= BABL_ALPHA_FLOOR)
{
dst[0] = 0;
dst[1] = 0;
@@ -124,20 +117,10 @@ conv_rgbafloat_linear_rgbau8_gamma (const Babl *conversion,unsigned char *src_ch
while (n--)
{
- if (src[3] <=0)
- {
- dst[0] = 0;
- dst[1] = 0;
- dst[2] = 0;
- dst[3] = 0;
- }
- else
- {
- dst[0] = conv_float_u8_two_table_map (src[0]);
- dst[1] = conv_float_u8_two_table_map (src[1]);
- dst[2] = conv_float_u8_two_table_map (src[2]);
- dst[3] = src[3] * 0xff + 0.5;
- }
+ dst[0] = conv_float_u8_two_table_map (src[0]);
+ dst[1] = conv_float_u8_two_table_map (src[1]);
+ dst[2] = conv_float_u8_two_table_map (src[2]);
+ dst[3] = src[3] * 0xff + 0.5;
src += 4;
dst += 4;
}
diff --git a/tools/babl_fish_path_fitness.c b/tools/babl_fish_path_fitness.c
index cd012c0..92c5935 100644
--- a/tools/babl_fish_path_fitness.c
+++ b/tools/babl_fish_path_fitness.c
@@ -18,14 +18,14 @@ int ok = 0;
static int qux = 0;
-#define UTF8
+//#define UTF8
#ifdef UTF8
-static char *utf8_bar[] = { " ", "·", "▁", "▂", "▃", "▄", "▅", "▆", "▇", "█" };
+static char *utf8_bar[] = { " %s%s", "·%s%s", "▁%s%s", "▂%s%s", "▃%s%s", "▄%s%s", "▅%s%s", "▆%s%s", "▇%s%s", "█%s%s" };
#define DIRECT " "
#define SELF " "
-#define EMPTY " "
+#define EMPTY " %s%s"
#define SL ""
#define NL "\n"
@@ -33,17 +33,17 @@ static char *utf8_bar[] = { " ", "·", "▁", "▂", "▃", "▄", "▅", "▆",
static char *utf8_bar[] = { " ",
- "<span class='direct'> </span>",
- "<span class='path2'> </span>",
- "<span class='path3'> </span>",
- "<span class='path4'> </span>",
- "<span class='path5'> </span>",
- "<span class='path6'> </span>",
- "<span class='path7'> </span>",
- "<span class='path8'> </span>"};
+ "<span class='direct' title=\"%s\" style='%s'>▄</span>",
+ "<span class='path2' title=\"%s\" style='%s'>▄</span>",
+ "<span class='path3' title=\"%s\" style='%s'>▄</span>",
+ "<span class='path4' title=\"%s\" style='%s'>▄</span>",
+ "<span class='path5' title=\"%s\" style='%s'>▄</span>",
+ "<span class='path6' title=\"%s\" style='%s'>▄</span>",
+ "<span class='path7' title=\"%s\" style='%s'>▄</span>",
+ "<span class='path8' title=\"%s\" style='%s'>▄</span>"};
#define SL "<div>"
-#define SELF "<span class='self'> </span>"
-#define EMPTY "<span class='empty'> </span>"
+#define SELF "<span class='self'>&nbsp;</span>"
+#define EMPTY "<span class='empty' title=\"%s\" style='%s'>▄</span>"
#define NL "</div>\n"
#endif
@@ -56,21 +56,147 @@ static char *utf8_bar[]={"·", "█", "▇", "▆", "▅", "▄", "▃", "▂",
static char *utf8_bar[]={" ","1","2","3","4","5","6","7","8"};
*/
+#define NUM_TEST_PIXELS (1024*1024)
+static float test_pixels_float[NUM_TEST_PIXELS*4];
+static char test_pixels_in[NUM_TEST_PIXELS * 6 * 8];
+static char test_pixels_out[NUM_TEST_PIXELS * 6 * 8];
+
+
+static double rand_double (void)
+{
+ return (double) random () / RAND_MAX;
+}
+
+static double rand_range_double (double min, double max)
+{
+ return rand_double () * (max - min) + min;
+}
+
+static void init_test_pixels (void)
+{
+ static int done = 0;
+ int i = 0;
+ int pix_no = 0;
+ srandom (111);
+
+ if (done)
+ return;
+ done = 1;
+
+
+ for (i = 0; i < 256 && pix_no < NUM_TEST_PIXELS; i++)
+ {
+ test_pixels_float[pix_no*4+0] = rand_double();
+ test_pixels_float[pix_no*4+1] = rand_double();
+ test_pixels_float[pix_no*4+2] = rand_double();
+ test_pixels_float[pix_no*4+3] = rand_double();
+ pix_no ++;
+ }
+ for (i = 0; i < 256 && pix_no < NUM_TEST_PIXELS; i++)
+ {
+ test_pixels_float[pix_no*4+0] = rand_range_double(1.0, 2.0);
+ test_pixels_float[pix_no*4+1] = rand_range_double(1.0, 2.0);
+ test_pixels_float[pix_no*4+2] = rand_range_double(1.0, 2.0);
+ test_pixels_float[pix_no*4+3] = rand_range_double(1.0, 2.0);
+ pix_no ++;
+ }
+ for (i = 0; i < 256 && pix_no < NUM_TEST_PIXELS; i++)
+ {
+ test_pixels_float[pix_no*4+0] = rand_range_double(-1.0, 1.0);
+ test_pixels_float[pix_no*4+1] = rand_range_double(-1.0, 1.0);
+ test_pixels_float[pix_no*4+2] = rand_range_double(-1.0, 1.0);
+ test_pixels_float[pix_no*4+3] = rand_range_double(-1.0, 1.0);
+ pix_no ++;
+ }
+ for (i = 0; i < 16 && pix_no < NUM_TEST_PIXELS; i++)
+ {
+ test_pixels_float[pix_no*4+0] = rand_range_double(0.0, 1.0);
+ test_pixels_float[pix_no*4+1] = rand_range_double(0.0, 1.0);
+ test_pixels_float[pix_no*4+2] = rand_range_double(0.0, 1.0);
+ test_pixels_float[pix_no*4+3] = 0;
+ pix_no ++;
+ }
+ for (i = 0; i < 16 && pix_no < NUM_TEST_PIXELS; i++)
+ {
+ test_pixels_float[pix_no*4+0] = rand_range_double(0.0, 16.0);
+ test_pixels_float[pix_no*4+1] = rand_range_double(0.0, 16.0);
+ test_pixels_float[pix_no*4+2] = rand_range_double(0.0, 16.0);
+ test_pixels_float[pix_no*4+2] = rand_range_double(-1.0, 1.0);
+ pix_no ++;
+ }
+ for (i = 0; pix_no < NUM_TEST_PIXELS; i++)
+ {
+ test_pixels_float[pix_no*4+0] = rand_range_double(-1.0, 61.0);
+ test_pixels_float[pix_no*4+1] = rand_range_double(-1.0, 61.0);
+ test_pixels_float[pix_no*4+2] = rand_range_double(-1.0, 66.0);
+ test_pixels_float[pix_no*4+3] = rand_range_double(-1.0, 3.0);
+ pix_no ++;
+ }
+ for (i = 0; i < sizeof(test_pixels_in); i++)
+ test_pixels_in[i]=(rand()/10000)&0xff;
+}
+
static int destination_each (Babl *babl,
void *userdata)
{
Babl *source = userdata;
Babl *destination = babl;
+ init_test_pixels ();
if (qux % babl_formats_count () == qux / babl_formats_count ())
printf (SELF);
else
{
Babl *temp = babl_fish_path (source, destination);
+ const Babl *fish = babl_fish (source, destination);
+
+ char style[128] = "";
+ char title[1024] = "";
+#ifdef UTF8
+#else
+ {
+ float pixels_per_second;
+ long ticks_start, ticks_end;
+
+ ticks_start = babl_ticks ();
+ babl_process (fish, &test_pixels_in[0],
+ &test_pixels_out[0],
+ NUM_TEST_PIXELS);
+ ticks_end = babl_ticks ();
+
+ pixels_per_second = (NUM_TEST_PIXELS) / ((ticks_end - ticks_start)/1000.0);
+
+ {
+ float colval = pixels_per_second/1000/1000.0/0.7;
+ if (colval > 1)
+ colval = 1;
+
+ if (colval < 0.2)
+ {
+ sprintf (style, "color:rgb(%i, 0, 0);", (int)(colval * 5 * 255));
+ }
+ else if (colval < 0.4)
+ {
+ sprintf (style, "color:rgb(255, %i, 0);", (int)((colval-0.2) * 5 * 255));
+ }
+ else
+ {
+ sprintf (style, "color:rgb(255, 255, %i);", (int)((colval-0.4) * 1.666 * 255));
+ }
+
+ }
+ {
+ int steps = 0;
+ if (temp)
+ steps = babl_list_size (temp->fish_path.conversion_list);
+ sprintf (title, "%s to %s %i steps %.3f mpix/s ", babl_get_name (source), babl_get_name (destination), steps, pixels_per_second/1000.0);
+ }
+ }
+#endif
if (temp)
{
- printf ("%s", utf8_bar[babl_list_size (temp->fish_path.conversion_list)]);
+ printf (utf8_bar[babl_list_size (temp->fish_path.conversion_list)], title, style);
total_length += babl_list_size (temp->fish_path.conversion_list);
total_cost += temp->fish_path.cost;
ok++;
@@ -78,7 +204,7 @@ static int destination_each (Babl *babl,
}
else
{
- printf (EMPTY);
+ printf (EMPTY, title, style);
total++;
}
}
@@ -114,10 +240,11 @@ int main (void)
printf ("<style>\n"
".empty, .direct, .self, .path1, .path2, .path3, .path4, .path5 { float:left; width: 1em; height: 1em; }"
-"body { background: black; padding: 2em; line-height: 1em; }"
-".empty { background: black; }"
-".self { background: yellow; }"
-".direct { background: blue; }"
+"body { background: black; color:white; padding: 2em; line-height: 1em; font-size: 9px;}"
+".empty { background: black; border-left: 1px solid transparent;}"
+".self { background: yellow;border-left: 1px solid transparent; }"
+".direct { background: blue; border-left: 1px solid blue;}"
+/*
".path1 { background: green; }"
".path2 { background: #8ff; }"
".path3 { background: #8f8; }"
@@ -126,10 +253,17 @@ int main (void)
".path6 { background: #082; }"
".path7 { background: #050; }"
".path8 { background: #020; }"
+*/
+
+".path1, .path2, .path3, .path4, .path5, .path6, .path7 "
+"{ border-left: 1px solid blue; }"
+
+".empty, .self, .direct, .path1, .path2, .path3, .path4, .path5, .path6, .path7 "
+"{ cursor: crosshair; }"
"</style>\n");
- printf ("</head><body>\n");
+ printf ("</head><body><p>babl profiling matrix, rows are source formats columns are destinations, blue background means direct conversion and blue left border means multi-step conversion, no blue means reference conversion, gradient from black, through red, yellow and white indicates memory-bandwidth sum bytes read + bytes written / time, hover items to see further details on an individual conversion.</p><div style='position:absolute; width:220em;'>\n");
#endif