Krita Source Code Documentation
Loading...
Searching...
No Matches
OverCompositor128< channels_type, alphaLocked, allChannelsFlag > Struct Template Reference

#include <KoOptimizedCompositeOpOver128.h>

Classes

struct  ParamsWrapper
 
struct  Pixel
 

Static Public Member Functions

template<bool haveMask, typename _impl >
static ALWAYS_INLINE void compositeOnePixelScalar (const quint8 *src, quint8 *dst, const quint8 *mask, float opacity, const ParamsWrapper &oparams)
 
template<bool haveMask, bool src_aligned, typename _impl >
static ALWAYS_INLINE void compositeVector (const quint8 *src, quint8 *dst, const quint8 *mask, float opacity, const ParamsWrapper &oparams)
 

Detailed Description

template<typename channels_type, bool alphaLocked, bool allChannelsFlag>
struct OverCompositor128< channels_type, alphaLocked, allChannelsFlag >

Definition at line 21 of file KoOptimizedCompositeOpOver128.h.

Member Function Documentation

◆ compositeOnePixelScalar()

template<typename channels_type , bool alphaLocked, bool allChannelsFlag>
template<bool haveMask, typename _impl >
static ALWAYS_INLINE void OverCompositor128< channels_type, alphaLocked, allChannelsFlag >::compositeOnePixelScalar ( const quint8 * src,
quint8 * dst,
const quint8 * mask,
float opacity,
const ParamsWrapper & oparams )
inlinestatic

Definition at line 133 of file KoOptimizedCompositeOpOver128.h.

138 {
139 using namespace Arithmetic;
140 const qint32 alpha_pos = 3;
141
142 const auto *s = reinterpret_cast<const channels_type*>(src);
143 auto *d = reinterpret_cast<channels_type*>(dst);
144
145 float srcAlpha = s[alpha_pos];
147 srcAlpha *= opacity;
148
149 if (haveMask) {
150 const float uint8Rec1 = 1.0f / 255.0f;
151 srcAlpha *= float(*mask) * uint8Rec1;
152 }
153
154#if INFO_DEBUG
155 static int xx = 0;
156 bool display = xx > 45 && xx < 50;
157 if (display) {
158 qInfo() << "O" << s[alpha_pos] << srcAlpha << haveMask << opacity;
159 }
160#endif
161
162 if (srcAlpha != 0.0f) {
163
164 float dstAlpha = d[alpha_pos];
166 float srcBlendNorm = 0.0f;
167
168 if (alphaLocked || dstAlpha == 1.0f) {
169 srcBlendNorm = srcAlpha;
170 } else if (dstAlpha == 0.0f) {
171 dstAlpha = srcAlpha;
172 srcBlendNorm = 1.0f;
173
174 if (!allChannelsFlag) {
175 KoStreamedMathFunctions::clearPixel<sizeof(Pixel)>(dst);
176 }
177 } else {
178 dstAlpha += (1.0f - dstAlpha) * srcAlpha;
179 srcBlendNorm = srcAlpha / dstAlpha;
180 }
181
182#if INFO_DEBUG
183 if (display) {
184 qInfo() << "params" << srcBlendNorm << allChannelsFlag << alphaLocked << dstAlpha << haveMask;
185 }
186#endif
187 if(allChannelsFlag) {
188 if (srcBlendNorm == 1.0f) {
189 if (!alphaLocked) {
190 KoStreamedMathFunctions::copyPixel<sizeof(Pixel)>(src, dst);
191 } else {
192 d[0] = s[0];
193 d[1] = s[1];
194 d[2] = s[2];
195 }
196 } else if (srcBlendNorm != 0.0f){
197#if INFO_DEBUG
198 if (display) {
199 qInfo() << "calc" << s[0] << d[0] << srcBlendNorm * (s[0] - d[0]) + d[0] << s[0] - d[0] << srcBlendNorm * (s[0] - d[0]) << srcBlendNorm;
200 }
201#endif
202
203 d[0] = PixelWrapper<channels_type, _impl>::lerpMixedUintFloat(d[0], s[0], srcBlendNorm);
204 d[1] = PixelWrapper<channels_type, _impl>::lerpMixedUintFloat(d[1], s[1], srcBlendNorm);
205 d[2] = PixelWrapper<channels_type, _impl>::lerpMixedUintFloat(d[2], s[2], srcBlendNorm);
206 }
207 } else {
208 const QBitArray &channelFlags = oparams.channelFlags;
209
210 if (srcBlendNorm == 1.0f) {
211 if(channelFlags.at(0)) d[0] = s[0];
212 if(channelFlags.at(1)) d[1] = s[1];
213 if(channelFlags.at(2)) d[2] = s[2];
214 } else if (srcBlendNorm != 0.0f) {
215 if(channelFlags.at(0)) d[0] = PixelWrapper<channels_type, _impl>::lerpMixedUintFloat(d[0], s[0], srcBlendNorm);
216 if(channelFlags.at(1)) d[1] = PixelWrapper<channels_type, _impl>::lerpMixedUintFloat(d[1], s[1], srcBlendNorm);;
217 if(channelFlags.at(2)) d[2] = PixelWrapper<channels_type, _impl>::lerpMixedUintFloat(d[2], s[2], srcBlendNorm);;
218 }
219 }
220
221 if (!alphaLocked) {
224 }
225#if INFO_DEBUG
226 if (display) {
227 qInfo() << "result" << d[0] << d[1] << d[2] << d[3];
228 }
229 ++xx;
230#endif
231 }
232 }

References OverCompositor128< channels_type, alphaLocked, allChannelsFlag >::ParamsWrapper::channelFlags.

◆ compositeVector()

template<typename channels_type , bool alphaLocked, bool allChannelsFlag>
template<bool haveMask, bool src_aligned, typename _impl >
static ALWAYS_INLINE void OverCompositor128< channels_type, alphaLocked, allChannelsFlag >::compositeVector ( const quint8 * src,
quint8 * dst,
const quint8 * mask,
float opacity,
const ParamsWrapper & oparams )
inlinestatic

The value of new_alpha can have some zero values, which will result in NaN values while division.

Definition at line 39 of file KoOptimizedCompositeOpOver128.h.

40 {
41#if INFO_DEBUG
42 static quint32 countTotal = 0;
43 static quint32 countOne = 0;
44 static quint32 countTwo = 0;
45 static quint32 countThree = 0;
46 static quint32 countFour = 0;
47
48 if (++countTotal % 250000 == 0) {
49 qInfo() << "count" << countOne << countTwo << countThree << countFour << countTotal << opacity;
50 }
51#endif
52 using float_v = typename KoStreamedMath<_impl>::float_v;
53 using float_m = typename float_v::batch_bool_type;
54
55 Q_UNUSED(oparams);
56
57 float_v src_alpha;
58 float_v dst_alpha;
59
60 float_v src_c1;
61 float_v src_c2;
62 float_v src_c3;
63
65 dataWrapper.read(src, src_c1, src_c2, src_c3, src_alpha);
66
67 //bool haveOpacity = opacity != 1.0;
68 const float_v opacity_norm_vec(opacity);
69 src_alpha *= opacity_norm_vec;
70
71 if (haveMask) {
72 const float_v uint8MaxRec1((float)1.0 / 255);
73 float_v mask_vec = KoStreamedMath<_impl>::fetch_mask_8(mask);
74 src_alpha *= mask_vec * uint8MaxRec1;
75 }
76
77 const float_v zeroValue(static_cast<float>(NATIVE_OPACITY_TRANSPARENT));
78 // The source cannot change the colors in the destination,
79 // since its fully transparent
80 if (xsimd::all(src_alpha == zeroValue)) {
81#if INFO_DEBUG
82 countFour++;
83#endif
84 return;
85 }
86
87 float_v dst_c1;
88 float_v dst_c2;
89 float_v dst_c3;
90
91 dataWrapper.read(dst, dst_c1, dst_c2, dst_c3, dst_alpha);
92
93 float_v src_blend;
94 float_v new_alpha;
95
96 const float_v oneValue(1.0f);
97 if (xsimd::all(dst_alpha == oneValue)) {
98 new_alpha = dst_alpha;
99 src_blend = src_alpha;
100 } else if (xsimd::all(dst_alpha == zeroValue)) {
101 new_alpha = src_alpha;
102 src_blend = oneValue;
103 } else {
108 new_alpha = dst_alpha + (oneValue - dst_alpha) * src_alpha;
109 const float_m mask = (new_alpha == zeroValue);
110 src_blend = src_alpha / new_alpha;
111 src_blend = xsimd::set_zero(src_blend, mask);
112 }
113
114 if (!xsimd::all(src_blend == oneValue)) {
115#if INFO_DEBUG
116 ++countOne;
117#endif
118
119 dst_c1 = src_blend * (src_c1 - dst_c1) + dst_c1;
120 dst_c2 = src_blend * (src_c2 - dst_c2) + dst_c2;
121 dst_c3 = src_blend * (src_c3 - dst_c3) + dst_c3;
122
123 dataWrapper.write(dst, dst_c1, dst_c2, dst_c3, new_alpha);
124 } else {
125#if INFO_DEBUG
126 ++countTwo;
127#endif
128 dataWrapper.write(dst, src_c1, src_c2, src_c3, new_alpha);
129 }
130 }
#define NATIVE_OPACITY_TRANSPARENT
auto set_zero(const batch< T, A > &src, const batch_bool< T, A > &mask) noexcept
xsimd::batch< float, _impl > float_v
static float_v fetch_mask_8(const quint8 *data)

References KoStreamedMath< _impl >::fetch_mask_8(), NATIVE_OPACITY_TRANSPARENT, and xsimd::set_zero().


The documentation for this struct was generated from the following file: