photo_tom photo_tom - 11 months ago 113
C++ Question

Fast Updating of QPixmap from byte array

I'm working on a vision application and I need to have a "Live View" from the camera displayed on the screen using a QPixmap object. We will be updating the screen at 30frames/second on a continuous basis.

My problem is that this application has to run on some 3-5 year old computers that, by todays standards, are slow. So what I would like to do is to be able to directly write to the display byte array inside of QPixmap. After going through the program code, almost option for changing the contents of a Pixmap results in a new QPixmap being created. This is the overhead I'm trying to get ride of.

Additionally, I would like to prevent all the new/deletes from occurring just to keep memory fragmentation under control.

Any suggestions?

Answer Source

First of all, the most important piece of information regarding the "picture" classes in Qt:

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.

What this means is that QPixmap is a generic representation of your platform's native image format: Pixmap on Unix, HBITMAP on Windows, CGImageRef on the Mac. QImage is a "pixel array with operations" type of class.

I'm assuming the following:

  • You are reading raw camera frames in a specific pixel format
  • You really are having memory fragmentation issues (as opposed to emotionally having them)

My advice is to use QImage instead of QPixmap. Specifically, there is a constructor that accepts a raw byte array and uses it directly as the pixel buffer:

QImage::QImage(uchar *data, int width, int height, int bytesPerLine, Format format)

Having constructed a QImage, use a QPainter to draw it to a widget at the desired frequency. Be warned however that:

  • If you are reading raw camera frames, format conversion may still be necessary. Twice, in the worst case: Camera ➔ Qimage ➔ Platform Bitmap.
  • You cannot avoid memory allocation from the free store when using QPixmap and QImage: they are implicitly shared classes and necessarily allocate memory from the free store. (On the other hand, that means you should not new/delete them explicitly.)

Our team managed to display fullscreen compressed video smoothly on Atom-powered computers using only Qt (albeit at a lower framerate). If this does not solve your problem, however, I'd bypass Qt and use the native drawing API. If you absolutely need platform independence, then OpenGL or SDL may be good solutions.