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

List:       kde-commits
Subject:    [calligra/krita-gmic-ltvrdy] krita/plugins/extensions/gmic: Implement import/export processing visit
From:       Lukáš Tvrdý <lukast.dev () gmail ! com>
Date:       2013-08-31 19:08:14
Message-ID: E1VFqWs-00027r-R9 () scm ! kde ! org
[Download RAW message or body]

Git commit 223d37e40234950093b0bf7161fcde570a748fa6 by Lukáš Tvrdý.
Committed on 31/08/2013 at 19:06.
Pushed by lukast into branch 'krita-gmic-ltvrdy'.

Implement import/export processing visitors

o now undo works correctly
o prepare the code for supporting gmic input/output layer modes

M  +4    -0    krita/plugins/extensions/gmic/CMakeLists.txt
A  +60   -0    krita/plugins/extensions/gmic/kis_export_gmic_processing_visitor.cpp   \
[License: GPL (v2+)] A  +55   -0    \
krita/plugins/extensions/gmic/kis_export_gmic_processing_visitor.h     [License: GPL \
(v2+)] A  +106  -0    krita/plugins/extensions/gmic/kis_gmic_command.cpp     \
[License: GPL (v2+)] C  +21   -20   krita/plugins/extensions/gmic/kis_gmic_command.h \
[from: krita/plugins/extensions/gmic/kis_gmic_plugin.h - 054% similarity] M  +68   -4 \
krita/plugins/extensions/gmic/kis_gmic_plugin.cpp M  +1    -0    \
krita/plugins/extensions/gmic/kis_gmic_plugin.h A  +264  -0    \
krita/plugins/extensions/gmic/kis_gmic_simple_convertor.cpp     [License: GPL (v2+)] \
A  +85   -0    krita/plugins/extensions/gmic/kis_gmic_simple_convertor.h     \
[License: GPL (v2+)] A  +80   -0    \
krita/plugins/extensions/gmic/kis_import_gmic_processing_visitor.cpp     [License: \
GPL (v2+)] A  +48   -0    \
krita/plugins/extensions/gmic/kis_import_gmic_processing_visitor.h     [License: GPL \
(v2+)]

http://commits.kde.org/calligra/223d37e40234950093b0bf7161fcde570a748fa6

diff --git a/krita/plugins/extensions/gmic/CMakeLists.txt \
b/krita/plugins/extensions/gmic/CMakeLists.txt index bc47635..d4c3bc4 100644
--- a/krita/plugins/extensions/gmic/CMakeLists.txt
+++ b/krita/plugins/extensions/gmic/CMakeLists.txt
@@ -58,6 +58,10 @@ set(kritagmic_PART_SRCS
     dlg_gmic.cpp
     kis_gmic.cpp
     kis_gmic_processing_visitor.cpp
+    kis_gmic_simple_convertor.cpp
+    kis_export_gmic_processing_visitor.cpp
+    kis_gmic_command.cpp
+    kis_import_gmic_processing_visitor.cpp
     kis_gmic_plugin.cpp ${kritagmic_shared_PART_SRCS}
 )
 
diff --git a/krita/plugins/extensions/gmic/kis_export_gmic_processing_visitor.cpp \
b/krita/plugins/extensions/gmic/kis_export_gmic_processing_visitor.cpp new file mode \
100644 index 0000000..f3f0c97
--- /dev/null
+++ b/krita/plugins/extensions/gmic/kis_export_gmic_processing_visitor.cpp
@@ -0,0 +1,60 @@
+/*
+ *  Copyright (c) 2013 Dmitry Kazakov <dimula73@gmail.com>
+ *  Copyright (c) 2013 Lukáš Tvrdý <lukast.dev@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_export_gmic_processing_visitor.h"
+#include <KoColorSpaceRegistry.h>
+#include <KoColorSpace.h>
+
+#include <kis_gmic_simple_convertor.h>
+#include <kis_node.h>
+
+KisExportGmicProcessingVisitor::KisExportGmicProcessingVisitor(const \
QList<KisNodeSP> &nodes, QSharedPointer<gmic_list<float> > images) +    : \
m_nodes(nodes), +      m_images(images)
+{
+}
+
+
+void KisExportGmicProcessingVisitor::visitNodeWithPaintDevice(KisNode *node, \
KisUndoAdapter *undoAdapter) +{
+    Q_UNUSED(undoAdapter);
+
+    int index = m_nodes.indexOf(node);
+    if (index >= 0)
+    {
+        qDebug() << "Found the LAYEEEEEEEEEEEEEEEEER!";
+
+        /* fill the image with data here */
+        KisGmicSimpleConvertor convertor;
+
+        KisPaintDeviceSP device = node->paintDevice();
+        gmic_image<float> &gimg = m_images->_data[index];
+
+
+        QRect rc = device->exactBounds();
+        quint32 x = rc.width();
+        quint32 y = rc.height();
+        quint32 z = 1;
+        quint32 colorChannelCount = 4; // RGBA
+        gimg.assign(x,y,z,colorChannelCount);
+
+        convertor.convertToGmicImage(device, gimg);
+    }
+}
+
diff --git a/krita/plugins/extensions/gmic/kis_export_gmic_processing_visitor.h \
b/krita/plugins/extensions/gmic/kis_export_gmic_processing_visitor.h new file mode \
100644 index 0000000..d3cca87
--- /dev/null
+++ b/krita/plugins/extensions/gmic/kis_export_gmic_processing_visitor.h
@@ -0,0 +1,55 @@
+/*
+ *  Copyright (c) 2013 Dmitry Kazakov <dimula73@gmail.com>
+ *  Copyright (c) 2013 Lukáš Tvrdý <lukast.dev@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_EXPORT_GMIC_PROCESSING_VISITOR_H
+#define __KIS_EXPORT_GMIC_PROCESSING_VISITOR_H
+
+#include <gmic.h>
+
+#include <QSharedPointer>
+#include <QList>
+
+#include <processing/kis_simple_processing_visitor.h>
+#include <kis_types.h>
+#include <kis_node.h>
+
+class KisNode;
+class KisUndoAdapter;
+
+#include <kis_paint_device.h>
+
+class KisExportGmicProcessingVisitor : public KisSimpleProcessingVisitor
+{
+public:
+    KisExportGmicProcessingVisitor(const QList<KisNodeSP> &nodes, QSharedPointer< \
gmic_list<float> > images); +
+protected:
+    void visitNodeWithPaintDevice(KisNode *node, KisUndoAdapter *undoAdapter);
+    void visitExternalLayer(KisExternalLayer *layer, KisUndoAdapter *undoAdapter){ \
Q_UNUSED(layer); Q_UNUSED(undoAdapter); } +
+private:
+    void convertToGmicImageOpti(KisPaintDeviceSP dev, gmic_image<float>& gmicImage);
+    void init();
+private:
+
+    QList<KisNodeSP> m_nodes;
+    QSharedPointer<gmic_list<float> > m_images;
+};
+
+#endif /* __KIS_EXPORT_GMIC_PROCESSING_VISITOR_H */
diff --git a/krita/plugins/extensions/gmic/kis_gmic_command.cpp \
b/krita/plugins/extensions/gmic/kis_gmic_command.cpp new file mode 100644
index 0000000..d7159de
--- /dev/null
+++ b/krita/plugins/extensions/gmic/kis_gmic_command.cpp
@@ -0,0 +1,106 @@
+/*
+ *  Copyright (c) 2013 Dmitry Kazakov <dimula73@gmail.com>
+ *  Copyright (c) 2013 Lukáš Tvrdý <lukast.dev@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_gmic_command.h"
+
+#include <QString>
+
+KisGmicCommand::KisGmicCommand(const QString &gmicCommandString, QSharedPointer< \
gmic_list<float> > images): +    m_gmicCommandString(gmicCommandString),
+    m_images(images),
+    m_firstRedo(true)
+{
+}
+
+void KisGmicCommand::undo()
+{
+    // do nothing
+}
+
+void KisGmicCommand::redo()
+{
+    if (m_firstRedo)
+    {
+        m_firstRedo = false;
+
+        /* process m_images using GMIC here */
+        // Second step : Call G'MIC API to process input images.
+        //------------------------------------------------------
+        std::fprintf(stderr,"\n- 2st step : Call G'MIC interpreter.\n");
+
+        gmic_list<char> images_names;
+        try
+        {
+            QString gmicCmd = "-+ -n 0,255 ";
+            gmicCmd.append(m_gmicCommandString);
+            qDebug() << m_gmicCommandString;
+            gmic(gmicCmd.toLocal8Bit().constData(), *m_images, images_names);
+        }
+        // Catch exception, if an error occured in the interpreter.
+        catch (gmic_exception &e)
+        {
+            qDebug() << "\n- Error encountered when calling G'MIC : '%s'\n" << \
e.what(); +            return;
+        }
+
+        // Third step : get back modified image data.
+        //-------------------------------------------
+        std::fprintf(stderr,"\n- 3st step : Returned %u output \
images.\n",m_images->_width); +        for (unsigned int i = 0; i<m_images->_width; \
++i) +        {
+            std::fprintf(stderr,"   Output image %u = %ux%ux%ux%u, buffer : %p\n",i,
+                        m_images->_data[i]._width,
+                        m_images->_data[i]._height,
+                        m_images->_data[i]._depth,
+                        m_images->_data[i]._spectrum,
+                        m_images->_data[i]._data);
+        }
+    }
+}
+
+/*
+
+KisProcessingApplicator applicator(this, m_d->rootLayer,
+                                   KisProcessingApplicator::RECURSIVE,
+                                   emitSignals, actionName);
+
+nodes.append(..);
+nodes.append(..);
+nodes.append(..);
+
+QSharedPointer<gmic_list<float> > m_images(new ...);
+
+KisProcessingVisitorSP visitor;
+
+visitor = new KisExportGmicProcessingVisitor(nodes, images);
+applicator.applyVisitor(visitor, KisStrokeJobData::CONCURRENT);
+
+applicator.applyCommand(new KisGmicCommand(images));
+
+visitor = new KisImportGmicProcessingVisitor(nodes, images);
+applicator.applyVisitor(visitor, KisStrokeJobData::CONCURRENT); // undo information \
is stored in this visitor +
+applicator.applyCommand(new CleanTheData(images));
+
+CleanTheData::redo() {
+    m_images->clear();
+}
+
+
+*/
diff --git a/krita/plugins/extensions/gmic/kis_gmic_plugin.h \
b/krita/plugins/extensions/gmic/kis_gmic_command.h similarity index 54%
copy from krita/plugins/extensions/gmic/kis_gmic_plugin.h
copy to krita/plugins/extensions/gmic/kis_gmic_command.h
index 2e1f44a..4a8f95c 100644
--- a/krita/plugins/extensions/gmic/kis_gmic_plugin.h
+++ b/krita/plugins/extensions/gmic/kis_gmic_command.h
@@ -1,5 +1,6 @@
 /*
- * Copyright (c) 2013 Lukáš Tvrdý <lukast.dev@gmail.com>
+ *  Copyright (c) 2013 Dmitry Kazakov <dimula73@gmail.com>
+ *  Copyright (c) 2013 Lukáš Tvrdý <lukast.dev@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
@@ -13,33 +14,33 @@
  *
  *  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. \
*/ + *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, \
USA. + */
 
