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 <sal/config.h>
27 #include <tools/color.hxx>
28 #include <tools/helpers.hxx>
29 #include <tools/long.hxx>
30 #include <o3tl/string_view.hxx>
31 #include <basegfx/color/bcolortools.hxx>
33 void Color::IncreaseLuminance(sal_uInt8 cLumInc
)
35 R
= sal_uInt8(std::clamp(R
+ cLumInc
, 0, 255));
36 G
= sal_uInt8(std::clamp(G
+ cLumInc
, 0, 255));
37 B
= sal_uInt8(std::clamp(B
+ cLumInc
, 0, 255));
40 void Color::DecreaseLuminance(sal_uInt8 cLumDec
)
42 R
= sal_uInt8(std::clamp(R
- cLumDec
, 0, 255));
43 G
= sal_uInt8(std::clamp(G
- cLumDec
, 0, 255));
44 B
= sal_uInt8(std::clamp(B
- cLumDec
, 0, 255));
47 void Color::DecreaseContrast(sal_uInt8 nContDec
)
51 const double fM
= (128.0 - 0.4985 * nContDec
) / 128.0;
52 const double fOff
= 128.0 - fM
* 128.0;
54 R
= sal_uInt8(std::clamp(FRound(R
* fM
+ fOff
), tools::Long(0), tools::Long(255)));
55 G
= sal_uInt8(std::clamp(FRound(G
* fM
+ fOff
), tools::Long(0), tools::Long(255)));
56 B
= sal_uInt8(std::clamp(FRound(B
* fM
+ fOff
), tools::Long(0), tools::Long(255)));
60 // color space conversion
62 void Color::RGBtoHSB( sal_uInt16
& nHue
, sal_uInt16
& nSat
, sal_uInt16
& nBri
) const
77 // Brightness = max(R, G, B);
78 nBri
= cMax
* 100 / 255;
86 sal_uInt8 cDelta
= cMax
- cMin
;
88 // Saturation = max - min / max
90 nSat
= cDelta
* 100 / cMax
;
95 nHue
= 0; // Default = undefined
102 dHue
= static_cast<double>( c
[1] - c
[2] ) / static_cast<double>(cDelta
);
104 else if( c
[1] == cMax
)
106 dHue
= 2.0 + static_cast<double>( c
[2] - c
[0] ) / static_cast<double>(cDelta
);
108 else if ( c
[2] == cMax
)
110 dHue
= 4.0 + static_cast<double>( c
[0] - c
[1] ) / static_cast<double>(cDelta
);
117 nHue
= static_cast<sal_uInt16
>(dHue
);
121 Color
Color::HSBtoRGB( sal_uInt16 nHue
, sal_uInt16 nSat
, sal_uInt16 nBri
)
123 sal_uInt8 cR
=0,cG
=0,cB
=0;
124 sal_uInt8 nB
= static_cast<sal_uInt8
>( nBri
* 255 / 100 );
141 n
= static_cast<sal_uInt16
>(dH
);
144 sal_uInt8 a
= static_cast<sal_uInt8
>( nB
* ( 100 - nSat
) / 100 );
145 sal_uInt8 b
= static_cast<sal_uInt8
>( nB
* ( 100 - ( static_cast<double>(nSat
) * f
) ) / 100 );
146 sal_uInt8 c
= static_cast<sal_uInt8
>( nB
* ( 100 - ( static_cast<double>(nSat
) * ( 1.0 - f
) ) ) / 100 );
150 case 0: cR
= nB
; cG
= c
; cB
= a
; break;
151 case 1: cR
= b
; cG
= nB
; cB
= a
; break;
152 case 2: cR
= a
; cG
= nB
; cB
= c
; break;
153 case 3: cR
= a
; cG
= b
; cB
= nB
; break;
154 case 4: cR
= c
; cG
= a
; cB
= nB
; break;
155 case 5: cR
= nB
; cG
= a
; cB
= b
; break;
159 return Color( cR
, cG
, cB
);
162 Color
Color::STRtoRGB(std::u16string_view colorname
)
165 if(colorname
.empty()) return col
;
167 switch(colorname
.size()){
169 col
.mValue
= o3tl::toUInt32(colorname
.substr(1,6), 16);
172 col
.mValue
= o3tl::toUInt32(colorname
, 16);
176 sal_Unicode data
[6] = { colorname
[1], colorname
[1], colorname
[2],
177 colorname
[2], colorname
[3], colorname
[3] };
178 col
.mValue
= o3tl::toUInt32(std::u16string_view(data
,6), 16);
183 sal_Unicode data
[6] = { colorname
[0], colorname
[0], colorname
[1],
184 colorname
[1], colorname
[2], colorname
[2] };
185 col
.mValue
= o3tl::toUInt32(std::u16string_view(data
,6), 16);
194 OUString
Color::AsRGBHexString() const
196 std::stringstream ss
;
197 ss
<< std::hex
<< std::setfill ('0') << std::setw(6) << sal_uInt32(GetRGBColor());
198 return OUString::createFromAscii(ss
.str());
201 OUString
Color::AsRGBHEXString() const
203 std::stringstream ss
;
204 ss
<< std::hex
<< std::uppercase
<< std::setfill ('0') << std::setw(6) << sal_uInt32(GetRGBColor());
205 return OUString::createFromAscii(ss
.str());
208 void Color::ApplyTintOrShade(sal_Int16 n100thPercent
)
210 if (n100thPercent
== 0)
213 basegfx::BColor aBColor
= basegfx::utils::rgb2hsl(getBColor());
214 double fFactor
= 1.0 - (std::abs(double(n100thPercent
)) / 10000.0);
217 if (n100thPercent
> 0) // tint
219 fResult
= aBColor
.getBlue() * fFactor
+ (1.0 - fFactor
);
223 fResult
= aBColor
.getBlue() * fFactor
;
226 aBColor
.setBlue(fResult
);
227 aBColor
= basegfx::utils::hsl2rgb(aBColor
);
229 R
= sal_uInt8(std::lround(aBColor
.getRed() * 255.0));
230 G
= sal_uInt8(std::lround(aBColor
.getGreen() * 255.0));
231 B
= sal_uInt8(std::lround(aBColor
.getBlue() * 255.0));
234 void Color::ApplyLumModOff(sal_Int16 nMod
, sal_Int16 nOff
)
236 if (nMod
== 10000 && nOff
== 0)
240 // Switch to HSL, where applying these transforms is easier.
241 basegfx::BColor aBColor
= basegfx::utils::rgb2hsl(getBColor());
243 // 50% is half luminance, 200% is double luminance. Unit is 100th percent.
244 aBColor
.setBlue(std::clamp(aBColor
.getBlue() * nMod
/ 10000, 0.0, 1.0));
245 // If color changes to black or white, it will stay gray if luminance changes again.
246 if ((aBColor
.getBlue() == 0.0) || (aBColor
.getBlue() == 1.0))
248 aBColor
.setGreen(0.0);
251 // Luminance offset means hue and saturation is left unchanged. Unit is 100th percent.
252 aBColor
.setBlue(std::clamp(aBColor
.getBlue() + static_cast<double>(nOff
) / 10000, 0.0, 1.0));
253 // If color changes to black or white, it will stay gray if luminance changes again.
254 if ((aBColor
.getBlue() == 0.0) || (aBColor
.getBlue() == 1.0))
256 aBColor
.setGreen(0.0);
259 // Switch back to RGB.
260 aBColor
= basegfx::utils::hsl2rgb(aBColor
);
261 R
= sal_uInt8(std::lround(aBColor
.getRed() * 255.0));
262 G
= sal_uInt8(std::lround(aBColor
.getGreen() * 255.0));
263 B
= sal_uInt8(std::lround(aBColor
.getBlue() * 255.0));
266 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */