【QT】QPixmap QImage QBitmap QPicture

文章目录

在Qt中, QPixmapQImageQBitmap 都是用于处理图像数据的类,但它们有不同的特性和适用场景。以下是它们的区别和典型应用场景:


1. QPixmap

特点

  • 设计目的:用于在屏幕上高效显示图像(渲染优化)。
  • 存储方式:依赖于底层图形系统(如X11、DirectFB、OpenGL等)。
  • 像素访问:通常不能直接访问或修改像素(在某些平台上可以,但不推荐)。
  • 线程安全不是线程安全的,只能在主线程(GUI线程)使用。
  • 适用格式:适合显示(如PNG、JPG等),但不适合直接操作像素。

典型应用场景

  • 在UI上显示图片 (如QLabel::setPixmap())。
  • 绘制到QPainter (如QPainter::drawPixmap())。
  • 图标(QIcon)和光标(QCursor)的存储
  • 离屏渲染 (如QPixmap::grabWidget(),但Qt5后推荐用QWidget::grab())。

示例

cpp 复制代码
QPixmap pixmap(":/images/logo.png");
QLabel label;
label.setPixmap(pixmap);

2. QImage

特点

  • 设计目的:用于直接访问和修改像素数据(CPU端操作)。
  • 存储方式:独立于底层图形系统,纯内存存储。
  • 像素访问 :可以直接读写像素(setPixel(), pixel())。
  • 线程安全线程安全,可以在非GUI线程操作(但渲染仍需在主线程)。
  • 适用格式 :支持多种像素格式(Format_RGB32Format_ARGB32等)。

典型应用场景

  • 图像处理(如滤镜、缩放、旋转、格式转换)。
  • 读取/保存图像文件QImage::load(), QImage::save())。
  • 摄像头帧处理 (如QVideoFrameQImage)。
  • OpenCV 和 Qt 结合cv::MatQImage)。

示例

cpp 复制代码
QImage image(":/images/photo.jpg");
image = image.scaled(800, 600, Qt::KeepAspectRatio);
image.setPixel(10, 10, qRgb(255, 0, 0)); // 修改像素
QPixmap pixmap = QPixmap::fromImage(image); // 转QPixmap用于显示

3. QBitmap

