Wednesday, July 22, 2009

We are in trunk!

New Krita tile engine is in trunk now on! You can try, test, see, change it! =)

Just checkout a trunk and switch engine in krita/image/CMakeLists.txt file
To activate a new one set USE_TILESYSTEM to '3'

Tuesday, July 21, 2009

Mipmapping for Krita's canvas subsys

Hi, all!

The tile engine has already come over to a quite stable state by this moment. I think today i'll publish patches for trunk. So now i'm publishing my ideas about mipmapping feature of viewing mechanism.

Well, mipmapping could be added in two parts of krita: the first - before actual merging and the second - after merging.

* The first could be done inside KisPaintDevice class and all merging would be done with prescaled images.

+ we merge only small images, not fullsized big ones
+ as a consequence, filter layers and masks are applied much

- too much overhead, in memory and in cpu time. Actually, a huge
piece of work is done for nothing. Parts of image pyramids
will never be used at all.
- complexity of the system: alignment between layers
- probable artefacts caused by merging after scaling

* The second - in KisPrescaledProjection. We merge original images, then create a pyramid of a projection and scale at last.

+ not so much overhead as we create only one pyramid for a view
+ zooming works fast thanks to the pyramid
+ no scale-merge artefacts.
+ no problems with alignment

- no help to filter layers

I think the second variant is better. At least for the beginning. So i'm going to add it to KisPrescaledProjection. More than that, i could try to make this image pyramid as encapsulated of the canvas subsystem as possible, so in fueature it could be ported to a paint device if needed, or even made as a template.

As i investigated, KisPrescaledProjection have three main entry points (input methods):


These methods fit for image pyramid very well:

updateCanvasProjection() would start a thread that would eventually update pyramid

preScale() would request scaled image from pyramid.
It would look like:
QPainter gc(m_prescaledQImage);
m_imagePyramid.drawScaledImage(gc, ..., ..., scale);

Here is a mockup of an interface of a KisImagePyramidClass:

class KisImagePyramid {
void updateCanvasProjection(QRect rect);

* Here are some problems with scaleX/scaleY
* as for image pyramid they should be equal
void drawScaledImage(QPainter gc,
QPointF topLeftScaled /* target topLeft point */,
QRect rectUnscaled /* source rect in image */,
qreal scale);
QVector m_pyramid;

KisProjectionCache /* or QImage */ m_original;
QThreadPool m_pyramidUpdater;

What do you think about this idea? Maybe i've missed something?
As always, comments are welcome! =)

There are some points where i'm in doubt now:

1) Should we use KisProjectionCache for storing original image or simple QImage? I guess not, because it could be used much in drawScaledImage much.

2) Which zoom-levels should be stored inside m_pyramid? I saw that when you press Ctrl+'+'/'-' Krita switches across some finite number of levels. Which part of Krita/Koffice decides, which levels to use? I guess, these levels and levels in m_pyramid should agree :)

3) KisPresceledProjection::Private::prescaledQImage vs
What is the difference and where are they mostly used?