Krita Source Code Documentation
Loading...
Searching...
No Matches
KoCompositeOpDissolve.h
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2011 Silvio Heinrich <plassy@web.de>
3 *
4 * SPDX-License-Identifier: LGPL-2.1-or-later
5*/
6
7#ifndef _KOCOMPOSITEOP_DISSOLVE_H_
8#define _KOCOMPOSITEOP_DISSOLVE_H_
9
10#include <KoColorSpaceMaths.h>
11#include <KoCompositeOp.h>
12
13#include <kis_random_source.h>
14#include <QThreadStorage>
15
16template<class Traits>
18{
19 typedef typename Traits::channels_type channels_type;
20
21 static const qint32 channels_nb = Traits::channels_nb;
22 static const qint32 alpha_pos = Traits::alpha_pos;
23
24 mutable QThreadStorage<KisRandomSource> m_randomGenerator;
25
26public:
31
33
34 void composite(const KoCompositeOp::ParameterInfo& params) const override {
42 if (!m_randomGenerator.hasLocalData()) {
43 m_randomGenerator.setLocalData(KisRandomSource());
44 }
45
46 const QBitArray& flags = params.channelFlags.isEmpty() ? QBitArray(channels_nb,true) : params.channelFlags;
47 bool alphaLocked = (alpha_pos != -1) && !flags.testBit(alpha_pos);
48
49 using namespace Arithmetic;
50
51// quint32 ctr = quint32(reinterpret_cast<quint64>(dstRowStart) % 256);
52 qint32 srcInc = (params.srcRowStride == 0) ? 0 : channels_nb;
53 bool useMask = params.maskRowStart != 0;
56
57 const quint8 *srcRowStart = params.srcRowStart;
58 quint8 *dstRowStart = params.dstRowStart;
59 const quint8 *maskRowStart = params.maskRowStart;
60
61 qint32 rows = params.rows;
62
63 for(; rows>0; --rows) {
64 const channels_type* src = reinterpret_cast<const channels_type*>(srcRowStart);
65 channels_type* dst = reinterpret_cast<channels_type*>(dstRowStart);
66 const quint8* mask = maskRowStart;
67
68 for(qint32 c=params.cols; c>0; --c) {
69 channels_type srcAlpha = (alpha_pos == -1) ? unitValue : src[alpha_pos];
70 channels_type dstAlpha = (alpha_pos == -1) ? unitValue : dst[alpha_pos];
71 channels_type blend = useMask ? mul(opacity, scale<channels_type>(*mask), srcAlpha) : mul(opacity, srcAlpha);
72
73 if (m_randomGenerator.localData().generate(0, 255) <= scale<quint8>(blend)
75 for(qint32 i=0; i <channels_nb; i++) {
76 if(i != alpha_pos && flags.testBit(i))
77 dst[i] = src[i];
78 }
79
80 if(alpha_pos != -1)
81 dst[alpha_pos] = alphaLocked ? dstAlpha : unitValue;
82 }
83
84 src += srcInc;
85 dst += channels_nb;
86// ctr = (ctr + 1) % 256;
87 if (mask) {
88 ++mask;
89 }
90 }
91
92 srcRowStart += params.srcRowStride;
93 dstRowStart += params.dstRowStride;
94 if (maskRowStart) {
95 maskRowStart += params.maskRowStride;
96 }
97 }
98 }
99};
100
101#endif // _KOCOMPOSITEOP_DISSOLVE_H_
const QString COMPOSITE_DISSOLVE
static _Tdst scaleToA(_T a)
QThreadStorage< KisRandomSource > m_randomGenerator
void composite(const KoCompositeOp::ParameterInfo &params) const override
Traits::channels_type channels_type
KoCompositeOpDissolve(const KoColorSpace *cs, const QString &category)
static const qint32 channels_nb
static const qint32 alpha_pos
void composite(quint8 *dstRowStart, qint32 dstRowStride, const quint8 *srcRowStart, qint32 srcRowStride, const quint8 *maskRowStart, qint32 maskRowStride, qint32 rows, qint32 numColumns, float opacity, const QBitArray &channelFlags=QBitArray()) const