KisPainter::paintPolygon used in paintops

LukasT.dev@gmail.com lukast.dev at gmail.com
Tue Sep 29 13:25:50 CEST 2009


On Sunday 12 April 2009 13:00:05 Cyrille Berger wrote:
> On Friday 10 April 2009, LukasT.dev at gmail.com wrote:
> > > I don't share your analysis of the problem :/ In the callgrind you
> > > give, the creation of selection and objects isn't visible at all. The
> > > main cost I see is the computation of exactBounds (and worse here, we
> > > pay it twice). One might note, that those exactBounds aren't needed in
> > > this case, since we allready know the extent of the function.
> >
> > Which function? Can you describe it more? I would implement it, but I
> > don't see what you see..You are standing on the shoulders of giants?
> > Can you take me there? :)
> 
> If you look at fillPainterPath, you can see the cost is divided in two
> functions:
> KisPaintDevice::applySelectionMask
> QPainter::fillRect
> 
> The first function represent 56% of the total cost, and most of what is
>  done inside of that function can be avoided in our case. We don't need the
>  call to exactBounds (we allready know it, 38%), and we don't need the crop
>  (the paint device allready have the correct dimension, 17.80%). So
>  basically we would just have to transfer the selection mask from
>  "polygonMaskImage" to "polygon".
> 
> There is an other possible improvement, since we only create
> "polygonMaskImage" to apply on the "polygon" paint device, we can also edit
> directly the alpha channel of polygon.  So instead of
> 
>             KisRectIterator rectIt = polygonMask->createRectIterator(x, y,
> rectWidth, rectHeight);
> 
>             while (!rectIt.isDone()) {
>                 (*rectIt.rawData()) =
>  qRed(polygonMaskImage.pixel(rectIt.x() - x, rectIt.y() - y));
>                 ++rectIt;
>             }
> 
> You can do:
> 
>             KisRectIterator rectIt = polygon->createRectIterator(x, y,
> rectWidth, rectHeight);
> 
>             while (!rectIt.isDone()) {
> 	            polygon->colorSpace()->applyAlphaU8Mask(pixelIt.rawData(),
> qRed(polygonMaskImage.pixel(rectIt.x() - x, rectIt.y() - y)), 1);
>                   ++rectIt;
>             }
> 
> And then remove all reference to polygonMask.
> 
> > > An other area of improvement could be to not use the QPainter, and to
> > > directly fill the mask, there is most likely going to be a huge speed
> > > up as well, since QPainter::fillRect is to general for our purpose.
> >
> > How would you fill it then? Using what class?
> 
> When I first wrote the mail (or at least as far as I remember...), I
>  thought it would be tricky... since I first thought that it was the
>  fillPath and not fillRect the problem... ok back to the point, this should
>  be ultra easy. QPainter::fillRect is just used to clean th QImage (which
>  really makes me wonder why it is that slow... they might have improve that
>  in Qt4.5 or it might be worth investigation...), so probably a call to
> QImage::fill(qRgba(OPACITY_TRANSPARENT, OPACITY_TRANSPARENT,
> OPACITY_TRANSPARENT, 255)) should be enough, and quiet cheap.
> 
> Hope it's more clear now :)
> 

I'm back on this issue. Last time I did not put enough effort into this. Now 
I'm more inspired.
if fillPainterPath there is 

        fillPainter.fillRect(fillRect, paintColor(), OPACITY_OPAQUE);

if fillRect in kis_fill_painter there 

KoColor kc2(kc); // get rid of const
kc2.convertTo(device()->colorSpace());

We create QImage polygonMaskImage 
and two QColor in fillRect, fillPath

so for every particle is created so much objects...Remember the easy 
optimizations? [1] Maybe the easy solution would be to cache colors as much as 
possible..

[1] http://wiki.koffice.org/index.php?title=Krita/Optimization

CyrilleB: I hope to catch you on IRC and you could mentor me to implement 
improvements you mention...








More information about the kimageshop mailing list