1 
2 
3 /*----------------------------------------------------------------------------*/
4 /*** The functions herein provide for nonlinear interpolation   ***
5  *** between RGB colors.  All colors are expressed as float     ***
6  *** triples, with values required to be in the range 0..1.     ***
7  *** This file is meant to be #include-d into another file!     ***/
8 /*----------------------------------------------------------------------------*/
9 
10 #ifndef TYPEDEF_float_triple
11 #define TYPEDEF_float_triple
12 typedef struct { float a,b,c ; } float_triple ;
13 #define float_trip float_triple
14 #endif
15 
16 #ifndef TYPEDEF_byte
17 #define TYPEDEF_byte
18 typedef unsigned char byte ;
19 #endif
20 
21 #ifndef INLINE
22 #ifdef __GNUC__
23 # define INLINE __inline__
24 #endif
25 #endif
26 
27 /*----------------------------------------------------------------------------*/
28 
29 #define rgb_up(x) ( ((x) > 0.040450f) ? powf(((x)+0.055f)/1.055f,2.4f)    : (x)/12.92f )
30 #define rgb_dn(x) ( ((x)> 0.0031308f) ? 1.055f*powf((x),0.416667f)-0.055f : 12.92f*(x) )
31 
32 /*----------------------------------------------------------------------------*/
33 
34 static byte rinit=0  ;
35 static byte rup[256] ;
36 static byte rdn[256] ;
37 
COLOR_init_rupdn(void)38 static void COLOR_init_rupdn(void)
39 {
40    unsigned short ii ; float rr;
41    if( rinit ) return ;
42    for( ii=1 ; ii < 255 ; ii++ ){
43      rr = ii / 255.0f ;
44      rup[ii] = (byte)(255.49f*rgb_up[rr]) ;
45      rdn[ii] = (byte)(255.49f*rgb_dn[rr]) ;
46    }
47    rup[0] = rdn[0] = 0 ; rup[255] = rdn[255] = 255 ; rinit = 1 ; return ;
48 }
49 
50 /*----------------------------------------------------------------------------*/
51 
COLOR_rgb_to_xyz(float_triple rgb)52 static INLINE float_triple COLOR_rgb_to_xyz( float_triple rgb )
53 {
54    float_triple xyz ; float xx,yy,zz ;
55 
56    xx = rgb_up(rgb.a) ; yy = rgb_up(rgb.b) ; zz = rgb_up(rgb.c) ;
57    xyz.a = 0.433877f*xx + 0.376223f*yy + 0.189900f*zz ;
58    xyz.b = 0.212600f*xx + 0.715200f*yy + 0.072200f*zz ;  /* luminance */
59    xyz.c = 0.017723f*xx + 0.109458f*yy + 0.872819f*zz ;
60    if( xyz.a > 1.0f ) xyz.a = 1.0f ; else if( xyz.a < 0.0f ) xyz.a = 0.0f ;
61    if( xyz.b > 1.0f ) xyz.b = 1.0f ; else if( xyz.b < 0.0f ) xyz.b = 0.0f ;
62    if( xyz.c > 1.0f ) xyz.c = 1.0f ; else if( xyz.c < 0.0f ) xyz.c = 0.0f ;
63    return xyz ;
64 }
65 
COLOR_xyz_to_rgb(float_triple xyz)66 static INLINE float_triple COLOR_xyz_to_rgb( float_triple xyz )
67 {
68    float_triple rgb ; float xx,yy,zz ;
69 
70    xx =  3.0802100f*xyz.a - 1.537210f*xyz.b - 0.5430060f*xyz.c ;
71    yy = -0.9209680f*xyz.a + 1.875760f*xyz.b + 0.0452125f*xyz.c ;
72    zz =  0.0529522f*xyz.a - 0.204021f*xyz.b + 1.1510700f*xyz.c ;
73 
74    rgb.a = rgb_dn(xx) ; rgb.b = rgb_dn(yy) ; rgb.c = rgb_dn(zz) ;
75    if( rgb.a > 1.0f ) rgb.a = 1.0f ; else if( rgb.a < 0.0f ) rgb.a = 0.0f ;
76    if( rgb.b > 1.0f ) rgb.b = 1.0f ; else if( rgb.b < 0.0f ) rgb.b = 0.0f ;
77    if( rgb.c > 1.0f ) rgb.c = 1.0f ; else if( rgb.c < 0.0f ) rgb.c = 0.0f ;
78    return rgb ;
79 }
80 
81 #undef rgb_up
82 #undef rgb_dn
83 
84 /*----------------------------------------------------------------------------*/
85 
86 #define XFUN(a) cbrtf(a)     /* nonlinear transform of XYZ before interp */
87 #define XINV(a) (a)*(a)*(a)  /* inverse transform after interp */
88 
COLOR_rgb_interp(float_triple rgb1,float_triple rgb2,float fac)89 float_triple COLOR_rgb_interp( float_triple rgb1, float_triple rgb2, float fac )
90 {
91    float_triple rgb , xyz1,xyz2 ;
92 
93         if( fac <= 0.0f ) return rgb2 ;
94    else if( fac >= 1.0f ) return rgb1 ;
95 
96    xyz1 = COLOR_rgb_to_xyz(rgb1) ;
97    xyz2 = COLOR_rgb_to_xyz(rgb2) ;
98    xyz1.a = fac*XFUN(xyz1.a) + (1.0f-fac)*XFUN(xyz2.a) ; xyz1.a = XINV(xyz1.a) ;
99    xyz1.b = fac*XFUN(xyz1.b) + (1.0f-fac)*XFUN(xyz2.b) ; xyz1.b = XINV(xyz1.b) ;
100    xyz1.c = fac*XFUN(xyz1.c) + (1.0f-fac)*XFUN(xyz2.c) ; xyz1.c = XINV(xyz1.c) ;
101    rgb = COLOR_xyz_to_rgb(xyz1) ; return rgb ;
102 }
103 
104 #undef XFUN
105 #undef XINV
106 
107 /*----------------------------------------------------------------------------*/
108