PDA

View Full Version : Efficient Scaling and Rotating of QGraphicsView



forrestfsu
27th November 2006, 23:29
I currently have a function which I call to scale and rotate a QGraphicsView.

The function is:


void theForm::scaleView(qreal scaleFactor)
{
qreal scale = pow(2.0, (scaleFactor));
QMatrix matrix;
matrix.scale(scale, scale);
matrix.rotate(levelRotate); // LevelRotate is a global variable
ui.graphicsView->setMatrix(matrix);
}


The QGraphicsView has a Pixmap drawn on it from a drawBackground function override.

The function is:


void Override::drawBackground(QPainter *painter, const QRectF &rect)
{
...
painter->drawPixmap(0,0, theForm->getBackground()); // getBackground() returns a pixmap
}


This above code worked fine at scaling and rotating when getBackground() was returning a reasonable sized (~2mb | 512x600) QPixmap. But I increased the image size (~10mb | 2400x4600) that I was testing with. Now that I've implemented a much larger image, it lags far to much to be useful. So I had a couple questions. Does anyone know of a more efficient way to scale and rotate an image? I tried to call the QGraphicsView's scale and rotate functions directly (i.e graphicsView->rotate(1.2)), without using a QMatrix. That had no effect in speed, and I'm assuming those functions using a QMatrix anyways.

My second related question is that I set the cacheMode on the QGraphicsView to be QGraphicsView::CacheBackground. Since I had overridden the the QGraphicsView with the Override class, does it still cache the background? Does the CacheBackground flag even set the program to cache items that I'm painting through the drawBackground function?

Thanks in advance! I apologize this is so long...

wysota
27th November 2006, 23:42
You may try to use a GL widget as a viewport for the view. It might speed up the operation.

forrestfsu
8th December 2006, 01:01
I've been trying to put together some code based upon what was suggested and from looking at Qt's HelloGL example. I can't seem to piece anything together and it's probably because I don't understand completely what the solution is. From the suggestion am I trying to set the QGraphicsView's viewport to be a QGLWidget (is that possible)? If so, is the purpose of doing that to replace my current drawBackground function override and do the painting within the QGLWidget? Or is the purpose of creating a QGLWidget only supposed to be used for zooming and scaling? I'm obviously a bit confused...can you give me a little more detail on your suggestion.

Thanks :)

wysota
8th December 2006, 01:24
Take a look at the "chips" demo that comes with Qt.

forrestfsu
8th December 2006, 15:36
I didn't see any increase in performance from doing:



ui.graphicsView->setViewport(new QGLWidget(QGLFormat(QGL::SampleBuffers)));


I also attempted to use a variety of other format flags (i.e. NoAlphaChannel and NoOverlay) to see if that would speed up the process, but no luck. :(

I checked to make sure my system has OpenGL support using QGL::hasOpenGL() and it returned true, so that doesn't seem to be an issue.

I'm using one of NVIDIA's newer video cards, so can I assume that I wouldn't see far better results from another card.

Does anyone have any other advice to lead me in the right direction?

wysota
8th December 2006, 17:14
But do you use OpenGL functions for drawing the background? Using QPainter is not enough here, I think.

Maybe your bottleneck is not drawing, rotating or scaling the pixmap but actually creating it? What does getBackground() do?

forrestfsu
8th December 2006, 19:33
No, I don't use OpenGL to draw the background. I do use painter and here is the code:



void Override::drawBackground(QPainter *painter, const QRectF &rect)
{
painter->save();
painter->setBrush(Qt::black);
painter->drawRect(rect);
painter->drawPixmap(0,0, theForm->getBackground()); // getBackground() returns a pixmap
painter->restore();
}

QPixmap theForm::getBackground()
{
return backgroundImage; // This is an image stored in a classes QPixmap variable.
}

wysota
8th December 2006, 20:54
I'm not sure, but it is possible that you need to draw the background using OpenGL code. Unfortunately "chips" doesn't draw a background, so we can't check in the example...

The pixmap you're using is very big, so obviously transforming it is very expensive. I understand that the background is getting rotated and scaled when items get scaled and rotated, correct?

forrestfsu
12th December 2006, 15:13
I'm not quite sure I understand what you mean by "the background is getting rotated and scaled when items get scaled and rotated." So I'll try and explain:

This specific graphicsView has a scene which it shares with 5 other graphicsView's. The only difference with this graphicsView is that I use drawBackground() to give it a unique background Pixmap (in this case a very large pixmap). I have zoom and rotate buttons on the widget which call the ScaleView() function for this graphicsView. ScaleView() scales and rotates all the contents within this graphicsView (the scene contents and the large background Pixmap).

Hope this clears it up.

forrestfsu
12th December 2006, 15:31
An additional note. Once the user has scaled the image to a different ratio then the original, even using the scroll bars for the graphicsView lag moving the content of the graphicsView.

forrestfsu
12th December 2006, 17:28
I just fixed the problem (still a few minor bugs to go through). Instead of returning an entire Pixmap, I needed only return the area of the Pixmap that I needed to display using the QPixmap's copy function. After I have all the code in place I will paste it for review.

Thanks Wysota for all your help on this issue.