8#ifndef KOALPHAMASKAPPLICATOR_H
9#define KOALPHAMASKAPPLICATOR_H
16template<
typename _channels_type_,
20 typename EnableDummyType =
void>
25 qint32 nPixels)
const override {
30 applyInverseAlphaNormedFloatMask(pixels, alpha, nPixels);
35 const quint8 *brushColor,
36 qint32 nPixels)
const override {
53#if !defined(XSIMD_NO_SUPPORTED_ARCHITECTURE)
57template<
typename _impl>
66 static constexpr int numChannels = 4;
67 static constexpr int alphaPos = 3;
71 qint32 nPixels)
const override
73 const int block1 = nPixels /
static_cast<int>(float_v::size);
74 const int block2 = nPixels %
static_cast<int>(float_v::size);
75 const int vectorPixelStride = numChannels *
static_cast<int>(float_v::size);
77 for (
int i = 0; i < block1; i++) {
78 const auto maskAlpha = float_v::load_unaligned(alpha);
80 auto data_i = uint_v::load_unaligned(
reinterpret_cast<const quint32 *
>(pixels));
82 const auto pixelAlpha = xsimd::to_float(xsimd::bitwise_cast_compat<int>(data_i >> 24U)) * (
float_v(1.0f) - maskAlpha);
84 const quint32 colorChannelsMask = 0x00FFFFFF;
86 const uint_v pixelAlpha_i = xsimd::bitwise_cast_compat<unsigned int>(xsimd::nearbyint_as_int(pixelAlpha));
87 data_i = (data_i & colorChannelsMask) | (pixelAlpha_i << 24);
88 data_i.store_unaligned(
reinterpret_cast<typename uint_v::value_type *
>(pixels));
90 pixels += vectorPixelStride;
91 alpha += float_v::size;
100 const quint8 *brushColor,
101 qint32 nPixels)
const override {
102 const int block1 = nPixels /
static_cast<int>(float_v::size);
103 const int block2 = nPixels %
static_cast<int>(float_v::size);
104 const int vectorPixelStride = numChannels *
static_cast<int>(float_v::size);
105 const uint_v brushColor_i(*
reinterpret_cast<const quint32*
>(brushColor) & 0x00FFFFFFu);
107 for (
int i = 0; i < block1; i++) {
108 const auto maskAlpha = float_v::load_unaligned(alpha);
109 const auto pixelAlpha =
float_v(255.0f) * (
float_v(1.0f) - maskAlpha);
111 const uint_v pixelAlpha_i = xsimd::bitwise_cast_compat<unsigned int>(xsimd::nearbyint_as_int(pixelAlpha));
112 const uint_v data_i = brushColor_i | (pixelAlpha_i << 24);
113 data_i.store_unaligned(
reinterpret_cast<typename uint_v::value_type *
>(pixels));
115 pixels += vectorPixelStride;
116 alpha += float_v::size;
125 const uint_v c = a * b + 0x80u;
126 return ((c >> 8) + c) >> 8;
130 const int block1 = nPixels /
static_cast<int>(float_v::size);
131 const int block2 = nPixels %
static_cast<int>(float_v::size);
132 const int vectorPixelStride = numChannels *
static_cast<int>(float_v::size);
133 const uint_v brushColor_i(*
reinterpret_cast<const quint32*
>(brushColor) & 0x00FFFFFFu);
135 const uint_v redChannelMask(0xFF);
137 for (
int i = 0; i < block1; i++) {
138 const auto maskPixels = uint_v::load_unaligned(
reinterpret_cast<const quint32*
>(brush));
140 const uint_v pixelAlpha = maskPixels >> 24;
141 const uint_v pixelRed = maskPixels & redChannelMask;
142 const uint_v pixelAlpha_i = multiply(redChannelMask - pixelRed, pixelAlpha);
144 const uint_v data_i = brushColor_i | (pixelAlpha_i << 24);
145 data_i.store_unaligned(
reinterpret_cast<typename uint_v::value_type *
>(dst));
147 dst += vectorPixelStride;
148 brush += float_v::size;
void applyInverseNormedFloatMask(quint8 *pixels, const float *alpha, qint32 nPixels) const override
void fillInverseAlphaNormedFloatMaskWithColor(quint8 *pixels, const float *alpha, const quint8 *brushColor, qint32 nPixels) const override
static uint_v multiply(uint_v a, uint_v b)
typename KoStreamedMath< _impl >::float_v float_v
void fillGrayBrushWithColor(quint8 *dst, const QRgb *brush, quint8 *brushColor, qint32 nPixels) const override
typename KoStreamedMath< _impl >::int_v int_v
typename KoStreamedMath< _impl >::uint_v uint_v
void fillInverseAlphaNormedFloatMaskWithColor(quint8 *pixels, const float *alpha, const quint8 *brushColor, qint32 nPixels) const override
void fillGrayBrushWithColor(quint8 *dst, const QRgb *brush, quint8 *brushColor, qint32 nPixels) const override
void applyInverseNormedFloatMask(quint8 *pixels, const float *alpha, qint32 nPixels) const override
static void fillInverseAlphaNormedFloatMaskWithColor(quint8 *pixels, const float *alpha, const quint8 *brushColor, qint32 nPixels)
static void applyInverseAlphaNormedFloatMask(quint8 *pixels, const float *alpha, qint32 nPixels)
static void fillGrayBrushWithColor(quint8 *pixels, const QRgb *brush, quint8 *brushColor, qint32 nPixels)
xsimd::batch< unsigned int, _impl > uint_v
xsimd::batch< float, _impl > float_v
xsimd::batch< int, _impl > int_v