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 159 : BColor rgb2hsl(const BColor& rRGBColor)
27 : {
28 159 : const double r=rRGBColor.getRed(), g=rRGBColor.getGreen(), b=rRGBColor.getBlue();
29 159 : const double minVal = ::std::min( ::std::min( r, g ), b );
30 159 : const double maxVal = ::std::max( ::std::max( r, g ), b );
31 159 : const double d = maxVal - minVal;
32 :
33 159 : double h=0, s=0, l=0;
34 :
35 159 : l = (maxVal + minVal) / 2.0;
36 :
37 159 : if( ::basegfx::fTools::equalZero(d) )
38 : {
39 15 : s = h = 0; // hue undefined (achromatic case)
40 : }
41 : else
42 : {
43 4 : s = l > 0.5 ? d/(2.0-maxVal-minVal) :
44 148 : d/(maxVal + minVal);
45 :
46 144 : if( r == maxVal )
47 10 : h = (g - b)/d;
48 134 : else if( g == maxVal )
49 9 : h = 2.0 + (b - r)/d;
50 : else
51 125 : h = 4.0 + (r - g)/d;
52 :
53 144 : h *= 60.0;
54 :
55 144 : if( h < 0.0 )
56 3 : h += 360.0;
57 : }
58 :
59 159 : return BColor(h,s,l);
60 : }
61 :
62 390 : static inline double hsl2rgbHelper( double nValue1, double nValue2, double nHue )
63 : {
64 : // clamp hue to [0,360]
65 390 : nHue = fmod( nHue, 360.0 );
66 :
67 : // cope with wrap-arounds
68 390 : if( nHue < 0.0 )
69 5 : nHue += 360.0;
70 :
71 390 : if( nHue < 60.0 )
72 124 : return nValue1 + (nValue2 - nValue1)*nHue/60.0;
73 266 : else if( nHue < 180.0 )
74 130 : return nValue2;
75 136 : else if( nHue < 240.0 )
76 6 : return nValue1 + (nValue2 - nValue1)*(240.0 - nHue)/60.0;
77 : else
78 130 : return nValue1;
79 : }
80 :
81 141 : BColor hsl2rgb(const BColor& rHSLColor)
82 : {
83 141 : const double h=rHSLColor.getRed(), s=rHSLColor.getGreen(), l=rHSLColor.getBlue();
84 :
85 141 : if( fTools::equalZero(s) )
86 11 : return BColor(l, l, l ); // achromatic case
87 :
88 130 : const double nVal1( l <= 0.5 ? l*(1.0 + s) : l + s - l*s );
89 130 : 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 130 : h - 120.0) );
101 : }
102 :
103 31 : BColor rgb2hsv(const BColor& rRGBColor)
104 : {
105 31 : const double r=rRGBColor.getRed(), g=rRGBColor.getGreen(), b=rRGBColor.getBlue();
106 31 : const double maxVal = std::max(std::max(r,g),b);
107 31 : const double minVal = std::min(std::min(r,g),b);
108 31 : const double delta = maxVal-minVal;
109 :
110 31 : double h=0, s=0, v=0;
111 :
112 31 : v = maxVal;
113 31 : if( fTools::equalZero(v) )
114 2 : s = 0;
115 : else
116 29 : s = delta / v;
117 :
118 31 : if( !fTools::equalZero(s) )
119 : {
120 25 : if( maxVal == r )
121 : {
122 16 : h = (g - b) / delta;
123 : }
124 9 : else if( maxVal == g )
125 : {
126 6 : h = 2.0 + (b - r) / delta;
127 : }
128 : else
129 : {
130 3 : h = 4.0 + (r - g) / delta;
131 : }
132 :
133 25 : h *= 60.0;
134 :
135 25 : if( h < 0 )
136 3 : h += 360;
137 : }
138 :
139 31 : return BColor(h,s,v);
140 : }
141 :
142 14 : BColor hsv2rgb(const BColor& rHSVColor)
143 : {
144 14 : double h=rHSVColor.getRed();
145 14 : const double s=rHSVColor.getGreen(), v=rHSVColor.getBlue();
146 :
147 14 : if( fTools::equalZero(s) )
148 : {
149 : // achromatic case: no hue.
150 2 : return BColor(v,v,v);
151 : }
152 : else
153 : {
154 12 : if( fTools::equal(h,360) )
155 0 : h = 0; // 360 degrees is equivalent to 0 degrees
156 :
157 12 : h /= 60.0;
158 12 : const sal_Int32 intval = static_cast< sal_Int32 >( h );
159 12 : const double f = h - intval;
160 12 : const double p = v*(1.0-s);
161 12 : const double q = v*(1.0-(s*f));
162 12 : const double t = v*(1.0-(s*(1.0-f)));
163 :
164 : /* which hue area? */
165 12 : switch( intval )
166 : {
167 : case 0:
168 7 : return BColor(v,t,p);
169 :
170 : case 1:
171 1 : return BColor(q,v,p);
172 :
173 : case 2:
174 1 : return BColor(p,v,t);
175 :
176 : case 3:
177 1 : return BColor(p,q,v);
178 :
179 : case 4:
180 1 : return BColor(t,p,v);
181 :
182 : case 5:
183 1 : return BColor(v,p,q);
184 :
185 : default:
186 : // hue overflow
187 0 : return BColor();
188 : }
189 : }
190 : }
191 :
192 8 : BColor rgb2ciexyz( const BColor& rRGBColor )
193 : {
194 : // from Poynton color faq, and SMPTE RP 177-1993, Derivation
195 : // of Basic Television Color Equations
196 8 : const double r=rRGBColor.getRed(), g=rRGBColor.getGreen(), b=rRGBColor.getBlue();
197 : return BColor(
198 8 : 0.412453*r + 0.35758*g + 0.180423*b,
199 8 : 0.212671*r + 0.71516*g + 0.072169*b,
200 24 : 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: */
|