当前位置: 首页 > news >正文

44、QImage---------绘图

QImage

QImage 是 Qt 框架中的一个类,用于处理和操作图像数据。它提供了多种功能,包括加载、保存、转换和绘制图像。以下是 QImage 的详细知识点和功能:

1. 基本概念
●定义: QImage 是一个用于处理图像的类,支持多种格式(如 BMP、PNG、JPEG 等),并提供了对图像数据的低级访问。
●用途: 常用于图形应用程序中,能够加载和保存图像文件,进行图像处理和绘制。

2. 创建 QImage

  • 默认构造函数: 创建一个空的QImage对象。
QImage image;
  • 指定大小和格式: 创建一个指定大小和格式的QImage
QImage image(width, height, QImage::Format_RGB32);
  • 从文件加载: 从文件加载图像。
QImage image("path/to/image.png");
  • 从其他 QImage 复制: 通过复制构造函数创建一个新的 QImage。
QImage copyImage(originalImage);

3. 图像格式

  • 格式类型
    • QImage::Format_RGB32:每个像素占用 32 位(RGBA),适用于高质量图像。
    • QImage::Format_ARGB32:包含 Alpha 通道(透明度)。
    • QImage::Format_Grayscale8:灰度图像。
    • QImage::Format_Mono:单色图像。

4. 图像操作

  • 图像大小:
    • 获取图像的宽度和高度:
int width = image.width(); int height = image.height();
  • 缩放和裁剪:
    • 缩放图像:
QImage scaledImage = image.scaled(newWidth, newHeight);
    • 裁剪图像:
QImage croppedImage = image.copy(x, y, width, height);
  • 旋转和翻转:
    • 旋转图像:
QImage rotatedImage = image.transformed(QMatrix().rotate(90));
    • 水平翻转:
image = image.mirrored(true, false);

5. 图像保存

  • 保存到文件: 将图像保存到文件中,支持多种格式。
image.save("path/to/save/image.png", "PNG");

7. 绘制 QImage

  • 在 QWidget 上绘制:
void MyWidget::paintEvent(QPaintEvent *event) { QPainter painter(this); painter.drawImage(0, 0, image); }
    • 使用QPainterQWidget上绘制QImage

8. 示例: 加载修改保存图像

我们希望创建一个ImageWidget,加载原有的图片资源,并在原有的图片资源基础上绘制一个圆形的红色圈圈,并且通过widget显示出来

实现过程

我们创建一个QT项目,名称为ImageWidget,窗口名称为ImageWidget继承自QWidget.

项目建立好后,右键项目添加新建文件,选择Qt resource file,名称叫做res即可

无需创建前缀,前缀为/即可,添加文件选择文件夹中的th.jpg

在ImageWidget中添加QImage成员和声明paintEvent函数

protected: void paintEvent(QPaintEvent* event) override; private: QImage image;

接下来在ImageWidget构造函数中加载图片资源

