[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-kimageshop
Subject:    [krita/krita/3.3] plugins/filters: [Feature] ASC-CDL color balance filter(Slope, Offset, Power)
From:       Boudewijn Rempt <null () kde ! org>
Date:       2017-10-14 8:59:36
Message-ID: E1e3IIC-0006Xj-UH () code ! kde ! org
[Download RAW message or body]

Git commit 3f81a96dc7d5b95ba4cc3c9b1eb647fb630a92dd by Boudewijn Rempt, on behalf of \
Wolthera van Hövell tot Westerflier. Committed on 14/10/2017 at 08:39.
Pushed by rempt into branch 'krita/3.3'.

[Feature] ASC-CDL color balance filter(Slope, Offset, Power)

This is a simple color balance filter as decided by the American
Society of Cinematographers. It's purpose is to make communicating color
balance easier over different applications.

It is also interesting in that it is so simple it does not clip high-bit depth
values.

There's still some issues with the filter, but they are mostly GUI issues,
so I am pushing this to prevent bitrot. I have noted the possible list of
improvements in the header of the widget class.

BUG:355747
Differential revision: https://phabricator.kde.org/D8184
CCMAIL:kimageshop@kde.org

M  +1    -0    plugins/filters/CMakeLists.txt
A  +11   -0    plugins/filters/asccdl/CMakeLists.txt
A  +127  -0    plugins/filters/asccdl/kis_asccdl_filter.cpp     [License: GPL (v2+)]
A  +61   -0    plugins/filters/asccdl/kis_asccdl_filter.h     [License: GPL (v2+)]
A  +103  -0    plugins/filters/asccdl/kis_wdg_asccdl.cpp     [License: GPL (v2+)]
A  +62   -0    plugins/filters/asccdl/kis_wdg_asccdl.h     [License: GPL (v2+)]
A  +9    -0    plugins/filters/asccdl/kritaasccdl.json
A  +105  -0    plugins/filters/asccdl/wdg_asccdl.ui

https://commits.kde.org/krita/3f81a96dc7d5b95ba4cc3c9b1eb647fb630a92dd

diff --git a/plugins/filters/CMakeLists.txt b/plugins/filters/CMakeLists.txt
index 8454461ca98..6faf7d54aba 100644
--- a/plugins/filters/CMakeLists.txt
+++ b/plugins/filters/CMakeLists.txt
@@ -26,3 +26,4 @@ add_subdirectory( normalize )
 add_subdirectory( gradientmap )
 add_subdirectory( threshold )
 add_subdirectory( halftone )
+add_subdirectory( asccdl )
diff --git a/plugins/filters/asccdl/CMakeLists.txt \
b/plugins/filters/asccdl/CMakeLists.txt new file mode 100644
index 00000000000..94a0aaeaa23
--- /dev/null
+++ b/plugins/filters/asccdl/CMakeLists.txt
@@ -0,0 +1,11 @@
+set(kritaasccdl_SOURCES
+    kis_asccdl_filter.cpp
+    kis_wdg_asccdl.cpp
+)
+
+ki18n_wrap_ui(kritaasccdl_SOURCES
+    wdg_asccdl.ui
+    )
+add_library(kritaasccdl MODULE ${kritaasccdl_SOURCES})
+target_link_libraries(kritaasccdl kritaui)
+install(TARGETS kritaasccdl  DESTINATION ${KRITA_PLUGIN_INSTALL_DIR})
diff --git a/plugins/filters/asccdl/kis_asccdl_filter.cpp \
b/plugins/filters/asccdl/kis_asccdl_filter.cpp new file mode 100644
index 00000000000..08df10514cc
--- /dev/null
+++ b/plugins/filters/asccdl/kis_asccdl_filter.cpp
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2017 Wolthera van Hövell tot Westerflier <griffinvalley@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 "kis_asccdl_filter.h"
+#include "kis_wdg_asccdl.h"
+#include <kpluginfactory.h>
+#include <klocalizedstring.h>
+#include <filter/kis_filter_registry.h>
+#include <filter/kis_color_transformation_configuration.h>
+#include <qmath.h>
+
+K_PLUGIN_FACTORY_WITH_JSON(KritaASCCDLFactory,
+                           "kritaasccdl.json",
+                           registerPlugin<KritaASCCDL>();)
+
+
+KritaASCCDL::KritaASCCDL(QObject *parent, const QVariantList &) : QObject(parent)
+{
+    KisFilterRegistry::instance()->add(KisFilterSP(new KisFilterASCCDL()));
+}
+
+KritaASCCDL::~KritaASCCDL()
+{
+
+}
+
+KisFilterASCCDL::KisFilterASCCDL(): KisColorTransformationFilter(id(), \
categoryAdjust(), i18n("&Slope, Offset, Power..")) +{
+    setSupportsPainting(true);
+    setSupportsAdjustmentLayers(true);
+    setSupportsLevelOfDetail(true);
+    setSupportsThreading(true);
+    setColorSpaceIndependence(FULLY_INDEPENDENT);
+    setShowConfigurationWidget(true);
+}
+
+KoColorTransformation *KisFilterASCCDL::createTransformation(const KoColorSpace *cs,
+                                                             const \
KisFilterConfigurationSP config) const +{
+    KoColor black(Qt::black, cs);
+    return new KisASCCDLTransformation(cs,
+                                       config->getColor("slope", black),
+                                       config->getColor("offset", black),
+                                       config->getColor("power", black));
+}
+
+KisConfigWidget *KisFilterASCCDL::createConfigurationWidget(QWidget *parent, const \
KisPaintDeviceSP dev) const +{
+    return new KisASCCDLConfigWidget(parent, dev->colorSpace());
+}
+
+bool KisFilterASCCDL::needsTransparentPixels(const KisFilterConfigurationSP config, \
const KoColorSpace *cs) const +{
+    KoColor black(Qt::black, cs);
+    KoColor offset = config->getColor("offset", black);
+    offset.convertTo(cs);
+    if (cs->difference(black.data(), offset.data())>0) {
+        return true;
+    }
+    return false;
+}
+
+KisFilterConfigurationSP KisFilterASCCDL::factoryConfiguration() const
+{
+    KisColorTransformationConfigurationSP config = new \
KisColorTransformationConfiguration(id().id(), 0); +    QVariant \
colorVariant("KoColor"); +    KoColor black;
+    black.fromQColor(QColor(Qt::black));
+    KoColor white;
+    white.fromQColor(QColor(Qt::white));
+    colorVariant.setValue(white);
+    config->setProperty( "slope", colorVariant);
+    config->setProperty( "power", colorVariant);
+    colorVariant.setValue(black);
+    config->setProperty("offset", colorVariant);
+    return config;
+}
+
+KisASCCDLTransformation::KisASCCDLTransformation(const KoColorSpace *cs, KoColor \
slope, KoColor offset, KoColor power) +{
+    QVector<float> slopeN(cs->channelCount());
+    slope.convertTo(cs);
+    slope.colorSpace()->normalisedChannelsValue(slope.data(), slopeN);
+    m_slope = slopeN;
+    offset.convertTo(cs);
+    QVector<float> offsetN(cs->channelCount());
+    offset.colorSpace()->normalisedChannelsValue(offset.data(), offsetN);
+    m_offset = offsetN;
+    power.convertTo(cs);
+    QVector<float> powerN(cs->channelCount());
+    power.colorSpace()->normalisedChannelsValue(power.data(), powerN);
+    m_power = powerN;
+    m_cs = cs;
+}
+
+void KisASCCDLTransformation::transform(const quint8 *src, quint8 *dst, qint32 \
nPixels) const +{
+    QVector<float> normalised(m_cs->channelCount());
+    const int pixelSize = m_cs->pixelSize();
+    while (nPixels--) {
+        m_cs->normalisedChannelsValue(src, normalised);
+
+        for (int c=0; c<m_cs->channelCount(); c++){
+            normalised[c] = qPow( (normalised.at(c)*m_slope.at(c))+m_offset.at(c), \
m_power.at(c)); +        }
+        m_cs->fromNormalisedChannelsValue(dst, normalised);
+        src += pixelSize;
+        dst += pixelSize;
+    }
+}
+
+#include "kis_asccdl_filter.moc"
diff --git a/plugins/filters/asccdl/kis_asccdl_filter.h \
b/plugins/filters/asccdl/kis_asccdl_filter.h new file mode 100644
index 00000000000..50c38efecc0
--- /dev/null
+++ b/plugins/filters/asccdl/kis_asccdl_filter.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2017 Wolthera van Hövell tot Westerflier <griffinvalley@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 KIS_ASCCDL_FILTER_H
+#define KIS_ASCCDL_FILTER_H
+
+#include <filter/kis_filter.h>
+#include "filter/kis_color_transformation_filter.h"
+
+class KritaASCCDL : public QObject
+{
+    Q_OBJECT
+public:
+    KritaASCCDL(QObject *parent, const QVariantList &);
+    ~KritaASCCDL() override;
+};
+
+class KisFilterASCCDL: public KisColorTransformationFilter
+{
+public:
+    KisFilterASCCDL();
+public:
+
+    static inline KoID id() {
+        return KoID("asc-cdl", i18n("Slope, Offset, Power(ASC-CDL)"));
+    }
+    KoColorTransformation *createTransformation(const KoColorSpace* cs, const \
KisFilterConfigurationSP config) const override; +    KisConfigWidget \
*createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP dev) const \
override; +    bool needsTransparentPixels(const KisFilterConfigurationSP config, \
const KoColorSpace *cs) const; +protected:
+    KisFilterConfigurationSP factoryConfiguration() const override;
+};
+
+class KisASCCDLTransformation : public KoColorTransformation
+{
+public:
+    KisASCCDLTransformation(const KoColorSpace *cs, KoColor slope, KoColor offset, \
KoColor power); +    void transform(const quint8* src, quint8* dst, qint32 nPixels) \
const override; +private:
+    QVector<float> m_slope;
+    QVector<float> m_offset;
+    QVector<float> m_power;
+    const KoColorSpace *m_cs;
+};
+
+#endif // KIS_ASCCDL_H
diff --git a/plugins/filters/asccdl/kis_wdg_asccdl.cpp \
b/plugins/filters/asccdl/kis_wdg_asccdl.cpp new file mode 100644
index 00000000000..afce1f6b334
--- /dev/null
+++ b/plugins/filters/asccdl/kis_wdg_asccdl.cpp
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2017 Wolthera van Hövell tot Westerflier <griffinvalley@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 "kis_wdg_asccdl.h"
+#include <kis_config.h>
+#include <kis_color_button.h>
+#include <kis_filter_configuration.h>
+#include <KisVisualColorSelectorShape.h>
+#include <KisVisualRectangleSelectorShape.h>
+#include <KisVisualEllipticalSelectorShape.h>
+
+KisASCCDLConfigWidget::KisASCCDLConfigWidget(QWidget *parent, const KoColorSpace \
*cs) +    :KisConfigWidget(parent),
+    m_page(new Ui_WdgASCCDL),
+    m_cs(cs)
+
+{
+    KoColor black(Qt::black, cs);
+    m_page->setupUi(this);
+    m_page->btnSlope->setColor(black);
+    m_page->btnOffset->setColor(black);
+    m_page->btnPower->setColor(black);
+
+    connect(m_page->btnSlope , SIGNAL(changed(const KoColor)), this,  \
SLOT(slopeColorChanged(const KoColor))); +    connect(m_page->btnOffset, \
SIGNAL(changed(const KoColor)), this,  SLOT(offsetColorChanged(const KoColor))); +    \
connect(m_page->btnPower , SIGNAL(changed(const KoColor)), this,  \
SLOT(powerColorChanged(const KoColor))); +    connect(m_page->slopeSelector, \
SIGNAL(sigNewColor(const KoColor)), this, SLOT(slopeColorChanged(const KoColor))); +  \
connect(m_page->offsetSelector, SIGNAL(sigNewColor(const KoColor)), this, \
SLOT(offsetColorChanged(const KoColor))); +    connect(m_page->powerSelector, \
SIGNAL(sigNewColor(const KoColor)), this, SLOT(powerColorChanged(const KoColor))); +}
+
+KisASCCDLConfigWidget::~KisASCCDLConfigWidget()
+{
+    delete m_page;
+}
+
+KisPropertiesConfigurationSP KisASCCDLConfigWidget::configuration() const
+{
+    KisFilterConfigurationSP config = new KisFilterConfiguration("asc-cdl", 0);
+    QVariant colorVariant("KoColor");
+    colorVariant.setValue(m_page->btnSlope->color());
+    config->setProperty("slope", colorVariant);
+    colorVariant.setValue(m_page->btnOffset->color());
+    config->setProperty("offset", colorVariant);
+    colorVariant.setValue(m_page->btnPower->color());
+    config->setProperty("power", colorVariant);
+    return config;
+}
+
+void KisASCCDLConfigWidget::setConfiguration(const KisPropertiesConfigurationSP \
config) +{
+    m_page->btnSlope->setColor (config->getColor( "slope", KoColor(Qt::white, \
m_cs))); +    m_page->slopeSelector->slotSetColor(config->getColor("slope", \
KoColor(Qt::white, m_cs))); +    \
m_page->btnOffset->setColor(config->getColor("offset", KoColor(Qt::black, m_cs))); +  \
m_page->offsetSelector->slotSetColor(config->getColor("offset", KoColor(Qt::white, \
m_cs))); +    m_page->btnPower->setColor (config->getColor( "power", \
KoColor(Qt::white, m_cs))); +    \
m_page->powerSelector->slotSetColor(config->getColor("power", KoColor(Qt::white, \
m_cs))); +}
+
+void KisASCCDLConfigWidget::slopeColorChanged(const KoColor &c)
+{
+    if (QObject::sender() == m_page->btnSlope) {
+        m_page->slopeSelector->slotSetColor(c);
+    } else {
+        m_page->btnSlope->setColor(c);
+    }
+    emit sigConfigurationItemChanged();
+}
+
+void KisASCCDLConfigWidget::offsetColorChanged(const KoColor &c)
+{
+    if (QObject::sender() == m_page->btnOffset) {
+        m_page->offsetSelector->slotSetColor(c);
+    } else {
+        m_page->btnOffset->setColor(c);
+    }
+    emit sigConfigurationItemChanged();
+}
+
+void KisASCCDLConfigWidget::powerColorChanged(const KoColor &c)
+{
+    if (QObject::sender() == m_page->btnPower) {
+        m_page->powerSelector->slotSetColor(c);
+    } else {
+        m_page->btnPower->setColor(c);
+    }
+    emit sigConfigurationItemChanged();
+}
diff --git a/plugins/filters/asccdl/kis_wdg_asccdl.h \
b/plugins/filters/asccdl/kis_wdg_asccdl.h new file mode 100644
index 00000000000..bdca6461020
--- /dev/null
+++ b/plugins/filters/asccdl/kis_wdg_asccdl.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2017 Wolthera van Hövell tot Westerflier <griffinvalley@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 KIS_WDG_ASCCDL_H
+#define KIS_WDG_ASCCDL_H
+#include <kis_config_widget.h>
+#include <QWidget>
+#include "ui_wdg_asccdl.h"
+#include <KisVisualRectangleSelectorShape.h>
+#include <KisVisualEllipticalSelectorShape.h>
+
+class Ui_WdgASCCDL;
+
+/**
+ * @brief The KisASCCDLConfigWidget class
+ * this handles the configuration widget for the slope offset power filter.
+ *
+ * Future improvements:
+ * 1. Have the cs that the widgets gets when being created be actually the image cs.
+ * 2. Have the shape be force to a HSV wheel with a slider.
+ * 3. Make it easier to select power higher than 1.0 (it is possible, but \
cumbersome) + * 4. make it easier to access ocio from filters.
+ * 5. Implement saturation whenever we can figure out what the formula is for that.
+ * 6. Implement a way to retrieve and store xml data according to the asc-cdl \
spec... + *
+ * The main problem for 5 and 6 is that I am unable to find the actual asc-cdl spec.
+ */
+
+class KisASCCDLConfigWidget : public KisConfigWidget
+{
+
+    Q_OBJECT
+
+public:
+    KisASCCDLConfigWidget(QWidget * parent, const KoColorSpace *cs);
+    ~KisASCCDLConfigWidget() override;
+
+    KisPropertiesConfigurationSP  configuration() const override;
+    void setConfiguration(const KisPropertiesConfigurationSP config) override;
+    Ui_WdgASCCDL *m_page;
+    const KoColorSpace *m_cs;
+public Q_SLOTS:
+    void slopeColorChanged(const KoColor &c);
+    void offsetColorChanged(const KoColor &c);
+    void powerColorChanged(const KoColor &c);
+};
+
+#endif //KIS_WDG_ASCCDL_H
diff --git a/plugins/filters/asccdl/kritaasccdl.json \
b/plugins/filters/asccdl/kritaasccdl.json new file mode 100644
index 00000000000..5e09c37b7ee
--- /dev/null
+++ b/plugins/filters/asccdl/kritaasccdl.json
@@ -0,0 +1,9 @@
+{
+    "Id": "ASC CDL Color Balance",
+    "Type": "Service",
+    "X-KDE-Library": "kritaasccdl",
+    "X-KDE-ServiceTypes": [
+        "Krita/Filter"
+    ],
+    "X-Krita-Version": "40"
+}
diff --git a/plugins/filters/asccdl/wdg_asccdl.ui \
b/plugins/filters/asccdl/wdg_asccdl.ui new file mode 100644
index 00000000000..be3f17056dd
--- /dev/null
+++ b/plugins/filters/asccdl/wdg_asccdl.ui
@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>WdgASCCDL</class>
+ <widget class="QWidget" name="WdgASCCDL">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>400</width>
+    <height>300</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string/>
+  </property>
+  <layout class="QGridLayout" name="gridLayout">
+   <item row="3" column="0">
+    <widget class="KisColorButton" name="btnSlope">
+     <property name="text">
+      <string>PushButton</string>
+     </property>
+    </widget>
+   </item>
+   <item row="3" column="2">
+    <widget class="KisColorButton" name="btnPower">
+     <property name="text">
+      <string>PushButton</string>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="1">
+    <widget class="QLabel" name="lblOffset">
+     <property name="text">
+      <string>Offset:</string>
+     </property>
+    </widget>
+   </item>
+   <item row="0" column="0" colspan="2">
+    <widget class="QLabel" name="lblBase">
+     <property name="text">
+      <string>ASC-CDL  color balance</string>
+     </property>
+    </widget>
+   </item>
+   <item row="3" column="1">
+    <widget class="KisColorButton" name="btnOffset">
+     <property name="text">
+      <string>PushButton</string>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="2">
+    <widget class="QLabel" name="lblPower">
+     <property name="text">
+      <string>Power:</string>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="0">
+    <widget class="QLabel" name="lblSlope">
+     <property name="text">
+      <string>Slope:</string>
+     </property>
+    </widget>
+   </item>
+   <item row="2" column="0">
+    <widget class="KisVisualColorSelector" name="slopeSelector" native="true"/>
+   </item>
+   <item row="2" column="1">
+    <widget class="KisVisualColorSelector" name="offsetSelector" native="true"/>
+   </item>
+   <item row="2" column="2">
+    <widget class="KisVisualColorSelector" name="powerSelector" native="true"/>
+   </item>
+   <item row="4" column="0" colspan="3">
+    <spacer name="verticalSpacer">
+     <property name="orientation">
+      <enum>Qt::Vertical</enum>
+     </property>
+     <property name="sizeHint" stdset="0">
+      <size>
+       <width>20</width>
+       <height>40</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+  </layout>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>KisColorButton</class>
+   <extends>QPushButton</extends>
+   <header>kis_color_button.h</header>
+  </customwidget>
+  <customwidget>
+   <class>KisVisualColorSelector</class>
+   <extends>QWidget</extends>
+   <header>KisVisualColorSelector.h</header>
+   <container>1</container>
+  </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic