PDA

View Full Version : QGraphicsPixmapItem and zooming - bad quality workaround, solution?



huilui
16th September 2013, 22:02
Hi guys,

I have a little problem concerning a GraphicsView/-PixmapItem and zooming. Well, let me first explain the problem and my current workaround, and then my attempt to solve it (which fails so far): (I'm using Qt4.8 btw)

I'm displaying an image in a QGraphicsView (ot the scene of it, if you want) using the QGraphicsPixmapItem (well, I actually subclassed it already, but that shouldn't matter here I think). If the image is bigger than the available space, then I scale it down to the right dimensions. That works quite well so far.
Now, in the application it is also possible to zoom the image. Currently, whenever somebody zooms the image in, right before the first zoom step I quickly replace the scaled down image with the full image zoomed out (so that it has the same dimensions as the scaled image) and then use QGraphicsView::scale() for zooming. The problem is, that if the image is quite big and I zoom it out a lot to fit the view, the displayed quality becomes really bad, it's pretty pixeled.

So, that's the problem (zooming an image), and my workaround (scale down image, replace with full image zoomed out).

Now, here are my attempts to solve this problem, i.e. to make an image zoomable while still looking good:

Attemp #1:
I set the following render hints to the GraphicsView:

this->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
Needless to say, that this doesn't change anything. Would have been to easy a fix.

Attempt #2:
I created a class where I always load the full image stored away in a QImage. Whenever I want to display an image I get a scaled copy of the full image from the class and display it.
In theory, that should work quite okay, but all my attempts to properly position the bigger/smaller image failed. The new position of the zoomed image depends on if the zoom was triggered via mouse or via keyboard shortcut. If it was triggered via mouse, then I want to keep the same spot where the mouse cursor was before to be the spot where it is afterwards (if possible, depending on dimensions and zoom step). If triggered via keyboard shortcut, then I want to keep the same spot that was in the center before the zoom step to be in the center again after the zoom step.
In order to achieve this, I tried to use the QCursor::pos() function in combination with the QGraphicsView::mapToParent() and mapFromParent() (I also tried it with mapToGlobal() and mapFromGlobal()), but I wasn't able to position the image at the right spot again afterwards (using QGraphicsPixmapItem::setPos() and QGraphicsView::centerOn()).
Then I tried to achieve this using the scrollbars and their values, just adding a certain proportion to them to ensure that they are in the same relative position afterwards as they have been before:

float scrollVertPos = float(graphicsView->verticalScrollBar()->value())/float(graphicsView->verticalScrollBar()->maximum());
float scrollHorPos = float(graphicsView->horizontalScrollBar()->value())/float(graphicsView->horizontalScrollBar()->maximum());
(...)
graphicsView->verticalScrollBar()->setValue(scrollVertPos * graphicsView->verticalScrollBar()->maximum());
graphicsView->horizontalScrollBar()->setValue(scrollHorPos * graphicsView->horizontalScrollBar()->maximum());
But this approach also didn't work, the view always centered almost all the way at the top left.


I'm kindy out of ideas what else to try... anybody has any ideas or suggestions? I'd really appreciate it!

Regards
huilui