[babl] Minimal float -> u8, u16 conversions



commit 478216a472527359814c4b376aecd167aa56cda0
Author: Daniel Sabo <DanielSabo gmail com>
Date:   Tue Jan 29 18:41:44 2013 -0800

    Minimal float -> u8, u16 conversions
    
    Add some simplistic but "accurate" float -> u8 and float -> u16
    conversions to make more non-reference paths usable.
    
    The main difference from the existing conversions is that these
    clamp out of range values and make the path error checker happy.
    
    I also had to fudge the float-to-8bit slightly because the prior
    values cause it to check for the rounding on an exact 0.5 value.

 extensions/Makefile.am   |    2 +
 extensions/gegl-fixups.c |   24 +++++++
 extensions/simple.c      |  164 ++++++++++++++++++++++++++++++++++++++++++++++
 tests/float-to-8bit.c    |    3 +-
 4 files changed, 192 insertions(+), 1 deletions(-)
---
diff --git a/extensions/Makefile.am b/extensions/Makefile.am
index 220d18a..2636f17 100644
--- a/extensions/Makefile.am
+++ b/extensions/Makefile.am
@@ -25,10 +25,12 @@ ext_LTLIBRARIES = \
        fast-float.la    \
        naive-CMYK.la   \
        HSV.la   \
+       simple.la       \
        sse-fixups.la
 
 cairo_la_SOURCES = cairo.c
 CIE_la_SOURCES = CIE.c
+expar_la_SOURCES = expar.c
 gegl_fixups_la_SOURCES = gegl-fixups.c
 gggl_lies_la_SOURCES = gggl-lies.c
 gggl_la_SOURCES = gggl.c
diff --git a/extensions/gegl-fixups.c b/extensions/gegl-fixups.c
index 5a1b972..7645993 100644
--- a/extensions/gegl-fixups.c
+++ b/extensions/gegl-fixups.c
@@ -465,6 +465,8 @@ conv_rgbAF_lrgba8 (unsigned char *srcc,
 }
 
 #define conv_rgb8_rgbAF    conv_rgb8_rgbaF
+#define conv_gamma_rgbaF_gamma_rgbAF   conv_rgbaF_rgbAF
+#define conv_gamma_rgbAF_gamma_rgbaF   conv_rgbAF_rgbaF
 
 int init (void);
 
@@ -487,6 +489,24 @@ init (void)
     babl_component ("Ba"),
     babl_component ("A"),
     NULL);
