Krita Source Code Documentation
Loading...
Searching...
No Matches
KoCompositeOpGreater.h
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2014 Nicholas Guttenberg <ngutten@gmail.com>
3 *
4 * Based on KoCompositeOpBehind.h,
5 * SPDX-FileCopyrightText: 2012 José Luis Vergara <pentalis@gmail.com>
6 *
7 * SPDX-License-Identifier: LGPL-2.0-or-later
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with this library; see the file COPYING.LIB. If not, write to
16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18*/
19
20#ifndef _KOCOMPOSITEOPGREATER_H_
21#define _KOCOMPOSITEOPGREATER_H_
22
23#include "KoCompositeOpBase.h"
24
28template<class CS_Traits, typename BlendingPolicy>
29class KoCompositeOpGreater : public KoCompositeOpBase<CS_Traits, KoCompositeOpGreater<CS_Traits, BlendingPolicy>>
30{
32 typedef typename CS_Traits::channels_type channels_type;
34
35 static const qint8 channels_nb = CS_Traits::channels_nb;
36 static const qint8 alpha_pos = CS_Traits::alpha_pos;
37
38public:
41
42public:
43 template<bool alphaLocked, bool allChannelFlags>
45 channels_type* dst, channels_type dstAlpha,
46 channels_type maskAlpha, channels_type opacity,
47 const QBitArray& channelFlags ) {
48 using namespace Arithmetic;
49
50 if (isUnitValueFuzzy(dstAlpha)) return dstAlpha;
51 channels_type appliedAlpha = mul(maskAlpha, srcAlpha, opacity);
52
53 if (isZeroValueFuzzy(appliedAlpha)) return dstAlpha;
54 channels_type newDstAlpha;
55
56 float dA = scale<float>(dstAlpha);
57
58 float w = 1.0/(1.0+exp(-40.0*(dA - scale<float>(appliedAlpha))));
59 float a = dA*w + scale<float>(appliedAlpha)*(1.0-w);
60 if (a < 0.0f) {
61 a = 0.0f;
62 }
63 if (a > 1.0f) {
64 a = 1.0f;
65 }
66
67 // For a standard Over, the resulting alpha is: a = opacity*dstAlpha + (1-opacity)*srcAlpha
68 // Let us assume we're blending with a color with srcAlpha = 1 here
69 // Therefore, opacity = (1.0 - a)/(1.0 - dstAlpha)
70 if (a<dA) a = dA;
71 float fakeOpacity = 1.0f - (1.0f - a)/(1.0f - dA + 1e-16f);
72 newDstAlpha=scale<channels_type>(a);
73
74 if (isZeroValueFuzzy(newDstAlpha)) {
75 // just do nothing with color channels and return null opacity
76 } else if (!isZeroValueFuzzy(dstAlpha)) {
77 for (qint8 channel = 0; channel < channels_nb; ++channel)
78 if(channel != alpha_pos && (allChannelFlags || channelFlags.testBit(channel)))
79 {
81
82 channels_type dstMult = mul(BlendingPolicy::toAdditiveSpace(dst[channel]), dstAlpha);
83 channels_type srcMult = mul(BlendingPolicy::toAdditiveSpace(src[channel]), unitValue<channels_type>());
84 channels_type blendedValue = lerp(dstMult, srcMult, scale<channels_type>(fakeOpacity));
85
86 composite_type normedValue = KoColorSpaceMaths<channels_type>::divide(blendedValue, newDstAlpha);
87
88 dst[channel] = BlendingPolicy::fromAdditiveSpace(KoColorSpaceMaths<channels_type>::clampAfterScale(normedValue));
89 }
90 }
91 else {
92 // don't blend if the color of the destination is undefined (has zero opacity)
93 // copy the source channel instead
94 for (qint8 channel = 0; channel < channels_nb; ++channel)
95 if(channel != alpha_pos && (allChannelFlags || channelFlags.testBit(channel)))
96 dst[channel] = src[channel];
97 }
98
99 return newDstAlpha;
100 }
101};
102
103#endif // _KOCOMPOSITEOPGREATER_H_
const QString COMPOSITE_GREATER
QPointF lerp(const QPointF &p1, const QPointF &p2, qreal t)
static dst_compositetype divide(_T a, _Tdst b)
KoCompositeOpBase< CS_Traits, KoCompositeOpGreater< CS_Traits, BlendingPolicy > > base_class
CS_Traits::channels_type channels_type
KoCompositeOpGreater(const KoColorSpace *cs)
static const qint8 channels_nb
static const qint8 alpha_pos
static channels_type composeColorChannels(const channels_type *src, channels_type srcAlpha, channels_type *dst, channels_type dstAlpha, channels_type maskAlpha, channels_type opacity, const QBitArray &channelFlags)
KoColorSpaceMathsTraits< typenameCS_Traits::channels_type >::compositetype composite_type
static QString categoryMix()