[Qt-interest] Best way to zoom an image

Oliver.Knoll at comit.ch Oliver.Knoll at comit.ch
Fri Jan 21 11:33:48 CET 2011


On 2011-01-21 Mihail Mihail Naydenov wrote:

> I meant to subclass an (QGraphics)Item not the view itself. QGraphicsView is a
> framework, a canvas for Items (lightweight widgets).

And as a matter of fact there is exactly a QGraphicsPixmap item which renders... a pixmap! :)

This item can then easily be scaled with the usual Qt paint transformations (study the QPainter documentation, for example, to understand the "affine transformations" it supports. Don't worry, luckily you *don't* have to understand *much* of Algebra - Qt does it all for you ;) But a basic understanding of what a "matrix" is doesn't harm either. Anyway, a simple scale() call placed at the correct position could be already the solution.

But the question was: what is the *best* way to scale (aka zoom) an image. Do it with hardware support! If your image exceeds some ridiculous large size, lets say 4096 pixels in any dimension, tile it! Use pre-calculated "multiple resolutions" of your original image, blend between them. Or let OpenGL do the blending for you ("layered textures!"). Etc. etc.

One easy step to make use of hardware (OpenGL) scaling is to simply put the viewport of your QGraphicsView to a QGLWidget - et voila! There you go, hardware-accelerated pixmap scaling! Wasn't that easy?

That was the second best solution. The best is off course tile the pixmap yourself (see above, "ridiculous large pixmaps"), transfer the data to the GPU memory with GL pixel buffers, map the texture to two triangles which form a rectangle (note: OpenGL 3 and above deprecated the good old quads! And "immediate rendering" with the beloved glWhatever calls as well, while we're at it - but that just as a little side-note ;), use your own GL calls to render the pixmap into a QGLWidget! It doesn't get any faster than that!

Okay, if you stopped reading when I mentioned GPU, pixel buffers, textures...then rendering your pixmap into a QGraphicsScene on top of a GL enabled QGraphicsView might be just the best solution for you! And it is not that difficult, there are plenty of Qt examples doing exactly that! However, if your original pixmap really exceeds some ridiculous size, then it is really better to "tile" it and have different "resolutions" ready. It does not make sense to squeeze a 10'000 x 10'000 pixmap into a tiny screen of say 2000 x 2000 when zooming out! And likewise it does not make sense to scale the entire same pixmap with a zoom level of say 100, when the graphic engine then ends up clipping away 95% of the pixmap anyway in the end (but that part was scaled and hence wasted CPU cycles!).

Also you can improve "life scaling" by reduce the image quality while scaling, e.g. disable anti-aliasing while scaling. If the user does not scale for say 100 ms then you can quickly re-render the scene with anti-aliasing enabled again etc.

Happy scaling!
  Oliver
--
Oliver Knoll
Dipl. Informatik-Ing. ETH
COMIT AG - ++41 79 520 95 22





More information about the Qt-interest-old mailing list