特点

  • 设计目的:单色(1-bit)图像,用于掩码(mask)或黑白图像。
  • 继承自 QPixmap,但只支持 Format_MonoFormat_MonoLSB
  • 典型用途
    • 窗口遮罩QWidget::setMask())。
    • 自定义光标(QCursor
    • 黑白图标或图案

示例

cpp 复制代码
QBitmap mask(100, 100);
mask.fill(Qt::color0); // 透明
QPainter painter(&mask);
painter.fillRect(20, 20, 60, 60, Qt::color1); // 不透明部分
widget->setMask(mask); // 设置窗口遮罩

4. 三者的主要区别

特性 QPixmap QImage QBitmap
设计用途 屏幕渲染 像素操作 单色掩码
存储位置 可能存储在GPU 存储在CPU内存 存储在GPU
像素访问 不支持(或受限) 支持(pixel() 不支持
线程安全 仅主线程 线程安全 仅主线程
适用场景 UI显示、绘制 图像处理、修改 遮罩、黑白图像

5. 如何选择?

使用 QPixmap 的情况

  • 需要在 QLabelQPushButton 或其他UI组件上显示图片。
  • 使用 QPainter 进行高效绘制(如游戏、图表渲染)。
  • 需要硬件加速的图形操作。

使用 QImage 的情况

  • 需要直接修改像素(如滤镜、缩放、旋转)。
  • 从摄像头或网络接收图像数据并处理。
  • 需要跨线程处理图像(如后台图像加载)。

使用 QBitmap 的情况

  • 需要创建窗口遮罩(setMask)。
  • 需要黑白图像或自定义光标。

6. 相互转换

  • QImageQPixmap (用于显示):

    cpp 复制代码
    QImage image("photo.jpg");
    QPixmap pixmap = QPixmap::fromImage(image);
  • QPixmapQImage (用于像素操作):

    cpp 复制代码
    QPixmap pixmap("icon.png");
    QImage image = pixmap.toImage();
  • QBitmapQPixmap 的子类 ,可以直接用 QBitmap::fromImage() 转换:

    cpp 复制代码
    QImage monoImage = image.convertToFormat(QImage::Format_Mono);
    QBitmap bitmap = QBitmap::fromImage(monoImage);

7. 性能考虑

  • QPixmap 适合渲染 ,但不能跨线程
  • QImage 适合处理 ,但转换成 QPixmap 有开销
  • 避免频繁转换 ,尽量在 QImage 完成处理后再转 QPixmap

总结

  • QPixmapUI显示(渲染优化)。
  • QImage图像处理(像素操作)。
  • QBitmap单色掩码(遮罩、光标)。

8. QPicture(矢量图形记录与回放)

特点

  • 用于记录和回放 QPainter 命令(如线条、矩形、文本等)。
  • 存储的是绘图指令,而不是像素数据,适合矢量图形。
  • 可以保存到文件(.pic 格式)或从文件加载。

典型应用场景

  • 需要保存和重放绘图操作(如自定义图表、流程图)。
  • 需要缩放无损的图形(因为是矢量格式)。
  • 替代 QPixmap 存储非像素图形。

示例

cpp 复制代码
QPicture picture;
QPainter painter;
painter.begin(&picture); // 记录绘图操作
painter.drawEllipse(10, 10, 100, 100);
painter.end();
picture.save("drawing.pic"); // 保存绘图指令

// 回放
QPicture loadedPic;
loadedPic.load("drawing.pic");
QPainter painter2(this);
painter2.drawPicture(0, 0, loadedPic); // 重新绘制

9. QImageReaderQImageWriter(高效图像读写)

特点

  • QImageReader:优化图像加载(支持渐进式加载、缩放加载)。
  • QImageWriter:优化图像保存(支持压缩、元数据写入)。
  • 比直接使用 QImage::load()/save() 更灵活,支持更多格式控制。

典型应用场景

  • 需要按需加载大图(如仅加载缩略图)。
  • 需要控制图像保存质量(如 JPEG 压缩级别)。
  • 支持动态图像格式(如 GIF、WebP)。

示例

cpp 复制代码
// 渐进式加载图像(适合大图)
QImageReader reader("large_image.jpg");
reader.setScaledSize(QSize(800, 600)); // 直接加载缩小版
QImage image = reader.read();

// 高质量保存 JPEG
QImageWriter writer("output.jpg", "jpg");
writer.setQuality(90); // 设置压缩质量
writer.write(image);

10. QSvgRenderer(SVG 矢量图形渲染)

特点

  • 用于渲染 SVG(Scalable Vector Graphics) 文件。
  • 支持缩放无损显示,适合高分辨率屏幕。
  • 可与 QPainter 结合动态绘制。

典型应用场景

  • 显示矢量图标(如 UI 图标、公司 Logo)。
  • 需要缩放不变形的图形(如地图、流程图)。
  • 替代位图资源,减少内存占用。

示例

cpp 复制代码
QSvgRenderer renderer("icon.svg");
QPainter painter(this);
renderer.render(&painter, QRectF(0, 0, 100, 100)); // 渲染到指定区域

11. QGraphicsPixmapItem(图形视图框架中的图像项)

特点

  • 用于在 QGraphicsScene 中显示 QPixmap
  • 支持平移、旋转、缩放等交互操作。
  • QGraphicsItem 的子类,可与其他图形项组合。

典型应用场景

  • 图形视图框架(如地图、画布)中管理图像。
  • 需要交互式操作的图像(如拖动、旋转)。
  • 游戏开发中的精灵(Sprite)渲染。

示例

cpp 复制代码
QGraphicsScene scene;
QPixmap pixmap("sprite.png");
QGraphicsPixmapItem *item = scene.addPixmap(pixmap);
item->setPos(50, 50);
item->setRotation(45); // 旋转 45 度

QGraphicsView view(&scene);
view.show();

12. QOpenGLTexture(OpenGL 纹理)

特点

  • 将图像绑定为 OpenGL 纹理,用于 3D 渲染。
  • 支持硬件加速的图像处理(如滤镜、着色器)。
  • 需要 Qt 的 OpenGL 模块(QtOpenGL)。

典型应用场景

  • 3D 图形渲染(如游戏、CAD 软件)。
  • GPU 加速的图像处理(如实时滤镜)。
  • QOpenGLWidget 结合使用。

示例

cpp 复制代码
QImage image("texture.png");
QOpenGLTexture texture(image);
texture.bind();
// 在 OpenGL 着色器中使用纹理

13. QVideoFrame(视频帧处理)

特点

  • 用于处理摄像头或视频流的帧数据。
  • 支持与 QImageQPixmap 的转换。
  • 通常与 QMediaPlayerQCamera 结合使用。

典型应用场景

  • 实时视频处理(如人脸检测、AR 应用)。
  • 从摄像头捕获帧并显示。

示例

cpp 复制代码
// 从摄像头获取 QVideoFrame 并转为 QImage
QVideoFrame frame = ...; // 从摄像头捕获
frame.map(QAbstractVideoBuffer::ReadOnly);
QImage image(
    frame.bits(),
    frame.width(),
    frame.height(),
    frame.bytesPerLine(),
    QImage::Format_ARGB32
);
frame.unmap();

// 显示
QPixmap pixmap = QPixmap::fromImage(image);
label.setPixmap(pixmap);

14. QIcon(跨平台图标管理)

特点

  • 封装多种状态的图标(正常、悬停、禁用等)。
  • 支持从 QPixmapQImage 或文件(.ico.png)创建。
  • 自动适配不同设备像素比(High-DPI 屏幕)。

典型应用场景

  • 按钮、菜单项的图标。
  • 适应不同主题(亮色/暗色)的图标切换。

示例

cpp 复制代码
QIcon icon(":/icons/app.png");
QPushButton button;
button.setIcon(icon);

总结:如何选择合适的类?

主要用途 关键优势
QPixmap UI 显示、渲染优化 硬件加速,适合显示
QImage 像素级操作、图像处理 直接访问像素,线程安全
QBitmap 单色掩码、黑白图形 轻量级,适合遮罩
QPicture 矢量图形记录与回放 存储绘图指令,缩放无损
QImageReader 高效图像加载(如渐进式) 支持按需解码
QSvgRenderer SVG 矢量图形渲染 高分辨率适配
QGraphicsPixmapItem 图形视图框架中的交互式图像 支持变换、组合
QOpenGLTexture OpenGL 纹理绑定 GPU 加速渲染
QVideoFrame 视频帧处理 与摄像头/视频流交互
QIcon 跨平台图标管理 支持多状态、High-DPI 适配

根据需求选择最合适的类,可以兼顾性能和功能! 🎨🚀

相关推荐
Stay Passion3 分钟前
Java 实用工具类:Apache Commons IO 的 IOUtils
java·开发语言·apache
海码0071 小时前
【Hot 100】 146. LRU 缓存
数据结构·c++·算法·链表·缓存·hot100
工藤新一¹2 小时前
C++/SDL 进阶游戏开发 —— 双人塔防(代号:村庄保卫战 20)
c++·单例模式·游戏引擎·sdl·c++游戏开发
买了一束花2 小时前
二、机器学习中Python变量基础
开发语言·python·机器学习·conda
heyCHEEMS2 小时前
最大子段和 Java
java·开发语言·算法
我是一只鱼02232 小时前
LeetCode算法题 (设计链表)Day16!!!C/C++
数据结构·c++·算法·leetcode·链表
hi0_62 小时前
Linux 第六讲 --- 工具篇(一)yum/apt与vim
linux·服务器·c++·vim·yum
wjm0410062 小时前
C++八股--5--设计模式--适配器模式,代理模式,观察者模式
c++·设计模式·适配器模式
bj32813 小时前
树的同构问题--Python
开发语言·python·算法
八股文领域大手子4 小时前
单机 vs 分布式:Java 后端限流的选择题
java·开发语言·数据结构·算法·spring