-#ifndef _KIS_GMIC_PLUGIN_H_
-#define _KIS_GMIC_PLUGIN_H_
+#ifndef __KIS_GMIC_COMMAND_H
+#define __KIS_GMIC_COMMAND_H
 
-#include <QVariant>
+#include <QSharedPointer>
 
-#include <kis_view_plugin.h>
-#include <kis_gmic_filter_settings.h>
-#include "kis_gmic_parser.h"
+#include <gmic.h>
 
-class KisGmicWidget;
+#include <kundo2command.h>
+#include "kis_types.h"
 
-class KisGmicPlugin : public KisViewPlugin
+class QString;
+
+class KisGmicCommand : public KUndo2Command
 {
-    Q_OBJECT
 public:
-    KisGmicPlugin(QObject *parent, const QVariantList &);
-    virtual ~KisGmicPlugin();
+    KisGmicCommand(const QString &gmicCommandString, QSharedPointer< \
gmic_list<float> > images);  
-private:
-    KisGmicWidget * m_gmicWidget;
-    QString m_gmicDefinitionFilePath;
+    void undo();
+    void redo();
 
-private slots:
-    void slotGmic();
-    void slotApplyGmicCommand(KisGmicFilterSetting* setting);
+private:
+    QString m_gmicCommandString;
+    QSharedPointer<gmic_list<float> > m_images;
+    bool m_firstRedo;
 };
 
-#endif
+#endif /* __KIS_GMIC_COMMAND_H */
diff --git a/krita/plugins/extensions/gmic/kis_gmic_plugin.cpp \
b/krita/plugins/extensions/gmic/kis_gmic_plugin.cpp index 304e46f..4c96a0b 100644
--- a/krita/plugins/extensions/gmic/kis_gmic_plugin.cpp
+++ b/krita/plugins/extensions/gmic/kis_gmic_plugin.cpp
@@ -49,9 +49,6 @@
 #include "kis_gmic.h"
 #include "dlg_gmic.h"
 
-K_PLUGIN_FACTORY(KisGmicPluginFactory, registerPlugin<KisGmicPlugin>();)
-K_EXPORT_PLUGIN(KisGmicPluginFactory("krita"))
-
 #include "gmic.h"
 #include "kis_gmic_parser.h"
 #include "Component.h"
