[krita/kazakov/lazy-brush-remastered] /: Implement "Limit to layer bounds" feature of the Colorize Mask

Dmitry Kazakov null at kde.org
Mon Dec 11 21:14:09 UTC 2017


Git commit dfae2014343f90cf0ad00adf37506dc945d92a5b by Dmitry Kazakov.
Committed on 11/12/2017 at 21:14.
Pushed by dkazakov into branch 'kazakov/lazy-brush-remastered'.

Implement "Limit to layer bounds" feature of the Colorize Mask

If the outer color of the mask is transparent (e.g. when coloring
a character), the user might select "Limit to layer bounds" option,
which will limit the coloring area by the non-zero area of the parent
layer. It might speedup the coloring significantly.

CC:kimageshop at kde.org

M  +37   -6    libs/image/lazybrush/kis_colorize_mask.cpp
M  +2    -0    libs/image/lazybrush/kis_colorize_mask.h
M  +2    -1    libs/image/lazybrush/kis_colorize_stroke_strategy.h
M  +2    -0    plugins/impex/libkra/kis_kra_loader.cpp
M  +1    -0    plugins/impex/libkra/kis_kra_savexml_visitor.cpp
M  +1    -0    plugins/impex/libkra/kis_kra_tags.h
M  +12   -1    plugins/tools/tool_lazybrush/kis_tool_lazy_brush_options_widget.cpp
M  +1    -0    plugins/tools/tool_lazybrush/kis_tool_lazy_brush_options_widget.h
M  +7    -0    plugins/tools/tool_lazybrush/kis_tool_lazy_brush_options_widget.ui

https://commits.kde.org/krita/dfae2014343f90cf0ad00adf37506dc945d92a5b

diff --git a/libs/image/lazybrush/kis_colorize_mask.cpp b/libs/image/lazybrush/kis_colorize_mask.cpp
index ad2d46f63a9..118f55b1cbf 100644
--- a/libs/image/lazybrush/kis_colorize_mask.cpp
+++ b/libs/image/lazybrush/kis_colorize_mask.cpp
@@ -65,7 +65,8 @@ struct KisColorizeMask::Private
           dirtyParentUpdateCompressor(200, KisSignalCompressor::FIRST_ACTIVE_POSTPONE_NEXT, _q),
           prefilterRecalculationCompressor(1000, KisSignalCompressor::POSTPONE, _q),
           updateIsRunning(false),
-          filteringOptions(false, 4.0, 15, 0.7)
+          filteringOptions(false, 4.0, 15, 0.7),
+          limitToDeviceBounds(false)
     {
     }
 
@@ -74,6 +75,7 @@ struct KisColorizeMask::Private
           coloringProjection(new KisPaintDevice(*rhs.coloringProjection)),
           fakePaintDevice(new KisPaintDevice(*rhs.fakePaintDevice)),
           filteredSource(new KisPaintDevice(*rhs.filteredSource)),
+          filteredDeviceBounds(rhs.filteredDeviceBounds),
           needAddCurrentKeyStroke(rhs.needAddCurrentKeyStroke),
           showKeyStrokes(rhs.showKeyStrokes),
           showColoring(rhs.showColoring),
@@ -84,7 +86,8 @@ struct KisColorizeMask::Private
           prefilterRecalculationCompressor(1000, KisSignalCompressor::POSTPONE, _q),
           offset(rhs.offset),
           updateIsRunning(false),