+    
+    
+  const Babl *gamma_rgbaF = babl_format_new (
+    babl_model ("R'G'B'A"),
+    babl_type ("float"),
+    babl_component ("R'"),
+    babl_component ("G'"),
+    babl_component ("B'"),
+    babl_component ("A"),
+    NULL);
+  const Babl *gamma_rgbAF = babl_format_new (
+    babl_model ("R'aG'aB'aA"),
+    babl_type ("float"),
+    babl_component ("R'a"),
+    babl_component ("G'a"),
+    babl_component ("B'a"),
+    babl_component ("A"),
+    NULL);
 
   const Babl *lrgba8 = babl_format_new (
     babl_model ("RGBA"),
@@ -529,6 +549,10 @@ init (void)
 
   o (rgbaF, rgbAF);
   o (rgbAF, rgbaF);
+  
+  o (gamma_rgbaF, gamma_rgbAF);
+  o (gamma_rgbAF, gamma_rgbaF);
+  
   o (rgbAF, lrgba8);
   o (rgb8, rgbaF);
   o (rgb8, rgbAF);
diff --git a/extensions/simple.c b/extensions/simple.c
new file mode 100644
index 0000000..bde7785
--- /dev/null
+++ b/extensions/simple.c
@@ -0,0 +1,164 @@
+#include <stdlib.h>
+#include <stdint.h>
+#include "babl.h"
+
+int init (void);
+
+static inline long
+float_to_u8 (unsigned char *src_char, unsigned char *dst, long samples)
+{
+  float *src = (float *)src_char;
+  long n = samples;
+  while (n--)
+    {
+      float r = src[0];
+      float g = src[1];
+      float b = src[2];
+      float a = src[3];
+            
+      dst[0] = (r >= 1.0f) ? 0xFF : ((r <= 0.0f) ? 0x0 : 0xFF * r + 0.5f);
+      dst[1] = (g >= 1.0f) ? 0xFF : ((g <= 0.0f) ? 0x0 : 0xFF * g + 0.5f);
+      dst[2] = (b >= 1.0f) ? 0xFF : ((b <= 0.0f) ? 0x0 : 0xFF * b + 0.5f);
+      dst[3] = (a >= 1.0f) ? 0xFF : ((a <= 0.0f) ? 0x0 : 0xFF * a + 0.5f);
+      
+      dst += 4;
+      src += 4;
+    }
+  return samples;
+}
+
+static inline long
+float_pre_to_u8_pre (unsigned char *src_char, unsigned char *dst, long samples)
+{
+  float *src = (float *)src_char;
+  long n = samples;
+  while (n--)
+    {
+      float r = src[0];
+      float g = src[1];
+      float b = src[2];
+      float a = src[3];
+      
+      if (a > 1.0f) {
+        r /= a;
+        g /= a;
+        b /= a;
+        a /= a;
+      }
+      
+      dst[0] = (r >= 1.0f) ? 0xFF : ((r <= 0.0f) ? 0x0 : 0xFF * r + 0.5f);
+      dst[1] = (g >= 1.0f) ? 0xFF : ((g <= 0.0f) ? 0x0 : 0xFF * g + 0.5f);
+      dst[2] = (b >= 1.0f) ? 0xFF : ((b <= 0.0f) ? 0x0 : 0xFF * b + 0.5f);
+      dst[3] = (a >= 1.0f) ? 0xFF : ((a <= 0.0f) ? 0x0 : 0xFF * a + 0.5f);
+      
+      dst += 4;
+      src += 4;
+
+    }
+  return samples;
+}
+
+static inline long
+float_to_u16 (unsigned char *src_char, unsigned char *dst_char, long samples)
+{
+  float *src    = (float *)src_char;
+  uint16_t *dst = (uint16_t *)dst_char;
+  long n = samples;
+  while (n--)
+    {
+      float r = src[0];
+      float g = src[1];
+      float b = src[2];
+      float a = src[3];
+            
+      dst[0] = (r >= 1.0f) ? 0xFFFF : ((r <= 0.0f) ? 0x0 : 0xFFFF * r + 0.5f);
+      dst[1] = (g >= 1.0f) ? 0xFFFF : ((g <= 0.0f) ? 0x0 : 0xFFFF * g + 0.5f);
+      dst[2] = (b >= 1.0f) ? 0xFFFF : ((b <= 0.0f) ? 0x0 : 0xFFFF * b + 0.5f);
+      dst[3] = (a >= 1.0f) ? 0xFFFF : ((a <= 0.0f) ? 0x0 : 0xFFFF * a + 0.5f);
+      
+      dst += 4;
+      src += 4;
+    }
+  return samples;
+}
+
+static inline long
+float_pre_to_u16_pre (unsigned char *src_char, unsigned char *dst_char, long samples)
+{
+  float *src = (float *)src_char;
+  uint16_t *dst = (uint16_t *)dst_char;
+  long n = samples;
+  while (n--)
+    {
+      float r = src[0];
+      float g = src[1];
+      float b = src[2];
+      float a = src[3];
+      
+      if (a > 1.0f) {
+        r /= a;
+        g /= a;
+        b /= a;
+        a /= a;
+      }
+      
+      dst[0] = (r >= 1.0f) ? 0xFFFF : ((r <= 0.0f) ? 0x0 : 0xFFFF * r + 0.5f);
+      dst[1] = (g >= 1.0f) ? 0xFFFF : ((g <= 0.0f) ? 0x0 : 0xFFFF * g + 0.5f);
+      dst[2] = (b >= 1.0f) ? 0xFFFF : ((b <= 0.0f) ? 0x0 : 0xFFFF * b + 0.5f);
+      dst[3] = (a >= 1.0f) ? 0xFFFF : ((a <= 0.0f) ? 0x0 : 0xFFFF * a + 0.5f);
+      
+      dst += 4;
+      src += 4;
+    }
+  return samples;
+}
+
+int
+init (void)
+{
+  /* float and u8 */
+  babl_conversion_new (babl_format ("R'G'B'A float"),
+                       babl_format ("R'G'B'A u8"),
+                      "linear", 
+                       float_to_u8,
+                       NULL);
+  babl_conversion_new (babl_format ("RGBA float"),
+                       babl_format ("RGBA u8"),
+                      "linear", 
+                       float_to_u8,
+                       NULL);
+  babl_conversion_new (babl_format ("R'aG'aB'aA float"),
+                       babl_format ("R'aG'aB'aA u8"),
+                      "linear", 
+                       float_pre_to_u8_pre,
+                       NULL);
+  babl_conversion_new (babl_format ("RaGaBaA float"),
+                       babl_format ("RaGaBaA u8"),
+                      "linear", 
+                       float_pre_to_u8_pre,
+                       NULL);
+
+  /* float and u16 */
+  babl_conversion_new (babl_format ("R'G'B'A float"),
+                       babl_format ("R'G'B'A u16"),
+                      "linear", 
+                       float_to_u16,
+                       NULL);
+  babl_conversion_new (babl_format ("RGBA float"),
+                       babl_format ("RGBA u16"),
+                      "linear", 
+                       float_to_u16,
+                       NULL);
+  babl_conversion_new (babl_format ("R'aG'aB'aA float"),
+                       babl_format ("R'aG'aB'aA u16"),
+                      "linear", 
+                       float_pre_to_u16_pre,
+                       NULL);
+  babl_conversion_new (babl_format ("RaGaBaA float"),
+                       babl_format ("RaGaBaA u16"),
+                      "linear", 
+                       float_pre_to_u16_pre,
+                       NULL);
+
+  return 0;
+}
diff --git a/tests/float-to-8bit.c b/tests/float-to-8bit.c
index b273008..a93591c 100644
--- a/tests/float-to-8bit.c
+++ b/tests/float-to-8bit.c
@@ -86,7 +86,8 @@ main (int    argc,
   }
 
   {
-    float in[][4]   = {{ 0.21582, -0.55, -0.14, 1.0 }, {0.2, 0.301, 0.5, 0.6}, {0.0, 3.0, 6.0, 3.0}};
+    /*                                                 (0.5 / 0.6) * 255 = 212.5, I'm not going to worry 
about rounding that close... */
+    float in[][4]   = {{ 0.21582, -0.55, -0.14, 1.0 }, {0.2, 0.301, 0.49998, 0.6}, {0.0, 3.0, 6.0, 3.0}};
     unsigned char out[][4]  = {{55, 0, 0, 255 }, {85,128,212,153}, {0,255,255,255}};
 
     CHECK_CONV("float -> u8 6", unsigned char,


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]