QPixmap vs. QImage

转载 2015年11月21日 15:12:09

Development/Tutorials/Graphics/Performance

Contents

QPixmap vs. QImage

QPixmap and QImage both contain images, but there is a key difference between the two that's important to understand when writing graphics code.

QImage

When you're using a QImage, the image data is stored your application's memory in a format of your choosing. This has the advantage that you can easily get to and manipulate the pixel data directly.

The disadvantages are that QPainter can't take advantage of the graphics hardware when rendering to a QImage. In other words, all rendering to a QImage is done without hardware acceleration.

QPixmap

When you're using a QPixmap, the image data is not stored in your application's memory, but in the X server process, and possibly in video RAM. The data stored in the QPixmap object itself is just a serial number that refers to the image in the X server (the pixmap).

The disadvantage of using a QPixmap is that you can't get to the pixel data directly, since it's out of process. QPainter can only manipulate a QPixmap indirectly, by sending requests to the X server asking it to manipulate the pixmap.

The advantage is that the X server can use the graphics hardware to do this, which means that when drawing on a QPixmap, you get hardware acceleration.

Conversions are expensive

Converting a QImage to a QPixmap is an expensive operation because the image data must first be converted to the appropriate format for pixmaps, and then be marshalled and sent over the socket to the X server.

Converting a QPixmap to a QImage is an even more expensive operation, because in order to do so your application must first send a request to the X server asking it to send the pixmap data to your application. It must then block and wait, first for the X server process to be scheduled in by the kernel, then while the X server marshalls and sends the pixmap data over the socket. When your application has received the data, it must then convert it to an appropriate QImage format.

Converting a QImage to a QPixmap is a less expensive operation because it's a fire-and-forget operation. Your application doesn't have to wait for the X server to receive the image data after the data has been written to the socket. It can simply continue executing.

Keep in mind that a QImage can't be drawn on a QPixmap or a QWidget without first being converted to a QPixmap. QPainter does this implicitly when you call QPainter::drawImage() on a QPixmap or a QWidget. Likewise, a QPixmap can't be drawn on a QImage without first being converted to a QImage.

 QPainter::setOpacity()

Never call QPainter::setOpacity() when painting on a QPixmap or a QWidget. QPainter::setOpacity() effectively disables all hardware acceleration, causing all subsequent rendering operations to be done in software. This means that a call to QPainter::setOpacity() in a performance critical path is the kiss of death.

 An alternative approach to the problem

If you're drawing something with a solid color, such as a QPainterPath, a line, a rectangle etc., the easiest and also the fastest solution is to just change the alpha value of the color you're using, like this:

<a target=_blank href="http://doc.trolltech.com/latest/qcolor.html" style="color: rgb(202, 0, 0); text-decoration: none;"><span style="color: rgb(34, 170, 221);">QColor</span></a> c <span style="color: rgb(0, 110, 40);">=</span> color<span style="color: rgb(0, 110, 40);">;</span>
c.<span style="color: rgb(43, 116, 199);">setAlphaF</span><span style="color: rgb(0, 110, 40);">(</span>c.<span style="color: rgb(43, 116, 199);">alphaF</span><span style="color: rgb(0, 110, 40);">(</span><span style="color: rgb(0, 110, 40);">)</span> <span style="color: rgb(0, 110, 40);">*</span> opacity<span style="color: rgb(0, 110, 40);">)</span><span style="color: rgb(0, 110, 40);">;</span>

If you're using pixmaps, gradients or brushes that you can't easily change the opacity of, you should use the following method instead.

Create a temporary pixmap, initialize it to fully transparent, and then draw on it with normal opacity. When you're done drawing on it, use the DestinationIn composition mode to reduce the alpha of the pixmap, and then draw the pixmap itself where you want the semi-transparent contents. If you need the same content again (for example when you're doing a fade out or fade in animation), it might pay off to cache the fully opaque version.