-          filteringOptions(rhs.filteringOptions)
+          filteringOptions(rhs.filteringOptions),
+          limitToDeviceBounds(rhs.limitToDeviceBounds)
     {
         Q_FOREACH (const KeyStroke &stroke, rhs.keyStrokes) {
             keyStrokes << KeyStroke(KisPaintDeviceSP(new KisPaintDevice(*stroke.dev)), stroke.color, stroke.isTransparent);
@@ -97,6 +100,7 @@ struct KisColorizeMask::Private
     KisPaintDeviceSP coloringProjection;
     KisPaintDeviceSP fakePaintDevice;
     KisPaintDeviceSP filteredSource;
+    QRect filteredDeviceBounds;
 
     KoColor currentColor;
     KisPaintDeviceSP currentKeyStrokeDevice;
@@ -122,6 +126,8 @@ struct KisColorizeMask::Private
     FilteringOptions filteringOptions;
     bool filteringDirty = true;
 
+    bool limitToDeviceBounds = false;
+
     bool filteredSourceValid(KisPaintDeviceSP parentDevice) {
         return !filteringDirty && originalSequenceNumber == parentDevice->sequenceNumber();
     }
@@ -130,7 +136,6 @@ struct KisColorizeMask::Private
 
     bool shouldShowFilteredSource() const;
     bool shouldShowColoring() const;
-
 };
 
 KisColorizeMask::KisColorizeMask()
@@ -327,12 +332,26 @@ void KisColorizeMask::slotUpdateRegenerateFilling(bool prefilterOnly)
     if (image) {
         m_d->updateIsRunning = true;
 
+        QRect fillBounds;
+
+        if (m_d->limitToDeviceBounds) {
+            fillBounds |= src->exactBounds();
+            Q_FOREACH (const KeyStroke &stroke, m_d->keyStrokes) {
+                fillBounds |= stroke.dev->exactBounds();
+            }
+            fillBounds &= image->bounds();
+        } else {
+            fillBounds = image->bounds();
+        }
+
+        m_d->filteredDeviceBounds = fillBounds;
+
         KisColorizeStrokeStrategy *strategy =
             new KisColorizeStrokeStrategy(src,
                                           m_d->coloringProjection,
                                           m_d->filteredSource,
                                           filteredSourceValid,
-                                          image->bounds(),
+                                          fillBounds,
                                           this,
                                           prefilterOnly);
 
@@ -475,7 +494,6 @@ bool KisColorizeMask::Private::shouldShowColoring() const
             coloringProjection;
 }
 
-
 QRect KisColorizeMask::decorateRect(KisPaintDeviceSP &src,
                                     KisPaintDeviceSP &dst,
                                     const QRect &rect,
@@ -498,8 +516,10 @@ QRect KisColorizeMask::decorateRect(KisPaintDeviceSP &src,
         KisPainter gc(dst);
 
         if (m_d->shouldShowFilteredSource()) {
+            const QRect drawRect = rect & m_d->filteredDeviceBounds;
+
             gc.setOpacity(128);
-            gc.bitBlt(rect.topLeft(), m_d->filteredSource, rect);
+            gc.bitBlt(drawRect.topLeft(), m_d->filteredSource, drawRect);
         } else {
             gc.setOpacity(255);
             gc.bitBlt(rect.topLeft(), src, rect);
@@ -1011,6 +1031,17 @@ qreal KisColorizeMask::cleanUpAmount() const
     return m_d->filteringOptions.cleanUpAmount;
 }
 
+void KisColorizeMask::setLimitToDeviceBounds(bool value)
+{
+    m_d->limitToDeviceBounds = value;
+    m_d->filteringDirty = true;
+    setNeedsUpdate(true);
+}
+
+bool KisColorizeMask::limitToDeviceBounds() const
+{
+    return m_d->limitToDeviceBounds;
+}
 
 void KisColorizeMask::rerenderFakePaintDevice()
 {
diff --git a/libs/image/lazybrush/kis_colorize_mask.h b/libs/image/lazybrush/kis_colorize_mask.h
index 50fd0ca2ff8..c6382e2145c 100644
--- a/libs/image/lazybrush/kis_colorize_mask.h
+++ b/libs/image/lazybrush/kis_colorize_mask.h
@@ -114,6 +114,8 @@ public:
     void setCleanUpAmount(qreal value);
     qreal cleanUpAmount() const;
 
+    void setLimitToDeviceBounds(bool value);
+    bool limitToDeviceBounds() const;
 
     void testingAddKeyStroke(KisPaintDeviceSP dev, const KoColor &color, bool isTransparent = false);
     void testingRegenerateMask();
diff --git a/libs/image/lazybrush/kis_colorize_stroke_strategy.h b/libs/image/lazybrush/kis_colorize_stroke_strategy.h
index dbec3b8f322..b5176f3947a 100644
--- a/libs/image/lazybrush/kis_colorize_stroke_strategy.h
+++ b/libs/image/lazybrush/kis_colorize_stroke_strategy.h
@@ -41,7 +41,8 @@ public:
                               KisPaintDeviceSP dst,
                               KisPaintDeviceSP filteredSource,
                               bool filteredSourceValid,
-                              const QRect &boundingRect, KisNodeSP progressNode,
+                              const QRect &boundingRect,
+                              KisNodeSP progressNode,
                               bool prefilterOnly = false);
     KisColorizeStrokeStrategy(const KisColorizeStrokeStrategy &rhs, int levelOfDetail);
     ~KisColorizeStrokeStrategy() override;
diff --git a/plugins/impex/libkra/kis_kra_loader.cpp b/plugins/impex/libkra/kis_kra_loader.cpp
index ae38512c0f1..ac8c5f61768 100644
--- a/plugins/impex/libkra/kis_kra_loader.cpp
+++ b/plugins/impex/libkra/kis_kra_loader.cpp
@@ -1039,11 +1039,13 @@ KisNodeSP KisKraLoader::loadColorizeMask(KisImageSP image, const KoXmlElement& e
     const qreal edgeDetectionSize = KisDomUtils::toDouble(element.attribute(COLORIZE_EDGE_DETECTION_SIZE, "4"));
     const qreal radius = KisDomUtils::toDouble(element.attribute(COLORIZE_FUZZY_RADIUS, "0"));
     const int cleanUp = KisDomUtils::toInt(element.attribute(COLORIZE_CLEANUP, "0"));
+    const bool limitToDevice = KisDomUtils::toInt(element.attribute(COLORIZE_LIMIT_TO_DEVICE, "0"));
 
     mask->setUseEdgeDetection(useEdgeDetection);
     mask->setEdgeDetectionSize(edgeDetectionSize);
     mask->setFuzzyRadius(radius);
     mask->setCleanUpAmount(qreal(cleanUp) / 100.0);
+    mask->setLimitToDeviceBounds(limitToDevice);
 
     delete mask->setColorSpace(colorSpace);
     mask->setImage(image);
diff --git a/plugins/impex/libkra/kis_kra_savexml_visitor.cpp b/plugins/impex/libkra/kis_kra_savexml_visitor.cpp
index 33716777be9..81d7b6fea9d 100644
--- a/plugins/impex/libkra/kis_kra_savexml_visitor.cpp
+++ b/plugins/impex/libkra/kis_kra_savexml_visitor.cpp
@@ -424,6 +424,7 @@ void KisSaveXmlVisitor::saveMask(QDomElement & el, const QString & maskType, con
             el.setAttribute(COLORIZE_EDGE_DETECTION_SIZE, KisDomUtils::toString(colorizeMask->edgeDetectionSize()));
             el.setAttribute(COLORIZE_FUZZY_RADIUS, KisDomUtils::toString(colorizeMask->fuzzyRadius()));
             el.setAttribute(COLORIZE_CLEANUP, int(100 * colorizeMask->cleanUpAmount()));
+            el.setAttribute(COLORIZE_LIMIT_TO_DEVICE, colorizeMask->limitToDeviceBounds());
         }
     }
 
diff --git a/plugins/impex/libkra/kis_kra_tags.h b/plugins/impex/libkra/kis_kra_tags.h
index 4dc80affdf4..249df5a7d08 100644
--- a/plugins/impex/libkra/kis_kra_tags.h
+++ b/plugins/impex/libkra/kis_kra_tags.h
@@ -104,6 +104,7 @@ const QString COLORIZE_USE_EDGE_DETECTION = "use-edge-detection";
 const QString COLORIZE_EDGE_DETECTION_SIZE = "edge-detection-size";
 const QString COLORIZE_FUZZY_RADIUS = "fuzzy-radius";
 const QString COLORIZE_CLEANUP = "cleanup";
+const QString COLORIZE_LIMIT_TO_DEVICE = "limit-to-device";
 const QString TRANSFORM_MASK = "transformmask";
 const QString UUID = "uuid";
 const QString VISIBLE = "visible";
diff --git a/plugins/tools/tool_lazybrush/kis_tool_lazy_brush_options_widget.cpp b/plugins/tools/tool_lazybrush/kis_tool_lazy_brush_options_widget.cpp
index 6cc6d079e02..b7ca2afc932 100644
--- a/plugins/tools/tool_lazybrush/kis_tool_lazy_brush_options_widget.cpp
+++ b/plugins/tools/tool_lazybrush/kis_tool_lazy_brush_options_widget.cpp
@@ -72,6 +72,7 @@ KisToolLazyBrushOptionsWidget::KisToolLazyBrushOptionsWidget(KisCanvasResourcePr
     connect(m_d->ui->intEdgeDetectionSize, SIGNAL(valueChanged(int)), SLOT(slotEdgeDetectionSizeChanged(int)));
     connect(m_d->ui->intRadius, SIGNAL(valueChanged(int)), SLOT(slotRadiusChanged(int)));
     connect(m_d->ui->intCleanUp, SIGNAL(valueChanged(int)), SLOT(slotCleanUpChanged(int)));
+    connect(m_d->ui->chkLimitToDevice, SIGNAL(toggled(bool)), SLOT(slotLimitToDeviceChanged(bool)));
 
     m_d->ui->intEdgeDetectionSize->setRange(0, 100);
     m_d->ui->intEdgeDetectionSize->setExponentRatio(2.0);
@@ -226,7 +227,8 @@ void KisToolLazyBrushOptionsWidget::slotUpdateNodeProperties()
     KisSignalsBlocker b2(m_d->ui->chkUseEdgeDetection,
                          m_d->ui->intEdgeDetectionSize,
                          m_d->ui->intRadius,
-                         m_d->ui->intCleanUp);
+                         m_d->ui->intCleanUp,
+                         m_d->ui->chkLimitToDevice);
 
     // not implemented yet!
     //m_d->ui->chkAutoUpdates->setEnabled(m_d->activeMask);
@@ -254,6 +256,9 @@ void KisToolLazyBrushOptionsWidget::slotUpdateNodeProperties()
     m_d->ui->intRadius->setValue(2 * (m_d->activeMask ? m_d->activeMask->fuzzyRadius() : 15));
     m_d->ui->intCleanUp->setEnabled(m_d->activeMask);
     m_d->ui->intCleanUp->setValue(100 * (m_d->activeMask ? m_d->activeMask->cleanUpAmount() : 0.7));
+
+    m_d->ui->chkLimitToDevice->setEnabled(m_d->activeMask);
+    m_d->ui->chkLimitToDevice->setChecked(m_d->activeMask && m_d->activeMask->limitToDeviceBounds());
 }
 
 void KisToolLazyBrushOptionsWidget::slotCurrentNodeChanged(KisNodeSP node)
@@ -362,3 +367,9 @@ void KisToolLazyBrushOptionsWidget::slotCleanUpChanged(int value)
     m_d->activeMask->setCleanUpAmount(qreal(value) / 100.0);
 }
 
+void KisToolLazyBrushOptionsWidget::slotLimitToDeviceChanged(bool value)
+{
+    KIS_SAFE_ASSERT_RECOVER_RETURN(m_d->activeMask);
+    m_d->activeMask->setLimitToDeviceBounds(value);
+}
+
diff --git a/plugins/tools/tool_lazybrush/kis_tool_lazy_brush_options_widget.h b/plugins/tools/tool_lazybrush/kis_tool_lazy_brush_options_widget.h
index e3b41631491..8512f6f5339 100644
--- a/plugins/tools/tool_lazybrush/kis_tool_lazy_brush_options_widget.h
+++ b/plugins/tools/tool_lazybrush/kis_tool_lazy_brush_options_widget.h
@@ -54,6 +54,7 @@ private Q_SLOTS:
     void slotEdgeDetectionSizeChanged(int value);
     void slotRadiusChanged(int value);
     void slotCleanUpChanged(int value);
+    void slotLimitToDeviceChanged(bool value);
 
 
     void slotUpdateNodeProperties();
diff --git a/plugins/tools/tool_lazybrush/kis_tool_lazy_brush_options_widget.ui b/plugins/tools/tool_lazybrush/kis_tool_lazy_brush_options_widget.ui
index d4841eef3e7..08bb910e5aa 100644
--- a/plugins/tools/tool_lazybrush/kis_tool_lazy_brush_options_widget.ui
+++ b/plugins/tools/tool_lazybrush/kis_tool_lazy_brush_options_widget.ui
@@ -43,6 +43,13 @@
      </property>
     </widget>
    </item>
+   <item>
+    <widget class="QCheckBox" name="chkLimitToDevice">
+     <property name="text">
+      <string>Limit to layer bounds</string>
+     </property>
+    </widget>
+   </item>
    <item>
     <spacer name="verticalSpacer">
      <property name="orientation">


More information about the kimageshop mailing list