karbon

vcolor.cpp
1/* This file is part of the KDE project
2 Copyright (C) 2001, The Karbon Developers
3 Copyright (C) 2002, The Karbon Developers
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to
17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21
22#include <tqdom.h>
23
24#include "vcolor.h"
25#include "vglobal.h"
26
27
29{
30 m_colorSpace = colorSpace;
31 m_opacity = 1.0;
32
33 m_value[0] = 0.0;
34 m_value[1] = 0.0;
35 m_value[2] = 0.0;
36 m_value[3] = 0.0;
37}
38
39VColor::VColor( const VColor& color )
40{
41 m_colorSpace = color.m_colorSpace;
42 m_opacity = color.m_opacity;
43
44 m_value[0] = color.m_value[0];
45 m_value[1] = color.m_value[1];
46 m_value[2] = color.m_value[2];
47 m_value[3] = color.m_value[3];
48}
49
50VColor::VColor( const TQColor& color )
51{
52 m_colorSpace = rgb;
53 m_opacity = 1.0;
54
55 m_value[0] = color.red() / 255.0;
56 m_value[1] = color.green() / 255.0;
57 m_value[2] = color.blue() / 255.0;
58}
59
60VColor::operator TQColor() const
61{
62 VColor copy( *this );
63 copy.convertToColorSpace( rgb );
64
65 TQColor color;
66 color.setRgb( int( 255 * copy[0] ), int( 255 * copy[1] ), int( 255 * copy[2] ) );
67
68 return color;
69}
70
71void
72VColor::setColorSpace( const VColorSpace colorSpace, bool convert )
73{
74 if( convert )
75 convertToColorSpace( colorSpace );
76
77 m_colorSpace = colorSpace;
78}
79
80void
81VColor::convertToColorSpace( const VColorSpace colorSpace )
82{
83 // TODO: numerical stability.
84 // TODO: undercolor removal with cmyk.
85
86 if( colorSpace == rgb )
87 {
88 if( m_colorSpace == rgb )
89 {
90 // Do nothing.
91 }
92 else if( m_colorSpace == cmyk )
93 {
94 m_value[0] = 1.0 - kMin( 1.0f, m_value[0] + m_value[3] );
95 m_value[1] = 1.0 - kMin( 1.0f, m_value[1] + m_value[3] );
96 m_value[2] = 1.0 - kMin( 1.0f, m_value[2] + m_value[3] );
97 }
98 else if( m_colorSpace == hsb )
99 {
100 // Achromatic case (saturation == 0.0).
101 if( m_value[1] == 0.0 )
102 {
103 // Set to brightness:
104 m_value[0] = m_value[2];
105 m_value[1] = m_value[2];
106 m_value[2] = m_value[2]; // For readability.
107 }
108 else
109 {
110 float hue6 = 6.0 * m_value[0];
111 uint i = static_cast<uint>( hue6 );
112 float f = hue6 - i;
113
114 float m = m_value[2] * ( 1.0 - m_value[1] );
115 float n = m_value[2] * ( 1.0 - m_value[1] * f );
116 float k = m_value[2] * ( 1.0 - m_value[1] * ( 1.0 - f ) );
117
118 float r;
119 float g;
120 float b;
121
122 switch( i )
123 {
124 case 1:
125 r = n;
126 g = m_value[2];
127 b = m;
128 break;
129 case 2:
130 r = m;
131 g = m_value[2];
132 b = k;
133 break;
134 case 3:
135 r = m;
136 g = n;
137 b = m_value[2];
138 break;
139 case 4:
140 r = k;
141 g = m;
142 b = m_value[2];
143 break;
144 case 5:
145 r = m_value[2];
146 g = m;
147 b = n;
148 break;
149 default:
150 r = m_value[2];
151 g = k;
152 b = m;
153 }
154
155 m_value[0] = r;
156 m_value[1] = g;
157 m_value[2] = b;
158 }
159 }
160 else if( m_colorSpace == gray )
161 {
162 m_value[0] = m_value[0]; // For readability.
163 m_value[1] = m_value[0];
164 m_value[2] = m_value[0];
165 }
166 }
167 else if( colorSpace == cmyk )
168 {
169 if( m_colorSpace == rgb )
170 {
171 m_value[0] = 1.0 - m_value[0];
172 m_value[1] = 1.0 - m_value[1];
173 m_value[2] = 1.0 - m_value[2];
174 m_value[3] = 0.0;
175 }
176 else if( m_colorSpace == cmyk )
177 {
178 // Do nothing.
179 }
180 else if( m_colorSpace == hsb )
181 {
182// TODO
183 }
184 else if( m_colorSpace == gray )
185 {
186 m_value[1] = 0.0;
187 m_value[2] = 0.0;
188 m_value[3] = 1.0 - m_value[0];
189 m_value[0] = 0.0;
190 }
191 }
192 else if( colorSpace == hsb )
193 {
194 if( m_colorSpace == rgb )
195 {
196 if(
197 m_value[0] == m_value[1] &&
198 m_value[1] == m_value[2] )
199 {
200 // Arbitrary:
201 m_value[3] = m_value[0];
202 m_value[1] = 0.0;
203 m_value[2] = 0.0;
204 }
205 else
206 {
207 float max;
208 float min;
209
210 // Find maximum + minimum rgb component:
211 if( m_value[0] > m_value[1] )
212 {
213 max = m_value[0];
214 min = m_value[1];
215 }
216 else
217 {
218 max = m_value[1];
219 min = m_value[0];
220 }
221
222 if( m_value[2] > max )
223 max = m_value[2];
224
225 if( m_value[2] < min )
226 min = m_value[2];
227
228
229 float hue;
230 const float diff = max - min;
231
232 // Which rgb component is maximum?
233 if( max == m_value[0] )
234 // Red:
235 hue = ( m_value[1] - m_value[2] ) * VGlobal::one_6 / diff;
236 else if( max == m_value[1] )
237 // Green:
238 hue = ( m_value[2] - m_value[0] ) * VGlobal::one_6 / diff + VGlobal::one_3;
239 else
240 // Blue:
241 hue = ( m_value[0] - m_value[1] ) * VGlobal::one_6 / diff + VGlobal::two_3;
242
243 if( hue < 0.0 )
244 hue += 1.0;
245
246
247 m_value[0] = hue;
248 m_value[1] = diff / max;
249 m_value[2] = max;
250 }
251 }
252 else if( m_colorSpace == cmyk )
253 {
254// TODO
255 }
256 else if( m_colorSpace == hsb )
257 {
258 // Do nothing.
259 }
260 else if( m_colorSpace == gray )
261 {
262 m_value[1] = 0.0;
263 m_value[2] = m_value[0];
264 m_value[0] = 0.0;
265 }
266 }
267 else if( colorSpace == gray )
268 {
269 if( m_colorSpace == rgb )
270 {
271 m_value[0] =
272 0.3 * m_value[0] +
273 0.59 * m_value[1] +
274 0.11 * m_value[2];
275 }
276 else if( m_colorSpace == cmyk )
277 {
278 m_value[0] =
279 1.0 - kMin( 1.0,
280 0.3 * m_value[0] +
281 0.59 * m_value[1] +
282 0.11 * m_value[2] +
283 m_value[3] );
284 }
285 else if( m_colorSpace == hsb )
286 {
287 m_value[0] = m_value[2];
288 }
289 else if( m_colorSpace == gray )
290 {
291 // Do nothing.
292 }
293 }
294}
295
296void
297VColor::save( TQDomElement& element ) const
298{
299 TQDomElement me = element.ownerDocument().createElement( "COLOR" );
300 element.appendChild( me );
301
302 if( m_colorSpace != rgb )
303 me.setAttribute( "colorSpace", m_colorSpace );
304 if( m_opacity != 1.0 )
305 me.setAttribute( "opacity", m_opacity );
306
307 if( m_colorSpace == gray )
308 me.setAttribute( "v", m_value[0] );
309 else
310 {
311 me.setAttribute( "v1", m_value[0] );
312 me.setAttribute( "v2", m_value[1] );
313 me.setAttribute( "v3", m_value[2] );
314
315 if( m_colorSpace == cmyk )
316 me.setAttribute( "v4", m_value[3] );
317 }
318}
319
320void
321VColor::load( const TQDomElement& element )
322{
323 switch( element.attribute( "colorSpace" ).toUShort() )
324 {
325 case 1:
326 m_colorSpace = cmyk; break;
327 case 2:
328 m_colorSpace = hsb; break;
329 case 3:
330 m_colorSpace = gray; break;
331 default:
332 m_colorSpace = rgb;
333 }
334
335 m_opacity = element.attribute( "opacity", "1.0" ).toFloat();
336
337 if( m_colorSpace == gray )
338 m_value[0] = element.attribute( "v", "0.0" ).toFloat();
339 else
340 {
341 m_value[0] = element.attribute( "v1", "0.0" ).toFloat();
342 m_value[1] = element.attribute( "v2", "0.0" ).toFloat();
343 m_value[2] = element.attribute( "v3", "0.0" ).toFloat();
344
345 if( m_colorSpace == cmyk )
346 m_value[3] = element.attribute( "v4", "0.0" ).toFloat();
347 }
348
349 if( m_value[0] < 0.0 || m_value[0] > 1.0 )
350 m_value[0] = 0.0;
351 if( m_value[1] < 0.0 || m_value[1] > 1.0 )
352 m_value[1] = 0.0;
353 if( m_value[2] < 0.0 || m_value[2] > 1.0 )
354 m_value[2] = 0.0;
355 if( m_value[3] < 0.0 || m_value[3] > 1.0 )
356 m_value[3] = 0.0;
357}
358
This class keeps track of color properties.
Definition vcolor.h:41
VColor(VColorSpace colorSpace=rgb)
Constructs a new VColor with the specified colorspace.
Definition vcolor.cpp:28
VColorSpace colorSpace() const
Returns the color's colorspace.
Definition vcolor.h:145
void load(const TQDomElement &element)
Load this color's state from xml and initialize it accordingly.
Definition vcolor.cpp:321
void setColorSpace(const VColorSpace colorSpace, bool convert=true)
Sets the color's colorspace.
Definition vcolor.cpp:72
void save(TQDomElement &element) const
Save this color's state to xml.
Definition vcolor.cpp:297
VColorSpace
Definition vcolor.h:44
@ gray
the Gray colorspace (gray from black to white)
Definition vcolor.h:48
@ cmyk
the CMYK colorspace (cyan, magenta, yellow and black components)
Definition vcolor.h:46
@ rgb
the RGB colorspace (red, green and blue components)
Definition vcolor.h:45
@ hsb
the HSB colorspace (hue, saturation and brightnes components)
Definition vcolor.h:47