<a target=_blank href="http://doc.trolltech.com/latest/qpixmap.html" style="color: rgb(202, 0, 0); text-decoration: none;"><span style="color: rgb(34, 170, 221);">QPixmap</span></a> pixmap<span style="color: rgb(0, 110, 40);">(</span>size<span style="color: rgb(0, 110, 40);">)</span><span style="color: rgb(0, 110, 40);">;</span>
pixmap.<span style="color: rgb(43, 116, 199);">fill</span><span style="color: rgb(0, 110, 40);">(</span><a target=_blank href="http://doc.trolltech.com/latest/qt.html" style="color: rgb(202, 0, 0); text-decoration: none;"><span style="color: rgb(34, 170, 221);">Qt</span></a><span style="color: rgb(0, 110, 40);">::</span><span style="color: rgb(43, 116, 199);">transparent</span><span style="color: rgb(0, 110, 40);">)</span><span style="color: rgb(0, 110, 40);">; //设置透明 QColor(0,0,0,0)</span>
 
<a target=_blank href="http://doc.trolltech.com/latest/qpainter.html" style="color: rgb(202, 0, 0); text-decoration: none;"><span style="color: rgb(34, 170, 221);">QPainter</span></a> p<span style="color: rgb(0, 110, 40);">;</span>
p.<span style="color: rgb(43, 116, 199);">begin</span><span style="color: rgb(0, 110, 40);">(</span><span style="color: rgb(0, 110, 40);">&</span>pixmap<span style="color: rgb(0, 110, 40);">)</span><span style="color: rgb(0, 110, 40);">;</span>
 
<span style="color: rgb(136, 136, 136);">// Do the rendering with full opacity</span>
 
p.<span style="color: rgb(43, 116, 199);">setCompositionMode</span><span style="color: rgb(0, 110, 40);">(</span><a target=_blank href="http://doc.trolltech.com/latest/qpainter.html" style="color: rgb(202, 0, 0); text-decoration: none;"><span style="color: rgb(34, 170, 221);">QPainter</span></a><span style="color: rgb(0, 110, 40);">::</span><span style="color: rgb(43, 116, 199);">CompositionMode_DestinationIn</span><span style="color: rgb(0, 110, 40);">)</span><span style="color: rgb(0, 110, 40);">;</span>
p.<span style="color: rgb(43, 116, 199);">fillRect</span><span style="color: rgb(0, 110, 40);">(</span>pixmap.<span style="color: rgb(43, 116, 199);">rect</span><span style="color: rgb(0, 110, 40);">(</span><span style="color: rgb(0, 110, 40);">)</span><span style="color: rgb(0, 110, 40);">,</span> <a target=_blank href="http://doc.trolltech.com/latest/qcolor.html" style="color: rgb(202, 0, 0); text-decoration: none;"><span style="color: rgb(34, 170, 221);">QColor</span></a><span style="color: rgb(0, 110, 40);">(</span>0<span style="color: rgb(0, 110, 40);">,</span> 0<span style="color: rgb(0, 110, 40);">,</span> 0<span style="color: rgb(0, 110, 40);">,</span> opacity<span style="color: rgb(0, 110, 40);">)</span><span style="color: rgb(0, 110, 40);">)</span><span style="color: rgb(0, 110, 40);">;</span>
p.<span style="color: rgb(43, 116, 199);">end</span><span style="color: rgb(0, 110, 40);">(</span><span style="color: rgb(0, 110, 40);">)</span><span style="color: rgb(0, 110, 40);">;</span>
 
painter<span style="color: rgb(0, 110, 40);">-></span><span style="color: rgb(43, 116, 199);">drawPixmap</span><span style="color: rgb(0, 110, 40);">(</span>0<span style="color: rgb(0, 110, 40);">,</span> 0<span style="color: rgb(0, 110, 40);">,</span> pixmap<span style="color: rgb(0, 110, 40);">)</span><span style="color: rgb(0, 110, 40);">;</span>

Note that you can check if setOpacity() is fast by calling painter->paintEngine()->hasFeature(QPaintEngine::ConstantOpacity), but my recommendation is to avoid it completely since it won't be fast on our main platform with the current Qt version (4.4).

QPainter::drawLine()

If you're drawing a fully horizontal or fully vertical opaque line, with a solid cosmetic (zero width) pen, you should disable anti aliasing before calling this function.

In all other cases you should make sure anti-aliasing is enabled before calling this function.

QPixmap::setAlphaChannel()

