LibreOffice Module basegfx (master) 1
bcolormodifier.cxx
Go to the documentation of this file.
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 <sal/config.h>
21#include <algorithm>
22#include <float.h>
24#include <comphelper/random.hxx>
25
26namespace basegfx
27{
29 {
30 }
31
33 {
34 }
35
37 {
38 return dynamic_cast< const BColorModifier_gray* >(&rCompare) != nullptr;
39 }
40
41 ::basegfx::BColor BColorModifier_gray::getModifiedColor(const ::basegfx::BColor& aSourceColor) const
42 {
43 const double fLuminance(aSourceColor.luminance());
44
45 return ::basegfx::BColor(fLuminance, fLuminance, fLuminance);
46 }
47
49 {
50 return "gray";
51 }
52
54 {
55 }
56
58 {
59 return dynamic_cast< const BColorModifier_invert* >(&rCompare) != nullptr;
60 }
61
62 ::basegfx::BColor BColorModifier_invert::getModifiedColor(const ::basegfx::BColor& aSourceColor) const
63 {
64 return ::basegfx::BColor(1.0 - aSourceColor.getRed(), 1.0 - aSourceColor.getGreen(), 1.0 - aSourceColor.getBlue());
65 }
66
68 {
69 return "invert";
70 }
71
73 {
74 }
75
77 {
78 return dynamic_cast< const BColorModifier_luminance_to_alpha* >(&rCompare) != nullptr;
79 }
80
82 {
83 const double fAlpha(1.0 - ((aSourceColor.getRed() * 0.2125) + (aSourceColor.getGreen() * 0.7154) + (aSourceColor.getBlue() * 0.0721)));
84
85 return ::basegfx::BColor(fAlpha, fAlpha, fAlpha);
86 }
87
89 {
90 return "luminance_to_alpha";
91 }
92
94 {
95 }
96
98 {
99 const BColorModifier_replace* pCompare = dynamic_cast< const BColorModifier_replace* >(&rCompare);
100
101 if(!pCompare)
102 {
103 return false;
104 }
105
106 return getBColor() == pCompare->getBColor();
107 }
108
109 ::basegfx::BColor BColorModifier_replace::getModifiedColor(const ::basegfx::BColor& /*aSourceColor*/) const
110 {
111 return maBColor;
112 }
113
115 {
116 return "replace";
117 }
118
120 {
121 }
122
124 {
125 const BColorModifier_interpolate* pCompare = dynamic_cast< const BColorModifier_interpolate* >(&rCompare);
126
127 if(!pCompare)
128 {
129 return false;
130 }
131
132 return maBColor == pCompare->maBColor && mfValue == pCompare->mfValue;
133 }
134
135 ::basegfx::BColor BColorModifier_interpolate::getModifiedColor(const ::basegfx::BColor& aSourceColor) const
136 {
137 return interpolate(maBColor, aSourceColor, mfValue);
138 }
139
141 {
142 return "interpolate";
143 }
144
146 {
147 }
148
150 {
151 const BColorModifier_matrix* pCompare = dynamic_cast< const BColorModifier_matrix* >(&rCompare);
152
153 if(!pCompare)
154 {
155 return false;
156 }
157
158 return maVector == pCompare->maVector;
159 }
160
161 ::basegfx::BColor BColorModifier_matrix::getModifiedColor(const ::basegfx::BColor& aSourceColor) const
162 {
163 if (maVector.size() != 20)
164 return aSourceColor;
165
166 const double aRed = maVector[0] * aSourceColor.getRed()
167 + maVector[1] * aSourceColor.getGreen()
168 + maVector[2] * aSourceColor.getBlue()
169 + maVector[3] * 1.0
170 + maVector[4];
171 const double aGreen = maVector[5] * aSourceColor.getRed()
172 + maVector[6] * aSourceColor.getGreen()
173 + maVector[7] * aSourceColor.getBlue()
174 + maVector[8] * 1.0
175 + maVector[9];
176 const double aBlue = maVector[10] * aSourceColor.getRed()
177 + maVector[11] * aSourceColor.getGreen()
178 + maVector[12] * aSourceColor.getBlue()
179 + maVector[13] * 1.0
180 + maVector[14];
181 /*TODO: add support for alpha
182 const double aAlpha = maVector[15] * aSourceColor.getRed()
183 + maVector[16] * aSourceColor.getGreen()
184 + maVector[17] * aSourceColor.getBlue()
185 + maVector[18] * 1.0
186 + maVector[19]);
187 */
188
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));
193 }
194
196 {
197 return "matrix";
198 }
199
201 {
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);
211 }
212
214 {
215 }
216
218 {
219 const BColorModifier_saturate* pCompare = dynamic_cast< const BColorModifier_saturate* >(&rCompare);
220
221 if(!pCompare)
222 {
223 return false;
224 }
225
226 return maSatMatrix == pCompare->maSatMatrix;
227 }
228
229 ::basegfx::BColor BColorModifier_saturate::getModifiedColor(const ::basegfx::BColor& aSourceColor) const
230 {
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());
235
236 aColorMatrix = maSatMatrix * aColorMatrix;
237 return ::basegfx::BColor(aColorMatrix.get(0, 0), aColorMatrix.get(1, 0), aColorMatrix.get(2, 0));
238 }
239
241 {
242 return "saturate";
243 }
244
246 {
247 const double fCos = cos(fRad);
248 const double fSin = sin(fRad);
249
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);
259 }
260
262 {
263 }
264
266 {
267 const BColorModifier_hueRotate* pCompare = dynamic_cast< const BColorModifier_hueRotate* >(&rCompare);
268
269 if(!pCompare)
270 {
271 return false;
272 }
273
274 return maHueMatrix == pCompare->maHueMatrix;
275 }
276
277 ::basegfx::BColor BColorModifier_hueRotate::getModifiedColor(const ::basegfx::BColor& aSourceColor) const
278 {
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());
283
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));
289 }
290
292 {
293 return "hueRotate";
294 }
295
297 {
298 }
299
301 {
302 const BColorModifier_black_and_white* pCompare = dynamic_cast< const BColorModifier_black_and_white* >(&rCompare);
303
304 if(!pCompare)
305 {
306 return false;
307 }
308
309 return mfValue == pCompare->mfValue;
310 }
311
312 ::basegfx::BColor BColorModifier_black_and_white::getModifiedColor(const ::basegfx::BColor& aSourceColor) const
313 {
314 const double fLuminance(aSourceColor.luminance());
315
316 if(fLuminance < mfValue)
317 {
318 return ::basegfx::BColor::getEmptyBColor();
319 }
320 else
321 {
322 return ::basegfx::BColor(1.0, 1.0, 1.0);
323 }
324 }
325
327 {
328 return "black_and_white";
329 }
330
331 BColorModifier_gamma::BColorModifier_gamma(double fValue)
332 : mfValue(fValue),
333 mfInvValue(fValue),
334 mbUseIt(!basegfx::fTools::equal(fValue, 1.0) && basegfx::fTools::more(fValue, 0.0) && basegfx::fTools::lessOrEqual(fValue, 10.0))
335 {
336 if(mbUseIt)
337 {
338 mfInvValue = 1.0 / mfValue;
339 }
340 }
341
342 BColorModifier_gamma::~BColorModifier_gamma()
343 {
344 }
345
346 bool BColorModifier_gamma::operator==(const BColorModifier& rCompare) const
347 {
348 const BColorModifier_gamma* pCompare = dynamic_cast< const BColorModifier_gamma* >(&rCompare);
349
350 if(!pCompare)
351 {
352 return false;
353 }
354
355 // getValue is sufficient, mfInvValue and mbUseIt are only helper values
356 return mfValue == pCompare->mfValue;
357 }
358
359 ::basegfx::BColor BColorModifier_gamma::getModifiedColor(const ::basegfx::BColor& aSourceColor) const
360 {
361 if(mbUseIt)
362 {
363 ::basegfx::BColor aRetval(
364 pow(aSourceColor.getRed(), mfInvValue),
365 pow(aSourceColor.getGreen(), mfInvValue),
366 pow(aSourceColor.getBlue(), mfInvValue));
367
368 aRetval.clamp();
369 return aRetval;
370 }
371 else
372 {
373 return aSourceColor;
374 }
375 }
376
377 OUString BColorModifier_gamma::getModifierName() const
378 {
379 return "gamma";
380 }
381
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)),
388 mfContrastOff(1.0),
389 mfRedOff(0.0),
390 mfGreenOff(0.0),
391 mfBlueOff(0.0),
392 mbUseIt(false)
393 {
397 && basegfx::fTools::equalZero(mfLuminance)
398 && basegfx::fTools::equalZero(mfContrast))
399 return;
400
401 // calculate slope
402 if(mfContrast >= 0.0)
403 {
404 mfContrastOff = 128.0 / (128.0 - (mfContrast * 127.0));
405 }
406 else
407 {
408 mfContrastOff = ( 128.0 + (mfContrast * 127.0)) / 128.0;
409 }
410
411 // calculate unified contrast offset
412 const double fPreparedContrastOff((128.0 - mfContrastOff * 128.0) / 255.0);
413 const double fCombinedOffset(mfLuminance + fPreparedContrastOff);
414
415 // set full offsets
416 mfRedOff = mfRed + fCombinedOffset;
417 mfGreenOff = mfGreen + fCombinedOffset;
418 mfBlueOff = mfBlue + fCombinedOffset;
419
420 mbUseIt = true;
421 }
422
423 BColorModifier_RGBLuminanceContrast::~BColorModifier_RGBLuminanceContrast()
424 {
425 }
426
427 bool BColorModifier_RGBLuminanceContrast::operator==(const BColorModifier& rCompare) const
428 {
429 const BColorModifier_RGBLuminanceContrast* pCompare = dynamic_cast< const BColorModifier_RGBLuminanceContrast* >(&rCompare);
430
431 if(!pCompare)
432 {
433 return false;
434 }
435
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;
442 }
443
444 ::basegfx::BColor BColorModifier_RGBLuminanceContrast::getModifiedColor(const ::basegfx::BColor& aSourceColor) const
445 {
446 if(mbUseIt)
447 {
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));
452 }
453 else
454 {
455 return aSourceColor;
456 }
457 }
458
459 OUString BColorModifier_RGBLuminanceContrast::getModifierName() const
460 {
461 return "RGBLuminanceContrast";
462 }
463
465 : mfRandomPart(fRandomPart)
466 {
467 }
468
470 {
471 }
472
473 // compare operator
475 {
476 const BColorModifier_randomize* pCompare = dynamic_cast< const BColorModifier_randomize* >(&rCompare);
477
478 if(!pCompare)
479 {
480 return false;
481 }
482
483 return mfRandomPart == pCompare->mfRandomPart;
484 }
485
486 // compute modified color
487 ::basegfx::BColor BColorModifier_randomize::getModifiedColor(const ::basegfx::BColor& aSourceColor) const
488 {
489 if(0.0 >= mfRandomPart)
490 {
491 // no randomizing, use orig color
492 return aSourceColor;
493 }
494
495 if(1.0 <= mfRandomPart)
496 {
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)));
502 }
503
504 // mixed color
505 const double fMulA(1.0 - mfRandomPart);
506 return basegfx::BColor(
507 aSourceColor.getRed() * fMulA +
509 aSourceColor.getGreen() * fMulA +
511 aSourceColor.getBlue() * fMulA +
513 }
514
516 {
517 return "randomize";
518 }
519
520 ::basegfx::BColor BColorModifierStack::getModifiedColor(const ::basegfx::BColor& rSource) const
521 {
522 if(maBColorModifiers.empty())
523 {
524 return rSource;
525 }
526
527 ::basegfx::BColor aRetval(rSource);
528
529 for(sal_uInt32 a(maBColorModifiers.size()); a;)
530 {
531 a--;
532 aRetval = maBColorModifiers[a]->getModifiedColor(aRetval);
533 }
534
535 return aRetval;
536 }
537} // end of namespace basegfx
538
539/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void set(sal_uInt16 nRow, sal_uInt16 nColumn, double fValue)
double get(sal_uInt16 nRow, sal_uInt16 nColumn) const
::std::vector< BColorModifierSharedPtr > maBColorModifiers
::basegfx::BColor getModifiedColor(const ::basegfx::BColor &rSource) const
convert color to black and white
virtual SAL_DLLPRIVATE ::basegfx::BColor getModifiedColor(const ::basegfx::BColor &aSourceColor) const override
virtual SAL_DLLPRIVATE bool operator==(const BColorModifier &rCompare) const override
virtual SAL_DLLPRIVATE OUString getModifierName() const override
convert color to gray
virtual SAL_DLLPRIVATE bool operator==(const BColorModifier &rCompare) const override
virtual SAL_DLLPRIVATE ::basegfx::BColor getModifiedColor(const ::basegfx::BColor &aSourceColor) const override
virtual ~BColorModifier_gray() override
virtual SAL_DLLPRIVATE OUString getModifierName() const override
Apply hueRotate This derivation is used for the svg importer and does exactly what SVG defines for th...
virtual SAL_DLLPRIVATE bool operator==(const BColorModifier &rCompare) const override
virtual SAL_DLLPRIVATE ::basegfx::BColor getModifiedColor(const ::basegfx::BColor &aSourceColor) const override
virtual SAL_DLLPRIVATE OUString getModifierName() const override
virtual ~BColorModifier_hueRotate() override
virtual ~BColorModifier_interpolate() override
virtual SAL_DLLPRIVATE bool operator==(const BColorModifier &rCompare) const override
virtual SAL_DLLPRIVATE ::basegfx::BColor getModifiedColor(const ::basegfx::BColor &aSourceColor) const override
virtual SAL_DLLPRIVATE OUString getModifierName() const override
virtual SAL_DLLPRIVATE bool operator==(const BColorModifier &rCompare) const override
virtual SAL_DLLPRIVATE OUString getModifierName() const override
virtual ~BColorModifier_invert() override
virtual SAL_DLLPRIVATE ::basegfx::BColor getModifiedColor(const ::basegfx::BColor &aSourceColor) const override
convert to alpha based on luminance
virtual SAL_DLLPRIVATE ::basegfx::BColor getModifiedColor(const ::basegfx::BColor &aSourceColor) const override
virtual SAL_DLLPRIVATE bool operator==(const BColorModifier &rCompare) const override
virtual SAL_DLLPRIVATE OUString getModifierName() const override
Apply matrix This derivation is used for the svg importer and does exactly what SVG defines for this ...
virtual SAL_DLLPRIVATE ::basegfx::BColor getModifiedColor(const ::basegfx::BColor &aSourceColor) const override
virtual SAL_DLLPRIVATE bool operator==(const BColorModifier &rCompare) const override
virtual ~BColorModifier_matrix() override
std::vector< double > maVector
virtual SAL_DLLPRIVATE OUString getModifierName() const override
virtual SAL_DLLPRIVATE bool operator==(const BColorModifier &rCompare) const override
virtual SAL_DLLPRIVATE OUString getModifierName() const override
BColorModifier_randomize(double fRandomPart=0.1)
virtual ~BColorModifier_randomize() override
virtual SAL_DLLPRIVATE ::basegfx::BColor getModifiedColor(const ::basegfx::BColor &aSourceColor) const override
const ::basegfx::BColor & getBColor() const
virtual SAL_DLLPRIVATE OUString getModifierName() const override
virtual SAL_DLLPRIVATE ::basegfx::BColor getModifiedColor(const ::basegfx::BColor &aSourceColor) const override
virtual ~BColorModifier_replace() override
virtual SAL_DLLPRIVATE bool operator==(const BColorModifier &rCompare) const override
Apply saturation This derivation is used for the svg importer and does exactly what SVG defines for t...
basegfx::B3DHomMatrix maSatMatrix
virtual SAL_DLLPRIVATE OUString getModifierName() const override
virtual SAL_DLLPRIVATE ::basegfx::BColor getModifiedColor(const ::basegfx::BColor &aSourceColor) const override
virtual SAL_DLLPRIVATE bool operator==(const BColorModifier &rCompare) const override
virtual ~BColorModifier_saturate() override
base class to define color modifications
Base Color class with three double values.
Definition: bcolor.hxx:41
uno_Any a
bool lessOrEqual(const T &rfValA, const T &rfValB)
Definition: ftools.hxx:188
bool more(const T &rfValA, const T &rfValB)
Definition: ftools.hxx:194
bool equalZero(const T &rfVal)
Compare against small value.
Definition: ftools.hxx:156
B2DTuple interpolate(const B2DTuple &rOld1, const B2DTuple &rOld2, double t)
Definition: b2dtuple.hxx:96
double uniform_real_distribution(double a=0.0, double b=1.0)
bool equal(Pair const &p1, Pair const &p2)