diff options
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 |
commit | ae60c4fca5c749cf556c86bf6e721f96e6639462 (patch) | |
tree | 98c81d95a926b69674396185cc9563f40c43589f | |
parent | a43f7fd533bcc21b1f0fb622d4d7aabe27128924 (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.c | 2 | ||||
-rw-r--r-- | babl/base/type-half.c | 245 | ||||
-rw-r--r-- | babl/base/type-u15.c | 101 | ||||
-rw-r--r-- | babl/base/type-u16.c | 99 | ||||
-rw-r--r-- | babl/base/type-u32.c | 100 | ||||
-rw-r--r-- | babl/base/type-u8.c | 128 | ||||
-rw-r--r-- | extensions/CIE.c | 230 |
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 |