Image update strategy

Emanuele Tamponi emanuele at valinor.it
Fri Apr 4 19:05:31 CEST 2008


Hello,
As I was trying to say to boud in IRC, in these days I had a simple idea on 
how to manage in a "easy" way the layering that occours when a KisImage needs 
a repaint. boud assured me that the current strategy has a strong 
infrastructure, so I don't want to propose a "substitute", but just a 
suggestion and if you consider it a really good solution, we can take into 
account even the substitution.

Anyway, now I'll try to explain; as often happens with my explanations, I'm 
sure that it will be of almost no use, but still... perhaps with a few images 
and some code I'll be a bit more successful :) Let's start.

Consider a multi-layered image as in this picture:

<picture1>

Each rect is a layer. When this image is being built, a method finds all 
the "simple" (as in not-more-decomponible) regions of the image:

<picture2>

In this example, as you see in the picture, there are 4 regions. Each "region 
object" should contain a list of layers that it contains, from the bottommost 
to the topmost (so in a bottom-up order)

Region 1: Layer I
Region 2: Layer I and II
Region 3: Layer I, II and III
Region 4: Layer I and III

These region objects calculate a list of the layers that are *visible* in 
their region. In the example, consider layer III being completely opaque, 
while layers I and II are semi-opaque; and consider layer order being I, III, 
II (from bottom to top). Then:

Visible layers:
  - Region 1: Layer I
  - Region 2: Layer I and II
  - Region 3: Layer II and III (because layer I is under layer III that's 
completely opaque, and layer II is anyway above layer III)
  - Region 4: Layer III (because layer I is under layer III)

This region list can stay in KisImage, for example (in this explanation I'll 
put it in KisImage).

Now consider for example that we're playing with the freehand tool on layer 
II, without resizing it (just to keep this explanation simple); after some 
strokes, the dirtied area that needs to be updated is:

<picture3>

Now, instead of doing complex things, an update request is sent to who's 
responsible to do the composition of the image (KisCanvas?) and it will just 
do this very very simple algorithm:

For each region in the region list, we iterate bottom-up throught the 
*visible* layers of the curent region. Once we get a dirty layer in the 
current region, its dirty area is added to an "overall" dirty region, and an 
update projection is sent to that layer. This layer has just to take the 
projection of the layer that's below it (it can ask its KisImage's region 
list for it) and compose the projection with its paintdevice and effects and 
filter and whatever.
At the end of this process, each region in the region list will get updated 
all the projections in its layers. The "final" projection is just the 
projection of the topmost layer in each region.
We take these projections and convert them to the QImage that has to be drawn 
on the canvas.

This easily takes into account layer moving and resizing, since when such an 
event occours, it's just needed to recalculate the region list and then call 
the previous algorithm.

Clone layers are not a problem too, and adj. layers should work flawlessy.
No problems with group layers too.
And speed should not be a problem since the update projection is called just 
in the areas that need an update. To give you some sample pseudo-code:

if (layer pos/size is changed or layer added/removed/hidden/shown)
    updateRegionList();

overallDirty = empty region;

foreach region in currentKisImage->regionList
    foreach layer in region->visibleLayers()    // (bottom-up)
        overallDirty += layer->dirtyRegion()
        if (overallDirty.intersection(region) is not empty)
            layer->updateProjection(overallDirtyRegion.intersection(region))
    end
end

updatedProjection = currentKisImage->globalProjection(overallDirty);
updateQImage(updatedProjection);

This code can be put in KisCanvas2.
"globalProjection" is a function that just put together the various 
projections of the topmost layer of each region in the region list and 
returns just the dirtied area of them.
"updateQImage" should just call toQImage to the updatable regions.

I hope that the explanation is clear...

Emanuele
-------------- next part --------------
A non-text attachment was scrubbed...
Name: picture1.png
Type: image/png
Size: 8493 bytes
Desc: not available
Url : http://mail.kde.org/pipermail/kimageshop/attachments/20080404/6e81169d/attachment-0003.png 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: picture2.png
Type: image/png
Size: 12477 bytes
Desc: not available
Url : http://mail.kde.org/pipermail/kimageshop/attachments/20080404/6e81169d/attachment-0004.png 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: picture3.png
Type: image/png
Size: 22398 bytes
Desc: not available
Url : http://mail.kde.org/pipermail/kimageshop/attachments/20080404/6e81169d/attachment-0005.png 


More information about the kimageshop mailing list