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

List:       kde-kimageshop
Subject:    Proof of concept patch for Wash Mode artifacts
From:       Dmitry Kazakov <dimula73 () gmail ! com>
Date:       2013-06-16 14:42:19
Message-ID: CAEkBSfXCQ+TiMxRi3Ynynn+rfeTLBw7cA1imT-nnxdc1shZVDg () mail ! gmail ! com
[Download RAW message or body]

[Attachment #2 (multipart/alternative)]


Hi!

One of the bugs I'm working on currently is Wash Mode bug, described by
Paul in the first part of the bug [0].

Technical part:

Actually, this is not a bug, but a flaw of the composition formula we use
in ALPHA_DARKEN composite op. So to fix this bug, we need to change the
formula (with all the obvious consequences). The problem is this formula is
not commutative, that is the order of application of dabs changes the
result dramatically.

The patch:

In the attachment you can find a patch which (should) fix this bug. It
would be nice if someone tested it and looked for some non-obvious
regressions in painting it introduces.

This patch implements:
1) Fixes the artifacts on the tail of the Wash Mode stroke

This patch breaks (known issues):
1) Flow option doesn't work (it is simply disabled)
2) It fixes the bug for a Pixel Brush only
3) It disables vector optimizations


[0] - https://bugs.kde.org/show_bug.cgi?id=320651

-- 
Dmitry Kazakov

[Attachment #5 (text/html)]

Hi!<br><br>One of the bugs I&#39;m working on currently is Wash Mode bug, described \
by Paul in the first part of the bug [0]. <br><br>Technical part:<br><br>Actually, \
this is not a bug, but a flaw of the composition formula we use in ALPHA_DARKEN \
composite op. So to fix this bug, we need to change the formula (with all the obvious \
consequences). The problem is this formula is not commutative, that is the order of \
application of dabs changes the result dramatically.<br> <br>The patch:<br><br>In the \
attachment you can find a patch which (should) fix this bug. It would be nice if \
someone tested it and looked for some non-obvious regressions in painting it \
introduces.<br><br>This patch implements:<br> 1) Fixes the artifacts on the tail of \
the Wash Mode stroke<br><br>This patch breaks (known issues):<br>1) Flow option \
doesn&#39;t work (it is simply disabled)<br>2) It fixes the bug for a Pixel Brush \
only<br>3) It disables vector optimizations<br> <br clear="all"><br>[0] - <a \
href="https://bugs.kde.org/show_bug.cgi?id=320651">https://bugs.kde.org/show_bug.cgi?id=320651</a><br><br>-- \
<br>Dmitry Kazakov

--047d7b3a85a0b7a9ca04df467ccf--


["alpha_darken.patch" (application/octet-stream)]

diff --git a/krita/plugins/paintops/defaultpaintops/brush/kis_brushop.cpp \
b/krita/plugins/paintops/defaultpaintops/brush/kis_brushop.cpp index 40679be..f9444a9 \
                100644
--- a/krita/plugins/paintops/defaultpaintops/brush/kis_brushop.cpp
+++ b/krita/plugins/paintops/defaultpaintops/brush/kis_brushop.cpp
@@ -88,6 +88,8 @@ KisBrushOp::KisBrushOp(const KisBrushBasedPaintOpSettings \
*settings, KisPainter  
     m_dabCache->setMirrorPostprocessing(&m_mirrorOption);
     m_dabCache->setSharpnessPostprocessing(&m_sharpnessOption);
+
+    m_haveLastOpacity = false;
 }
 
 KisBrushOp::~KisBrushOp()
@@ -156,6 +158,19 @@ qreal KisBrushOp::paintAt(const KisPaintInformation& info)
                                                      xFraction, yFraction,
                                                      m_softnessOption.apply(info));
 
+    //////////
+    if (m_haveLastOpacity) {
+        painter()->setFlow(m_lastOpacity);
+    } else {
+        painter()->setFlow(painter()->opacity());
+        m_lastOpacity = painter()->opacity();
+        m_haveLastOpacity = true;
+    }
+
+    m_lastOpacity = 0.1 * painter()->opacity() + 0.9 * m_lastOpacity;
+    //m_lastOpacity = painter()->opacity();
+    //////////
+
     painter()->bltFixed(QPoint(x, y), dab, dab->bounds());
 
     painter()->renderMirrorMaskSafe(QRect(QPoint(x,y), \
                QSize(dab->bounds().width(),dab->bounds().height())),
diff --git a/krita/plugins/paintops/defaultpaintops/brush/kis_brushop.h \
b/krita/plugins/paintops/defaultpaintops/brush/kis_brushop.h index 6d198e0..bb8ebbb \
                100644
--- a/krita/plugins/paintops/defaultpaintops/brush/kis_brushop.h
+++ b/krita/plugins/paintops/defaultpaintops/brush/kis_brushop.h
@@ -74,6 +74,9 @@ private:
     KoColorTransformation *m_hsvTransformation;
     KisPaintDeviceSP m_lineCacheDevice;
     KisPaintDeviceSP m_colorSourceDevice;
+
+    bool m_haveLastOpacity;
+    quint8 m_lastOpacity;
 };
 
 #endif // KIS_BRUSHOP_H_
diff --git a/libs/pigment/compositeops/KoOptimizedCompositeOpAlphaDarken32.h \
b/libs/pigment/compositeops/KoOptimizedCompositeOpAlphaDarken32.h index \
                172bf30..90c8b23 100644
--- a/libs/pigment/compositeops/KoOptimizedCompositeOpAlphaDarken32.h
+++ b/libs/pigment/compositeops/KoOptimizedCompositeOpAlphaDarken32.h
@@ -145,6 +145,8 @@ struct AlphaDarkenCompositor32 {
     {
         Q_UNUSED(channelFlags);
 
+        float lastOpacity = flow;
+
         using namespace Arithmetic;
         const qint32 alpha_pos = 3;
 
@@ -161,7 +163,7 @@ struct AlphaDarkenCompositor32 {
          * FIXME: precalculate this value on a higher level for
          * not doing it on every cycle
          */
-        opacity *= flow;
+        //opacity *= flow;
 
         if (haveMask) {
             mskAlphaNorm = float(*mask) * uint8Rec2 * src[alpha_pos];
@@ -181,9 +183,18 @@ struct AlphaDarkenCompositor32 {
             *d = *s;
         }
 
-        float alpha1 = unionShapeOpacity(srcAlphaNorm, dstAlphaNorm);                \
// alpha with 0% flow +        //qDebug() << "Last Opacity" << (lastOpacity) << \
"Opacity" << (opacity); +
+        //float alpha1 = unionShapeOpacity(srcAlphaNorm, dstAlphaNorm);              \
// alpha with 0% flow +
+        float alpha1 = (lastOpacity > dstAlphaNorm) ? lerp(srcAlphaNorm, \
                lastOpacity, dstAlphaNorm / lastOpacity) : dstAlphaNorm; // alpha \
                with 100% flow
         float alpha2 = (opacity > dstAlphaNorm) ? lerp(dstAlphaNorm, opacity, \
                mskAlphaNorm) : dstAlphaNorm; // alpha with 100% flow
-        dst[alpha_pos] = quint8(lerp(alpha1, alpha2, flow) * uint8Max);
+
+        float alpha = lastOpacity > opacity ? alpha1 : alpha2;
+        //float alpha = alpha2;
+
+        dst[alpha_pos] = quint8(alpha * uint8Max);
+        //dst[alpha_pos] = quint8(lerp(alpha1, alpha2, flow) * uint8Max);
     }
 };
 
diff --git a/libs/pigment/compositeops/KoStreamedMath.h \
b/libs/pigment/compositeops/KoStreamedMath.h index 34b1887..bacc351 100644
--- a/libs/pigment/compositeops/KoStreamedMath.h
+++ b/libs/pigment/compositeops/KoStreamedMath.h
@@ -232,7 +232,7 @@ template<bool useMask, bool useFlow, class Compositor>
             srcAlignment == dstAlignment || !srcVectorInc ?
             &blockAlignedVector : &blockUnalignedVector;
 
-        if (!dstAlignment) {
+        /*if (!dstAlignment) {
             blockAlign = 0;
             *vectorBlock = params.cols / vectorSize;
             blockRest = params.cols % vectorSize;
@@ -241,7 +241,7 @@ template<bool useMask, bool useFlow, class Compositor>
             const int restCols = params.cols - blockAlign;
             *vectorBlock = restCols / vectorSize;
             blockRest = restCols % vectorSize;
-        }
+            }*/
 
         for(int i = 0; i < blockAlign; i++) {
             Compositor::template compositeOnePixelScalar<useMask, _impl>(src, dst, \
mask, params.opacity, params.flow, params.channelFlags);



_______________________________________________
Krita mailing list
kimageshop@kde.org
https://mail.kde.org/mailman/listinfo/kimageshop


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

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