转载自http://www.civilnet.cn/bbs/browse.php?topicno=4691

用Qt程序在手机上显示一幅图片对编程人员来说是再基础不过的一件事情了。那么先让大家看两段代码:

//dangerous should not be used, cannot display earth.png,  
//but if we change earth.png to a smaller image e.g. apple.png, apple.png can be displayed
QPixmap pixmap;
pixmap.load( ":/pics/earth.png" );
label->setPixmap( pixmap );

//dangerous should not be used, cannot display earth.png,  
//but if we change earth.png to a smaller image e.g. apple.png, apple.png can be displayed
QPixmap pixmap;
pixmap.load( ":/pics/earth.png" );
QPainter painter(this);
painter.drawPixmap(0,0, pixmap);
大家认为这两段代码有什么问题吗? 看起来好像没什么问题啊。是的,在Windows操作系统上是没有问题的。问题是我们做的是Qt for Symbian! 手机上的资源本来就是比较紧缺的,所以我们使用的时候就需要更加注意。 Qt 为我们提供了四个处理图像的类:QImage,QPixmap,QBitmap 和QPicture。其中前两个是最常使用的。

本文就通过一个例子,一步一步为大家讲解QImage与QPixmap的使用奥秘,在此过程中为大家揭示以上代码存在的缺陷。

 
 
     
 
QPixmap依赖于硬件

首先需要知道的是QPixmap的具体实现是依赖于系统的。在Symbian系统上QPixmap是被存放在Server端的。 
目前的Qt会把QPixmap都存储在graphics memory中,这明显是依赖硬件的。因此我们对QPixmap的使用需要格外注意。这也正是以上两段代码存在问题的根源。
那么Qt为什么要这么做呢?很简单,设计之初QPixmap就是用来加速显示的,例如我们在paint的时候用QPixmap就会比用其他类的效果好许多。

现在回到我们最初的问题,以上代码到底有什么问题呢?我们可以先用本文提供的例子程序做个试验。当使用上述代码显示较小图片的时候(比如例子程序中的background.png 和apple.png)是没有问题的,图片都能在手机上正确显示。
但是当我们把图片换成一副较大图片287KB,1058 x 1058的“earth.png”的时候就出现问题了,图片无法显示,程序的界面是一片空白。

据测算,“earth.png”被完全解码后存储在graphics memory中会占用大约4.3MB的空间。如果此时还有其他加载的窗口和QPixmap,很可能就没有空间了。

 
 
     
 
 
 
使用QImage加载后转换成QPixmap 显示

那么安全和正确的方法应该是什么呢?答案是我们需要用QImage做一下预处理:

//correct and recommended way
QImage image;
image.load( ":/pics/earth.png" );

QPainter painter(this);
QPixmap pixmapToShow = QPixmap::fromImage( image.scaled(size(), Qt::KeepAspectRatio) );
painter.drawPixmap(0,0, pixmapToShow);
和QPixmap 不同,QImage是独立于硬件的,它可以同时被另一个线程访问。QImage是存储在客户端的,对QImage的使用是非常方便和安全的。 又由于 QImage 也是一种QPaintDevice,因此我们可以在另一个线程中对其进行绘制,而不需要在GUI 线程中处理,使用这一方式可以很大幅度提高UI响应速度。 因此当图片较大时,我们可以先通过QImage将图片加载进来,然后把图片缩放成需要的尺寸,最后转换成QPixmap 进行显示。 下图是显示效果(图片是按照earth.png的原始尺寸比例缩放后显示的):

其中需要注意的是Qt::KeepAspectRatio的使用,默认参数是Qt::IgnoreAspectRatio,如果我们在程序中这么写:

QPixmap pixmapToShow = QPixmap::fromImage( image.scaled(size(), Qt::IgnoreAspectRatio) );
效果就是下面这个样子,earth.png被拉伸以充满整个屏幕:

 
 
     
 
 
 
直接使用QImage 显示

我们也可以直接使用QImage做显示,而不转换成QPixmap ,这要根据我们应用的具体需求来决定,如果需要的话我们可以这么写:

//correct, some times may be needed
QImage image;
image.load( ":/pics/earth.png" );

QPainter painter(this);
painter.drawImage(0,0, image);
下面是显示效果(当然我们也可以对其进行缩放之后再显示) 从图片可以看出来它是按照原始尺寸显示earth.png的:

测试设备

本代码已通过在N97和N8上的测试。

 
 
     
 
 
 
下载样例程序:
http://www.forum.nokia.com/piazza/wiki/images/f/f0/ImageTest.zip?20100915060150