ImageWidget::ImageWidget(QWidget *parent) : QWidget(parent), ui(new Ui::ImageWidget) { ui->setupUi(this); //加载图像 if(!image.load(":/th.jpg")){ // 确保资源路径正确,如果加载失败则创建一个像素32位的图像 image = QImage(200,200,QImage::Format_ARGB32); //填充颜色 image.fill(Qt::white); } //对图像处理... }

我们可以使用QPainter在图片中心上绘制一个红色的圆圈

ImageWidget::ImageWidget(QWidget *parent) : QWidget(parent), ui(new Ui::ImageWidget) { ui->setupUi(this); //加载图像 if(!image.load(":/th.jpg")){ // 确保资源路径正确,如果加载失败则创建一个像素32位的图像 image = QImage(200,200,QImage::Format_ARGB32); //填充颜色 image.fill(Qt::white); } // 对图像进行简单处理:在图像中心绘制一个红色圆圈 QPainter painter(&image); //设置抗锯齿 painter.setRenderHint(QPainter::Antialiasing, true); //设置画刷 painter.setBrush(Qt::red); //画圆形,在图片中心且半径为50 painter.drawEllipse(image.rect().center(), 50, 50); // 保存修改后的图像(可选) image.save("modified_image.png"); // 设置固定的大小 setFixedSize(image.size()); }

此时运行程序后,去运行的目录里会看到有一个新的图片modified_image.png,打开看图片上有一个红色的圆圈

我们接下来在ImageWidget上绘制这个图片,可以重写paintEvent函数,采用QPainter绘制

void ImageWidget::paintEvent(QPaintEvent *event) { Q_UNUSED(event); QPainter painter(this); //绘制图像函数 painter.drawImage(0, 0, image); }

程序启动后,可以看到widget中绘制了我们添加的图片

9. 示例: 图像转灰度图像

我们实现在一个widget中展示一个图片的不同效果,一个原图,一个灰度图,如下图所示

实现过程

我们新建项目,主窗口创建GrayscaleWidget继承自QWidget

接下来我们在类的声明中声明两个QImage类型的变量, 并且重写paintEvent函数

class GrayscaleWidget : public QWidget { Q_OBJECT public: explicit GrayscaleWidget(QWidget *parent = nullptr); ~GrayscaleWidget(); protected: //重写绘制逻辑 virtual void paintEvent(QPaintEvent *event) override; private: Ui::GrayscaleWidget *ui; //存储彩色图像 QImage colorImage; //存储灰度图 QImage grayImage; };

接下来我们在构造函数中加载我们的彩色图片资源,加载图片资源前也是需要将图片资源添加到项目里,通过创建qt 资源再添加

GrayscaleWidget::GrayscaleWidget(QWidget *parent) : QWidget(parent), ui(new Ui::GrayscaleWidget) { ui->setupUi(this); // 加载彩色图像 if (!colorImage.load(":/th.jpg")) { // 确保资源路径正确 colorImage = QImage(200, 200, QImage::Format_ARGB32); colorImage.fill(Qt::white); } // 转换为灰度图像 grayImage = colorImage.convertToFormat(QImage::Format_Grayscale8); //设置窗口大小 setFixedSize(colorImage.width() * 2 + 10, colorImage.height()); }

重写绘制事件

void GrayscaleWidget::paintEvent(QPaintEvent *event) { Q_UNUSED(event); //创建painter QPainter painter(this); // 绘制彩色图像 painter.drawImage(0, 0, colorImage); // 在彩色图像右侧绘制灰度图像 painter.drawImage(colorImage.width() + 10, 0, grayImage); }
http://www.jsqmd.com/news/599811/

相关文章:

  • 即时通信|自定义基于 Netty 的二进制协议(应用层协议)+心跳检测
  • 模拟函数memmove
  • SEO 排名优化软件如何进行竞争对手分析
  • Java 集合框架全景图:一篇文章带你认识所有集合类
  • GraphRAG硬核实战:打造企业“数字老师傅”
  • Android studio新版本无法在ai对话框使用中文输入法候选框
  • React 自定义 Hook 的命名规范与调用规则详解
  • XBusServo嵌入式舵机控制库:X-Bus协议驱动与实时闭环实践
  • 2026四川西北隔断厂家top推荐:pvc隔断/不锈钢隔断/公共卫生间隔断/医院卫生间隔断/卫生间隔断批发/选择指南 - 优质品牌商家
  • Win11安装Claude-Code出现报错问题解决
  • 基于STM32的简易示波器设计与实现
  • 2026交流充电桩优质厂家推荐指南:四川充电桩升级改造/四川充电桩维修/四川充电桩运维/四川充电设备厂家/选择指南 - 优质品牌商家
  • 从MATLAB到Python:我如何把那个课程大作业的OCR算法“移植”并优化了一遍
  • 配置嵌入式Linux系统从NFS启动
  • 基于STM32微控制器的频率计设计与实现
  • STM32外设驱动库解析与实战应用
  • 设计服务公司可能最适合跑AI工作流
  • OpenClaw环境隔离:Qwen3-4B模型与技能的沙盒运行配置
  • OpenClaw效率对比测试:Qwen3-14b_int4_awq在不同量化精度下的表现
  • OpenClaw跨平台控制方案:千问3.5-9B同步操作多台设备
  • 利用json-to-ts工具进行转换,放置在typeScript.ts文件中
  • 网络通信三表解析:ARP、MAC与路由表实战指南
  • 30B 脉冲分裂手术报告
  • SEO_从零开始构建可持续的SEO优化体系(468 )
  • CSS如何实现背景颜色的棋盘格分布_利用repeating-gradient
  • CSS如何制作透明度渐变的蒙版_使用linear-gradient从黑色过渡到透明
  • SecGPT-14B知识库增强:让OpenClaw支持最新CVE漏洞库
  • 嵌入式开发中的模块化设计实践与优势
  • 别再傻傻分不清!ESP32-S3上USB CDC、UART0和板载CH340到底谁在干活?
  • 基于Zigbee的智能果园灌溉系统设计与实现