前言

绘图设备是指继承 QPaintDevice 的子类,你可以使用 QPainter 直接在其上面绘制图形,Qt 一共提供了四个这样继承 QPaintDevice 的绘图设备类,分别是:QPixmap、QBitmap、QImage和 QPicture。其中:

  • QPixmap专门为图像在屏幕上的显示做了优化;
  • QBitmap是 QPixmap 的一个子类,它的色深限定为 1,你可以使用 QPixmap 的 isQBitmap() 函数来确定这个QPixmap 是不是一个 QBitmap;
  • QImage专门为图像的像素级访问做了优化;
  • QPicture则可以记录和重现 QPainter 的各条命令;
  • 下面我们将分两部分介绍这四种绘图设备。

一、QPixmap

QPixmap 继承了QPaintDevice,因此,可以使用 QPainter 直接在上面绘制图形。QPixmap 也可以接受一个字符串作为一个文件的路径来显示这个文件,比如想在程序之中打开 png、jpeg 之类的文件,就可以使用 QPixmap。使用 QPainter 的drawPixmap()函数可以把这个文件绘制到一个 QLabel、QPushButton 或者其他的设备上面。QPixmap 是针对屏幕进行特殊优化的,因此,它与实际的底层显示设备息息相关。注意,这里说的显示设备并不是硬件,而是操作系统提供的原生的绘图引擎。所以,在不同的操作系统平台下,QPixmap 的显示可能会有所差别。

Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);// Pixmap绘图设备,对显示做了优化// 指定宽高QPixmap pix(300, 300);// 填充颜色pix.fill(Qt::white);// 创建画家,并画一个圆QPainter painter(&pix);painter.setPen(QPen(Qt::green));painter.drawEllipse(QPoint(50,50), 50, 50);// 保存pix.save(/*路径*/);
}

二、QBitmap

QBitmap 继承自 QPixmap,因此具有 QPixmap 的所有特性,提供单色图像。QBitmap 的色深始终为 1。色深这个概念来自计算机图形学,是指用于表现颜色的二进制的位数。计算机里面的数据都是使用二进制表示的,为了表示一种颜色,也会使用二进制,比如要表示 8 种颜色,需要用 3 个二进制位,这时就说色深是 3。因此,所谓色深为 1,也就是使用 1 个二进制位表示颜色。1 个位只有两种状态:0 和 1,因此它所表示的颜色就有两种,黑和白。所以说,QBitmap 实际上是只有黑白两色的图像数据。由于 QBitmap 色深小,因此只占用很少的存储空间,所以适合做光标文件和笔刷。

三、QImage

QPixmap 使用底层平台的绘制系统进行绘制,无法提供像素级别的操作,而 QImage 则是使用独立于硬件的绘制系统,实际上是自己绘制自己,因此提供了像素级别的操作,并且能够在不同系统之上提供一个一致的显示形式。

Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);// QImage绘图设备,可以对像素访问// 指定宽高QImage img(300, 300, QImage::Format_RGB32);// 填充颜色img.fill(Qt::white);// 创建画家,并画一个圆QPainter painter(&img);painter.setPen(QPen(Qt::green));painter.drawEllipse(QPoint(50,50), 50, 50);// 保存img.save(/*路径*/);
}

使用 QImage 对像素进行访问:

void PaintWidget::paintEvent(QPaintEvent *)
{QPainter painter(this);// 利用QImage对像素进行修改QImage image(300, 300, QImage::Format_RGB32);//将图片背景填充为白色image.fill(Qt::white);//改变指定区域的像素点的值for(int i=50; i<100; ++i){for(int j=50; j<100; ++j){QRgb value = qRgb(255, 0, 0);image.setPixel(i, j, value);}}//将图片绘制到窗口中painter.drawImage(QPoint(0, 0), image);
}

四、QPicture

