Hi all!<br><br>It seems to me that filters do not pay any attention to the <i>selection</i> parameter passed to them. They simply ignore it (at least i can say so for colors filters). And i don&#39;t know how to fix this well.<br>
<br>Let&#39;s take a look into KisColorTransformationFilter:<br><br><font face="courier new,monospace">KisHLineConstIteratorPixel srcIt = src-&gt;createHLineConstIterator(srcTopLeft.x(), srcTopLeft.y(), size.width());<br>
    KisHLineIteratorPixel dstIt = dst-&gt;createHLineIterator(dstTopLeft.x(), dstTopLeft.y(), size.width());<br><br>    for (int row = 0; row &lt; size.height(); ++row) {<br>        while (! srcIt.isDone()) {<br>            int srcItConseq = srcIt.nConseqHPixels();<br>
            int dstItConseq = dstIt.nConseqHPixels();<br>            int conseqPixels = qMin(srcItConseq, dstItConseq);<br><br>            int pixels = 0;<br><br>            if (hasSelection) {<br>                // Get largest horizontal row of selected pixels<br>
<br>                while (srcIt.isSelected() &amp;&amp; pixels &lt; conseqPixels) {<br>                    ++pixels;<br>                }<br>                inverter-&gt;transform(srcIt.oldRawData(), dstIt.rawData(), pixels);<br>
<br>                // We apparently found a non-selected pixels, or the row<br>                // was done; get the stretch of non-selected pixels<br>                while (!srcIt.isSelected() &amp;&amp; pixels &lt; conseqPixels) {<br>
                    ++ pixels;<br>                }<br>            } else {<br>                pixels = conseqPixels;<br>                inverter-&gt;transform(srcIt.oldRawData(), dstIt.rawData(), pixels);<br>            }<br>
<br>            // Update progress<br>            srcIt += pixels;<br>            dstIt += pixels;<br>        }<br>        srcIt.nextRow();<br>        dstIt.nextRow();<br>    }<br><br><br></font>First of all, this function doesn&#39;t initialize srcIt with <i>selection</i>. But this is not a problem - the first line should be changed to:<br>
<font face="courier new,monospace"><br>KisHLineConstIteratorPixel srcIt = src-&gt;createHLineConstIterator(srcTopLeft.x(), srcTopLeft.y(), size.width(), selection);</font><br><br>That is not a problem. The problem is:<br>
<br>* The filter can&#39;t update semi-selected pixel (0&lt;selectedness&lt;255). The destination pixel will be either fully substituted with a new one (selectedness&gt;=1), or left untouched (selectedness==0).<br><br>The right way - a filter should blend colors if selectedness is more than 0 and less than 255<br>
<br>I see two solutions for this problem:<br><br>1) To force filters to use some complex algorithm that applies selectedness (which is a usual alpha mask (but inverted)). Something like:<br><br><font face="courier new,monospace">inverter-&gt;transform(srcIt.oldRawData(), dstIt.rawData(), pixels);<br>
colorSpace-&gt;applyInverseAlphaU8Mask(dstIt.rawData(), selectionIt.rawData(), pixels);<br></font><br>Pros:<br>+ may (i&#39;m not sure) be a bit faster than the second solution<br>Cons:<br>- all the filters should be modified (in case they are broken, of course)<br>
- the architecture as a whole is quite complex (too many roles for the filter class;  more parameters are given to the filter in comparison with the second solution)<br>- the work of filter-developers is more difficult. More than that, it&#39;s really unneeded work for them and the fact they should work with selections discloses our internals of selections framework, that breaks encapsulation.<br>
<br><br>2) Remove all the selection stuff from filters. Just modify caller&#39;s code: filter a layer onto a temporary paint device and bitBlt it to destination device then (with selection turned on in KisPainter).<br><br>
Pros:<br>+ the system is clear KisFilter - works with filtering only, KisPainter - works with selections<br>+ it&#39;s much easier to write new filters, you shouldn&#39;t bother with selections<br>+ we do not disclose our internals to filter developers<br>
+ this solution fits very well into Adj. layers stuff (as it&#39;s already have additional device - projection)<br>Cons:<br>- can be a bit slower because of cold cache (two cycles instead of one)<br>- can be MUCH slower with selections with holes inside<br>
- fits not so well into Filter masks stuff as it needs additional paint device<br><br><br>What can you say about this?<br>For me, i like the second case for simplicity of the design and maintainability, but i&#39;m afraid of some perfomance problems.<br>
<br>How should i solve this problem? Any ideas?<br><br><br>PS:<br><br>Btw, where are filters called form in Krita? I know only three places:<br>- adj. layers<br>- filter masks<br>- filter menu (actually, uses masks)<br><br>
PPS:<br>Btw, this bug seems to be present in Blur filter too.<br clear="all"><br>-- <br>Dmitry Kazakov<br>