@@ -59,6 +56,14 @@ K_EXPORT_PLUGIN(KisGmicPluginFactory("krita"))
 #include "kis_gmic_widget.h"
 #include "kis_gmic_processing_visitor.h"
 
+#include "kis_export_gmic_processing_visitor.h"
+#include "kis_gmic_command.h"
+#include "kis_import_gmic_processing_visitor.h"
+
+
+K_PLUGIN_FACTORY(KisGmicPluginFactory, registerPlugin<KisGmicPlugin>();)
+K_EXPORT_PLUGIN(KisGmicPluginFactory("krita"))
+
 KisGmicPlugin::KisGmicPlugin(QObject *parent, const QVariantList &)
         : KisViewPlugin(parent, "kritaplugins/gmic.rc"),m_gmicWidget(0)
 {
@@ -102,7 +107,7 @@ void KisGmicPlugin::slotGmic()
 }
 
 
-void KisGmicPlugin::slotApplyGmicCommand(KisGmicFilterSetting* setting)
+void KisGmicPlugin::slotApplyGmicCommandOld(KisGmicFilterSetting* setting)
 {
     KisImageWSP image = m_view->image();
 
@@ -143,4 +148,63 @@ void KisGmicPlugin::slotApplyGmicCommand(KisGmicFilterSetting* \
setting)  }
 }
 
+void KisGmicPlugin::slotApplyGmicCommand(KisGmicFilterSetting* setting)
+{
+    QString actionName;
+    KisNodeSP node;
+
+    if (setting->inputLayerMode() == ACTIVE_LAYER)
+    {
+        //TODO: Undo string for gimp plug-in is G'MIC, I would like to use \
G'MIC+filtername +        actionName = i18n("Gmic: Active Layer");
+        node = m_view->activeNode();
+    }
+    else
+    {
+        KMessageBox::sorry(m_gmicWidget, i18n("Sorry, this input mode is not \
implemented"), i18n("Krita")); +        return;
+    }
+
+    if (setting->outputMode() != IN_PLACE)
+    {
+        KMessageBox::sorry(m_gmicWidget,QString("Sorry, this output mode is not \
implemented"),"Krita"); +        return;
+    }
+
+    KisImageSignalVector emitSignals;
+    emitSignals << ModifiedSignal;
+
+
+    KisProcessingApplicator applicator(m_view->image(), node,
+                                   KisProcessingApplicator::RECURSIVE,
+                                   emitSignals, actionName);
+
+    QList<KisNodeSP> kritaNodes;
+    kritaNodes.append(m_view->activeNode());
+
+    QSharedPointer< gmic_list<float> > gmicLayers(new gmic_list<float>);
+    gmicLayers->assign(kritaNodes.size());
+
+
+    KisProcessingVisitorSP visitor;
+    visitor = new KisExportGmicProcessingVisitor(kritaNodes, gmicLayers);
+    applicator.applyVisitor(visitor, KisStrokeJobData::CONCURRENT);
+
+    applicator.applyCommand(new KisGmicCommand(setting->gmicCommand(), gmicLayers));
+
+    visitor = new KisImportGmicProcessingVisitor(kritaNodes, gmicLayers);
+    applicator.applyVisitor(visitor, KisStrokeJobData::CONCURRENT); // undo \
information is stored in this visitor +    applicator.end();
+
+    // TODO: applicator.applyCommand(new CleanTheData(images));
+
+    /*CleanTheData::redo() {
+        m_images->clear();
+    }/*/
+
+
+
+}
+
+
 #include "kis_gmic_plugin.moc"
diff --git a/krita/plugins/extensions/gmic/kis_gmic_plugin.h \
b/krita/plugins/extensions/gmic/kis_gmic_plugin.h index 2e1f44a..8404cf8 100644
--- a/krita/plugins/extensions/gmic/kis_gmic_plugin.h
+++ b/krita/plugins/extensions/gmic/kis_gmic_plugin.h
@@ -39,6 +39,7 @@ private:
 
 private slots:
     void slotGmic();
+    void slotApplyGmicCommandOld(KisGmicFilterSetting* setting);
     void slotApplyGmicCommand(KisGmicFilterSetting* setting);
 };
 