QPicture 是一个可以记录和重现 QPainter 命令的绘图设备。QPicture 将 QPainter 的命令序列化到一个 IO 设备,保存为一个平台独立的文件格式。这种格式有时候会是 “元文件(meta-files)”。Qt 的这种格式是二进制的,不同于某些本地的元文件,Qt 的 pictures 文件没有内容上的限制,只要是能够被 QPainter 绘制的元素,不论是字体还是 pixmap,或者是变换,都可以保存进一个 picture中。QPicture 是平台无关的,因此它可以使用在多种设备之上,比如 svg、pdf、ps、打印机或者屏幕。回忆上文所说的 QPaintDevice,实际上是说可以有 QPainter 绘制的对象。QPicture 使用系统的分辨率,并且可以调整 QPainter 来消除不同设备之间的显示差异。
如果要记录下 QPainter 的命令,首先要使用QPainter::begin()函数,将 QPicture 实例作为参数传递进去,以便告诉系统开始记录,记录完毕后使用QPainter::end()命令终止。

// 保存命令
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);// QPicture绘图设备,记录和重现绘图指令QPicture pic;// 创建画家QPainter painter;// 开始绘制painter.begin(&pic);painter.setPen(QPen(Qt::green));painter.drawEllipse(QPoint(50,50), 50, 50);// 结束绘制painter.end();// 保存到磁盘pic.save(/*路径*/);
}// 重现命令
void PaintWidget::paintEvent(QPaintEvent *)
{QPicture pic;//将保存的绘图动作重新绘制到设备上pic.load("D:\\drawing.pic");QPainter painter;painter.drawPicture(200, 200, pic);
}

五、QImage与pixmap的区别

1、QPixmap 主要是用于绘图,针对屏幕显示而最佳化设计,QImage 主要是为图像 I/O、图片访问和像素修改而设计的。

2、QPixmap 依赖于所在的平台的绘图引擎,故例如反锯齿等一些效果在不同的平台上可能会有不同的显示效果,QImage 使用 Qt 自身的绘图引擎,可在不同平台上具有相同的显示效果。

3、目前的 Qt 会把 QPixmap 都存储在 graphics memory 中,QImage 是存储在客户端的,是独立于硬件的。在 X11, Mac 以及 Symbian平台上,QPixmap 是存储在服务器端,而 QImage 则是存储在客户端,所以 QPixmap 上绘图比较慢,但显示它则比较快。但在 Windows 平台上,QPixmap 和 QImage 都是存储在客户端,并不使用任何的 GDI 资源,所以可能看起来并没有多大区别。

4、由于 QImage 是独立于硬件的,也是一种 QPaintDevice,因此我们可以在另一个线程中对其进行绘制,而不需要在 GUI 线程中处理,使用这一方式可以很大幅度提高 UI 响应速度。而 QPixmap 不可以使用在子线程中加载图片。

5、QImage 可通过 setPixpel() 和 pixel() 等方法直接存取指定的像素。

当图片小的情况下,直接用 QPixmap 进行加载,画图时无所谓,当图片大的时候如果直接用 QPixmap 进行加载,会占很大的内存,一般一张几十 K 的图片,用 QPixmap 加载进来会放大很多倍,所以一般图片大的情况下,用 QImage 进行加载,然后转成 QPixmap 绘制。QPixmap 绘制性能是最好的。

所以当绘画大图片时候,此时最好先使用 QImage 进行加载,因为 QImage 本身主要是为图像 I/O、图片访问和像素修改而设计的,它可以实现对图片旋转、缩放等。然后通过 QPixmap 实现绘图。

六、QPixmap与QImage相互转换

QImage image = pixmap.toImage();
QPixmap pixmap = QPixmap::fromImage(image);

七、视频显示的用法

QImage 准备好图像数据:

QImage nImage((uchar *)mAVFrameRGB->data[0], mTargetWidth, mTargetHeight, QImage::Format_RGB888);
emit displayImage(nImage); // 发送图片,显示图片

QPixmap 用于绘图显示数据:

void SatVideoWidget::showImage(QImage nImage){nImage = nImage.scaled(640*0.8, 480*0.8, Qt::KeepAspectRatio);mImageLabel->setPixmap(QPixmap::fromImage(nImage));qDebug("[D]Lin >> The VideoWidget Debug!==");
}// ```cpp
// 2、在paintEvent()中直接画
void MyWindow::paintEvent(QPaintEvent*)
{QPainter paint(this);paint.drawImage(0,0,*image);
}

