babl-fish-reference: reintroduce single precision processing
authorØyvind Kolås <pippin@gimp.org>
Mon, 27 Aug 2018 23:52:54 +0000 (01:52 +0200)
committerØyvind Kolås <pippin@gimp.org>
Mon, 27 Aug 2018 23:52:57 +0000 (01:52 +0200)
only for matching components for now

babl/babl-fish-reference.c
babl/base/type-half.c

index 2dceba02b2c3d2849938968580465c8de4776e5e..0f6c4b4b4772c5c9cb6a70af5e15d15a7f8ece90 100644 (file)
@@ -400,6 +400,76 @@ static int compatible_components (const BablFormat *a,
   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
 process_same_model (const Babl  *babl,
                     const char *source,
@@ -426,19 +496,37 @@ process_same_model (const Babl  *babl,
   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
-      );
+      const void *type_float = babl_type_from_id (BABL_FLOAT);
 
-      ncomponent_convert_from_double (
-        (BablFormat *) BABL (babl->fish.destination),
-        double_buf,
-        (char *) destination,
-        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))
+      {
+        ncomponent_convert_to_float (
+          (BablFormat *) BABL (babl->fish.source),
+          (char *) source,
+          double_buf,
+          n);
+        ncomponent_convert_from_float (
+          (BablFormat *) BABL (babl->fish.destination),
+          double_buf,
+          (char *) destination,
+          n);
+      }
+      else
+      {
+        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
     {
index f31cfa0fb7cf7c7d85356fcf1055ec2d4fcc99e3..d163300a36f95a1941948d02d31ffbd3f46a8ea9 100644 (file)
@@ -184,112 +184,69 @@ 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)
+static void
+singles2halfp(uint16_t *hp, const uint32_t *xp, 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
-    }
+    uint16_t    hs, he, hm;
+    uint32_t x, xs, xe, xm;
+    int hes;    
     
-    if( source == NULL || target == NULL ) { // Nothing to convert (e.g., imag part of pure real)
-        return 0;
+   
+    
+    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_TYPE) (x >> 16);  // Return the 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_TYPE) (xs >> 16);
+                *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_TYPE) ((xs >> 16) | 0x7C00u); // Signed Inf
+                    *hp++ = (uint16_t) ((xs >> 16) | 0x7C00u); // Signed Inf
                 } else {
-                    *hp++ = (UINT16_TYPE) 0xFE00u; // NaN, only 1st mantissa bit set
+                    *hp++ = (uint16_t) 0xFE00u; // NaN, only 1st mantissa bit set
                 }
             } else { // Normalized number
-                hs = (UINT16_TYPE) (xs >> 16); // Sign bit
+                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_TYPE) ((xs >> 16) | 0x7C00u); // Signed Inf
+                    *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_TYPE) 0u;  // Set mantissa to zero
+                        hm = (uint16_t) 0u;  // Set mantissa to zero
                     } else {
                         xm |= 0x00800000u;  // Add the hidden leading bit
-                        hm = (UINT16_TYPE) (xm >> (14 - hes)); // Mantissa
+                        hm = (uint16_t) (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
+                            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_TYPE) (hes << 10); // Exponent
-                    hm = (UINT16_TYPE) (xm >> 13); // Mantissa
+                    he = (uint16_t) (hes << 10); // Exponent
+                    hm = (uint16_t) (xm >> 13); // Mantissa
                     if( xm & 0x00001000u ) // Check for rounding
-                        *hp++ = (hs | he | hm) + (UINT16_TYPE) 1u; // Round, might overflow to inf, this is OK
+                        *hp++ = (hs | he | hm) + (uint16_t) 1u; // Round, might overflow to inf, this is OK
                     else
                         *hp++ = (hs | he | hm);  // No rounding
                 }
             }
         }
     }
-    return 0;
+    return;
 }
 
 
+    
+   
+                       
 //-----------------------------------------------------------------------------
 //
 // Routine:  halfp2singles
@@ -298,52 +255,30 @@ static int singles2halfp(void *target, void *source, int numel)
 //         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)
+static void
+halfp2singles(uint32_t *xp, const uint16_t *hp, 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
-    }
+    uint16_t h, hs, he, hm;
+    uint32_t xs, xe, xm;
+    int32_t xes;
+    int e;
+
+
     
-    if( source == NULL || target == NULL ) // Nothing to convert (e.g., imag part of pure real)
-        return 0;
+    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_TYPE) h) << 16;  // Return the 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
@@ -354,30 +289,33 @@ static int halfp2singles(void *target, void *source, int numel)
                     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
+                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_TYPE) hs) << 16) | ((UINT32_TYPE) 0x7F800000u); // Signed Inf
+                    *xp++ = (((uint32_t) hs) << 16) | ((uint32_t) 0x7F800000u); // Signed Inf
                 } else {
-                    *xp++ = (UINT32_TYPE) 0xFFC00000u; // NaN, only 1st mantissa bit set
+                    *xp++ = (uint32_t) 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
+                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 0;
+    return;
 }
 
 
+
+
+
 static void
 convert_double_half (BablConversion *conversion,
                      char *src,
@@ -421,7 +359,7 @@ convert_float_half (BablConversion *conversion,
 {
   while (n--)
     {
-      singles2halfp (dst, src, 1);
+      singles2halfp ((void*)dst, (void*)src, 1);
       dst             += dst_pitch;
       src             += src_pitch;
     }
@@ -437,7 +375,7 @@ convert_half_float (BablConversion *conversion,
 {
   while (n--)
     {
-      halfp2singles (dst, src, 1);
+      halfp2singles ((void*)dst, (void*)src, 1);
       dst              += dst_pitch;
       src              += src_pitch;
     }