Bad paint performance on QImage with transparency
-
I'm subclassing QOpenGLWidget and overriding paintGL() to render video frames with images composed by edges detected in each frame( consider it as some sort of edge sharpening ). QPainter takes only 1 - 3 ms on rendering video frame, but 60 - 80 ms on the edge image. Code is presented below:
paintGL()
void VideoGLWidget::paintGL() { if(!queue_frames.isEmpty() && tml.state() == QTimeLine::Running) { QElapsedTimer timer; timer.start(); QPainter p(this); p.beginNativePainting(); p.setRenderHint(QPainter::Antialiasing, true); p.setRenderHint(QPainter::SmoothPixmapTransform, true); p.drawImage(rect(), queue_frames.first().first); //queue_frames stores QPair<QImage, qint64> qDebug() << "rendering video frame took" << timer.elapsed() << "ms"; if(!queue_edges.isEmpty()) { p.drawImage(rect(), queue_edges.first().first); //queue_edges stores QPair<QImage, qint64> } p.endNativePainting(); qDebug() << "paintGL took" << timer.elapsed() << "ms"; } }
Edge image is constructed this way:
QImage img(buf_edge, width, height, QImage::Format_Mono); //buf_edge is a XBM format array img.setColorCount(2); img.setColor(0, qRgba(0, 0, 0, 0)); img.setColor(1, qRgba(255, 0, 0, 255));
What is causing the second drawImage() to be so much slower than the first one?
-
Hi,
I wild guess: conversion from the current image format to something suitable for drawing.
-
Hi @SGaist ,
Thanks for the reply! Turns out your guess is right, converting the QImage to QPixmap takes about 50 ms and painting it takes about 10 ms. I went through QImage doc again and found something I neglected for a long time:Note: Avoid most rendering directly to most of these formats using QPainter. Rendering is best optimized to the Format_RGB32 and Format_ARGB32_Premultiplied formats, and secondarily for rendering to the Format_RGB16, Format_RGBX8888, Format_RGBA8888_Premultiplied, Format_RGBX64 and Format_RGBA64_Premultiplied formats
But now the question splits into two:
- Why does image with transparency takes more time to paint?
- How to improve efficiency (from construction to painting)?
-
I haven't check the implementation recently but there's likely a form of composition to do in order to properly respect the transparency.
Did you change the image format ?
-
@SGaist Ops, this actually reminds me to use ARGB instead of XBM for output, since it's a parallel operation done by CUDA. Now Format_ARGB32_Premutiplied does the job well. Thank you!
Though the topic can be marked solved now, I'm still wondering why QBitmap and mono format QImage can not be used directly for painting (looks like a bitmap is also converted to pixmap on drawPixmap()), sorry if it's a stupid basic question :)
-
AFAIK, only the
QImage::Format_Indexed8
cannot be painted on. But maybe we are not talking about the same thing. -
That's were I am not sure we are talking about the same thing. Are you talking about them as target for painting ?
-
One of the issue here is that the conversion must be done each time the draw method is called. If you know that your images will not change or not much then you should do the conversion upfront so that the painting can be optimized.