[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-commits
Subject: [calligra/calligra/2.9] /: [FEATURE] Lightness curve for per-channel filter
From: Dmitry Kazakov <dimula73 () gmail ! com>
Date: 2015-05-30 22:15:24
Message-ID: E1Yyp2K-0002L5-69 () scm ! kde ! org
[Download RAW message or body]
Git commit 45d4e30d35c9e027021b1a6ff585c9687cf1de83 by Dmitry Kazakov.
Committed on 30/05/2015 at 22:04.
Pushed by dkazakov into branch 'calligra/2.9'.
[FEATURE] Lightness curve for per-channel filter
Now the curves filter can do everything:
1) Correct colors directly by editing RGB curves
2) Correct 'Lightness' using a special curve. Please
not that this is not a 'RGB' curve like in Photoshop,
it is a real Lightness curve from Lab color space.
3) Edit a curve for alpha
BUG:324332
Ref T352
M +13 -0 krita/image/kis_cubic_curve.cpp
M +2 -0 krita/image/kis_cubic_curve.h
M +17 -0 krita/image/tests/kis_cubic_curve_test.cpp
M +1 -0 krita/image/tests/kis_cubic_curve_test.h
M +1 -0 krita/plugins/filters/colorsfilters/CMakeLists.txt
M +156 -121 krita/plugins/filters/colorsfilters/kis_perchannel_filter.cpp
M +7 -1 krita/plugins/filters/colorsfilters/kis_perchannel_filter.h
A +62 -0 krita/plugins/filters/colorsfilters/virtual_channel_info.cpp \
[License: GPL (v2+)] C +25 -21 \
krita/plugins/filters/colorsfilters/virtual_channel_info.h [from: \
krita/image/tests/kis_cubic_curve_test.h - 053% similarity] M +1 -0 \
libs/pigment/CMakeLists.txt A +62 -0 \
libs/pigment/KoCompositeColorTransformation.cpp [License: GPL (v2+)] A +48 -0 \
libs/pigment/KoCompositeColorTransformation.h [License: GPL (v2+)]
http://commits.kde.org/calligra/45d4e30d35c9e027021b1a6ff585c9687cf1de83
diff --git a/krita/image/kis_cubic_curve.cpp b/krita/image/kis_cubic_curve.cpp
index c19381b..8924eb7 100644
--- a/krita/image/kis_cubic_curve.cpp
+++ b/krita/image/kis_cubic_curve.cpp
@@ -406,6 +406,19 @@ void KisCubicCurve::removePoint(int idx)
d->data->invalidate();
}
+bool KisCubicCurve::isNull() const
+{
+ const QList<QPointF> &points = d->data->points;
+
+ foreach (const QPointF &pt, points) {
+ if (!qFuzzyCompare(pt.x(), pt.y())) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
const QString& KisCubicCurve::name() const
{
return d->data->name;
diff --git a/krita/image/kis_cubic_curve.h b/krita/image/kis_cubic_curve.h
index 1eb9371..77351dc 100644
--- a/krita/image/kis_cubic_curve.h
+++ b/krita/image/kis_cubic_curve.h
@@ -54,6 +54,8 @@ public:
int addPoint(const QPointF& point);
void removePoint(int idx);
+ bool isNull() const;
+
/**
* This allows us to carry around a display name for the curve internally. It is \
used
* currently in Sketch for perchannel, but would potentially be useful anywhere
diff --git a/krita/image/tests/kis_cubic_curve_test.cpp \
b/krita/image/tests/kis_cubic_curve_test.cpp index e934768..27f2a0e 100644
--- a/krita/image/tests/kis_cubic_curve_test.cpp
+++ b/krita/image/tests/kis_cubic_curve_test.cpp
@@ -139,6 +139,23 @@ void KisCubicCurveTest::testValue()
}
}
+void KisCubicCurveTest::testNull()
+{
+ KisCubicCurve cc;
+ QVERIFY(cc.isNull());
+
+ cc.addPoint(QPointF(0.2, 0.3));
+ QVERIFY(!cc.isNull());
+
+ QList<QPointF> points;
+ points << QPointF();
+ points << QPointF(0.2,0.2);
+ points << QPointF(1.0,1.0);
+
+ cc.setPoints(points);
+ QVERIFY(cc.isNull());
+}
+
void KisCubicCurveTest::testTransfer()
{
diff --git a/krita/image/tests/kis_cubic_curve_test.h \
b/krita/image/tests/kis_cubic_curve_test.h index 60ffaff..28c0385 100644
--- a/krita/image/tests/kis_cubic_curve_test.h
+++ b/krita/image/tests/kis_cubic_curve_test.h
@@ -36,6 +36,7 @@ private Q_SLOTS:
void testComparison();
void testSerialization();
void testValue();
+ void testNull();
void testTransfer();
private:
QPointF pt0, pt1, pt2, pt3, pt4, pt5;
diff --git a/krita/plugins/filters/colorsfilters/CMakeLists.txt \
b/krita/plugins/filters/colorsfilters/CMakeLists.txt index 4062dbe..d6024a6 100644
--- a/krita/plugins/filters/colorsfilters/CMakeLists.txt
+++ b/krita/plugins/filters/colorsfilters/CMakeLists.txt
@@ -3,6 +3,7 @@
set(kritacolorsfilters_PART_SRCS
colorsfilters.cpp
kis_hsv_adjustment_filter.cpp
+ virtual_channel_info.cpp
kis_perchannel_filter.cpp
kis_brightness_contrast_filter.cpp
kis_color_balance_filter.cpp
diff --git a/krita/plugins/filters/colorsfilters/kis_perchannel_filter.cpp \
b/krita/plugins/filters/colorsfilters/kis_perchannel_filter.cpp index \
55cfae9..6bdc828 100644
--- a/krita/plugins/filters/colorsfilters/kis_perchannel_filter.cpp
+++ b/krita/plugins/filters/colorsfilters/kis_perchannel_filter.cpp
@@ -33,9 +33,12 @@
#include "KoBasicHistogramProducers.h"
#include "KoColorSpace.h"
#include "KoColorTransformation.h"
+#include "KoCompositeColorTransformation.h"
#include "KoCompositeOp.h"
#include "KoID.h"
+#include "kis_signals_blocker.h"
+
#include "kis_bookmarked_configuration_manager.h"
#include "kis_config_widget.h"
#include <filter/kis_filter_configuration.h>
@@ -47,7 +50,22 @@
#include "kis_painter.h"
#include "widgets/kis_curve_widget.h"
+QVector<VirtualChannelInfo> getVirtualChannels(const KoColorSpace *cs)
+{
+ QVector<VirtualChannelInfo> vchannels;
+
+ QList<KoChannelInfo *> sortedChannels =
+ KoChannelInfo::displayOrderSorted(cs->channels());
+
+ vchannels << VirtualChannelInfo(VirtualChannelInfo::LIGHTNESS, -1, 0);
+
+ foreach(KoChannelInfo *channel, sortedChannels) {
+ int pixelIndex = \
KoChannelInfo::displayPositionToChannelIndex(channel->displayPosition(), \
sortedChannels); + vchannels << VirtualChannelInfo(VirtualChannelInfo::REAL, \
pixelIndex, channel); + }
+ return vchannels;
+}
KisPerChannelConfigWidget::KisPerChannelConfigWidget(QWidget * parent, \
KisPaintDeviceSP dev, Qt::WFlags f) : KisConfigWidget(parent, f), m_histogram(0)
@@ -61,27 +79,22 @@ KisPerChannelConfigWidget::KisPerChannelConfigWidget(QWidget * \
parent, KisPaintD layout->addWidget(m_page);
m_dev = dev;
- m_activeCh = 0;
+ m_activeVChannel = 0;
+
+ // fill in the channel chooser, in the display order, but store the pixel index \
as well. +
+ m_virtualChannels = getVirtualChannels(dev->colorSpace());
+ const int virtualChannelCount = m_virtualChannels.size();
KisPerChannelFilterConfiguration::initDefaultCurves(m_curves,
- m_dev->colorSpace()->channelCount());
+ virtualChannelCount);
+ for (int i = 0; i < virtualChannelCount; i++) {
+ const VirtualChannelInfo &info = m_virtualChannels[i];
- QList<KoChannelInfo *> colorChannels;
- foreach(KoChannelInfo *channel, dev->colorSpace()->channels()) {
- if (channel->channelType() == KoChannelInfo::COLOR || channel->channelType() \
== KoChannelInfo::ALPHA) {
- colorChannels.append(channel);
- }
- }
- // fill in the channel chooser, in the display order, but store the pixel index \
as well.
- QList<KoChannelInfo *> sortedChannels = \
KoChannelInfo::displayOrderSorted(colorChannels);
- foreach(KoChannelInfo *channel, sortedChannels) {
- QVariant pixelIndex(KoChannelInfo::displayPositionToChannelIndex(channel->displayPosition(), \
- \
KoChannelInfo::displayOrderSorted(dev->colorSpace()->channels())));
- m_page->cmbChannel->addItem(channel->name(), pixelIndex);
- KisCubicCurve curve = m_curves[m_page->cmbChannel->count() - 1];
- curve.setName(channel->name());
- m_curves[m_page->cmbChannel->count() - 1] = curve;
+ m_page->cmbChannel->addItem(info.name(), info.pixelIndex());
+ m_curves[i].setName(info.name());
}
+
connect(m_page->cmbChannel, SIGNAL(activated(int)), this, \
SLOT(setActiveChannel(int)));
// create the horizontal and vertical gradient labels
@@ -91,7 +104,7 @@ KisPerChannelConfigWidget::KisPerChannelConfigWidget(QWidget * \
parent, KisPaintD // init histogram calculator
QList<QString> keys =
KoHistogramProducerFactoryRegistry::instance()->keysCompatibleWith(m_dev->colorSpace());
-
+
if(keys.size() > 0) {
KoHistogramProducerFactory *hpf;
hpf = KoHistogramProducerFactoryRegistry::instance()->get(keys.at(0));
@@ -102,10 +115,11 @@ KisPerChannelConfigWidget::KisPerChannelConfigWidget(QWidget * \
parent, KisPaintD
m_page->curveWidget->setupInOutControls(m_page->intIn, m_page->intOut, 0, 100);
- m_page->curveWidget->blockSignals(true);
- m_page->curveWidget->setCurve(m_curves[0]);
- setActiveChannel(0);
- m_page->curveWidget->blockSignals(false);
+ {
+ KisSignalsBlocker b(m_page->curveWidget);
+ m_page->curveWidget->setCurve(m_curves[0]);
+ setActiveChannel(0);
+ }
}
KisPerChannelConfigWidget::~KisPerChannelConfigWidget()
@@ -147,9 +161,11 @@ inline QPixmap KisPerChannelConfigWidget::getHistogram()
QPainter p(&pix);
p.setPen(QPen(Qt::gray, 1, Qt::SolidLine));
- if(m_histogram)
+ const VirtualChannelInfo &info = m_virtualChannels[m_activeVChannel];
+
+ if (m_histogram && info.type() == VirtualChannelInfo::REAL)
{
- m_histogram->setChannel(m_activeCh);
+ m_histogram->setChannel(info.pixelIndex());
double highest = (double)m_histogram->calculations().getHighest();
qint32 bins = m_histogram->producer()->numberOfBins();
@@ -174,22 +190,27 @@ inline QPixmap KisPerChannelConfigWidget::getHistogram()
void KisPerChannelConfigWidget::setActiveChannel(int ch)
{
- m_curves[m_activeCh] = m_page->curveWidget->curve();
- m_activeCh = ch;
- m_page->curveWidget->setCurve(m_curves[m_activeCh]);
+ m_curves[m_activeVChannel] = m_page->curveWidget->curve();
+
+ m_activeVChannel = ch;
+ m_page->curveWidget->setCurve(m_curves[m_activeVChannel]);
m_page->curveWidget->setPixmap(getHistogram());
- m_page->cmbChannel->setCurrentIndex(ch);
+ m_page->cmbChannel->setCurrentIndex(m_activeVChannel);
+
// Getting range accepted by channel
- KoChannelInfo *channel = m_dev->colorSpace()->channels()[m_activeCh];
- int order = BITS_PER_BYTE * channel->size();
+ VirtualChannelInfo ¤tVChannel = m_virtualChannels[m_activeVChannel];
+
+ KoChannelInfo::enumChannelValueType valueType = currentVChannel.valueType();
+
+ int order = BITS_PER_BYTE * currentVChannel.channelSize();
int maxValue = pwr2(order);
int min;
int max;
m_page->curveWidget->dropInOutControls();
- switch (channel->channelValueType()) {
+ switch (valueType) {
case KoChannelInfo::UINT8:
case KoChannelInfo::UINT16:
case KoChannelInfo::UINT32:
@@ -223,13 +244,12 @@ void KisPerChannelConfigWidget::setActiveChannel(int ch)
KisPropertiesConfiguration * KisPerChannelConfigWidget::configuration() const
{
- int nCh = m_dev->colorSpace()->channelCount();
- KisPerChannelFilterConfiguration * cfg = new \
KisPerChannelFilterConfiguration(nCh); + int numChannels = \
m_virtualChannels.size(); + KisPerChannelFilterConfiguration * cfg = new \
KisPerChannelFilterConfiguration(numChannels);
- // updating current state
- if (m_activeCh < m_curves.size()) {
- m_curves[m_activeCh] = m_page->curveWidget->curve();
- }
+ KIS_ASSERT_RECOVER(m_activeVChannel < m_curves.size()) { return cfg; }
+
+ m_curves[m_activeVChannel] = m_page->curveWidget->curve();
cfg->setCurves(m_curves);
return cfg;
@@ -245,36 +265,31 @@ void KisPerChannelConfigWidget::setConfiguration(const \
KisPropertiesConfiguratio /**
* HACK ALERT: our configuration factory generates
* default configuration with nTransfers==0.
- * Catching it here.
+ * Catching it here. Just reset all the transfers.
*/
+ const int virtualChannelCount = m_virtualChannels.size();
KisPerChannelFilterConfiguration::initDefaultCurves(m_curves,
- m_dev->colorSpace()->channelCount());
+ virtualChannelCount);
- // Getting the names of the color channels {
- QList<KoChannelInfo *> colorChannels;
- foreach(KoChannelInfo *channel, m_dev->colorSpace()->channels()) {
- if (channel->channelType() == KoChannelInfo::COLOR || \
channel->channelType() == KoChannelInfo::ALPHA) {
- colorChannels.append(channel);
- }
+ for (int i = 0; i < virtualChannelCount; i++) {
+ const VirtualChannelInfo &info = m_virtualChannels[i];
+ m_curves[i].setName(info.name());
}
- // Get the channel information, but listed in display order
- QList<KoChannelInfo *> sortedChannels = \
KoChannelInfo::displayOrderSorted(colorChannels);
- int i = 0;
- foreach(KoChannelInfo *channel, sortedChannels) {
- KisCubicCurve curve = m_curves[i];
- curve.setName(channel->name());
- m_curves[i++] = curve;
- }
- // } Getting the names of the color channels
- } else if (cfg->curves().size() != int(m_dev->colorSpace()->channelCount())) {
+
+ } else if (cfg->curves().size() != int(m_virtualChannels.size())) {
+ qWarning() << "WARNING: trying to load a curve with incorrect number of \
channels!"; + qWarning() << "WARNING: expected:" << \
m_virtualChannels.size(); + qWarning() << "WARNING: got:" << \
cfg->curves().size(); return;
} else {
for (int ch = 0; ch < cfg->curves().size(); ch++)
m_curves[ch] = cfg->curves()[ch];
}
- m_page->curveWidget->setCurve(m_curves[m_activeCh]);
+ // HACK: we save the previous curve in setActiveChannel, so just copy it
+ m_page->curveWidget->setCurve(m_curves[m_activeVChannel]);
+
setActiveChannel(0);
}
@@ -350,8 +365,6 @@ void KisPerChannelFilterConfiguration::fromXML(const QDomElement& \
root) while (!e.isNull()) {
if ((attributeName = e.attribute("name")) == "nTransfers") {
numTransfers = e.text().toUShort();
- } else if ((attributeName = e.attribute("name")) == "nTransfersWithAlpha") {
- numTransfers = e.text().toUShort();
} else {
QRegExp rx("curve(\\d+)");
if (rx.indexIn(attributeName, 0) != -1) {
@@ -364,25 +377,10 @@ void KisPerChannelFilterConfiguration::fromXML(const \
QDomElement& root) }
curves.insert(index, curve);
}
- QRegExp rxAlphaCurve("alphaCurve");
- if (rxAlphaCurve.indexIn(attributeName, 0) != -1) {
- index = curves.count() + 1;
-
- if (!e.text().isEmpty()) {
- curve.fromString(e.text());
- }
- curves.insert(index,curve);
- }
}
e = e.nextSiblingElement();
}
- curve.fromString("0,0;1,1");
- if(numTransfers == 3) {
- numTransfers++;
- curves.insert(index + 1, curve);
- }
-
if (!numTransfers)
return;
@@ -395,66 +393,45 @@ void KisPerChannelFilterConfiguration::fromXML(const \
QDomElement& root)
*/
//void KisPerChannelFilterConfiguration::fromXML(const QString& s)
+void addParamNode(QDomDocument& doc,
+ QDomElement& root,
+ const QString &name,
+ const QString &value)
+{
+ QDomText text = doc.createTextNode(value);
+ QDomElement t = doc.createElement("param");
+ t.setAttribute("name", name);
+ t.appendChild(text);
+ root.appendChild(t);
+}
+
void KisPerChannelFilterConfiguration::toXML(QDomDocument& doc, QDomElement& root) \
const {
/**
* <params version=1>
* <param name="nTransfers">3</param>
- * <param name="nTransfersWithAlpha">4</param>
* <param name="curve0">0,0;0.5,0.5;1,1;</param>
* <param name="curve1">0,0;1,1;</param>
* <param name="curve2">0,0;1,1;</param>
- * <param name="alphaCurve">0,0;1,1;</param>
- * <!-- for the future
- * <param name="commonCurve">0,0;1,1;</param>
- * -->
* </params>
*/
root.setAttribute("version", version());
- QDomElement t = doc.createElement("param");
- QDomText text, textAlpha;
- if(m_curves.size() == 4) {
- text = doc.createTextNode(QString::number(m_curves.size()-1));
- textAlpha = doc.createTextNode(QString::number(m_curves.size()));
- }
- else {
- text = doc.createTextNode(QString::number(m_curves.size()));
- textAlpha = doc.createTextNode(QString::number(m_curves.size()));
- }
+ QDomText text;
+ QDomElement t;
- t.setAttribute("name", "nTransfers");
- t.appendChild(text);
- root.appendChild(t);
-
- t = doc.createElement("param");
- t.setAttribute("name", "nTransfersWithAlpha");
- t.appendChild(textAlpha);
- root.appendChild(t);
+ addParamNode(doc, root, "nTransfers", QString::number(m_curves.size()));
KisCubicCurve curve;
QString paramName;
- for (int i = 0; i < m_curves.size() - 1; ++i) {
- paramName = QLatin1String("curve") + QString::number(i);
- t = doc.createElement("param");
- t.setAttribute("name", paramName);
+ for (int i = 0; i < m_curves.size(); ++i) {
+ QString name = QLatin1String("curve") + QString::number(i);
+ QString value = m_curves[i].toString();
- curve = m_curves[i];
- text = doc.createTextNode(curve.toString());
- t.appendChild(text);
- root.appendChild(t);
+ addParamNode(doc, root, name, value);
}
-
- paramName = QLatin1String("alphaCurve");
- t = doc.createElement("param");
- t.setAttribute("name", paramName);
-
- curve = m_curves[m_curves.size()-1];
- text = doc.createTextNode(curve.toString());
- t.appendChild(text);
- root.appendChild(t);
}
/**
@@ -485,21 +462,79 @@ KoColorTransformation* \
KisPerChannelFilter::createTransformation(const KoColorSp
dynamic_cast<const KisPerChannelFilterConfiguration*>(config); // Somehow, \
this shouldn't happen Q_ASSERT(configBC);
- const QVector<QVector<quint16> > &originalTransfers =
- configBC->transfers();
+ const QVector<QVector<quint16> > &originalTransfers = configBC->transfers();
+ const QList<KisCubicCurve> &originalCurves = configBC->curves();
+
+ /**
+ * TODO: What about the order of channels? (DK)
+ *
+ * Virtual channels are sorted in display order, does Lcms accepts
+ * transforms in display order? Why on Earth it works?! Is it
+ * documented anywhere?
+ */
+ const QVector<VirtualChannelInfo> virtualChannels = getVirtualChannels(cs);
- if (originalTransfers.size() != int(cs->channelCount())) {
- // We got an illegal number of colorchannels.KisFilter
+ if (originalTransfers.size() != int(virtualChannels.size())) {
+ // We got an illegal number of colorchannels :(
return 0;
}
+ bool colorsNull = true;
+ bool lightnessNull = true;
+
+ QVector<QVector<quint16> > realTransfers;
+ QVector<quint16> lightnessTansfer;
+ for (int i = 0; i < virtualChannels.size(); i++) {
+ if (virtualChannels[i].type() == VirtualChannelInfo::REAL) {
+ realTransfers << originalTransfers[i];
+ if (colorsNull && !originalCurves[i].isNull()) {
+ colorsNull = false;
+ }
+ } else if (virtualChannels[i].type() == VirtualChannelInfo::LIGHTNESS) {
+ KIS_ASSERT_RECOVER_NOOP(lightnessTansfer.isEmpty());
+ lightnessTansfer = originalTransfers[i];
+
+ if (lightnessNull && !originalCurves[i].isNull()) {
+ lightnessNull = false;
+ }
+ }
+ }
+
const quint16** transfers = new const quint16*[configBC->curves().size()];
- for(int i = 0; i < originalTransfers.size(); ++i) {
- transfers[i] = originalTransfers[i].constData();
+ for(int i = 0; i < realTransfers.size(); ++i) {
+ transfers[i] = realTransfers[i].constData();
}
- KoColorTransformation* t = cs->createPerChannelAdjustment(transfers);
+
+ KoColorTransformation *lightnessTransform = 0;
+ KoColorTransformation *colorTransform = 0;
+
+ if (!colorsNull) {
+ colorTransform = cs->createPerChannelAdjustment(transfers);
+ }
+
+ if (!lightnessNull) {
+ lightnessTransform = \
cs->createBrightnessContrastAdjustment(lightnessTansfer.constData()); + }
+
+ KoColorTransformation *finalTransform = 0;
+
+ if (colorTransform && lightnessTransform) {
+ KoCompositeColorTransformation *compositeTransform =
+ new KoCompositeColorTransformation(
+ KoCompositeColorTransformation::INPLACE);
+
+ compositeTransform->appendTransform(colorTransform);
+ compositeTransform->appendTransform(lightnessTransform);
+
+ finalTransform = compositeTransform;
+ } else if (lightnessTransform) {
+ finalTransform = lightnessTransform;
+ } else if (colorTransform) {
+ finalTransform = colorTransform;
+ }
+
delete [] transfers;
- return t;
+ return finalTransform;
}
#include "kis_perchannel_filter.moc"
diff --git a/krita/plugins/filters/colorsfilters/kis_perchannel_filter.h \
b/krita/plugins/filters/colorsfilters/kis_perchannel_filter.h index 2aa03a0..6b53075 \
100644
--- a/krita/plugins/filters/colorsfilters/kis_perchannel_filter.h
+++ b/krita/plugins/filters/colorsfilters/kis_perchannel_filter.h
@@ -30,6 +30,9 @@
#include <kis_paint_device.h>
#include "ui_wdg_perchannel.h"
+#include "virtual_channel_info.h"
+
+
class WdgPerChannel : public QWidget, public Ui::WdgPerChannel
{
Q_OBJECT
@@ -108,6 +111,10 @@ private Q_SLOTS:
private:
+ QVector<VirtualChannelInfo> m_virtualChannels;
+ int m_activeVChannel;
+
+
// private routines
inline QPixmap getHistogram();
inline QPixmap createGradient(Qt::Orientation orient /*, int invert (not used \
now) */); @@ -117,7 +124,6 @@ private:
KisPaintDeviceSP m_dev;
KisHistogram *m_histogram;
mutable QList<KisCubicCurve> m_curves;
- int m_activeCh;
// scales for displaying color numbers
double m_scale;
diff --git a/krita/plugins/filters/colorsfilters/virtual_channel_info.cpp \
b/krita/plugins/filters/colorsfilters/virtual_channel_info.cpp new file mode 100644
index 0000000..aae5806
--- /dev/null
+++ b/krita/plugins/filters/colorsfilters/virtual_channel_info.cpp
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2015 Dmitry Kazakov <dimula73@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "virtual_channel_info.h"
+#include <klocale.h>
+
+
+
+VirtualChannelInfo::VirtualChannelInfo()
+ : m_type(LIGHTNESS),
+ m_pixelIndex(-1),
+ m_realChannelInfo(0)
+{
+}
+
+VirtualChannelInfo::VirtualChannelInfo(Type type,
+ int pixelIndex,
+ KoChannelInfo *realChannelInfo)
+ : m_type(type),
+ m_pixelIndex(pixelIndex),
+ m_realChannelInfo(realChannelInfo)
+{
+}
+
+VirtualChannelInfo::Type VirtualChannelInfo::type() const {
+ return m_type;
+}
+
+KoChannelInfo* VirtualChannelInfo::channelInfo() const {
+ return m_realChannelInfo;
+}
+
+QString VirtualChannelInfo::name() const {
+ return m_type == REAL ? m_realChannelInfo->name() : i18n("Lightness");
+}
+
+int VirtualChannelInfo::pixelIndex() const {
+ return m_pixelIndex;
+}
+
+KoChannelInfo::enumChannelValueType VirtualChannelInfo::valueType() const {
+ return m_type == REAL ? m_realChannelInfo->channelValueType() : \
KoChannelInfo::FLOAT32; +}
+
+int VirtualChannelInfo::channelSize() const {
+ return m_type == REAL ? m_realChannelInfo->size() : 4;
+}
diff --git a/krita/image/tests/kis_cubic_curve_test.h \
b/krita/plugins/filters/colorsfilters/virtual_channel_info.h similarity index 53%
copy from krita/image/tests/kis_cubic_curve_test.h
copy to krita/plugins/filters/colorsfilters/virtual_channel_info.h
index 60ffaff..9af3ab5 100644
--- a/krita/image/tests/kis_cubic_curve_test.h
+++ b/krita/plugins/filters/colorsfilters/virtual_channel_info.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010 Cyrille Berger <cberger@cberger.net>
+ * Copyright (c) 2015 Dmitry Kazakov <dimula73@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -16,30 +16,34 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#ifndef _KIS_CUBIC_CURVE_TEST_H_
-#define _KIS_CUBIC_CURVE_TEST_H_
+#ifndef __VIRTUAL_CHANNEL_INFO_H
+#define __VIRTUAL_CHANNEL_INFO_H
-#include <QtTest>
+#include <KoChannelInfo.h>
-#include <QPointF>
-
-class KisCubicCurveTest : public QObject
+class VirtualChannelInfo
{
- Q_OBJECT
public:
- KisCubicCurveTest();
-private Q_SLOTS:
-
- void testCreation();
- void testCopy();
- void testEdition();
- void testComparison();
- void testSerialization();
- void testValue();
- void testTransfer();
+ enum Type {
+ REAL,
+ LIGHTNESS
+ };
+
+ VirtualChannelInfo();
+
+ VirtualChannelInfo(Type type, int pixelIndex, KoChannelInfo *realChannelInfo);
+
+ Type type() const;
+ KoChannelInfo* channelInfo() const;
+ QString name() const;
+ int pixelIndex() const;
+ KoChannelInfo::enumChannelValueType valueType() const;
+ int channelSize() const;
+
private:
- QPointF pt0, pt1, pt2, pt3, pt4, pt5;
+ Type m_type;
+ int m_pixelIndex;
+ KoChannelInfo *m_realChannelInfo;
};
-
-#endif
+#endif /* __VIRTUAL_CHANNEL_INFO_H */
diff --git a/libs/pigment/CMakeLists.txt b/libs/pigment/CMakeLists.txt
index ae6651b..4f54815 100644
--- a/libs/pigment/CMakeLists.txt
+++ b/libs/pigment/CMakeLists.txt
@@ -52,6 +52,7 @@ set(pigmentcms_SRCS
KoColorTransformation.cpp
KoColorTransformationFactory.cpp
KoColorTransformationFactoryRegistry.cpp
+ KoCompositeColorTransformation.cpp
KoCompositeOp.cpp
KoCompositeOpRegistry.cpp
KoCopyColorConversionTransformation.cpp
diff --git a/libs/pigment/KoCompositeColorTransformation.cpp \
b/libs/pigment/KoCompositeColorTransformation.cpp new file mode 100644
index 0000000..2de2ecf
--- /dev/null
+++ b/libs/pigment/KoCompositeColorTransformation.cpp
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2015 Dmitry Kazakov <dimula73@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "KoCompositeColorTransformation.h"
+
+#include <QVector>
+
+
+struct KoCompositeColorTransformation::Private
+{
+ ~Private() {
+ qDeleteAll(transformations);
+ }
+
+ QVector<KoColorTransformation*> transformations;
+};
+
+
+KoCompositeColorTransformation::KoCompositeColorTransformation(Mode mode)
+ : m_d(new Private)
+{
+ Q_ASSERT_X(mode == INPLACE, "KoCompositeColorTransformation", "BUFFERED mode is \
not implemented yet!"); +}
+
+KoCompositeColorTransformation::~KoCompositeColorTransformation()
+{
+}
+
+void KoCompositeColorTransformation::appendTransform(KoColorTransformation \
*transform) +{
+ m_d->transformations.append(transform);
+}
+
+void KoCompositeColorTransformation::transform(const quint8 *src, quint8 *dst, \
qint32 nPixels) const +{
+ QVector<KoColorTransformation*>::const_iterator begin = \
m_d->transformations.begin(); + QVector<KoColorTransformation*>::const_iterator it \
= begin; + QVector<KoColorTransformation*>::const_iterator end = \
m_d->transformations.end(); +
+ for (; it != end; ++it) {
+ if (it == begin) {
+ (*it)->transform(src, dst, nPixels);
+ } else {
+ (*it)->transform(dst, dst, nPixels);
+ }
+ }
+}
diff --git a/libs/pigment/KoCompositeColorTransformation.h \
b/libs/pigment/KoCompositeColorTransformation.h new file mode 100644
index 0000000..1c4bf28
--- /dev/null
+++ b/libs/pigment/KoCompositeColorTransformation.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2015 Dmitry Kazakov <dimula73@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __KO_COMPOSITE_COLOR_TRANSFORMATION_H
+#define __KO_COMPOSITE_COLOR_TRANSFORMATION_H
+
+#include "KoColorTransformation.h"
+
+#include <QScopedPointer>
+
+
+class PIGMENTCMS_EXPORT KoCompositeColorTransformation : public \
KoColorTransformation +{
+public:
+ enum Mode {
+ INPLACE = 0, /// transform pixels in place (in 'dst' buffer)
+ BUFFERED /// transform using a temporary buffer (not implemented yet)
+ };
+
+public:
+ KoCompositeColorTransformation(Mode mode);
+ ~KoCompositeColorTransformation();
+
+ void appendTransform(KoColorTransformation *transform);
+
+ void transform(const quint8 *src, quint8 *dst, qint32 nPixels) const;
+
+private:
+ struct Private;
+ const QScopedPointer<Private> m_d;
+};
+
+#endif /* __KO_COMPOSITE_COLOR_TRANSFORMATION_H */
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic