Typo: 'individualy' -> 'individually'.
[synfig.git] / synfig-core / trunk / src / synfig / gamma.cpp
1 /* === S Y N F I G ========================================================= */
2 /*!     \file gamma.cpp
3 **      \brief Template File
4 **
5 **      $Id$
6 **
7 **      \legal
8 **      Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
9 **
10 **      This package is free software; you can redistribute it and/or
11 **      modify it under the terms of the GNU General Public License as
12 **      published by the Free Software Foundation; either version 2 of
13 **      the License, or (at your option) any later version.
14 **
15 **      This package is distributed in the hope that it will be useful,
16 **      but WITHOUT ANY WARRANTY; without even the implied warranty of
17 **      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 **      General Public License for more details.
19 **      \endlegal
20 */
21 /* ========================================================================= */
22
23 /* === H E A D E R S ======================================================= */
24
25 #ifdef USING_PCH
26 #       include "pch.h"
27 #else
28 #ifdef HAVE_CONFIG_H
29 #       include <config.h>
30 #endif
31
32 #include "gamma.h"
33 #include <cmath>
34 #include <algorithm>
35 #endif
36
37 /* === U S I N G =========================================================== */
38
39 using namespace std;
40 //using namespace etl;
41 using namespace synfig;
42
43 /* === M A C R O S ========================================================= */
44
45 /* === G L O B A L S ======================================================= */
46
47 /* === P R O C E D U R E S ================================================= */
48
49 /* === M E T H O D S ======================================================= */
50
51 void
52 Gamma::set_gamma(float x)
53 {
54         gamma_r=gamma_g=gamma_b=x;
55         int i;
56         red_blue_level=1.0f;
57         for(i=0;i<65536;i++)
58         {
59                 float f(float(i)/65536.0f);
60                 f=pow(f,gamma_r);
61                 table_r_U16_to_U8[i]=table_g_U16_to_U8[i]=table_b_U16_to_U8[i]=(unsigned char)(f*(255.0f-(black_level*255))+0.5f + black_level*255.0f);
62         }
63
64         for(i=0;i<256;i++)
65                 table_r_U8_to_F32[i]=table_g_U8_to_F32[i]=table_b_U8_to_F32[i]=pow((float(i)/255.0f)*(1.0f-black_level)+black_level,gamma_r);
66 }
67
68
69 void
70 Gamma::refresh_gamma_r()
71 {
72         int i;
73 //      const float scalar(min(red_blue_level,1.0f));
74         const float scalar(1.0f);
75         for(i=0;i<65536;i++)
76         {
77                 float f(float(i)/65536.0f);
78                 f=pow(f,gamma_r)*scalar;
79                 table_r_U16_to_U8[i]=(unsigned char)(f*(255.0f-(black_level*255))+0.5f + black_level*255.0f);
80         }
81
82         for(i=0;i<256;i++)
83                 table_r_U8_to_F32[i]=pow((float(i)/255.0f)*(1.0f-black_level)+black_level,gamma_r)*scalar;
84 }
85
86 void
87 Gamma::refresh_gamma_g()
88 {
89         int i;
90 //      const float scalar(sqrt(min(red_blue_level,2.0f-red_blue_level)));
91         const float scalar(1.0f);
92         for(i=0;i<65536;i++)
93         {
94                 float f(float(i)/65536.0f);
95                 f=pow(f,gamma_g)*scalar;
96                 table_g_U16_to_U8[i]=(unsigned char)(f*(255.0f-(black_level*255))+0.5f + black_level*255.0f);
97         }
98         for(i=0;i<256;i++)
99                 table_g_U8_to_F32[i]=pow((float(i)/255.0f)*(1.0f-black_level)+black_level,gamma_g)*scalar;
100 }
101
102 void
103 Gamma::refresh_gamma_b()
104 {
105         int i;
106 //      const float scalar(min(2.0f-red_blue_level,1.0f));
107         const float scalar(1.0f);
108         for(i=0;i<65536;i++)
109         {
110                 float f(float(i)/65536.0f);
111                 f=pow(f,gamma_b)*scalar;
112                 table_b_U16_to_U8[i]=(unsigned char)(f*(255.0f-(black_level*255))+0.5f + black_level*255.0f);
113         }
114         for(i=0;i<256;i++)
115                 table_b_U8_to_F32[i]=pow((float(i)/255.0f)*(1.0f-black_level)+black_level,gamma_b)*scalar;
116 }
117
118 void
119 Gamma::set_gamma_r(float x)
120 {
121         // If the gamma hasn't changed, then don't recompute the tables
122         if(x==gamma_r) return;
123
124         gamma_r=x;
125         refresh_gamma_r();
126 }
127
128 void
129 Gamma::set_gamma_g(float x)
130 {
131         // If the gamma hasn't changed, then don't recompute the tables
132         if(x==gamma_g) return;
133
134         gamma_g=x;
135         refresh_gamma_g();
136 }
137
138 void
139 Gamma::set_gamma_b(float x)
140 {
141         // If the gamma hasn't changed, then don't recompute the tables
142         if(x==gamma_b) return;
143
144         gamma_b=x;
145         refresh_gamma_b();
146 }
147
148 void
149 Gamma::set_black_level(float x)
150 {
151         // If the black_level hasn't changed, then don't recompute the tables
152         if(x==black_level) return;
153
154         black_level=x;
155
156         // Rebuild tables
157         refresh_gamma_r();
158         refresh_gamma_g();
159         refresh_gamma_b();
160 }
161
162 void
163 Gamma::set_red_blue_level(float x)
164 {
165         // If the black_level hasn't changed, then don't recompute the tables
166         if(x==red_blue_level) return;
167
168         red_blue_level=x;
169
170         // Rebuild tables
171         refresh_gamma_r();
172         refresh_gamma_g();
173         refresh_gamma_b();
174 }
175
176 void
177 Gamma::set_all(float r, float g, float b, float black, float red_blue)
178 {
179         // If nothing has changed, then don't recompute the tables
180         if(gamma_r==r && gamma_g==g && gamma_b==b && black_level==black && red_blue_level==red_blue)
181                 return;
182
183         gamma_r=r;
184         gamma_g=g;
185         gamma_b=b;
186         black_level=black;
187         red_blue_level=red_blue;
188
189         // Rebuild tables
190         refresh_gamma_r();
191         refresh_gamma_g();
192         refresh_gamma_b();
193 }