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>
23 #include <basegfx/color/bcolormodifier.hxx>
24 #include <comphelper/random.hxx>
28 BColorModifier::~BColorModifier()
32 BColorModifier_gray::~BColorModifier_gray()
36 bool BColorModifier_gray::operator==(const BColorModifier
& rCompare
) const
38 return dynamic_cast< const BColorModifier_gray
* >(&rCompare
) != nullptr;
41 ::basegfx::BColor
BColorModifier_gray::getModifiedColor(const ::basegfx::BColor
& aSourceColor
) const
43 const double fLuminance(aSourceColor
.luminance());
45 return ::basegfx::BColor(fLuminance
, fLuminance
, fLuminance
);
48 OUString
BColorModifier_gray::getModifierName() const
53 BColorModifier_invert::~BColorModifier_invert()
57 bool BColorModifier_invert::operator==(const BColorModifier
& rCompare
) const
59 return dynamic_cast< const BColorModifier_invert
* >(&rCompare
) != nullptr;
62 ::basegfx::BColor
BColorModifier_invert::getModifiedColor(const ::basegfx::BColor
& aSourceColor
) const
64 return ::basegfx::BColor(1.0 - aSourceColor
.getRed(), 1.0 - aSourceColor
.getGreen(), 1.0 - aSourceColor
.getBlue());
67 OUString
BColorModifier_invert::getModifierName() const
72 BColorModifier_luminance_to_alpha::~BColorModifier_luminance_to_alpha()
76 bool BColorModifier_luminance_to_alpha::operator==(const BColorModifier
& rCompare
) const
78 return dynamic_cast< const BColorModifier_luminance_to_alpha
* >(&rCompare
) != nullptr;
81 ::basegfx::BColor
BColorModifier_luminance_to_alpha::getModifiedColor(const ::basegfx::BColor
& aSourceColor
) const
83 const double fAlpha(1.0 - ((aSourceColor
.getRed() * 0.2125) + (aSourceColor
.getGreen() * 0.7154) + (aSourceColor
.getBlue() * 0.0721)));
85 return ::basegfx::BColor(fAlpha
, fAlpha
, fAlpha
);
88 OUString
BColorModifier_luminance_to_alpha::getModifierName() const
90 return "luminance_to_alpha";
93 BColorModifier_replace::~BColorModifier_replace()
97 bool BColorModifier_replace::operator==(const BColorModifier
& rCompare
) const
99 const BColorModifier_replace
* pCompare
= dynamic_cast< const BColorModifier_replace
* >(&rCompare
);
106 return getBColor() == pCompare
->getBColor();
109 ::basegfx::BColor
BColorModifier_replace::getModifiedColor(const ::basegfx::BColor
& /*aSourceColor*/) const
114 OUString
BColorModifier_replace::getModifierName() const
119 BColorModifier_interpolate::~BColorModifier_interpolate()
123 bool BColorModifier_interpolate::operator==(const BColorModifier
& rCompare
) const
125 const BColorModifier_interpolate
* pCompare
= dynamic_cast< const BColorModifier_interpolate
* >(&rCompare
);
132 return maBColor
== pCompare
->maBColor
&& mfValue
== pCompare
->mfValue
;
135 ::basegfx::BColor
BColorModifier_interpolate::getModifiedColor(const ::basegfx::BColor
& aSourceColor
) const
137 return interpolate(maBColor
, aSourceColor
, mfValue
);
140 OUString
BColorModifier_interpolate::getModifierName() const
142 return "interpolate";
145 BColorModifier_matrix::~BColorModifier_matrix()
149 bool BColorModifier_matrix::operator==(const BColorModifier
& rCompare
) const
151 const BColorModifier_matrix
* pCompare
= dynamic_cast< const BColorModifier_matrix
* >(&rCompare
);
158 return maVector
== pCompare
->maVector
;
161 ::basegfx::BColor
BColorModifier_matrix::getModifiedColor(const ::basegfx::BColor
& aSourceColor
) const
163 if (maVector
.size() != 20)
166 const double aRed
= maVector
[0] * aSourceColor
.getRed()
167 + maVector
[1] * aSourceColor
.getGreen()
168 + maVector
[2] * aSourceColor
.getBlue()
171 const double aGreen
= maVector
[5] * aSourceColor
.getRed()
172 + maVector
[6] * aSourceColor
.getGreen()
173 + maVector
[7] * aSourceColor
.getBlue()
176 const double aBlue
= maVector
[10] * aSourceColor
.getRed()
177 + maVector
[11] * aSourceColor
.getGreen()
178 + maVector
[12] * aSourceColor
.getBlue()
181 /*TODO: add support for alpha
182 const double aAlpha = maVector[15] * aSourceColor.getRed()
183 + maVector[16] * aSourceColor.getGreen()
184 + maVector[17] * aSourceColor.getBlue()
189 return ::basegfx::BColor(
190 std::clamp(aRed
, 0.0, 1.0),
191 std::clamp(aGreen
, 0.0, 1.0),
192 std::clamp(aBlue
, 0.0, 1.0));
195 OUString
BColorModifier_matrix::getModifierName() const
200 BColorModifier_saturate::BColorModifier_saturate(double fValue
)
202 maSatMatrix
.set(0, 0, 0.213 + 0.787 * fValue
);
203 maSatMatrix
.set(0, 1, 0.715 - 0.715 * fValue
);
204 maSatMatrix
.set(0, 2, 0.072 - 0.072 * fValue
);
205 maSatMatrix
.set(1, 0, 0.213 - 0.213 * fValue
);
206 maSatMatrix
.set(1, 1, 0.715 + 0.285 * fValue
);
207 maSatMatrix
.set(1, 2, 0.072 - 0.072 * fValue
);
208 maSatMatrix
.set(2, 0, 0.213 - 0.213 * fValue
);
209 maSatMatrix
.set(2, 1, 0.715 - 0.715 * fValue
);
210 maSatMatrix
.set(2, 2, 0.072 + 0.928 * fValue
);
213 BColorModifier_saturate::~BColorModifier_saturate()
217 bool BColorModifier_saturate::operator==(const BColorModifier
& rCompare
) const
219 const BColorModifier_saturate
* pCompare
= dynamic_cast< const BColorModifier_saturate
* >(&rCompare
);
226 return maSatMatrix
== pCompare
->maSatMatrix
;
229 ::basegfx::BColor
BColorModifier_saturate::getModifiedColor(const ::basegfx::BColor
& aSourceColor
) const
231 basegfx::B3DHomMatrix aColorMatrix
;
232 aColorMatrix
.set(0, 0, aSourceColor
.getRed());
233 aColorMatrix
.set(1, 0, aSourceColor
.getGreen());
234 aColorMatrix
.set(2, 0, aSourceColor
.getBlue());
236 aColorMatrix
= maSatMatrix
* aColorMatrix
;
237 return ::basegfx::BColor(aColorMatrix
.get(0, 0), aColorMatrix
.get(1, 0), aColorMatrix
.get(2, 0));
240 OUString
BColorModifier_saturate::getModifierName() const
245 BColorModifier_hueRotate::BColorModifier_hueRotate(double fRad
)
247 const double fCos
= cos(fRad
);
248 const double fSin
= sin(fRad
);
250 maHueMatrix
.set(0, 0, 0.213 + fCos
* 0.787 - fSin
* 0.213);
251 maHueMatrix
.set(0, 1, 0.715 - fCos
* 0.715 - fSin
* 0.715);
252 maHueMatrix
.set(0, 2, 0.072 - fCos
* 0.072 + fSin
* 0.928);
253 maHueMatrix
.set(1, 0, 0.213 - fCos
* 0.213 + fSin
* 0.143);
254 maHueMatrix
.set(1, 1, 0.715 + fCos
* 0.285 + fSin
* 0.140);
255 maHueMatrix
.set(1, 2, 0.072 - fCos
* 0.072 - fSin
* 0.283);
256 maHueMatrix
.set(2, 0, 0.213 - fCos
* 0.213 - fSin
* 0.787);
257 maHueMatrix
.set(2, 1, 0.715 - fCos
* 0.715 + fSin
* 0.715);
258 maHueMatrix
.set(2, 2, 0.072 + fCos
* 0.928 + fSin
* 0.072);
261 BColorModifier_hueRotate::~BColorModifier_hueRotate()
265 bool BColorModifier_hueRotate::operator==(const BColorModifier
& rCompare
) const
267 const BColorModifier_hueRotate
* pCompare
= dynamic_cast< const BColorModifier_hueRotate
* >(&rCompare
);
274 return maHueMatrix
== pCompare
->maHueMatrix
;
277 ::basegfx::BColor
BColorModifier_hueRotate::getModifiedColor(const ::basegfx::BColor
& aSourceColor
) const
279 basegfx::B3DHomMatrix aColorMatrix
;
280 aColorMatrix
.set(0, 0, aSourceColor
.getRed());
281 aColorMatrix
.set(1, 0, aSourceColor
.getGreen());
282 aColorMatrix
.set(2, 0, aSourceColor
.getBlue());
284 aColorMatrix
= maHueMatrix
* aColorMatrix
;
285 return ::basegfx::BColor(
286 std::clamp(aColorMatrix
.get(0, 0), 0.0, 1.0),
287 std::clamp(aColorMatrix
.get(1, 0), 0.0, 1.0),
288 std::clamp(aColorMatrix
.get(2, 0), 0.0, 1.0));
291 OUString
BColorModifier_hueRotate::getModifierName() const
296 BColorModifier_black_and_white::~BColorModifier_black_and_white()
300 bool BColorModifier_black_and_white::operator==(const BColorModifier
& rCompare
) const
302 const BColorModifier_black_and_white
* pCompare
= dynamic_cast< const BColorModifier_black_and_white
* >(&rCompare
);
309 return mfValue
== pCompare
->mfValue
;
312 ::basegfx::BColor
BColorModifier_black_and_white::getModifiedColor(const ::basegfx::BColor
& aSourceColor
) const
314 const double fLuminance(aSourceColor
.luminance());
316 if(fLuminance
< mfValue
)
318 return ::basegfx::BColor::getEmptyBColor();
322 return ::basegfx::BColor(1.0, 1.0, 1.0);
326 OUString
BColorModifier_black_and_white::getModifierName() const
328 return "black_and_white";
331 BColorModifier_gamma::BColorModifier_gamma(double fValue
)
334 mbUseIt(!basegfx::fTools::equal(fValue
, 1.0) && basegfx::fTools::more(fValue
, 0.0) && basegfx::fTools::lessOrEqual(fValue
, 10.0))
338 mfInvValue
= 1.0 / mfValue
;
342 BColorModifier_gamma::~BColorModifier_gamma()
346 bool BColorModifier_gamma::operator==(const BColorModifier
& rCompare
) const
348 const BColorModifier_gamma
* pCompare
= dynamic_cast< const BColorModifier_gamma
* >(&rCompare
);
355 // getValue is sufficient, mfInvValue and mbUseIt are only helper values
356 return mfValue
== pCompare
->mfValue
;
359 ::basegfx::BColor
BColorModifier_gamma::getModifiedColor(const ::basegfx::BColor
& aSourceColor
) const
363 ::basegfx::BColor
aRetval(
364 pow(aSourceColor
.getRed(), mfInvValue
),
365 pow(aSourceColor
.getGreen(), mfInvValue
),
366 pow(aSourceColor
.getBlue(), mfInvValue
));
377 OUString
BColorModifier_gamma::getModifierName() const
382 BColorModifier_RGBLuminanceContrast::BColorModifier_RGBLuminanceContrast(double fRed
, double fGreen
, double fBlue
, double fLuminance
, double fContrast
)
383 : mfRed(std::clamp(fRed
, -1.0, 1.0)),
384 mfGreen(std::clamp(fGreen
, -1.0, 1.0)),
385 mfBlue(std::clamp(fBlue
, -1.0, 1.0)),
386 mfLuminance(std::clamp(fLuminance
, -1.0, 1.0)),
387 mfContrast(std::clamp(fContrast
, -1.0, 1.0)),
394 if(basegfx::fTools::equalZero(mfRed
)
395 && basegfx::fTools::equalZero(mfGreen
)
396 && basegfx::fTools::equalZero(mfBlue
)
397 && basegfx::fTools::equalZero(mfLuminance
)
398 && basegfx::fTools::equalZero(mfContrast
))
402 if(mfContrast
>= 0.0)
404 mfContrastOff
= 128.0 / (128.0 - (mfContrast
* 127.0));
408 mfContrastOff
= ( 128.0 + (mfContrast
* 127.0)) / 128.0;
411 // calculate unified contrast offset
412 const double fPreparedContrastOff((128.0 - mfContrastOff
* 128.0) / 255.0);
413 const double fCombinedOffset(mfLuminance
+ fPreparedContrastOff
);
416 mfRedOff
= mfRed
+ fCombinedOffset
;
417 mfGreenOff
= mfGreen
+ fCombinedOffset
;
418 mfBlueOff
= mfBlue
+ fCombinedOffset
;
423 BColorModifier_RGBLuminanceContrast::~BColorModifier_RGBLuminanceContrast()
427 bool BColorModifier_RGBLuminanceContrast::operator==(const BColorModifier
& rCompare
) const
429 const BColorModifier_RGBLuminanceContrast
* pCompare
= dynamic_cast< const BColorModifier_RGBLuminanceContrast
* >(&rCompare
);
436 // no need to compare other values, these are just helpers
437 return mfRed
== pCompare
->mfRed
438 && mfGreen
== pCompare
->mfGreen
439 && mfBlue
== pCompare
->mfBlue
440 && mfLuminance
== pCompare
->mfLuminance
441 && mfContrast
== pCompare
->mfContrast
;
444 ::basegfx::BColor
BColorModifier_RGBLuminanceContrast::getModifiedColor(const ::basegfx::BColor
& aSourceColor
) const
448 return basegfx::BColor(
449 std::clamp(aSourceColor
.getRed() * mfContrastOff
+ mfRedOff
, 0.0, 1.0),
450 std::clamp(aSourceColor
.getGreen() * mfContrastOff
+ mfGreenOff
, 0.0, 1.0),
451 std::clamp(aSourceColor
.getBlue() * mfContrastOff
+ mfBlueOff
, 0.0, 1.0));
459 OUString
BColorModifier_RGBLuminanceContrast::getModifierName() const
461 return "RGBLuminanceContrast";
464 BColorModifier_randomize::BColorModifier_randomize(double fRandomPart
)
465 : mfRandomPart(fRandomPart
)
469 BColorModifier_randomize::~BColorModifier_randomize()
474 bool BColorModifier_randomize::operator==(const BColorModifier
& rCompare
) const
476 const BColorModifier_randomize
* pCompare
= dynamic_cast< const BColorModifier_randomize
* >(&rCompare
);
483 return mfRandomPart
== pCompare
->mfRandomPart
;
486 // compute modified color
487 ::basegfx::BColor
BColorModifier_randomize::getModifiedColor(const ::basegfx::BColor
& aSourceColor
) const
489 if(0.0 >= mfRandomPart
)
491 // no randomizing, use orig color
495 if(1.0 <= mfRandomPart
)
497 // full randomized color
498 return basegfx::BColor(
499 comphelper::rng::uniform_real_distribution(0.0, nextafter(1.0, DBL_MAX
)),
500 comphelper::rng::uniform_real_distribution(0.0, nextafter(1.0, DBL_MAX
)),
501 comphelper::rng::uniform_real_distribution(0.0, nextafter(1.0, DBL_MAX
)));
505 const double fMulA(1.0 - mfRandomPart
);
506 return basegfx::BColor(
507 aSourceColor
.getRed() * fMulA
+
508 comphelper::rng::uniform_real_distribution(0.0, nextafter(mfRandomPart
, DBL_MAX
)),
509 aSourceColor
.getGreen() * fMulA
+
510 comphelper::rng::uniform_real_distribution(0.0, nextafter(mfRandomPart
, DBL_MAX
)),
511 aSourceColor
.getBlue() * fMulA
+
512 comphelper::rng::uniform_real_distribution(0.0, nextafter(mfRandomPart
, DBL_MAX
)));
515 OUString
BColorModifier_randomize::getModifierName() const
520 ::basegfx::BColor
BColorModifierStack::getModifiedColor(const ::basegfx::BColor
& rSource
) const
522 if(maBColorModifiers
.empty())
527 ::basegfx::BColor
aRetval(rSource
);
529 for(sal_uInt32
a(maBColorModifiers
.size()); a
;)
532 aRetval
= maBColorModifiers
[a
]->getModifiedColor(aRetval
);
537 } // end of namespace basegfx
539 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */