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't know how to fix this well.<br>
<br>Let's take a look into KisColorTransformationFilter:<br><br><font face="courier new,monospace">KisHLineConstIteratorPixel srcIt = src->createHLineConstIterator(srcTopLeft.x(), srcTopLeft.y(), size.width());<br>
KisHLineIteratorPixel dstIt = dst->createHLineIterator(dstTopLeft.x(), dstTopLeft.y(), size.width());<br><br> for (int row = 0; row < 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() && pixels < conseqPixels) {<br> ++pixels;<br> }<br> inverter->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() && pixels < conseqPixels) {<br>
++ pixels;<br> }<br> } else {<br> pixels = conseqPixels;<br> inverter->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'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->createHLineConstIterator(srcTopLeft.x(), srcTopLeft.y(), size.width(), selection);</font><br><br>That is not a problem. The problem is:<br>
<br>* The filter can't update semi-selected pixel (0<selectedness<255). The destination pixel will be either fully substituted with a new one (selectedness>=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->transform(srcIt.oldRawData(), dstIt.rawData(), pixels);<br>
colorSpace->applyInverseAlphaU8Mask(dstIt.rawData(), selectionIt.rawData(), pixels);<br></font><br>Pros:<br>+ may (i'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'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'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's much easier to write new filters, you shouldn'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'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'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>