Krita Source Code Documentation
Loading...
Searching...
No Matches
threshold.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the KDE project
3 *
4 * SPDX-FileCopyrightText: 2016 Boudewijn Rempt <boud@valdyas.org>
5 *
6 * SPDX-License-Identifier: GPL-2.0-or-later
7 */
8
9#include "threshold.h"
10#include <stdlib.h>
11#include <vector>
12
13#include <QPoint>
14#include <QTime>
15
16#include <klocalizedstring.h>
17
18#include <kis_debug.h>
19#include <kpluginfactory.h>
20
23#include <kis_global.h>
24#include "KisLevelsSlider.h"
25#include "kis_histogram.h"
26#include <kis_layer.h>
27#include "kis_paint_device.h"
28#include "kis_painter.h"
30#include <kis_selection.h>
31#include <kis_types.h>
33#include <kis_signals_blocker.h>
34
37#include <KoColorSpace.h>
39#include <KoUpdater.h>
41
42K_PLUGIN_FACTORY_WITH_JSON(KritaThresholdFactory, "kritathreshold.json", registerPlugin<KritaThreshold>();)
43
44KritaThreshold::KritaThreshold(QObject *parent, const QVariantList &)
45 : QObject(parent)
46{
48}
49
53
65
67 const QRect& applyRect,
68 const KisFilterConfigurationSP config,
69 KoUpdater *progressUpdater) const
70{
71 Q_ASSERT(!device.isNull());
72
73 const int threshold = config->getInt("threshold");
74
75 KoColor white(Qt::white, device->colorSpace());
76 KoColor black(Qt::black, device->colorSpace());
77
78 KisSequentialIteratorProgress it(device, applyRect, progressUpdater);
79 const int pixelSize = device->colorSpace()->pixelSize();
80
81 while (it.nextPixel()) {
82 if (device->colorSpace()->intensity8(it.oldRawData()) > threshold) {
83 white.setOpacity(device->colorSpace()->opacityU8(it.oldRawData()));
84 memcpy(it.rawData(), white.data(), pixelSize);
85 }
86 else {
87 black.setOpacity(device->colorSpace()->opacityU8(it.oldRawData()));
88 memcpy(it.rawData(), black.data(), pixelSize);
89 }
90 }
91
92}
93
94
96{
97 KisFilterConfigurationSP config = factoryConfiguration(resourcesInterface);
98 config->setProperty("threshold", 128);
99 return config;
100}
101
103{
104 return new KisThresholdConfigWidget(parent, dev);
105}
106
108 : KisConfigWidget(parent)
109{
110 Q_ASSERT(dev);
111 m_page.setupUi(this);
112
113 m_page.thresholdGradient->setThreshold(0.5);
114 m_page.intThreshold->setValue(128);
115
116 connect(m_page.intThreshold, SIGNAL(valueChanged(int)), SIGNAL(sigConfigurationItemChanged()));
117 connect(m_page.intThreshold, QOverload<int>::of(&QSpinBox::valueChanged),
118 [this](int value)
119 {
120 KisSignalsBlocker blocker(m_page.thresholdGradient);
121 m_page.thresholdGradient->setThreshold(static_cast<qreal>(value) / 255.0);
122 }
123 );
124 connect(m_page.thresholdGradient, SIGNAL(thresholdChanged(qreal)), SIGNAL(sigConfigurationItemChanged()));
126 [this](qreal value)
127 {
128 KisSignalsBlocker blocker(m_page.intThreshold);
129 m_page.intThreshold->setValue(static_cast<int>(qRound(value * 255.0)));
130 }
131 );
132
133 connect((QObject*)(m_page.chkLogarithmic), SIGNAL(toggled(bool)), this, SLOT(slotDrawHistogram(bool)));
134
136 m_histogram.reset( new KisHistogram(dev, dev->exactBounds(), producer, LINEAR) );
137 m_histlog = false;
138 m_page.histview->resize(288,100);
140
141}
142
146
148{
149 int wHeight = m_page.histview->height();
150 int wHeightMinusOne = wHeight - 1;
151 int wWidth = m_page.histview->width();
152
153 if (m_histlog != logarithmic) {
154 // Update the m_histogram
155 if (logarithmic)
156 m_histogram->setHistogramType(LOGARITHMIC);
157 else
158 m_histogram->setHistogramType(LINEAR);
159 m_histlog = logarithmic;
160 }
161
162 QPalette appPalette = QApplication::palette();
163 QPixmap pix(wWidth-100, wHeight);
164
165 pix.fill(QColor(appPalette.color(QPalette::Base)));
166 QPainter p(&pix);
167
168 p.setPen(QPen(Qt::gray, 1, Qt::SolidLine));
169
170 double highest = (double)m_histogram->calculations().getHighest();
171 qint32 bins = m_histogram->producer()->numberOfBins();
172
173 // use nearest neighbour interpolation
174 if (m_histogram->getHistogramType() == LINEAR) {
175 double factor = (double)(wHeight - wHeight / 5.0) / highest;
176 for (int i = 0; i < wWidth; i++) {
177 int binNo = qRound((double)i / wWidth * (bins - 1));
178 if ((int)m_histogram->getValue(binNo) != 0)
179 p.drawLine(i, wHeightMinusOne, i, wHeightMinusOne - (int)m_histogram->getValue(binNo) * factor);
180 }
181 } else {
182 double factor = (double)(wHeight - wHeight / 5.0) / (double)log(highest);
183 for (int i = 0; i < wWidth; i++) {
184 int binNo = qRound((double)i / wWidth * (bins - 1)) ;
185 if ((int)m_histogram->getValue(binNo) != 0)
186 p.drawLine(i, wHeightMinusOne, i, wHeightMinusOne - log((double)m_histogram->getValue(binNo)) * factor);
187 }
188 }
189
190 m_page.histview->setPixmap(pix);
191}
192
194{
195 m_page.intThreshold->setMaximum(limit - 1);
196}
197
199{
201 config->setProperty("threshold", m_page.intThreshold->value());
202 return config;
203}
204
206{
207 QVariant value;
208 if (config->getProperty("threshold", value)) {
209 KisSignalsBlocker blocker(m_page.intThreshold, m_page.thresholdGradient);
210 m_page.intThreshold->setValue(value.toUInt());
211 m_page.thresholdGradient->setThreshold(static_cast<qreal>(value.toUInt()) / 255.0);
212 }
214}
215
216
217#include "threshold.moc"
float value(const T *src, size_t ch)
const Params2D p
@ FULLY_INDEPENDENT
connect(this, SIGNAL(optionsChanged()), this, SLOT(saveOptions()))
void sigConfigurationItemChanged()
void add(KisFilterSP item)
static KisFilterRegistry * instance()
KisConfigWidget * createConfigurationWidget(QWidget *parent, const KisPaintDeviceSP dev, bool useForMasks) const override
KisFilterConfigurationSP defaultConfiguration(KisResourcesInterfaceSP resourcesInterface) const override
Definition threshold.cpp:95
void processImpl(KisPaintDeviceSP device, const QRect &applyRect, const KisFilterConfigurationSP config, KoUpdater *progressUpdater) const override
Definition threshold.cpp:66
void setSupportsLevelOfDetail(bool value)
static KisResourcesInterfaceSP instance()
QRect exactBounds() const
const KoColorSpace * colorSpace() const
ALWAYS_INLINE quint8 * rawData()
ALWAYS_INLINE const quint8 * oldRawData() const
bool isNull() const
KisPropertiesConfigurationSP configuration() const override
void setConfiguration(const KisPropertiesConfigurationSP config) override
void slotDrawHistogram(bool logarithmic=false)
Ui::WdgThreshold m_page
Definition threshold.h:64
~KisThresholdConfigWidget() override
KisThresholdConfigWidget(QWidget *parent, KisPaintDeviceSP dev)
QScopedPointer< KisHistogram > m_histogram
Definition threshold.h:73
void thresholdChanged(qreal newThreshold)
Signal emitted when the threshold value changes.
virtual quint8 intensity8(const quint8 *src) const =0
virtual quint32 pixelSize() const =0
virtual quint8 opacityU8(const quint8 *pixel) const =0
void setOpacity(quint8 alpha)
Definition KoColor.cpp:333
quint8 * data()
Definition KoColor.h:144
~KritaThreshold() override
Definition threshold.cpp:50
KritaThreshold(QObject *parent, const QVariantList &)
Definition threshold.cpp:44
K_PLUGIN_FACTORY_WITH_JSON(KritaASCCDLFactory, "kritaasccdl.json", registerPlugin< KritaASCCDL >();) KritaASCCDL
const KoID FiltersCategoryAdjustId("adjust_filters", ki18nc("The category of color adjustment filters, like levels. Verb.", "Adjust"))
@ LOGARITHMIC
@ LINEAR
Definition nugrid.h:26
void setSupportsThreading(bool v)
void setShowConfigurationWidget(bool v)
virtual KisFilterConfigurationSP factoryConfiguration(KisResourcesInterfaceSP resourcesInterface) const
void setSupportsAdjustmentLayers(bool v)
void setSupportsPainting(bool v)
void setColorSpaceIndependence(ColorSpaceIndependence v)