QT drawing pixels to graphics scene - qt

I need to write a std::vector< double > values to a qGraphicsScene. (values between 0-1, each element represents a pixel - grayscale)
Later i want to access the pixels of the image for replace the color (i don't have time to replace the whole image)
thx. for the answer!

If you're wanting to do such low level modification, I'd recommend taking a look at the QImage class. Members such as QImage::setPixel will give you access to individual pixels for modification.
If you need this kind of functionality on a QGraphicsScene, then you could draw to the QImage and then convert that to a QPixmap (with QPixmap::convertFromImage) for use with a QGraphicsPixmapItem, and then place the QGraphicsPixmapItem onto the scene.
You may want to take a look at the generic Qt containers, such as QVector as well.

Related

Animating QGraphicsItem Efficiently

I have a QGraphicsSvgItem that I need to rotate a certain amount based on an external variable coming into my application. Currently I'm directly setting the rotation property of the item, but this appears to significantly drop my frame rate. (117.0 fps -> 98.0 fps) is this normal? Is this the correct way to animate a QGraphicsItem? I realize that the framerate sounds plenty high, but I'm concerned that as more items in the view are animated, that the performance will become a problem.
The code below is being called via a QTimer timeout signal at an interval of 0.
Note that I have also tried using a QGraphicsItem with a custom QPainterPath to draw the item rather than an SVG and it made no noticeable performance difference.
qreal diff = m_rope_length_ft[0] - m_rope_length_ft_prev[0];
qreal angle = diff * 5.0;
m_rope_reel[0]->setRotation(m_rope_reel[0]->rotation() + angle);
m_rope_reel[1]->setRotation(m_rope_reel[1]->rotation() + angle);
m_rope_reel[0]->update();
m_rope_reel[1]->update();
A more proper way to animate in Qt is to use QPropertyAnimation. It requires that:
your graphics item is inherited from both QObject and QGraphicsSvgItem;
rotation is registered as property with Q_PROPERTY (getters and setters already exist so there is no need to implement them).
Also you should try to tune graphics item's cache mode. ItemCoordinateCache seems to be suitable for your case. There is also view cache mode, but it's hard to say which is better in your case.
Note that performance optimization should be done using average amount of items your program should be able to process. Optimizing a single item rendering may be pointless.

QGraphicsView: How to efficiently get the viewport coordinates of QGraphicsItems?

Is there a fast way to get the viewport coordinates of QGraphicsItems in a QGraphicsView? The only way I can think of is to call QGraphicsView::items(), and then QGraphicsItem::pos() followed by QGraphicsView::mapFromScene.
I must be missing something, though, because items are already converted to viewport coordinates to position them correctly on the QGraphicsView, so converting it to viewport coordinates again with mapFromScene seems inefficient--especially because in my case this is occurring often and for many items. Is there a more direct approach?
Probably not. A QGraphicScene can be rendered by more than one QGraphicsView simultaneously. It makes no sense to keep only one set of view port coordinates.
Also. All operation between QGraphicsItems are calculated in scene coordinate directly. Events from view port are convert to scene before processing. Working off view port which is only integer-based can also loose precision. A QGraphicsView is only a representation of the mathematical model of a scene. It's not the actual model.
Maybe you can ask a more specific question on what exactly you are trying to accomplish. There may be a better way to do it in scene coordinate.

Qt, low cost way to display only part of large QImage

I draw frequency spectrum of WAV file inside QImage (example: http://savepic.net/2350314.jpg). The WAV file may be long enough to not fit into screen considering good time resolution.
I need to be able to srcoll through entire file fast enough, possibly without filesystem reading operations.
So i have to keep large QImage in memory for fast scrolling. Another desigion would be slower, because it would require me to redraw QImage (QImages) every time user scrolls a screen.
Assuming the desigion with keeping large QImage in memory (1024x50000, for example) i must be able to display some part of that large QImage in the program window.
What is the solution with lowest cost? Using QScrollArea or maybe using QPainter method drawImage() with offset arguments?
I would definitely build a small custom widget and reimplement its paint() method with a QPainter (and scrolling with offsets etc).
Using QPixmap for showing the needed parts of the image should be faster then natively drawing (a part of) a QImage.

Fastest way to draw 1024x1024 dots on screen

I am developing a program that must calculate a color of each point on a 1024x1024 picture using a special algorithm. The color of a point represents some value. So each point is independent of other points and must be drawn separately. I do not have to refresh the picture too frequently. Actually, I need to display it only once.
What is the fastest approach to drawing separate pixels in Qt?
Can I get some sort of "screen memory" and write all the picture as an array of 4-byte sets, representing each pixel as 4 bytes in that memory?
The QImage class is optimized for pixel manipulation. You can instantiate one with the requred size and then either set the pixels individually setPixel, or access the raw data and manipulate them in place via bits(). Just be sure to use the correct format (e.g. RGBA values or color indices for 8-bit images)
The fastest solution may be to create a QImage, manipulate it (set the pixels) and then get Qt to draw it.
The QImage class is for fast IO, from the manual:
The QImage class provides a hardware-independent image representation that allows direct access to the pixel data, and can be used as a paint device.
The QImage class supports several image formats described by the Format enum. These include monochrome, 8-bit, 32-bit and alpha-blended images which are available in all versions of Qt 4.x.
There is information on pixel manipulation in the Detailed Description section.
To display it the simplest way would be to convert it to a pixmap with QPixmap::fromImage and then put it in a label with QLabel::setPixmap.
For more control, you could sub-class QWidget, overload the paintEvent, and draw the QImage with a QPainter with QPainter::drawImage.
You might try to use an OpenGL widget and the glDrawPixels function.

How can QPainter performance be improved?

I have a large display (about 1000x2000 pixels) and I'm doing the following to draw images to the screen:
QImage *pImage = GetImage(); // from wherever
QPainter painter(this);
painter.drawImage((0,0), *pImage); // this line takes over 100ms to complete.
The larger the screen is that I'm drawing to, the longer this paint takes. I guess the pImage is being memcpy'd and that's the difference. How can I reduce this overhead? I'm not trying to scale or anything here.
Thanks.
You're painting a QImage. Don't do that, try with a QPixmap instead.
From the QImage documentation:
QImage is designed and optimized for I/O, and for direct pixel access and manipulation, while QPixmap is designed and optimized for showing images on screen."
Depending on the platform, getting the QImage data into the format and location needed for painting, can be extremely expensive.
P.S.: There is no need to create QImages on the heap, as
QImage objects can be passed around by value since the QImage class uses implicit data sharing.
One simple improvement you can make is to draw only the area that needs updated (if you can). The QPaintEvent contains a rect for the changed area, and the QPainter::drawImage has overloads that can take rects for the portion to draw.
You might also look at the ImageConversionFlags options for faster options.

Resources