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