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