File indexing completed on 2024-06-09 04:23:29
0001 /* 0002 * SPDX-FileCopyrightText: 2011 Silvio Heinrich <plassy@web.de> 0003 * 0004 * SPDX-License-Identifier: LGPL-2.1-or-later 0005 */ 0006 0007 #ifndef _KOCOMPOSITEOP_DISSOLVE_H_ 0008 #define _KOCOMPOSITEOP_DISSOLVE_H_ 0009 0010 #include <KoCompositeOp.h> 0011 #include <KoColorSpaceMaths.h> 0012 0013 template<class Traits> 0014 class KoCompositeOpDissolve: public KoCompositeOp 0015 { 0016 typedef typename Traits::channels_type channels_type; 0017 0018 static const qint32 channels_nb = Traits::channels_nb; 0019 static const qint32 alpha_pos = Traits::alpha_pos; 0020 0021 inline static quint8 getRandomValue(quint32 i) 0022 { 0023 static const quint8 randomValues[256] = 0024 { 0025 0x50, 0xAD, 0x7D, 0xA9, 0x10, 0x75, 0xCA, 0x57, 0xE2, 0x06, 0x77, 0x39, 0xD9, 0xFA, 0x5C, 0x24, 0026 0xEB, 0x1A, 0x6F, 0x15, 0xE7, 0x8B, 0x11, 0x71, 0xF0, 0xB9, 0x44, 0x8A, 0x27, 0x5E, 0xA1, 0x6A, 0027 0x47, 0x94, 0x03, 0xD5, 0xB7, 0x56, 0xEF, 0x45, 0xED, 0xBE, 0xE8, 0xB2, 0x4C, 0x0D, 0x65, 0x9E, 0028 0x55, 0xD7, 0x30, 0x0F, 0x52, 0xA6, 0x4D, 0x86, 0xAF, 0x66, 0x33, 0x6B, 0x3E, 0x89, 0xBD, 0xFB, 0029 0x00, 0xC4, 0x36, 0xFC, 0x8D, 0x4E, 0x19, 0x3F, 0x91, 0xC1, 0x40, 0x14, 0x67, 0x80, 0x17, 0x3A, 0030 0xF2, 0xB4, 0xD1, 0xFF, 0x35, 0xA7, 0xF7, 0x1C, 0x84, 0x2A, 0xBF, 0x46, 0xC6, 0x2B, 0x98, 0x41, 0031 0xF4, 0xB8, 0xA0, 0x78, 0x5A, 0xBC, 0x3B, 0x62, 0xB6, 0x7A, 0x2E, 0x07, 0x8F, 0x4A, 0xAB, 0x2F, 0032 0x79, 0x54, 0x81, 0x69, 0x18, 0x4F, 0xA5, 0x21, 0xD3, 0x26, 0x7C, 0x9F, 0xCF, 0xB0, 0x34, 0xCC, 0033 0x8C, 0xAA, 0xDB, 0x32, 0xE5, 0x1F, 0x7B, 0x37, 0x64, 0x0A, 0xF9, 0x63, 0xF5, 0x38, 0x13, 0xA2, 0034 0x12, 0xF6, 0xC9, 0x5D, 0xDF, 0xC7, 0x97, 0xC0, 0x51, 0xE1, 0x9A, 0x58, 0x76, 0xC3, 0x83, 0xC2, 0035 0x04, 0x22, 0x60, 0x9D, 0xF1, 0x5F, 0xEC, 0x6D, 0x4B, 0xE0, 0x6C, 0xD8, 0xAC, 0x25, 0xA8, 0x1E, 0036 0x96, 0x7E, 0x49, 0x61, 0xCD, 0x0E, 0xE3, 0xC5, 0x7F, 0x5B, 0x05, 0x6E, 0xBA, 0x0C, 0x8E, 0xF8, 0037 0x82, 0xDA, 0x72, 0x01, 0x23, 0x9B, 0xD2, 0x99, 0xE9, 0xC8, 0xB1, 0x28, 0xD4, 0xAE, 0x48, 0xFD, 0038 0x95, 0x2C, 0xE4, 0x93, 0x09, 0x3D, 0x70, 0x85, 0x43, 0x20, 0xBB, 0xDE, 0x90, 0xB3, 0x3C, 0xDD, 0039 0xA3, 0x73, 0x9C, 0x16, 0xDC, 0x42, 0xEA, 0x74, 0x92, 0xE6, 0xCB, 0x53, 0x08, 0xEE, 0x59, 0x02, 0040 0xF3, 0x29, 0xFE, 0xA4, 0x1B, 0xD6, 0x87, 0xB5, 0xCE, 0x1D, 0x68, 0x88, 0x31, 0x0B, 0x2D, 0xD0 0041 }; 0042 0043 return randomValues[i]; 0044 } 0045 0046 public: 0047 KoCompositeOpDissolve(const KoColorSpace* cs, const QString& category) 0048 : KoCompositeOp(cs, COMPOSITE_DISSOLVE, category) { } 0049 0050 using KoCompositeOp::composite; 0051 0052 void composite(quint8* dstRowStart , qint32 dstRowStride , 0053 const quint8* srcRowStart , qint32 srcRowStride , 0054 const quint8* maskRowStart, qint32 maskRowStride, 0055 qint32 rows, qint32 cols, quint8 U8_opacity, const QBitArray& channelFlags) const override { 0056 0057 const QBitArray& flags = channelFlags.isEmpty() ? QBitArray(channels_nb,true) : channelFlags; 0058 bool alphaLocked = (alpha_pos != -1) && !flags.testBit(alpha_pos); 0059 0060 using namespace Arithmetic; 0061 0062 // quint32 ctr = quint32(reinterpret_cast<quint64>(dstRowStart) % 256); 0063 qint32 srcInc = (srcRowStride == 0) ? 0 : channels_nb; 0064 bool useMask = maskRowStart != 0; 0065 channels_type unitValue = KoColorSpaceMathsTraits<channels_type>::unitValue; 0066 channels_type opacity = KoColorSpaceMaths<quint8,channels_type>::scaleToA(U8_opacity); 0067 0068 for(; rows>0; --rows) { 0069 const channels_type* src = reinterpret_cast<const channels_type*>(srcRowStart); 0070 channels_type* dst = reinterpret_cast<channels_type*>(dstRowStart); 0071 const quint8* mask = maskRowStart; 0072 0073 for(qint32 c=cols; c>0; --c) { 0074 channels_type srcAlpha = (alpha_pos == -1) ? unitValue : src[alpha_pos]; 0075 channels_type dstAlpha = (alpha_pos == -1) ? unitValue : dst[alpha_pos]; 0076 channels_type blend = useMask ? mul(opacity, scale<channels_type>(*mask), srcAlpha) : mul(opacity, srcAlpha); 0077 0078 // if(getRandomValue(ctr) <= scale<quint8>(blend) && blend != KoColorSpaceMathsTraits<channels_type>::zeroValue) { 0079 if((qrand() % 256) <= scale<quint8>(blend) && blend != KoColorSpaceMathsTraits<channels_type>::zeroValue) { 0080 for(qint32 i=0; i <channels_nb; i++) { 0081 if(i != alpha_pos && flags.testBit(i)) 0082 dst[i] = src[i]; 0083 } 0084 0085 if(alpha_pos != -1) 0086 dst[alpha_pos] = alphaLocked ? dstAlpha : unitValue; 0087 } 0088 0089 src += srcInc; 0090 dst += channels_nb; 0091 // ctr = (ctr + 1) % 256; 0092 if (mask) { 0093 ++mask; 0094 } 0095 } 0096 0097 srcRowStart += srcRowStride; 0098 dstRowStart += dstRowStride; 0099 if (maskRowStart) { 0100 maskRowStart += maskRowStride; 0101 } 0102 } 0103 } 0104 }; 0105 0106 #endif // _KOCOMPOSITEOP_DISSOLVE_H_