QT 之绘图进阶: 图片绘图类QPixmap、QImage、QPicture相关推荐

  1. Qt实用技巧:使用Qt加载超大图片的耗时测试

    若该文为原创文章,未经允许不得转载 原博主博客地址:https://blog.csdn.net/qq21497936 原博主博客导航:https://blog.csdn.net/qq21497936/ ...

  2. QPixmap,QImage load图片失败问题

    Qt封装了很多关于图片加载的类,主要有QPixmap,QImage,QPicture,QBitmap四种.QImage一般用于数据流IO操作,运用此类可以直接获取像素详细信息:QPixmap:一般用于 ...

  3. Qt图片绘图类QPixmap、QImage、QPicture

    绘图设备是指继承 QPaintDevice 的子类,你可以使用 QPainter 直接在其上面绘制图形,Qt 一共提供了四个这样继承 QPaintDevice 的绘图设备类,分别是:QPixmap.Q ...

  4. 【QT 5 学习笔记-学习绘图相关+画图形图片等+绘图设备+基础学习(2)】

    [QT 5 学习笔记-学习绘图相关+画图形图片等+绘图设备+基础学习(2)] 1.说明 2.实验环境 3.参照连接 4.自己的学习与理解 5.学习与实践代码 (1)移动图片测试实验 (1)继续之前的工 ...

  5. matlab 进阶绘图:图片保存,极坐标绘图,函数绘图,等高线地图,三维条形图,三维散点图,gif 绘图

    本文所包含的绘图方式: 极坐标绘图,函数绘图,等高线地图,三维条形图,三维散点图,gif 绘图 1 常用命令 hold on; % 持续绘图 hold off; 1.1 标注 xlabel(''); ...

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

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

  7. Qt学习笔记之2D绘图

    一.概要 Qt中提供了强大的2D绘图系统,可以使用相同的API在屏幕和绘图设备上进行绘制,它主要基于QPainter.QPaintDevice和QPaintEngine这三个类.其中QPainter用 ...

  8. Qt中使用OpenGL进行绘图

    Qt Creator中的3D绘图及动画教程(参照NeHe) 刚刚学习了Qt Creator,发现Qt提供了QtOpenGL模块,对OpenGL做了不错的封装,这使得我们可以很轻松地在Qt程序中使用Op ...

  9. 【Qt OpenGL】Qt Creator中的3D绘图及动画教程

    Qt Creator中的3D绘图及动画教程(参照NeHe) 刚刚学习了Qt Creator,发现Qt提供了QtOpenGL模块,对OpenGL做了不错的封装,这使得我们可以很轻松地在Qt程序中使用Op ...

最新文章

  1. 看网友如何定义C++
  2. idea连接mysql
  3. java封装概念_Java面向对象----封装概念
  4. 9个适合web开发人员的CSS工具
  5. 卡尔曼滤波算法_GPS定位笔记3 (卡尔曼滤波定位算法)
  6. 能“社交”的机器人助理问世 可“察言观色”
  7. Django模板语言及视图
  8. 太平洋女性网焦点图的几种写法
  9. 一些很有用的JS特效
  10. 互联网企业安全高级指南3.9 关于ISO27001
  11. 泰克示波器3系MDO再次升级,使EMI测试不再求人
  12. 浪潮服务器dhcp修改ip,IP地址管理—DDI(DNS, DHCP, IPAM)解决方案
  13. ADS1278学习总结
  14. 一张照片就能攻破人脸识别系统,人脸识别安全性亟需提高
  15. 4款国产良心软件,完全免费,其中两款一直被误认为外国人开发
  16. linux命令行显示主机名和当前目录
  17. Ubuntu 安装和卸载mysql
  18. Centos7创建DNS服务器(超级简单,一看就会)
  19. dubbo面试知识总结
  20. 小白学python.1

热门文章

  1. Android开发者选项之GPU过度绘制
  2. 工程师到谷歌_我如何在2020年通过Google专业数据工程师考试
  3. 捕鱼人的构想:一篇关于钓鱼的构想
  4. MakefileCMake
  5. 【三维点云】2-三维点云表征
  6. 记一个bug : C2555 overriding virtual function return type differs and is not covariant from
  7. 华三无线设备系列 (瘦AP转胖AP的配置方法)
  8. 思考者人工智能语音机器人
  9. 第一届天池 PolarDB 数据库性能大赛
  10. python005 -- from inport 作用