Index: krita/krita.action
===================================================================
--- krita/krita.action
+++ krita/krita.action
@@ -2616,6 +2616,18 @@
false
+
+
+ Wavelet Decompose ...
+
+ Wavelet Decompose
+ Wavelet Decompose
+ 1000
+ 1
+
+ false
+
+
symmetry-horizontal
Mirror Layer Hori&zontally
Index: krita/krita.xmlgui
===================================================================
--- krita/krita.xmlgui
+++ krita/krita.xmlgui
@@ -202,6 +202,7 @@
+
Index: plugins/extensions/CMakeLists.txt
===================================================================
--- plugins/extensions/CMakeLists.txt
+++ plugins/extensions/CMakeLists.txt
@@ -14,6 +14,7 @@
add_subdirectory( layergroupswitcher )
add_subdirectory( resourcemanager )
add_subdirectory( layersplit )
+add_subdirectory( waveletdecompose )
# Allow to skip building GMIC plugin
option(WITH_GMIC "Build the G'Mic plugin" ON)
Index: plugins/extensions/waveletdecompose/CMakeLists.txt
===================================================================
--- /dev/null
+++ plugins/extensions/waveletdecompose/CMakeLists.txt
@@ -0,0 +1,14 @@
+set(kritawaveletdecompose_SOURCES
+ waveletdecompose.cpp
+ dlg_waveletdecompose.cpp
+ kis_wavelet_kernel.cpp
+ )
+
+ki18n_wrap_ui(kritawaveletdecompose_SOURCES
+ wdg_waveletdecompose.ui
+ )
+
+add_library(kritawaveletdecompose MODULE ${kritawaveletdecompose_SOURCES})
+target_link_libraries(kritawaveletdecompose kritaui)
+install(TARGETS kritawaveletdecompose DESTINATION ${KRITA_PLUGIN_INSTALL_DIR})
+install( FILES waveletdecompose.xmlgui DESTINATION ${DATA_INSTALL_DIR}/kritaplugins)
Index: plugins/extensions/waveletdecompose/dlg_waveletdecompose.h
===================================================================
--- /dev/null
+++ plugins/extensions/waveletdecompose/dlg_waveletdecompose.h
@@ -0,0 +1,60 @@
+/*
+ *
+ * Copyright (c) 2016 Miroslav Talasek
+ *
+ * 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 DLG_WAVELETDECOMPOSE
+#define DLG_WAVELETDECOMPOSE
+
+#include
+
+#include "ui_wdg_waveletdecompose.h"
+
+class WdgWaveletDecompose : public QWidget, public Ui::WdgWaveletDecompose
+{
+ Q_OBJECT
+
+public:
+ WdgWaveletDecompose(QWidget *parent) : QWidget(parent) {
+ setupUi(this);
+ }
+};
+
+class DlgWaveletDecompose: public KoDialog
+{
+
+ Q_OBJECT
+
+public:
+
+ DlgWaveletDecompose(QWidget * parent = 0,
+ const char* name = 0);
+ ~DlgWaveletDecompose();
+
+ void setScales(quint32 scales);
+ qint32 scales();
+
+private Q_SLOTS:
+
+ void okClicked();
+
+private:
+
+ WdgWaveletDecompose * m_page;
+
+};
+
+#endif // DLG_WAVELETDECOMPOSE
Index: plugins/extensions/waveletdecompose/dlg_waveletdecompose.cpp
===================================================================
--- /dev/null
+++ plugins/extensions/waveletdecompose/dlg_waveletdecompose.cpp
@@ -0,0 +1,71 @@
+/*
+ *
+ * Copyright (c) 2016 Miroslav Talasek
+ *
+ * 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 "dlg_waveletdecompose.h"
+
+#include
+#include
+
+DlgWaveletDecompose::DlgWaveletDecompose(QWidget * parent,
+ const char * name)
+ : KoDialog(parent)
+{
+ setCaption(i18n("WaveletDecompose"));
+ setButtons(Ok | Cancel);
+ setDefaultButton(Ok);
+ setObjectName(name);
+
+ m_page = new WdgWaveletDecompose(this);
+ Q_CHECK_PTR(m_page);
+ m_page->layout()->setMargin(0);
+ m_page->setObjectName("wavelet_decompose");
+
+ setMainWidget(m_page);
+ resize(m_page->sizeHint());
+
+ connect(this, SIGNAL(okClicked()),
+ this, SLOT(okClicked()));
+
+}
+
+DlgWaveletDecompose::~DlgWaveletDecompose()
+{
+ delete m_page;
+}
+
+void DlgWaveletDecompose::setScales(quint32 scales)
+{
+ m_page->scales->setValue(scales);
+
+}
+
+
+qint32 DlgWaveletDecompose::scales()
+{
+ return m_page->scales->value();
+}
+
+
+// SLOTS
+
+void DlgWaveletDecompose::okClicked()
+{
+ accept();
+}
+
Index: plugins/extensions/waveletdecompose/kis_wavelet_kernel.h
===================================================================
--- /dev/null
+++ plugins/extensions/waveletdecompose/kis_wavelet_kernel.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2016 Miroslav Talasek
+ *
+ * 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_WAVELET_KERNEL_H
+#define __KIS_WAVELET_KERNEL_H
+
+#include "kritaimage_export.h"
+#include "kis_types.h"
+
+#include
+using namespace Eigen;
+
+class QRect;
+
+class KRITAIMAGE_EXPORT KisWaveletKernel
+{
+public:
+ static Matrix
+ createHorizontalMatrix(qreal radius);
+
+ static Matrix
+ createVerticalMatrix(qreal radius);
+
+ static KisConvolutionKernelSP
+ createHorizontalKernel(qreal radius);
+
+ static KisConvolutionKernelSP
+ createVerticalKernel(qreal radius);
+
+ static int kernelSizeFromRadius(qreal radius);
+
+ static void applyWavelet(KisPaintDeviceSP device,
+ const QRect& rect,
+ qreal xRadius, qreal yRadius,
+ const QBitArray &channelFlags,
+ KoUpdater *updater);
+};
+
+#endif /* __KIS_WAVELET_KERNEL_H */
Index: plugins/extensions/waveletdecompose/kis_wavelet_kernel.cpp
===================================================================
--- /dev/null
+++ plugins/extensions/waveletdecompose/kis_wavelet_kernel.cpp
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2016 Miroslav Talasek
+ *
+ * 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_wavelet_kernel.h"
+
+#include "kis_convolution_kernel.h"
+#include
+#include
+
+
+
+int KisWaveletKernel::kernelSizeFromRadius(qreal radius)
+{
+ return 2 * ceil(radius) + 1;
+}
+
+Matrix
+KisWaveletKernel::createHorizontalMatrix(qreal radius)
+{
+ int kernelSize = kernelSizeFromRadius(radius);
+ Matrix matrix(1, kernelSize);
+
+ /**
+ * The kernel size should always be odd, then the position of the
+ * central pixel can be easily calculated
+ */
+ KIS_ASSERT_RECOVER_NOOP(kernelSize & 0x1);
+ const int center = kernelSize / 2;
+
+ for (int x = 0; x < kernelSize; x++) {
+ if (x == 0 || x == kernelSize - 1)
+ matrix(0, x) = 0.25;
+ else if (x == center)
+ matrix(0, x) = 0.5;
+ else
+ matrix(0, x) = 0;
+ }
+
+ return matrix;
+}
+
+Matrix
+KisWaveletKernel::createVerticalMatrix(qreal radius)
+{
+ int kernelSize = kernelSizeFromRadius(radius);
+ Matrix matrix(kernelSize, 1);
+
+
+ /**
+ * The kernel size should always be odd, then the position of the
+ * central pixel can be easily calculated
+ */
+ KIS_ASSERT_RECOVER_NOOP(kernelSize & 0x1);
+ const int center = kernelSize / 2;
+
+ for (int y = 0; y < kernelSize; y++) {
+ if (y == 0 || y == kernelSize - 1)
+ matrix(y, 0) = 0.25;
+ else if (y == center)
+ matrix(y, 0) = 0.5;
+ else
+ matrix(y, 0) = 0;
+ }
+
+ return matrix;
+}
+
+KisConvolutionKernelSP
+KisWaveletKernel::createHorizontalKernel(qreal radius)
+{
+ Matrix matrix = createHorizontalMatrix(radius);
+ return KisConvolutionKernel::fromMatrix(matrix, 0, matrix.sum());
+}
+
+KisConvolutionKernelSP
+KisWaveletKernel::createVerticalKernel(qreal radius)
+{
+ Matrix matrix = createVerticalMatrix(radius);
+ return KisConvolutionKernel::fromMatrix(matrix, 0, matrix.sum());
+}
+
+void KisWaveletKernel::applyWavelet(KisPaintDeviceSP device,
+ const QRect& rect,
+ qreal xRadius, qreal yRadius,
+ const QBitArray &channelFlags,
+ KoUpdater *progressUpdater)
+{
+ QPoint srcTopLeft = rect.topLeft();
+
+ if (xRadius > 0.0 && yRadius > 0.0) {
+ KisPaintDeviceSP interm = new KisPaintDevice(device->colorSpace());
+
+ KisConvolutionKernelSP kernelHoriz = KisWaveletKernel::createHorizontalKernel(xRadius);
+ KisConvolutionKernelSP kernelVertical = KisWaveletKernel::createVerticalKernel(yRadius);
+
+ qreal verticalCenter = qreal(kernelVertical->height()) / 2.0;
+
+ KisConvolutionPainter horizPainter(interm);
+ horizPainter.setChannelFlags(channelFlags);
+ horizPainter.setProgress(progressUpdater);
+ horizPainter.applyMatrix(kernelHoriz, device,
+ srcTopLeft - QPoint(0, ceil(verticalCenter)),
+ srcTopLeft - QPoint(0, ceil(verticalCenter)),
+ rect.size() + QSize(0, 2 * ceil(verticalCenter)), BORDER_REPEAT);
+
+ KisConvolutionPainter verticalPainter(device);
+ verticalPainter.setChannelFlags(channelFlags);
+ verticalPainter.setProgress(progressUpdater);
+ verticalPainter.applyMatrix(kernelVertical, interm, srcTopLeft, srcTopLeft, rect.size(), BORDER_REPEAT);
+
+ } else if (xRadius > 0.0) {
+ KisConvolutionPainter painter(device);
+ painter.setChannelFlags(channelFlags);
+ painter.setProgress(progressUpdater);
+
+ KisConvolutionKernelSP kernelHoriz = KisWaveletKernel::createHorizontalKernel(xRadius);
+ painter.applyMatrix(kernelHoriz, device, srcTopLeft, srcTopLeft, rect.size(), BORDER_REPEAT);
+
+ } else if (yRadius > 0.0) {
+ KisConvolutionPainter painter(device);
+ painter.setChannelFlags(channelFlags);
+ painter.setProgress(progressUpdater);
+
+ KisConvolutionKernelSP kernelVertical = KisWaveletKernel::createVerticalKernel(yRadius);
+ painter.applyMatrix(kernelVertical, device, srcTopLeft, srcTopLeft, rect.size(), BORDER_REPEAT);
+ }
+}
Index: plugins/extensions/waveletdecompose/kritawaveletdecompose.json
===================================================================
--- /dev/null
+++ plugins/extensions/waveletdecompose/kritawaveletdecompose.json
@@ -0,0 +1,9 @@
+{
+ "Id": "Wavelet decomposer",
+ "Type": "Service",
+ "X-KDE-Library": "kritawaveletdecompose",
+ "X-KDE-ServiceTypes": [
+ "Krita/ViewPlugin"
+ ],
+ "X-Krita-Version": "28"
+}
Index: plugins/extensions/waveletdecompose/waveletdecompose.h
===================================================================
--- /dev/null
+++ plugins/extensions/waveletdecompose/waveletdecompose.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2016 Miroslav Talasek
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+#ifndef WAVELETDECOMPOSE_H
+#define WAVETETDECOMPOSE_H
+
+#include
+
+#include
+#include
+
+class WaveletDecompose : public KisViewPlugin
+{
+ Q_OBJECT
+public:
+ WaveletDecompose(QObject *parent, const QVariantList &);
+ virtual ~WaveletDecompose();
+
+private Q_SLOTS:
+
+ void slotWaveletDecompose();
+
+};
+
+#endif // WAVELETDECOMPOSE_H
Index: plugins/extensions/waveletdecompose/waveletdecompose.cpp
===================================================================
--- /dev/null
+++ plugins/extensions/waveletdecompose/waveletdecompose.cpp
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2016 Miroslav Talasek
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "waveletdecompose.h"
+
+#include
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "dlg_waveletdecompose.h"
+#include "kis_node_manager.h"
+#include "kis_node_commands_adapter.h"
+#include "kis_undo_adapter.h"
+
+#include
+#include
+
+
+
+K_PLUGIN_FACTORY_WITH_JSON(WaveletDecomposeFactory, "kritawaveletdecompose.json", registerPlugin();)
+
+WaveletDecompose::WaveletDecompose(QObject *parent, const QVariantList &)
+ : KisViewPlugin(parent)
+{
+ KisAction *action = createAction("waveletdecompose");
+ connect(action, SIGNAL(triggered()), this, SLOT(slotWaveletDecompose()));
+}
+
+WaveletDecompose::~WaveletDecompose()
+{
+}
+
+void WaveletDecompose::slotWaveletDecompose()
+{
+ DlgWaveletDecompose dlg(m_view->mainWindow(), "WaveletDecompose");
+
+ if (dlg.exec() == QDialog::Accepted) {
+
+ QApplication::setOverrideCursor(Qt::WaitCursor);
+
+ KoProgressUpdater* pu = m_view->createProgressUpdater(KoProgressUpdater::Unthreaded);
+ pu->start(100, i18n("Wavelet Decompose"));
+ QPointer updater = pu->startSubtask();
+ updater->setProgress(0);
+
+ KisImageSP image = m_view->image();
+ if (!image) return;
+
+ image->lock();
+
+ KisLayerSP layer = m_view->activeLayer();
+ if (!layer) return;
+
+ KisPaintDeviceSP projection = new KisPaintDevice(*(layer->projection()), false, 0);
+ if (!projection) return;
+
+ const KoColorSpace *cs = projection->colorSpace();
+
+ const KoCompositeOp* op = cs->compositeOp(COMPOSITE_GRAIN_EXTRACT);
+
+ int scales = dlg.scales();
+
+ QList results;
+ const QBitArray flags(0);
+
+ QRect rc = image->bounds();
+
+ KisPaintDeviceSP original = projection;
+
+ //main loop
+ for(int level = 0; level < scales; ++level){
+
+ //copy original
+ KisPaintDeviceSP blur = new KisPaintDevice(*original, false, 0);
+
+ //blur it
+ KisWaveletKernel::applyWavelet(blur, rc, 1 << level, 1 << level, flags, 0);
+
+ //do grain extract blur from original
+ KisPainter painter(original);
+ painter.setCompositeOp(op);
+ painter.bitBlt(0, 0, blur, 0, 0, rc.width(), rc.height());
+ painter.end();
+
+ //original is new scale and blur is new original
+ results << original;
+ original = blur;
+ updater->setProgress((level * 100) / scales);
+ }
+ //add new layers
+ KisUndoAdapter *undo = image->undoAdapter();
+ undo->beginMacro(kundo2_i18n("Wavelet decompose"));
+
+ KisNodeCommandsAdapter adapter(m_view);
+
+ KisGroupLayerSP baseGroup = dynamic_cast(layer->parent().data());
+
+ if (!baseGroup) {
+ // Masks are never nested
+ baseGroup = dynamic_cast(layer->parent()->parent().data());
+ }
+
+ //add layer goup
+ KisGroupLayerSP grp = new KisGroupLayer(image, i18n("Wavelet decompose"), OPACITY_OPAQUE_U8);
+ adapter.addNode(grp, baseGroup, 1);
+ baseGroup = grp;
+
+ //add scales
+ int i = 1;
+ const KoCompositeOp* op2 = cs->compositeOp(COMPOSITE_GRAIN_MERGE);
+ Q_FOREACH (const KisPaintDeviceSP &l, results) {
+ KisPaintLayerSP paintLayer = new KisPaintLayer(image, QStringLiteral("Scale %1").arg(i), OPACITY_OPAQUE_U8, l);
+ adapter.addNode(paintLayer, baseGroup, 0);
+ adapter.setCompositeOp(paintLayer, op2);
+ ++i;
+ }
+
+ //add residual
+ KisPaintLayerSP paintLayer = new KisPaintLayer(image, "Residual", OPACITY_OPAQUE_U8, original);
+ adapter.addNode(paintLayer, baseGroup, 0);
+
+ undo->endMacro();
+ updater->setProgress(100);
+ image->unlock();
+ image->setModified();
+ }
+
+ QApplication::restoreOverrideCursor();
+}
+
+#include "waveletdecompose.moc"
Index: plugins/extensions/waveletdecompose/waveletdecompose.xmlgui
===================================================================
--- /dev/null
+++ plugins/extensions/waveletdecompose/waveletdecompose.xmlgui
@@ -0,0 +1,8 @@
+
+
+
+
+
+
Index: plugins/extensions/waveletdecompose/wdg_waveletdecompose.ui
===================================================================
--- /dev/null
+++ plugins/extensions/waveletdecompose/wdg_waveletdecompose.ui
@@ -0,0 +1,47 @@
+
+
+ WdgWaveletDecompose
+
+
+
+ 0
+ 0
+ 340
+ 76
+
+
+
+ Wavelet Decompose
+
+
+ -
+
+
+ Wavelet scales:
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
+
+ 32767
+ 100
+
+
+
+ 10
+
+
+ 5
+
+
+
+
+
+
+
+