Mipmapping for canvas. Ideas and comments.
Dmitry Kazakov
dimula73 at gmail.com
Tue Jul 21 12:43:12 CEST 2009
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.
Pros:
+ we merge only small images, not fullsized big ones
+ as a consequence, filter layers and masks are applied much
faster
Cons:
- 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.
Pros:
+ 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
Cons:
- 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):
->updateCanvasProjection(rect)
->preScale()
->resizePrescaledImage(size)
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 {
public:
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);
private:
QVector<QImage> 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! =)
PS:
There are some points where i'm in doubt now:
1) Should we use KisProjectionCache for storing original image?
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
KisPresceledProjection::Private::prescaledQPixmap?
What is the difference and where are they mostly used?
--
Dmitry Kazakov
--
Dmitry Kazakov
More information about the kimageshop
mailing list