1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <basegfx/numeric/ftools.hxx>
21 #include <basegfx/color/bcolor.hxx>
22 #include <basegfx/color/bcolortools.hxx>
23 #include <rtl/math.hxx>
25 namespace basegfx::utils
27 BColor
rgb2hsl(const BColor
& rRGBColor
)
29 const double r
=rRGBColor
.getRed(), g
=rRGBColor
.getGreen(), b
=rRGBColor
.getBlue();
30 const double minVal
= std::min( std::min( r
, g
), b
);
31 const double maxVal
= std::max( std::max( r
, g
), b
);
32 const double d
= maxVal
- minVal
;
36 l
= (maxVal
+ minVal
) / 2.0;
38 if( ::basegfx::fTools::equalZero(d
) )
40 s
= h
= 0; // hue undefined (achromatic case)
44 s
= l
> 0.5 ? d
/(2.0-maxVal
-minVal
) :
47 if( rtl::math::approxEqual(r
, maxVal
) )
49 else if( rtl::math::approxEqual(g
, maxVal
) )
63 static double hsl2rgbHelper( double nValue1
, double nValue2
, double nHue
)
65 // clamp hue to [0,360]
66 nHue
= fmod( nHue
, 360.0 );
68 // cope with wrap-arounds
73 return nValue1
+ (nValue2
- nValue1
)*nHue
/60.0;
74 else if( nHue
< 180.0 )
76 else if( nHue
< 240.0 )
77 return nValue1
+ (nValue2
- nValue1
)*(240.0 - nHue
)/60.0;
82 BColor
hsl2rgb(const BColor
& rHSLColor
)
84 const double h
=rHSLColor
.getRed(), s
=rHSLColor
.getGreen(), l
=rHSLColor
.getBlue();
86 if( fTools::equalZero(s
) )
87 return BColor(l
, l
, l
); // achromatic case
89 const double nVal1( l
<= 0.5 ? l
*(1.0 + s
) : l
+ s
- l
*s
);
90 const double nVal2( 2.0*l
- nVal1
);
104 BColor
rgb2hsv(const BColor
& rRGBColor
)
106 const double r
=rRGBColor
.getRed(), g
=rRGBColor
.getGreen(), b
=rRGBColor
.getBlue();
107 const double maxVal
= std::max(std::max(r
,g
),b
);
108 const double minVal
= std::min(std::min(r
,g
),b
);
109 const double delta
= maxVal
-minVal
;
111 double h
=0, s
=0, v
=0;
114 if( fTools::equalZero(v
) )
119 if( !fTools::equalZero(s
) )
121 if( rtl::math::approxEqual(maxVal
, r
) )
125 else if( rtl::math::approxEqual(maxVal
, g
) )
127 h
= 2.0 + (b
- r
) / delta
;
131 h
= 4.0 + (r
- g
) / delta
;
140 return BColor(h
,s
,v
);
143 BColor
hsv2rgb(const BColor
& rHSVColor
)
145 double h
=rHSVColor
.getRed();
146 const double s
=rHSVColor
.getGreen(), v
=rHSVColor
.getBlue();
148 if( fTools::equalZero(s
) )
150 // achromatic case: no hue.
151 return BColor(v
,v
,v
);
155 if( fTools::equal(h
, 360.0) )
156 h
= 0; // 360 degrees is equivalent to 0 degrees
159 const sal_Int32 intval
= static_cast< sal_Int32
>( h
);
160 const double f
= h
- intval
;
161 const double p
= v
*(1.0-s
);
162 const double q
= v
*(1.0-(s
*f
));
163 const double t
= v
*(1.0-(s
*(1.0-f
)));
165 /* which hue area? */
169 return BColor(v
,t
,p
);
172 return BColor(q
,v
,p
);
175 return BColor(p
,v
,t
);
178 return BColor(p
,q
,v
);
181 return BColor(t
,p
,v
);
184 return BColor(v
,p
,q
);
193 } // end of namespace
195 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */