一、基于Qt的图像矩形区域改色
Qt环境下图像的打开和涂色
一、设计目标
能够在 Qt QtCreator 环境下打开常用图像格式文件,诸如 bmp、jpg、png 图像等,然后将他们转化为 Qt 中的 QImage 类,并进行矩形范围内的涂色。
二、需要提前掌握的知识
1.Qt 图像类
Qt 中用于图像操作的类有 QImage 和 QPixmap,其中 QImage 主要负责图像编辑和修改,而 QPixmap 则负责图像的显示。
2.Qt 如何修改图像
QImage 中有一个 setPixelColor() 方法可以对image 的像素点进行操作,但是当需要操作的图像区域面积较大时,该方法的效率较低。这时最有效率的方法就是直接操作 image 在内存中的数据,可以通过 bits() 方法来获取 image 数据的首地址。
3.Qt 如何显示图像
Qt 中图像的显示主要是通过使用 QLabel 类来实现的。步骤:先打开一个图像;将图像加载进 QImage 中;在用 QPixmap 对象获得图像;最后用 QLabel 使用 setPixmap() 方法显示。
三、程序需求
1.一个包含打开图像,涂色功能的菜单的主窗口;
2.一个可以获取需要修改的矩形范围、颜色,并返回给主窗口的编辑对话框;
四、实现大致过程
1.首先实现主窗口和编辑对话框的布局;
2.分别在两个窗口中加入需要的信号和槽;
3.完成窗口内部控件以及两窗口之间的通信;
五、详细步骤
(一)主窗口
1.头文件
在 MainWindow 的头文件中引用头文件(Qt中使用一个类,就要引用这个类的头文件):
- #include <Qlabel>
- #include <QPixmap>
- #include <QImage>
- #include <QMenuBar>
- #include <QMenu>
- #include <QAction>
- #include <QFileDialog>
- #include <QString>
- #include <QPoint>
- #include <QDebug>
2.布局
在 MainWindow 的定义中加入
- private:
- QLabel *label;
- QImage *image; // 全局image
- QMenuBar *menubar;
- QMenu *fileMenu;
- QMenu *editMenu;
- QAction *openAction;
- QAction *rectAction;
然后在MainWindow的构造函数中加入
- label = new QLabel(this);
- menubar = this->menuBar();
- fileMenu = menubar->addMenu("file");
- editMenu = menubar->addMenu("edit");
- openAction = fileMenu->addAction("openfile");
- rectAction = editMenu->addAction("rect");
这样,主窗口的空间布局就完成了。效果如下:
3.信号
在MianWindow的定义中加入 freshSignal 信号,该信号用于通知窗口需要更新label上的图片内容:
- signals:
- void freshSignal();
4.槽函数
在MainWIndow的定义中加入下列槽函数:
- private slots:
- void openFileSlot(); // 打开文件
- void freshSlot(); // 刷新label上的图片
- void editDialogSlot(); // 打开编辑对话框
- void rectChangeSlot(QPoint,QPoint,QColor); // 修改制定rect中的像素
它们的实现如下:
- void MainWindow::openFileSlot()
- {
- QString path = QFileDialog::getOpenFileName(
- this,
- "文件对话框",
- "../",//上一级路径
- "Image(*.bmp *.jpg *.png)"
- );
- image = new QImage(path);
- emit freshSignal();
- }
- void MainWindow::freshSlot()
- {
- label->setPixmap(QPixmap::fromImage(*image));
- label->resize(image->size());
- }
- void MainWindow::editDialogSlot()
- {
- editDialog->show();
- }
- void MainWindow::rectChangeSlot(QPoint startPoint,QPoint endPoint,QColor color)
- {
- // Qt 打开的 bmp、jpg 图像格式为 Format_RGB32,在内存中的顺序为 B G R 0
- // 打开的 png 图像的格式为 Format_ARGB32,在内存中的顺序为 B G R A
- unsigned char *scrdata = image->bits();
- int width = image->width();
- int height = image->height();
- int bytesPerLine = image->bytesPerLine();//图像每行字节对齐
- unsigned char *dstdata = new unsigned char[bytesPerLine*height];//存储处理后的数据
- int r = color.red();
- int g = color.green();
- int b = color.blue();
- for(int i=;i<height;i++)
- for(int j=;j<width;j++)
- {
- if((i>=startPoint.x())&&i<endPoint.x()&&
- (j>=startPoint.y())&&j<endPoint.y())
- {
- dstdata[i*bytesPerLine+j*] = b;
- dstdata[i*bytesPerLine+j*+]= g;
- dstdata[i*bytesPerLine+j*+]= r;
- }
- else{
- dstdata[i*bytesPerLine+j*] = scrdata[];
- dstdata[i*bytesPerLine+j*+]= scrdata[];
- dstdata[i*bytesPerLine+j*+]= scrdata[];
- }
- scrdata+=;
- }
- image= new QImage(dstdata,width,height,bytesPerLine,QImage::Format_RGB32);
- emit freshSignal();
- }
5.连接信号与槽
在MainWindow的实现函数中进行连接:
- connect(openAction,SIGNAL(triggered()),this,SLOT(openFileSlot()));
- connect(this,SIGNAL(freshSignal()),this,SLOT(freshSlot()));
- connect(rectAction,SIGNAL(triggered()),this,SLOT(editDialogSlot()));
这样,MainWindow 的实现就基本完成
(二)编辑对话框
1.创建编辑对话框类
编辑对话框类需要自己创建,步骤:右键项目文件夹->添加新文件
->选择C++类
->选择基类为QWidget->命名为EditDialog->完成。这样工程就会自动添加两个新的文件
,编辑对话框创建完成。
2.头文件
在 EditDialog 的头文件中加入头文件(Qt中使用一个类,就要引用这个类的头文件):
- #include <QLabel>
- #include <QGridLayout>
- #include <QPushButton>
- #include <QLineEdit>
- #include <QPoint>
3.布局
在 EditDialog 的定义中加入
- public:
- QGridLayout *layout;
- QLabel *startLabel;
- QLabel *endLabel;
- QLineEdit *x1Text;
- QLineEdit *y1Text;
- QLineEdit *x2Text;
- QLineEdit *y2Text;
- QLabel *rLabel;
- QLabel *gLabel;
- QLabel *bLabel;
- QLineEdit *rText;
- QLineEdit *gText;
- QLineEdit *bText;
- QPushButton *okButton;
然后在 EditDialog 的构造函数中加入
- layout = new QGridLayout(this);
- startLabel = new QLabel("start",this);
- endLabel = new QLabel("end",this);
- x1Text = new QLineEdit("",this);
- y1Text = new QLineEdit("",this);
- x2Text = new QLineEdit("",this);
- y2Text = new QLineEdit("",this);
- rLabel = new QLabel("R:",this);
- gLabel = new QLabel("G:",this);
- bLabel = new QLabel("B:",this);
- rText = new QLineEdit("",this);
- gText = new QLineEdit("",this);
- bText = new QLineEdit("",this);
- okButton = new QPushButton("OK",this);
- layout->addWidget(startLabel,,,,); // 添加布局
- layout->addWidget(x1Text,,,,);
- layout->addWidget(y1Text,,,,);
- layout->addWidget(endLabel,,,,);
- layout->addWidget(x2Text,,,,);
- layout->addWidget(y2Text,,,,);
- layout->addWidget(rLabel,,,,);
- layout->addWidget(gLabel,,,,);
- layout->addWidget(bLabel,,,,);
- layout->addWidget(rText,,,,);
- layout->addWidget(gText,,,,);
- layout->addWidget(bText,,,,);
- layout->addWidget(okButton,,,,);
这样 EditDialog 的布局完成,效果如下
4.信号
在 EditDialog 的定义中加入如下信号,该信号用于向 MainWindow 返回需要涂色的矩形起点和终点,并告诉 MainWIndow 执行涂色操作。
- signals:
- void resultSignal(QPoint,QPoint,QColor);
5.槽函数
在 EditDialog 的定义中加入如下函数
- public slots:
- void okButtonSlot(); // 处理案件操作
槽函数的实现:
- void EditDialog::okButtonSlot()
- {
- int x1 = x1Text->text().toInt();
- int y1 = y1Text->text().toInt();
- int x2 = x2Text->text().toInt();
- int y2 = y2Text->text().toInt();
- int r = rText->text().toInt();
- int g = gText->text().toInt();
- int b = bText->text().toInt();
- QPoint startPoint = QPoint(x1,y1);
- QPoint endPoint = QPoint(x2,y2);
- QColor color = QColor(r,g,b);
- emit resultSignal(startPoint,endPoint,color);
- this->hide();
- }
6.连接信号与槽
在 EditDialog 的构造函数中加入
- connect(okButton,SIGNAL(clicked()),this,SLOT(okButtonSlot()));
(三)主窗口与编辑对话框的连接
1.在 MainWindow 的头文件中引用头文件
- #include "editdialog.h"
2.在 MainWindow 的定义中加入
- EditDialog *editDialog;
3.在 MainWindow 的构造函数中加入
- editDialog = new EditDialog();
4.在 MainWIndow 的构造函数中加入
- connect(editDialog,SIGNAL(resultSignal(QPoint,QPoint,QColor)),this,SLOT(rectChangeSlot(QPoint,QPoint,QColor)));
至此,整个程序就编写完成,效果图如下:
github代码链接:
https://github.com/851984709/Junjie-Hu/tree/master/code/qt/task/BmpEdit
如果上述教程或代码中有任何错误,欢迎批评和指证。
一、基于Qt的图像矩形区域改色的更多相关文章
- 基础的基于QT的图像查看程序
代码来自<QT5.9c++开发指南>,因为实现了图片的遍历显示,对于将来编写ImageShop一类的图像程序来说将非常有用(这个程序目前存在一定问题,在研究过程中进行解决) 一.基本功能 ...
- 基于Qt的图像采集系统
硬件 Point Gray Camera 型号:FL3-U3-13S2C-CS 参数 Sony IMX035 CMOS, 1/3", 3.63 µm Rolling Shutter 1328 ...
- opencv2 使用鼠标绘制矩形并截取和保存矩形区域图像
前言 好长时间没写博文了,今天偷偷懒写篇关于opencv2中鼠标响应操作的文章. 鼠标操作属于用户接口设计,以前一直使用Qt来做,但是如果只需要简单的鼠标,键盘操作,直接调用opencv库的函数也未尝 ...
- 在OpenCV中利用鼠标绘制矩形和截取图像的矩形区域
这是两个相关的程序,前者是后者的基础.实际上前一个程序也是在前面博文的基础上做的修改,请参考<在OpenCV中利用鼠标绘制直线> .下面贴出代码. 程序之一,在OpenCV中利用鼠标绘制矩 ...
- 基于Qt实现的截图小程序
在最近做的行人检测项目中,由于需要训练分类器,而分类器的训练又需要有一个一定长宽的样本.为了方便样本的采集,因此实现了这样的一个截图程序.该程序的主要功能是加载视频到程序中,程序可以对视频进行播放.暂 ...
- Win32 GDI 非矩形区域剪裁,双缓冲技术
传统的Win32通过GDI提供图形显示的功能,包括了基本的绘图功能,如画线.方块.椭圆等等,高级功能包括了多边形和Bezier的绘制.这样app就不用关心那些图形学的细节了,有点类似于UNIX上的X- ...
- Java基于opencv实现图像数字识别(四)—图像降噪
Java基于opencv实现图像数字识别(四)-图像降噪 我们每一步的工作都是基于前一步的,我们先把我们前面的几个函数封装成一个工具类,以后我们所有的函数都基于这个工具类 这个工具类呢,就一个成员变量 ...
- 玩转Android Camera开发(四):预览界面四周暗中间亮,仅仅拍摄矩形区域图片(附完整源代码)
杂家前文曾写过一篇关于仅仅拍摄特定区域图片的demo.仅仅是比較简陋.在坐标的换算上不是非常严谨,并且没有完毕预览界面四周暗中间亮的效果,深以为憾.今天把这个补齐了. 在上代码之前首先交代下,这里面存 ...
- HT for Web基于HTML5的图像操作(二)
上篇介绍了HT for Web采用HTML5 Canvas的getImageData和setImageData函数,通过颜色乘积实现的染色效果,本文将再次介绍另一种更为高效的实现方式,当然要实现的功能 ...
随机推荐
- 项目中gulp使用发生的错误及解决
在项目开发中,执行gulp css来生成合成的css文件时,报如下错误 Error: Cannot find module 'browserslist' 解决方法: npm install brows ...
- 8.bwapp亲测xxe漏洞
这几天在学习XXE漏洞,这里用靶机bwapp来练习一下这个漏洞,重在学习 xxe漏洞主要针对webservice危险的引用的外部实体并且未对外部实体进行敏感字符的过滤, 从而可以造成命令执行,目录遍历 ...
- Flask 入门(第一篇)
1. 认识 Flask Flask 是一个微型 Web 框架,依赖于 jinjia2 模板系统和 Werkzeug WSGI(本质为 Socket 服务端) 服务,默认情况不支持数据库抽象层.表单验证 ...
- Ajax原生请求及Json基础
1.基本结构 <script type="text/javascript"> // 创建XMLHttpRequest对象 var request = new XMLHt ...
- CF70D Professor's task(动态凸包)
题面 两种操作: 1 往点集S中添加一个点(x,y); 2 询问(x,y)是否在点集S的凸包中. 数据保证至少有一个2操作, 保证刚开始会给出三个1操作, 且这三个操作中的点不共线. 题解 动态凸包板 ...
- POJ1027 The Same Game
题目来源:http://poj.org/problem?id=1027 题目大意: 题目说的就是现在蛮流行的手机小游戏popstar,求用贪心方法能得到多少分. 小球有三种颜色:R/G/B.横向.纵向 ...
- 如何顺畅使用sourcetree可视化工具
http://www.360doc.com/content/17/0711/10/11253639_670493403.shtml sourcetree软件下载 下载地址:https://www.so ...
- Java中只有按值传递,没有按引用传递!(两种参数情况下都是值传递)
今天,我在一本面试书上看到了关于java的一个参数传递的问题: 写道 java中对象作为参数传递给一个方法,到底是值传递,还是引用传递? 我毫无疑问的回答:“引用传递!”,并且还觉得自己对java的这 ...
- #define 只是字符替换
可以使用 #define MAX 100 int main (int argc, char *argv[]) { printf("MAX is %d\n", MAX); ; } g ...
- 利用Python进行数据分析 2017 第二版 项目代码
最近在学习<利用Python进行数据分析>,找到了github项目的地址, 英文版本,中文版本 (非常感谢翻译中文的作者). mark一下,方便后边学习查找.