File indexing completed on 2024-06-16 04:16:43

0001 /*
0002  * This file is part of the KDE project
0003  *
0004  * SPDX-FileCopyrightText: 2005 Cyrille Berger <cberger@cberger.net>
0005  *
0006  *  SPDX-License-Identifier: GPL-2.0-or-later
0007  */
0008 
0009 #include "randompickfilter.h"
0010 #include <stdlib.h>
0011 #include <vector>
0012 #include <math.h>
0013 
0014 #include <QPoint>
0015 
0016 #include <kis_debug.h>
0017 
0018 #include <kpluginfactory.h>
0019 #include <klocalizedstring.h>
0020 
0021 #include <KoUpdater.h>
0022 
0023 #include <KoMixColorsOp.h>
0024 #include <filter/kis_filter_registry.h>
0025 #include <kis_global.h>
0026 #include <kis_image.h>
0027 #include <kis_layer.h>
0028 #include <kis_paint_device.h>
0029 #include <kis_random_accessor_ng.h>
0030 #include <kis_random_generator.h>
0031 #include <kis_selection.h>
0032 #include <kis_types.h>
0033 #include <filter/kis_filter_category_ids.h>
0034 #include <filter/kis_filter_configuration.h>
0035 #include <kis_processing_information.h>
0036 
0037 #include "kis_wdg_random_pick.h"
0038 #include "ui_wdgrandompickoptions.h"
0039 #include <kis_iterator_ng.h>
0040 #include <KisSequentialIteratorProgress.h>
0041 
0042 K_PLUGIN_FACTORY_WITH_JSON(KritaRandomPickFilterFactory, "kritarandompickfilter.json", registerPlugin<KritaRandomPickFilter>();)
0043 
0044 KritaRandomPickFilter::KritaRandomPickFilter(QObject *parent, const QVariantList &)
0045         : QObject(parent)
0046 {
0047     KisFilterRegistry::instance()->add(new KisFilterRandomPick());
0048 }
0049 
0050 KritaRandomPickFilter::~KritaRandomPickFilter()
0051 {
0052 }
0053 
0054 KisFilterRandomPick::KisFilterRandomPick() : KisFilter(id(), FiltersCategoryOtherId, i18n("&Random Pick..."))
0055 {
0056     setColorSpaceIndependence(FULLY_INDEPENDENT);
0057     setSupportsPainting(true);
0058 }
0059 
0060 
0061 void KisFilterRandomPick::processImpl(KisPaintDeviceSP device,
0062                                       const QRect& applyRect,
0063                                       const KisFilterConfigurationSP config,
0064                                       KoUpdater* progressUpdater
0065                                       ) const
0066 {
0067     Q_UNUSED(config);
0068     Q_ASSERT(!device.isNull());
0069 
0070     const KoColorSpace * cs = device->colorSpace();
0071 
0072     QVariant value;
0073     int level = (config && config->getProperty("level", value)) ? value.toInt() : 50;
0074     int opacity = (config && config->getProperty("opacity", value)) ? value.toInt() : 100;
0075     double windowsize = (config && config->getProperty("windowsize", value)) ? value.toDouble() : 2.5;
0076 
0077     int seedThreshold = rand();
0078     int seedH = rand();
0079     int seedV = rand();
0080 
0081     if (config) {
0082         seedThreshold = config->getInt("seedThreshold", seedThreshold);
0083         seedH = config->getInt("seedH", seedH);
0084         seedV = config->getInt("seedV", seedV);
0085     }
0086     KisRandomGenerator randT(seedThreshold);
0087     KisRandomGenerator randH(seedH);
0088     KisRandomGenerator randV(seedV);
0089 
0090     KisSequentialIteratorProgress dstIt(device, applyRect, progressUpdater);
0091     KisRandomConstAccessorSP srcRA = device->createRandomConstAccessorNG();
0092 
0093     double threshold = (100 - level) / 100.0;
0094 
0095     qint16 weights[2];
0096     weights[0] = (255 * opacity) / 100; weights[1] = 255 - weights[0];
0097     const quint8* pixels[2];
0098     KoMixColorsOp * mixOp = cs->mixColorsOp();
0099     while (dstIt.nextPixel()) {
0100         if (randT.doubleRandomAt(dstIt.x(), dstIt.y()) > threshold) {
0101             int x = static_cast<int>(dstIt.x() + windowsize * (randH.doubleRandomAt(dstIt.x(), dstIt.y()) - 0.5));
0102             int y = static_cast<int>(dstIt.y() +  windowsize * (randV.doubleRandomAt(dstIt.x(), dstIt.y()) -0.5));
0103             srcRA->moveTo(x, y);
0104             pixels[0] = srcRA->oldRawData();
0105             pixels[1] = dstIt.oldRawData();
0106             mixOp->mixColors(pixels, weights, 2, dstIt.rawData());
0107         }
0108     }
0109 
0110 }
0111 
0112 KisConfigWidget * KisFilterRandomPick::createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP dev, bool) const
0113 {
0114     Q_UNUSED(dev);
0115     return new KisWdgRandomPick((KisFilter*)this, (QWidget*)parent);
0116 }
0117 
0118 KisFilterConfigurationSP KisFilterRandomPick::defaultConfiguration(KisResourcesInterfaceSP resourcesInterface) const
0119 {
0120     KisFilterConfigurationSP config = factoryConfiguration(resourcesInterface);
0121     config->setProperty("level", 50);
0122     config->setProperty("windowsize", 2.5);
0123     config->setProperty("opacity", 100);
0124     config->setProperty("seedThreshold", rand());
0125     config->setProperty("seedH", rand());
0126     config->setProperty("seedV", rand());
0127 
0128     return config;
0129 }
0130 
0131 QRect KisFilterRandomPick::neededRect(const QRect& rect, const KisFilterConfigurationSP config, int lod) const
0132 {
0133     Q_UNUSED(lod);
0134 
0135     QVariant value;
0136     int windowsize = ceil((config && config->getProperty("windowsize", value)) ? value.toDouble() : 2.5);
0137     return rect.adjusted(-windowsize, -windowsize, windowsize, windowsize);
0138 }
0139 
0140 QRect KisFilterRandomPick::changedRect(const QRect &rect, const KisFilterConfigurationSP config, int lod) const
0141 {
0142     return neededRect(rect, config, lod);
0143 }
0144 
0145 #include "randompickfilter.moc"