Never use QPixmap::setAlphaChannel() to make a pixmap semi-transparent. In fact you should never ever call QPixmap::setAlphaChannel() for any reason if you can avoid it. This function will convert both pixmaps to images (this involves two blocking synchronous calls to the X server, plus expensive image transport over the socket for each call), expensive format conversion of both images, copying the alpha channel one pixel at a time from the alpha image to the other image, followed by a final conversion of the resulting image back to a pixmap (which is also a very expensive operation).

The right way to do it

Check if the pixmap has an alpha channel, using QPixmap::hasAlphaChannel(). If it has one, start a QPainter on the pixmap, and reduce the alpha using the DestinationIn composition mode. If the pixmap doesn't have an alpha channel, you're going to have to create a new pixmap that has one and copy the content of the original pixmap into it, like this:

<a target=_blank href="http://doc.trolltech.com/latest/qpixmap.html" style="color: rgb(34, 0, 0); text-decoration: none;"><span style="color: rgb(34, 170, 221);">QPixmap</span></a> temp<span style="color: rgb(0, 110, 40);">(</span>pixmap.<span style="color: rgb(43, 116, 199);">size</span><span style="color: rgb(0, 110, 40);">(</span><span style="color: rgb(0, 110, 40);">)</span><span style="color: rgb(0, 110, 40);">)</span><span style="color: rgb(0, 110, 40);">;</span>
temp.<span style="color: rgb(43, 116, 199);">fill</span><span style="color: rgb(0, 110, 40);">(</span><a target=_blank href="http://doc.trolltech.com/latest/qt.html" style="color: rgb(202, 0, 0); text-decoration: none;"><span style="color: rgb(34, 170, 221);">Qt</span></a><span style="color: rgb(0, 110, 40);">::</span><span style="color: rgb(43, 116, 199);">transparent</span><span style="color: rgb(0, 110, 40);">)</span><span style="color: rgb(0, 110, 40);">;</span>
 
<a target=_blank href="http://doc.trolltech.com/latest/qpainter.html" style="color: rgb(202, 0, 0); text-decoration: none;"><span style="color: rgb(34, 170, 221);">QPainter</span></a> p<span style="color: rgb(0, 110, 40);">(</span><span style="color: rgb(0, 110, 40);">&</span>temp<span style="color: rgb(0, 110, 40);">)</span><span style="color: rgb(0, 110, 40);">;</span>
p.<span style="color: rgb(43, 116, 199);">setCompositionMode</span><span style="color: rgb(0, 110, 40);">(</span><a target=_blank href="http://doc.trolltech.com/latest/qpainter.html" style="color: rgb(202, 0, 0); text-decoration: none;"><span style="color: rgb(34, 170, 221);">QPainter</span></a><span style="color: rgb(0, 110, 40);">::</span><span style="color: rgb(43, 116, 199);">CompositionMode_Source</span><span style="color: rgb(0, 110, 40);">)</span><span style="color: rgb(0, 110, 40);">;</span>
p.<span style="color: rgb(43, 116, 199);">drawPixmap</span><span style="color: rgb(0, 110, 40);">(</span>0<span style="color: rgb(0, 110, 40);">,</span> 0<span style="color: rgb(0, 110, 40);">,</span> pixmap<span style="color: rgb(0, 110, 40);">)</span><span style="color: rgb(0, 110, 40);">;</span>
p.<span style="color: rgb(43, 116, 199);">setCompositionMode</span><span style="color: rgb(0, 110, 40);">(</span><a target=_blank href="http://doc.trolltech.com/latest/qpainter.html" style="color: rgb(202, 0, 0); text-decoration: none;"><span style="color: rgb(34, 170, 221);">QPainter</span></a><span style="color: rgb(0, 110, 40);">::</span><span style="color: rgb(43, 116, 199);">CompositionMode_DestinationIn</span><span style="color: rgb(0, 110, 40);">)</span><span style="color: rgb(0, 110, 40);">;</span>
p.<span style="color: rgb(43, 116, 199);">fillRect</span><span style="color: rgb(0, 110, 40);">(</span>temp.<span style="color: rgb(43, 116, 199);">rect</span><span style="color: rgb(0, 110, 40);">(</span><span style="color: rgb(0, 110, 40);">)</span><span style="color: rgb(0, 110, 40);">,</span> <a target=_blank href="http://doc.trolltech.com/latest/qcolor.html" style="color: rgb(202, 0, 0); text-decoration: none;"><span style="color: rgb(34, 170, 221);">QColor</span></a><span style="color: rgb(0, 110, 40);">(</span>0<span style="color: rgb(0, 110, 40);">,</span> 0<span style="color: rgb(0, 110, 40);">,</span> 0<span style="color: rgb(0, 110, 40);">,</span> opacity<span style="color: rgb(0, 110, 40);">)</span><span style="color: rgb(0, 110, 40);">)</span><span style="color: rgb(0, 110, 40);">;</span>
p.<span style="color: rgb(43, 116, 199);">end</span><span style="color: rgb(0, 110, 40);">(</span><span style="color: rgb(0, 110, 40);">)</span><span style="color: rgb(0, 110, 40);">;</span>
 