QImage与QPixmap完全解析的更多相关文章

  1. 如何正确地在手机上显示图片——QImage与QPixmap完全解析

    引言 用Qt程序在手机上显示一幅图片对编程人员来说是再基础不过的一件事情了.那么先让大家看两段代码: //dangerous should not be used, cannot display ea ...

  2. QImage与QPixmap加载图片效果(QImage不能拉伸图片,QPixmap默认拉伸图片)

    QImage与QPixmap加载图片 效果 . 分类: QT开发 qtQtQT PixmapTest::PixmapTest(QWidget *parent) : QDialog(parent) {t ...

  3. Qt 编程指南10 QImage Mat QPixmap转换

      //示例 pushButtonOpenPicBig按钮clicked单击动作触发 void Qt_Window::on_pushButtonOpenPicBig_clicked() { strin ...

  4. 【资料收集】Converting Between cv::Mat and QImage or QPixmap

    参考: 方法一 Convert between cv::Mat and QImage 两种图片类转换 - Grandyang - 博客园 http://www.cnblogs.com/grandyan ...

  5. Qt的4个图像类QImage/QPixmap/QBitmap/QPicture 转

    Qt的4个图像类QImage/QPixmap/QBitmap/QPicture 转 (一)QPixmap和QImage的区别 http://www.thisisqt.com/forum/viewthr ...

  6. bryce1010的图像处理课程设计

    一.要求 完成课程教学中的大部分图像处理功能 二.平台 Qt c++ windows或者linux下 三.思路收集 1.QPixmap类 (一)QPixmap和QImage的区别 QPixmap是专门 ...

  7. Qt QPixmap和QImage的相互转换

    QPixmap转为Image: QPixmap pixmap; pixmap.load("../Image/1.jpg"); QImage tempImage = pixmap.t ...

  8. Qt QPixmap QImage 图片等比例缩放到指定大小

    QPixmap pixmap(path); //pixmap=QPixmap::fromImage(imgShow); pixmap = pixmap.scaled(, , Qt::KeepAspec ...

  9. [Qt2D绘图]-05绘图设备-QPixmap&&QBitmap&&QImage&&QPicture

    这篇笔记记录的是QPainterDevice(绘图设备,可以理解为一个画板) 大纲:     绘图设备相关的类:QPixmap QBitmap QImage QPicture     QPixmap ...

随机推荐

  1. springMVC前后台交互

    后台返回json对象: package com.sawshaw.controller; import org.springframework.stereotype.Controller; import ...

  2. MJExtension的一些实用技巧

    1.在代码文件中 引入"MJExtension.h" :解决属性中的命名和服务端传过来的数据中的key不同的问题 -(NSDcitionrary *)replacedkeyFrom ...

  3. Shell if else

    语句1if [ expression ]then ...fi 语句2if [ expression ]then ...else ...fi 语句3if [ expression 1 ]then ... ...

  4. flask BytesIO() 多个文件打包下载 zipfile

    使用zipfile模块可以将多个文件打包成zip文件进行下载,但是常规的操作方式会在服务器磁盘上生成一个zip文件占用磁盘空间. 后引入BytesIO将文件写入到内存中然后下载: def dl_pla ...

  5. openstack 部署(Q版)-----keystone认证服务安装配置

    一.新建数据库及用户 CREATE DATABASE keystone; GRANT ALL PRIVILEGES ON keystone.* TO 'keystone'@'localhost' ID ...

  6. 查找算法:二分法查找及其python实现案例

    承接上一篇:查找:顺序查找与二分法查找,将二分法更多详细的python实现解题写下笔记. 简单方法 ''' 二分法查找在列表中的用户输入值,返回index 三种情况跳出循环体: LR相邻 LR位置重合 ...

  7. 区块链,Ethereum-Wallet

    https://blockchain.info/charts/transactions-per-second https://slock.it/     https://en.wikipedia.or ...

  8. zookeeper源码导入

    1 搭建步骤 1.1 到github中下载该项目 项目地址 https://github.com/apache/zookeeper.下载.zip包到本地解压. 解压后文件目录: 1.2 使用ant对源 ...

  9. Unity-反编译由IL生成的DLL文件

        本文由博主SunboyL原创,转载请注明出处:http://www.cnblogs.com/xsln/p/DLL_DeCompilation.html     在Unity实际开发过程中,我们 ...

  10. 【剑指offer】变态跳台阶

    一.题目: 一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级.求该青蛙跳上一个n级的台阶总共有多少种跳法. 二.思路: f(n)=f(n-1)+f(n-2)+...+f(0),f(1) ...