Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <basegfx/numeric/ftools.hxx>
21 : #include <basegfx/color/bcolor.hxx>
22 : #include <basegfx/color/bcolortools.hxx>
23 :
24 : namespace basegfx { namespace tools
25 : {
26 246 : BColor rgb2hsl(const BColor& rRGBColor)
27 : {
28 246 : const double r=rRGBColor.getRed(), g=rRGBColor.getGreen(), b=rRGBColor.getBlue();
29 246 : const double minVal = ::std::min( ::std::min( r, g ), b );
30 246 : const double maxVal = ::std::max( ::std::max( r, g ), b );
31 246 : const double d = maxVal - minVal;
32 :
33 246 : double h=0, s=0, l=0;
34 :
35 246 : l = (maxVal + minVal) / 2.0;
36 :
37 246 : if( ::basegfx::fTools::equalZero(d) )
38 : {
39 30 : s = h = 0; // hue undefined (achromatic case)
40 : }
41 : else
42 : {
43 8 : s = l > 0.5 ? d/(2.0-maxVal-minVal) :
44 224 : d/(maxVal + minVal);
45 :
46 216 : if( r == maxVal )
47 20 : h = (g - b)/d;
48 196 : else if( g == maxVal )
49 18 : h = 2.0 + (b - r)/d;
50 : else
51 178 : h = 4.0 + (r - g)/d;
52 :
53 216 : h *= 60.0;
54 :
55 216 : if( h < 0.0 )
56 6 : h += 360.0;
57 : }
58 :
59 246 : return BColor(h,s,l);
60 : }
61 :
62 564 : static inline double hsl2rgbHelper( double nValue1, double nValue2, double nHue )
63 : {
64 : // clamp hue to [0,360]
65 564 : nHue = fmod( nHue, 360.0 );
66 :
67 : // cope with wrap-arounds
68 564 : if( nHue < 0.0 )
69 10 : nHue += 360.0;
70 :
71 564 : if( nHue < 60.0 )
72 176 : return nValue1 + (nValue2 - nValue1)*nHue/60.0;
73 388 : else if( nHue < 180.0 )
74 188 : return nValue2;
75 200 : else if( nHue < 240.0 )
76 12 : return nValue1 + (nValue2 - nValue1)*(240.0 - nHue)/60.0;
77 : else
78 188 : return nValue1;
79 : }
80 :
81 210 : BColor hsl2rgb(const BColor& rHSLColor)
82 : {
83 210 : const double h=rHSLColor.getRed(), s=rHSLColor.getGreen(), l=rHSLColor.getBlue();
84 :
85 210 : if( fTools::equalZero(s) )
86 22 : return BColor(l, l, l ); // achromatic case
87 :
88 188 : const double nVal1( l <= 0.5 ? l*(1.0 + s) : l + s - l*s );
89 188 : const double nVal2( 2.0*l - nVal1 );
90 :
91 : return BColor(
92 : hsl2rgbHelper(nVal2,
93 : nVal1,
94 : h + 120.0),
95 : hsl2rgbHelper(nVal2,
96 : nVal1,
97 : h),
98 : hsl2rgbHelper(nVal2,
99 : nVal1,
100 188 : h - 120.0) );
101 : }
102 :
103 62 : BColor rgb2hsv(const BColor& rRGBColor)
104 : {
105 62 : const double r=rRGBColor.getRed(), g=rRGBColor.getGreen(), b=rRGBColor.getBlue();
106 62 : const double maxVal = std::max(std::max(r,g),b);
107 62 : const double minVal = std::min(std::min(r,g),b);
108 62 : const double delta = maxVal-minVal;
109 :
110 62 : double h=0, s=0, v=0;
111 :
112 62 : v = maxVal;
113 62 : if( fTools::equalZero(v) )
114 4 : s = 0;
115 : else
116 58 : s = delta / v;
117 :
118 62 : if( !fTools::equalZero(s) )
119 : {
120 50 : if( maxVal == r )
121 : {
122 32 : h = (g - b) / delta;
123 : }
124 18 : else if( maxVal == g )
125 : {
126 12 : h = 2.0 + (b - r) / delta;
127 : }
128 : else
129 : {
130 6 : h = 4.0 + (r - g) / delta;
131 : }
132 :
133 50 : h *= 60.0;
134 :
135 50 : if( h < 0 )
136 6 : h += 360;
137 : }
138 :
139 62 : return BColor(h,s,v);
140 : }
141 :
142 28 : BColor hsv2rgb(const BColor& rHSVColor)
143 : {
144 28 : double h=rHSVColor.getRed();
145 28 : const double s=rHSVColor.getGreen(), v=rHSVColor.getBlue();
146 :
147 28 : if( fTools::equalZero(s) )
148 : {
149 : // achromatic case: no hue.
150 4 : return BColor(v,v,v);
151 : }
152 : else
153 : {
154 24 : if( fTools::equal(h,360) )
155 0 : h = 0; // 360 degrees is equivalent to 0 degrees
156 :
157 24 : h /= 60.0;
158 24 : const sal_Int32 intval = static_cast< sal_Int32 >( h );
159 24 : const double f = h - intval;
160 24 : const double p = v*(1.0-s);
161 24 : const double q = v*(1.0-(s*f));
162 24 : const double t = v*(1.0-(s*(1.0-f)));
163 :
164 : /* which hue area? */
165 24 : switch( intval )
166 : {
167 : case 0:
168 14 : return BColor(v,t,p);
169 :
170 : case 1:
171 2 : return BColor(q,v,p);
172 :
173 : case 2:
174 2 : return BColor(p,v,t);
175 :
176 : case 3:
177 2 : return BColor(p,q,v);
178 :
179 : case 4:
180 2 : return BColor(t,p,v);
181 :
182 : case 5:
183 2 : return BColor(v,p,q);
184 :
185 : default:
186 : // hue overflow
187 0 : return BColor();
188 : }
189 : }
190 : }
191 :
192 16 : BColor rgb2ciexyz( const BColor& rRGBColor )
193 : {
194 : // from Poynton color faq, and SMPTE RP 177-1993, Derivation
195 : // of Basic Television Color Equations
196 16 : const double r=rRGBColor.getRed(), g=rRGBColor.getGreen(), b=rRGBColor.getBlue();
197 : return BColor(
198 16 : 0.412453*r + 0.35758*g + 0.180423*b,
199 16 : 0.212671*r + 0.71516*g + 0.072169*b,
200 48 : 0.019334*r + 0.119193*g + 0.950227*b);
201 : }
202 :
203 : } } // end of namespace basegfx
204 :
205 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|