diff --git a/krita/plugins/extensions/gmic/kis_gmic_simple_convertor.cpp \
b/krita/plugins/extensions/gmic/kis_gmic_simple_convertor.cpp new file mode 100644
index 0000000..3da1fd5
--- /dev/null
+++ b/krita/plugins/extensions/gmic/kis_gmic_simple_convertor.cpp
@@ -0,0 +1,264 @@
+/*
+ * Copyright (c) 2013 Lukáš Tvrdý <lukast.dev@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 <QRect>
+
+#include <kis_gmic_simple_convertor.h>
+
+#include <kis_paint_device.h>
+#include <KoColorSpaceRegistry.h>
+#include <KoColorSpace.h>
+#include <KoColorModelStandardIds.h>
+#include <KoColorSpaceTraits.h>
+
+using namespace cimg_library;
+
+
+KisGmicSimpleConvertor::KisGmicSimpleConvertor():m_channelSize(0)
+{
+
+}
+
+
+KisGmicSimpleConvertor::~KisGmicSimpleConvertor()
+{
+    deletePlanes();
+}
+
+
+void KisGmicSimpleConvertor::convertToGmicImage(KisPaintDeviceSP dev, gmic_image< \
float >& gmicImage) +{
+    const KoColorSpace *rgbaFloat32bitcolorSpace = \
KoColorSpaceRegistry::instance()->colorSpace(RGBAColorModelID.id(), +                 \
Float32BitsColorDepthID.id(), +                                                       \
KoColorSpaceRegistry::instance()->rgb8()->profile()); +
+    Q_CHECK_PTR(rgbaFloat32bitcolorSpace);
+    dev->convertTo(rgbaFloat32bitcolorSpace);
+
+    QRect rc = dev->exactBounds();
+    m_planarBytes = dev->readPlanarBytes(rc.x(), rc.y(), rc.width(), rc.height());
+    setChannelSize(rc.width() * rc.height());
+
+    int greenOffset = gmicImage._width * gmicImage._height;
+    int blueOffset = greenOffset * 2;
+    int alphaOffset = greenOffset * 3;
+    quint8 * redChannelBytes   = m_planarBytes.at(KoRgbF32Traits::red_pos);
+    quint8 * greenChannelBytes = m_planarBytes.at(KoRgbF32Traits::green_pos);
+    quint8 * blueChannelBytes  = m_planarBytes.at(KoRgbF32Traits::blue_pos);
+    quint8 * alphaChannelBytes = m_planarBytes.at(KoRgbF32Traits::alpha_pos);
+
+    unsigned int channelSize = sizeof(float);
+
+    memcpy(gmicImage._data                  ,redChannelBytes    ,gmicImage._width * \
gmicImage._height * channelSize); +    memcpy(gmicImage._data + greenOffset    \
,greenChannelBytes  ,gmicImage._width * gmicImage._height * channelSize); +    \
memcpy(gmicImage._data + blueOffset     ,blueChannelBytes   ,gmicImage._width * \
gmicImage._height * channelSize); +    memcpy(gmicImage._data + alphaOffset    \
,alphaChannelBytes  ,gmicImage._width * gmicImage._height * channelSize); +}
+
+
+KisPaintDeviceSP KisGmicSimpleConvertor::convertFromGmicImage(CImg< float >& \
gmicImage, bool &preserveAlpha) +{
+    const KoColorSpace *rgbaFloat32bitcolorSpace = \
KoColorSpaceRegistry::instance()->colorSpace(RGBAColorModelID.id(), +                 \
Float32BitsColorDepthID.id(), +                                                       \
KoColorSpaceRegistry::instance()->rgb8()->profile()); +
+    KisPaintDeviceSP dev = new KisPaintDevice(rgbaFloat32bitcolorSpace);
+
+
+    unsigned int channelBytes = gmicImage._width * gmicImage._height * \
sizeof(float); +    if (channelBytes == channelSize() * sizeof(float))
+    {
+        // ok, we can reuse read plannar bytes here
+        qDebug() << "[krita] Re-using read plannar bytes";
+        if ((gmicImage._spectrum == 1) || (gmicImage._spectrum == 3))
+        {
+            qDebug() << "[krita] Releasing alpha channel";
+            // we can delete alpha channel
+            releaseAlphaChannel();
+        }
+
+    }
+    else
+    {
+        // re-accumullate buffers, output image has different dimension..not sure if \
this ever happens +        deletePlanes();
+        bool alphaChannelEnabled = ((gmicImage._spectrum == 2) || \
(gmicImage._spectrum == 4)); +        qDebug() << "Accumulating...!";
+        accumulate(gmicImage._width * gmicImage._height, alphaChannelEnabled);
+    }
+
+    switch (gmicImage._spectrum)
+    {
+        case 1:
+        {
+            grayscale2rgb(gmicImage, m_planarBytes);
+            preserveAlpha = true;
+            break;
+        }
+        case 2:
+        {
+            grayscaleAlpha2rgba(gmicImage, m_planarBytes);
+            break;
+        }
+        case 3:
+        {
+            rgb2rgb(gmicImage, m_planarBytes);
+            preserveAlpha = true;
+            break;
+        }
+        case 4:
+            rgba2rgba(gmicImage, m_planarBytes);
+            break;
+        default:
+        {
+            qDebug() << "Unsupported gmic output format : " <<  gmicImage._width << \
gmicImage._height << gmicImage._depth << gmicImage._spectrum; +        }
+    }
+
+    dev->writePlanarBytes(m_planarBytes, 0, 0, gmicImage._width, gmicImage._height);
+
+    // release planes
+    deletePlanes();
+    return dev;
+}
+
+void KisGmicSimpleConvertor::grayscale2rgb(CImg< float >& gmicImage, QVector< quint8 \
* > &planes) +{
+    quint8 * redChannelBytes = planes[0];
+    quint8 * greenChannelBytes = planes[1];
+    quint8 * blueChannelBytes = planes[2];
+    // alphaChannel will be preserved
+
+    int pos = 0;
+    float r,g,b;
+
+    // iterate over gmic image and fill plane buffers
+    for (unsigned int y = 0; y < gmicImage._height; y++)
+    {
+        for (unsigned int x = 0; x < gmicImage._width; x++)
+        {
+            pos = y * gmicImage._width + x;
+            // gmic assumes 0.0 - 255.0, Krita stores 0.0 - 1.0
+            r = g = b = gmicImage._data[pos]                / 255.0;
+            memcpy(redChannelBytes,     &r, 4); redChannelBytes     += 4;
+            memcpy(greenChannelBytes,   &g, 4); greenChannelBytes   += 4;
+            memcpy(blueChannelBytes,    &b, 4); blueChannelBytes    += 4;
+        }
+    }
+    // TODO: check performance if memcpy whole channel is faster
+}
+
+
+void KisGmicSimpleConvertor::grayscaleAlpha2rgba(CImg< float >& gmicImage, QVector< \
quint8 * > &planes) +{
+    quint8 * redChannelBytes = planes[0];
+    quint8 * greenChannelBytes = planes[1];
+    quint8 * blueChannelBytes = planes[2];
+    quint8 * alphaChannelBytes = planes[3];
+
+    int pos = 0;
+    int alphaOffset = gmicImage._width * gmicImage._height;
+    float r,g,b,a;
+
+    // iterate over gmic image and fill plane buffers
+    for (unsigned int y = 0; y < gmicImage._height; y++)
+    {
+        for (unsigned int x = 0; x < gmicImage._width; x++){
+            pos = y * gmicImage._width + x;
+
+            // gmic assumes 0.0 - 255.0, Krita stores 0.0 - 1.0
+            r = g = b = gmicImage._data[pos]                / 255.0;
+            a = gmicImage._data[pos + alphaOffset]   / 255.0;
+
+            memcpy(redChannelBytes,     &r, 4); redChannelBytes     += 4;
+            memcpy(greenChannelBytes,   &g, 4); greenChannelBytes   += 4;
+            memcpy(blueChannelBytes,    &b, 4); blueChannelBytes    += 4;
+            memcpy(alphaChannelBytes,   &a, 4); alphaChannelBytes   += 4;
+        }
+    }
+}
+
+
+void KisGmicSimpleConvertor::rgb2rgb(CImg< float >& gmicImage, QVector< quint8 * > \
&planes) +{
+    quint8 * redChannelBytes = planes[0];
+    quint8 * greenChannelBytes = planes[1];
+    quint8 * blueChannelBytes = planes[2];
+    // alphaChannel will be preserved
+
+    int pos = 0;
+    int greenOffset = gmicImage._width * gmicImage._height;
+    int blueOffset = greenOffset * 2;
+
+    float r,g,b;
+
+    // iterate over gmic image and fill plane buffers
+    for (unsigned int y = 0; y < gmicImage._height; y++)
+    {
+        for (unsigned int x = 0; x < gmicImage._width; x++)
+        {
+            pos = y * gmicImage._width + x;
+
+            // gmic assumes 0.0 - 255.0, Krita stores 0.0 - 1.0
+            r = gmicImage._data[pos]                / 255.0;
+            g = gmicImage._data[pos + greenOffset]  / 255.0;
+            b = gmicImage._data[pos + blueOffset]   / 255.0;
+
+            memcpy(redChannelBytes,     &r, 4); redChannelBytes     += 4;
+            memcpy(greenChannelBytes,   &g, 4); greenChannelBytes   += 4;
+            memcpy(blueChannelBytes,    &b, 4); blueChannelBytes    += 4;
+        }
+    }
+}
+
+void KisGmicSimpleConvertor::rgba2rgba(CImg< float >& gmicImage, QVector< quint8 * > \
&planes) +{
+    qDebug() <<"planes-size"<< planes.size();
+
+    quint8 * redChannelBytes = planes[0];
+    quint8 * greenChannelBytes = planes[1];
+    quint8 * blueChannelBytes = planes[2];
+    quint8 * alphaChannelBytes = planes[3];
+
+    int pos = 0;
+    int greenOffset = gmicImage._width * gmicImage._height;
+    int blueOffset = greenOffset * 2;
+    int alphaOffset = greenOffset * 3;
+
+    float r,g,b,a;
+
+    // iterate over gmic image and fill plane buffers
+    for (unsigned int y = 0; y < gmicImage._height; y++)
+    {
+        for (unsigned int x = 0; x < gmicImage._width; x++)
+        {
+            pos = y * gmicImage._width + x;
+
+            // gmic assumes 0.0 - 255.0, Krita stores 0.0 - 1.0
+            r = gmicImage._data[pos]                / 255.0;
+            g = gmicImage._data[pos + greenOffset]  / 255.0;
+            b = gmicImage._data[pos + blueOffset]   / 255.0;
+            a = gmicImage._data[pos + alphaOffset]  / 255.0;
+
+            memcpy(redChannelBytes,     &r, 4); redChannelBytes     += 4;
+            memcpy(greenChannelBytes,   &g, 4); greenChannelBytes   += 4;
+            memcpy(blueChannelBytes,    &b, 4); blueChannelBytes    += 4;
+            memcpy(alphaChannelBytes,   &a, 4); alphaChannelBytes   += 4;
+        }
+    }
+}
diff --git a/krita/plugins/extensions/gmic/kis_gmic_simple_convertor.h \
b/krita/plugins/extensions/gmic/kis_gmic_simple_convertor.h new file mode 100644
index 0000000..4bc8830
--- /dev/null
+++ b/krita/plugins/extensions/gmic/kis_gmic_simple_convertor.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2013 Lukáš Tvrdý <lukast.dev@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_gmic.h>
+
+#include <QVector>
+
+#ifndef __KIS_GMIC_SIMPLE_CONVERTOR_H
+#define __KIS_GMIC_SIMPLE_CONVERTOR_H
+
+class KisGmicSimpleConvertor
+{
+public:
+    KisGmicSimpleConvertor();
+    ~KisGmicSimpleConvertor();
+
+public:
+    // convert functions
+    void convertToGmicImage(KisPaintDeviceSP dev, gmic_image<float>& gmicImage);
+
+    KisPaintDeviceSP convertFromGmicImage(gmic_image<float>& gmicImage, bool \
&preserveAlpha); +    // re-align functions
+    void grayscale2rgb(cimg_library::CImg< float >& gmicImage, QVector< quint8 * > \
&planes); +    void grayscaleAlpha2rgba(cimg_library::CImg< float >& gmicImage, \
QVector< quint8 * > &planes); +    void rgb2rgb(cimg_library::CImg< float >& \
gmicImage, QVector< quint8 * > &planes); +    void rgba2rgba(cimg_library::CImg< \
float >& gmicImage, QVector< quint8 * > &planes); +
+
+    void releaseAlphaChannel()
+    {
+        // alphaPos == 3
+        delete m_planarBytes[3];
+        m_planarBytes[3] = 0;
+    }
+
+    void deletePlanes()
+    {
+        qDeleteAll(m_planarBytes);
+        m_planarBytes.clear();
+    }
+
+    void accumulate(unsigned int channelSize, bool alphaChannelEnabled = true)
+    {
+        setChannelSize(channelSize);
+        m_planarBytes.resize(4);
+
+        int channelCount = 4;
+        if (!alphaChannelEnabled)
+        {
+            m_planarBytes[3] = 0;
+            channelCount = 3;
+        }
+
+        for (int i=0;i<channelCount;i++)
+        {
+            m_planarBytes[i] = new quint8[channelSize * sizeof(float)];
+        }
+    }
+
+    void setChannelSize(unsigned int channelSize) { m_channelSize = channelSize; }
+    // count of float pixels per channel
+    unsigned int channelSize() {return m_channelSize;}
+
+private:
+    unsigned int m_channelSize;
+    QVector<quint8 *> m_planarBytes;
+
+};
+
+#endif
diff --git a/krita/plugins/extensions/gmic/kis_import_gmic_processing_visitor.cpp \
b/krita/plugins/extensions/gmic/kis_import_gmic_processing_visitor.cpp new file mode \
100644 index 0000000..f3a7677
--- /dev/null
+++ b/krita/plugins/extensions/gmic/kis_import_gmic_processing_visitor.cpp
@@ -0,0 +1,80 @@
+/*
+ *  Copyright (c) 2013 Dmitry Kazakov <dimula73@gmail.com>
+ *  Copyright (c) 2013 Lukáš Tvrdý <lukast.dev@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_import_gmic_processing_visitor.h"
+
+#include <kis_transaction.h>
+#include <kis_paint_device.h>
+
+#include <gmic.h>
+#include "kis_gmic_simple_convertor.h"
+#include <kis_node.h>
+#include <kis_painter.h>
+#include <KoCompositeOpRegistry.h>
+
+KisImportGmicProcessingVisitor::KisImportGmicProcessingVisitor(const \
QList<KisNodeSP> &nodes,QSharedPointer<gmic_list<float> > images) +    : \
m_nodes(nodes), +      m_images(images)
+{
+}
+
+void KisImportGmicProcessingVisitor::visitNodeWithPaintDevice(KisNode *node, \
KisUndoAdapter *undoAdapter) +{
+    int index = m_nodes.indexOf(node);
+    if (index >= 0)
+    {
+        gmic_image<float> &gimg = m_images->_data[index];
+
+        qDebug() << "Importing: " << gimg._width << gimg._height << gimg._spectrum;
+
+
+        KisPaintDeviceSP src = node->paintDevice();
+        KisTransaction transaction("", src);
+
+        bool preserveAlpha = false;
+
+        KisGmicSimpleConvertor convertor;
+        KisPaintDeviceSP dstDev = \
convertor.convertFromGmicImage(m_images->_data[index], preserveAlpha); +
+
+        // to actual layer colorspace
+        dstDev->convertTo(src->colorSpace());
+        // bitBlt back -- we don't write the pixel data back directly, but bitBlt so \
the +        // unselected pixels are not overwritten.
+        KisPainter gc(src);
+        gc.setCompositeOp(COMPOSITE_COPY);
+
+        // preserve alpha if grayscale or RGB output
+        QRect rc(0,0,m_images->_data[index]._width, m_images->_data[index]._height);
+        if (preserveAlpha)
+        {
+            gc.setLockAlpha(true);
+        }
+        gc.bitBlt(rc.topLeft(), dstDev, rc);
+        gc.end();
+
+        transaction.commit(undoAdapter);
+    }
+}
+
+void KisImportGmicProcessingVisitor::visitExternalLayer(KisExternalLayer *layer, \
KisUndoAdapter *undoAdapter) +{
+    Q_UNUSED(layer);
+    Q_UNUSED(undoAdapter);
+}
diff --git a/krita/plugins/extensions/gmic/kis_import_gmic_processing_visitor.h \
b/krita/plugins/extensions/gmic/kis_import_gmic_processing_visitor.h new file mode \
100644 index 0000000..61a4fa5
--- /dev/null
+++ b/krita/plugins/extensions/gmic/kis_import_gmic_processing_visitor.h
@@ -0,0 +1,48 @@
+/*
+ *  Copyright (c) 2013 Dmitry Kazakov <dimula73@gmail.com>
+ *  Copyright (c) 2013 Lukáš Tvrdý <lukast.dev@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_IMPORT_GMIC_PROCESSING_VISITOR_H
+#define __KIS_IMPORT_GMIC_PROCESSING_VISITOR_H
+
+#include <processing/kis_simple_processing_visitor.h>
+#include <QList>
+
+#include <QSharedPointer>
+
+#include <gmic.h>
+
+#include <kis_node.h>
+class KisUndoAdapter;
+
+class KisImportGmicProcessingVisitor : public KisSimpleProcessingVisitor
+{
+public:
+    KisImportGmicProcessingVisitor(const QList<KisNodeSP> &nodes,
+                                   QSharedPointer<gmic_list<float> > images);
+
+protected:
+    void visitNodeWithPaintDevice(KisNode *node, KisUndoAdapter *undoAdapter);
+    void visitExternalLayer(KisExternalLayer *layer, KisUndoAdapter *undoAdapter);
+
+private:
+    QList<KisNodeSP> m_nodes;
+    QSharedPointer<gmic_list<float> > m_images;
+};
+
+#endif /* __KIS_IMPORT_GMIC_PROCESSING_VISITOR_H */


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

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