summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorØyvind Kolås <pippin@gimp.org>2018-08-27 21:44:32 +0200
committerØyvind Kolås <pippin@gimp.org>2018-08-28 00:37:04 +0200
commitae60c4fca5c749cf556c86bf6e721f96e6639462 (patch)
tree98c81d95a926b69674396185cc9563f40c43589f
parenta43f7fd533bcc21b1f0fb622d4d7aabe27128924 (diff)
base: register single precision conversions for types
We're already registering double versions, having single precision and in practice possibly sufficient precision for commonly used conversions.
-rw-r--r--babl/base/babl-base.c2
-rw-r--r--babl/base/type-half.c245
-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--extensions/CIE.c230
7 files changed, 904 insertions, 1 deletions
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/type-half.c b/babl/base/type-half.c
index 93d5e5b..f31cfa0 100644
--- a/babl/base/type-half.c
+++ b/babl/base/type-half.c
@@ -183,6 +183,201 @@ static void halfp2doubles(void *target, void *source, long numel)
}
}
+
+#define INT16_TYPE short
+#define UINT16_TYPE unsigned short
+#define INT32_TYPE long
+#define UINT32_TYPE unsigned long
+
+// Prototypes -----------------------------------------------------------------
+
+static int singles2halfp(void *target, void *source, int numel);
+static int halfp2singles(void *target, void *source, int numel);
+
+//-----------------------------------------------------------------------------
+//
+// Routine: singles2halfp
+//
+// Input: source = Address of 32-bit floating point data to convert
+// numel = Number of values at that address to convert
+//
+// Output: target = Address of 16-bit data to hold output (numel values)
+// return value = 0 if native floating point format is IEEE
+// = 1 if native floating point format is not IEEE
+//
+// Programmer: James Tursa
+//
+//-----------------------------------------------------------------------------
+
+static int singles2halfp(void *target, void *source, int numel)
+{
+ UINT16_TYPE *hp = (UINT16_TYPE *) target; // Type pun output as an unsigned 16-bit int
+ UINT32_TYPE *xp = (UINT32_TYPE *) source; // Type pun input as an unsigned 32-bit int
+ UINT16_TYPE hs, he, hm;
+ UINT32_TYPE x, xs, xe, xm;
+ int hes;
+ static int next; // Little Endian adjustment
+ static int checkieee = 1; // Flag to check for IEEE754, Endian, and word size
+ double one = 1.0; // Used for checking IEEE754 floating point format
+ UINT32_TYPE *ip; // Used for checking IEEE754 floating point format
+
+ if( checkieee ) { // 1st call, so check for IEEE754, Endian, and word size
+ ip = (UINT32_TYPE *) &one;
+ if( *ip ) { // If Big Endian, then no adjustment
+ next = 0;
+ } else { // If Little Endian, then adjustment will be necessary
+ next = 1;
+ ip++;
+ }
+ if( *ip != 0x3FF00000u ) { // Check for exact IEEE 754 bit pattern of 1.0
+ return 1; // Floating point bit pattern is not IEEE 754
+ if (next)
+ return 1; // not used, but silences gcc
+ }
+ if( sizeof(INT16_TYPE) != 2 || sizeof(INT32_TYPE) != 4 ) {
+ return 1; // short is not 16-bits, or long is not 32-bits.
+ }
+ checkieee = 0; // Everything checks out OK
+ }
+
+ if( source == NULL || target == NULL ) { // Nothing to convert (e.g., imag part of pure real)
+ return 0;
+ }
+
+ while( numel-- ) {
+ x = *xp++;
+ if( (x & 0x7FFFFFFFu) == 0 ) { // Signed zero
+ *hp++ = (UINT16_TYPE) (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_TYPE) (xs >> 16);
+ } else if( xe == 0x7F800000u ) { // Inf or NaN (all the exponent bits are set)
+ if( xm == 0 ) { // If mantissa is zero ...
+ *hp++ = (UINT16_TYPE) ((xs >> 16) | 0x7C00u); // Signed Inf
+ } else {
+ *hp++ = (UINT16_TYPE) 0xFE00u; // NaN, only 1st mantissa bit set
+ }
+ } else { // Normalized number
+ hs = (UINT16_TYPE) (xs >> 16); // Sign bit
+ hes = ((int)(xe >> 23)) - 127 + 15; // Exponent unbias the single, then bias the halfp
+ if( hes >= 0x1F ) { // Overflow
+ *hp++ = (UINT16_TYPE) ((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_TYPE) 0u; // Set mantissa to zero
+ } else {
+ xm |= 0x00800000u; // Add the hidden leading bit
+ hm = (UINT16_TYPE) (xm >> (14 - hes)); // Mantissa
+ if( (xm >> (13 - hes)) & 0x00000001u ) // Check for rounding
+ hm += (UINT16_TYPE) 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_TYPE) (hes << 10); // Exponent
+ hm = (UINT16_TYPE) (xm >> 13); // Mantissa
+ if( xm & 0x00001000u ) // Check for rounding
+ *hp++ = (hs | he | hm) + (UINT16_TYPE) 1u; // Round, might overflow to inf, this is OK
+ else
+ *hp++ = (hs | he | hm); // No rounding
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+
+//-----------------------------------------------------------------------------
+//
+// 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)
+// return value = 0 if native floating point format is IEEE
+// = 1 if native floating point format is not IEEE
+//
+// Programmer: James Tursa
+//
+//-----------------------------------------------------------------------------
+
+static int halfp2singles(void *target, void *source, int numel)
+{
+ UINT16_TYPE *hp = (UINT16_TYPE *) source; // Type pun input as an unsigned 16-bit int
+ UINT32_TYPE *xp = (UINT32_TYPE *) target; // Type pun output as an unsigned 32-bit int
+ UINT16_TYPE h, hs, he, hm;
+ UINT32_TYPE xs, xe, xm;
+ INT32_TYPE xes;
+ int e;
+ static int next; // Little Endian adjustment
+ static int checkieee = 1; // Flag to check for IEEE754, Endian, and word size
+ double one = 1.0; // Used for checking IEEE754 floating point format
+ UINT32_TYPE *ip; // Used for checking IEEE754 floating point format
+
+ if( checkieee ) { // 1st call, so check for IEEE754, Endian, and word size
+ ip = (UINT32_TYPE *) &one;
+ if( *ip ) { // If Big Endian, then no adjustment
+ next = 0;
+ } else { // If Little Endian, then adjustment will be necessary
+ next = 1;
+ ip++;
+ }
+ if( *ip != 0x3FF00000u ) { // Check for exact IEEE 754 bit pattern of 1.0
+ return 1; // Floating point bit pattern is not IEEE 754
+ if (next)
+ return 1; // not used but silences gcc
+ }
+ if( sizeof(INT16_TYPE) != 2 || sizeof(INT32_TYPE) != 4 ) {
+ return 1; // short is not 16-bits, or long is not 32-bits.
+ }
+ checkieee = 0; // Everything checks out OK
+ }
+
+ if( source == NULL || target == NULL ) // Nothing to convert (e.g., imag part of pure real)
+ return 0;
+
+ while( numel-- ) {
+ h = *hp++;
+ if( (h & 0x7FFFu) == 0 ) { // Signed zero
+ *xp++ = ((UINT32_TYPE) 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_TYPE) hs) << 16; // Sign bit
+ xes = ((INT32_TYPE) (he >> 10)) - 15 + 127 - e; // Exponent unbias the halfp, then bias the single
+ xe = (UINT32_TYPE) (xes << 23); // Exponent
+ xm = ((UINT32_TYPE) (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_TYPE) hs) << 16) | ((UINT32_TYPE) 0x7F800000u); // Signed Inf
+ } else {
+ *xp++ = (UINT32_TYPE) 0xFFC00000u; // NaN, only 1st mantissa bit set
+ }
+ } else { // Normalized number
+ xs = ((UINT32_TYPE) hs) << 16; // Sign bit
+ xes = ((INT32_TYPE) (he >> 10)) - 15 + 127; // Exponent unbias the halfp, then bias the single
+ xe = (UINT32_TYPE) (xes << 23); // Exponent
+ xm = ((UINT32_TYPE) hm) << 13; // Mantissa
+ *xp++ = (xs | xe | xm); // Combine sign bit, exponent bits, and mantissa bits
+ }
+ }
+ }
+ return 0;
+}
+
+
static void
convert_double_half (BablConversion *conversion,
char *src,
@@ -215,6 +410,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 (dst, 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 (dst, src, 1);
+ dst += dst_pitch;
+ src += src_pitch;
+ }
+}
+
+
+
+
void
babl_base_type_half (void)
{
@@ -237,4 +468,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..68a99bc 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,
+ 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 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,
+ 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 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..1cf0629 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,
+ 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 (BablConversion *c,
+ 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_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/extensions/CIE.c b/extensions/CIE.c
index b96e124..4c11c3b 100644
--- a/extensions/CIE.c
+++ b/extensions/CIE.c
@@ -1779,6 +1779,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 +1917,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 +2032,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 +2169,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