Krita Source Code Documentation
Loading...
Searching...
No Matches
noisefilter.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the KDE project
3 *
4 * SPDX-FileCopyrightText: 2005 Cyrille Berger <cberger@cberger.net>
5 *
6 * SPDX-License-Identifier: GPL-2.0-or-later
7 */
8
9#include "noisefilter.h"
10#include <vector>
11
12#include <kpluginfactory.h>
13#include <klocalizedstring.h>
14
15#include <KoUpdater.h>
16#include <KoMixColorsOp.h>
18#include <kis_paint_device.h>
19#include <kis_types.h>
24
25#include "kis_wdg_noise.h"
26#include "ui_wdgnoiseoptions.h"
27
28
29K_PLUGIN_FACTORY_WITH_JSON(KritaNoiseFilterFactory, "kritanoisefilter.json", registerPlugin<KritaNoiseFilter>();)
30
31KritaNoiseFilter::KritaNoiseFilter(QObject *parent, const QVariantList &)
32 : QObject(parent)
33{
35
36}
37
41
47
49{
50 KisFilterConfigurationSP config = factoryConfiguration(resourcesInterface);
51 config->setProperty("level", 50);
52 config->setProperty("opacity", 100);
53 config->setProperty("seedThreshold", rand());
54 config->setProperty("seedRed", rand());
55 config->setProperty("seedGreen", rand());
56 config->setProperty("seedBlue", rand());
57 config->setProperty("grayscale", false);
58 return config;
59}
60
62{
63 Q_UNUSED(dev);
64 return new KisWdgNoise((KisFilter*)this, (QWidget*)parent);
65}
66
68 const QRect& rect,
69 const KisFilterConfigurationSP config,
70 KoUpdater* progressUpdater) const
71{
72 Q_UNUSED(progressUpdater);
73 Q_ASSERT(!device.isNull());
74
75 QVariant value;
76 const int level = (config && config->getProperty("level", value)) ? value.toInt() : 50;
77 const int opacity = (config && config->getProperty("opacity", value)) ? value.toInt() : 100;
78 const bool isGrayscale = (config && config->getProperty("grayscale", value)) ? value.toBool() : false;
79
80 const double threshold = (100.0 - level) * 0.01;
81 const KoColorSpace* colorSpace = device->colorSpace();
82 const quint32 pixelSize = colorSpace->pixelSize();
83 const KoMixColorsOp* mixOp = colorSpace->mixColorsOp();
84
85 std::vector<quint8> scratchPixel(pixelSize);
86
87 constexpr quint32 numMixPixels = 2;
88 qint16 weights[numMixPixels];
89 weights[0] = (255 * opacity) / 100;
90 weights[1] = 255 - weights[0];
91
92 const quint8* pixels[numMixPixels];
93 pixels[0] = scratchPixel.data();
94
95 int seedThreshold = rand();
96 int seedRed = rand();
97 int seedGreen = rand();
98 int seedBlue = rand();
99
100 if (config) {
101 seedThreshold = config->getInt("seedThreshold", seedThreshold);
102 seedRed = config->getInt("seedRed", seedRed);
103 seedGreen = config->getInt("seedGreen", seedGreen);
104 seedBlue = config->getInt("seedBlue", seedBlue);
105 }
106
107 KisRandomGenerator2D randt(seedThreshold);
108 KisRandomGenerator2D randr(seedRed);
109 KisRandomGenerator2D randg(seedGreen);
110 KisRandomGenerator2D randb(seedBlue);
111
113
114 qint32 dstY_ = rect.y();
115 qint32 rowsRemaining = rect.height();
116
117 while (rowsRemaining > 0) {
118 qint32 dstX_ = rect.x();
119 qint32 columnsRemaining = rect.width();
120 qint32 numContiguousDstRows = dstIt->numContiguousRows(dstY_);
121 qint32 rows = qMin(numContiguousDstRows, rowsRemaining);
122
123 while (columnsRemaining > 0) {
124 qint32 numContiguousDstColumns = dstIt->numContiguousColumns(dstX_);
125 qint32 columns = qMin(numContiguousDstColumns, columnsRemaining);
126
127 qint32 dstRowStride = dstIt->rowStride(dstX_, dstY_);
128 dstIt->moveTo(dstX_, dstY_);
129
130 for (int rowIndex = 0; rowIndex < rows; ++rowIndex) {
131 for (int colIndex = 0; colIndex < columns; ++colIndex) {
132 const int px = dstX_ + colIndex;
133 const int py = dstY_ + rowIndex;
134 if (randt.doubleRandomAt(px, py) > threshold) {
135 QColor color;
136 if (isGrayscale) {
137 const int gray = static_cast<int>(randr.doubleRandomAt(px, py) * 255);
138 color = qRgb(gray, gray, gray);
139 } else {
140 color = qRgb(static_cast<int>(randr.doubleRandomAt(px, py) * 255),
141 static_cast<int>(randg.doubleRandomAt(px, py) * 255),
142 static_cast<int>(randb.doubleRandomAt(px, py) * 255));
143 }
144 const quint32 dataOffset = colIndex * pixelSize + rowIndex * dstRowStride;
145 if (opacity == 100) {
146 colorSpace->fromQColor(color, dstIt->rawData() + dataOffset);
147 } else {
148 colorSpace->fromQColor(color, scratchPixel.data());
149 pixels[1] = dstIt->oldRawData() + dataOffset;
150 mixOp->mixColors(pixels, weights, numMixPixels, dstIt->rawData() + dataOffset);
151 }
152 }
153 }
154 }
155
156 dstX_ += columns;
157 columnsRemaining -= columns;
158 }
159
160 dstY_ += rows;
161 rowsRemaining -= rows;
162 }
163}
164
165#include "noisefilter.moc"
166
float value(const T *src, size_t ch)
@ FULLY_INDEPENDENT
virtual quint8 * rawData()=0
virtual const quint8 * oldRawData() const =0
void processImpl(KisPaintDeviceSP device, const QRect &applyRect, const KisFilterConfigurationSP config, KoUpdater *progressUpdater) const override
KisConfigWidget * createConfigurationWidget(QWidget *parent, const KisPaintDeviceSP dev, bool useForMasks) const override
KisFilterConfigurationSP defaultConfiguration(KisResourcesInterfaceSP resourcesInterface) const override
void add(KisFilterSP item)
static KisFilterRegistry * instance()
const KoColorSpace * colorSpace() const
KisRandomAccessorSP createRandomAccessorNG()
virtual qint32 rowStride(qint32 x, qint32 y) const =0
virtual qint32 numContiguousRows(qint32 y) const =0
virtual void moveTo(qint32 x, qint32 y)=0
virtual qint32 numContiguousColumns(qint32 x) const =0
bool isNull() const
virtual quint32 pixelSize() const =0
virtual void fromQColor(const QColor &color, quint8 *dst) const =0
KoMixColorsOp * mixColorsOp
virtual void mixColors(const quint8 *const *colors, const qint16 *weights, int nColors, quint8 *dst, int weightSum=255) const =0
~KritaNoiseFilter() override
KritaNoiseFilter(QObject *parent, const QVariantList &)
K_PLUGIN_FACTORY_WITH_JSON(KritaASCCDLFactory, "kritaasccdl.json", registerPlugin< KritaASCCDL >();) KritaASCCDL
const KoID FiltersCategoryOtherId("other_filters", ki18nc("The category of filters that do not fit in a category. Noun.", "Other"))
virtual KisFilterConfigurationSP factoryConfiguration(KisResourcesInterfaceSP resourcesInterface) const
void setSupportsPainting(bool v)
void setColorSpaceIndependence(ColorSpaceIndependence v)
double doubleRandomAt(qint64 x, qint64 y)