pixmap <span style="color: rgb(0, 110, 40);">=</span> temp<span style="color: rgb(0, 110, 40);">;</span>



FROM:  http://blog.csdn.net/mociml/article/details/4840207

QPixmap与QImage的相互转化

QString path = "E:/image.jpg";   QPixmap-->QImage: QPixmap pix(path); QImage img = pix.toImage()...
  • DK29030901065
  • DK29030901065
  • 2015年11月24日 20:02
  • 484

QImage与QPixmap完全解析

转载自http://www.civilnet.cn/bbs/browse.php?topicno=4691 用Qt程序在手机上显示一幅图片对编程人员来说是再基...
  • jiong_1988
  • jiong_1988
  • 2012年04月18日 09:33
  • 15732

QImage和QPixmap小区别

如果单纯的show出来一张图片,不做操作,选用QPixmap效率高一些,如果带操作,使用QImage吧~   QImage是与设备无关,QPixmap是与设备相关   QPixmap是专门为了...
  • u014597198
  • u014597198
  • 2016年09月22日 18:19
  • 440

QImage与QPixmap

http://www.360doc.com/content/12/0228/09/7899729_190188690.shtml
  • tianzhijiaozi19
  • tianzhijiaozi19
  • 2016年09月02日 18:24
  • 214

QPixmap、QImage、QBitmap和QPicture的区别

·QImage与Qpixmap的区别      1、QPixmap主要是用于绘图,针对屏幕显示而最佳化设计,QImage主要是为图像I/O、图片访问和像素修改而设计的     ...
  • u011348999
  • u011348999
  • 2014年05月19日 15:57
  • 1906

QT三大绘图类:Qpixmap/QImage/Qpicture

QPixmap QImage QPicture 以上都是QPaintDevice的子类QPixmap 依赖硬件、加速显示、适合小图片 QPixmap的设计本来就是用来加速显示,用paint绘图时用...
  • ycyzrenlifei
  • ycyzrenlifei
  • 2016年09月30日 10:33
  • 1674

QPixmap vs. QImage

 Development/Tutorials/Graphics/PerformanceDevelopment | TutorialsContents1 QPixmap vs. QImage 1.1 Q...
  • mociml
  • mociml
  • 2009年11月20日 11:08
  • 3002

QImage Mat QPixmap转换

简介: Qt提供了四种类用于处理图像数据: QImage, QPixmap, QBitmap, QPicture。QImage用来设计优化I/O,对像素直接进行访问与操作。 QImage类支持多种...
  • u010945073
  • u010945073
  • 2016年11月23日 14:26
  • 1388

Qt绘制 QImage、QPixmap/事件处理

1. 在界面上绘制图片是遇到了问题,就是在tuo
  • jingjing123123jing
  • jingjing123123jing
  • 2014年11月23日 20:57
  • 1614

QImage与QPixmap加载图片效果 【两者的区别】

QImage与QPixmap加载图片 效果 . 分类: QT开发 qtQtQT PixmapTest::PixmapTest(QWidget *parent) : QDial...
  • linpuliang
  • linpuliang
  • 2014年08月21日 09:35
  • 2271
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:QPixmap vs. QImage
举报原因:
原因补充:

(最多只允许输入30个字)