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中使用一个类,就要引用这个类的头文件):

  1. #include <Qlabel>
  2.  
  3. #include <QPixmap>
  4.  
  5. #include <QImage>
  6.  
  7. #include <QMenuBar>
  8.  
  9. #include <QMenu>
  10.  
  11. #include <QAction>
  12.  
  13. #include <QFileDialog>
  14.  
  15. #include <QString>
  16.  
  17. #include <QPoint>
  18.  
  19. #include <QDebug>

2.布局

在 MainWindow 的定义中加入

  1. private:
  2.  
  3. QLabel *label;
  4.  
  5. QImage *image; // 全局image
  6.  
  7. QMenuBar *menubar;
  8.  
  9. QMenu *fileMenu;
  10.  
  11. QMenu *editMenu;
  12.  
  13. QAction *openAction;
  14.  
  15. QAction *rectAction;

然后在MainWindow的构造函数中加入

  1. label = new QLabel(this);
  2.  
  3. menubar = this->menuBar();
  4.  
  5. fileMenu = menubar->addMenu("file");
  6.  
  7. editMenu = menubar->addMenu("edit");
  8.  
  9. openAction = fileMenu->addAction("openfile");
  10.  
  11. rectAction = editMenu->addAction("rect");

这样,主窗口的空间布局就完成了。效果如下:

3.信号

在MianWindow的定义中加入 freshSignal 信号,该信号用于通知窗口需要更新label上的图片内容:

  1. signals:
  2.  
  3. void freshSignal();

4.槽函数

在MainWIndow的定义中加入下列槽函数:

  1. private slots:
  2.  
  3. void openFileSlot(); // 打开文件
  4.  
  5. void freshSlot(); // 刷新label上的图片
  6.  
  7. void editDialogSlot(); // 打开编辑对话框
  8.  
  9. void rectChangeSlot(QPoint,QPoint,QColor); // 修改制定rect中的像素

它们的实现如下:

  1. void MainWindow::openFileSlot()
  2.  
  3. {
  4.  
  5. QString path = QFileDialog::getOpenFileName(
  6.  
  7. this,
  8.  
  9. "文件对话框",
  10.  
  11. "../",//上一级路径
  12.  
  13. "Image(*.bmp *.jpg *.png)"
  14.  
  15. );
  16.  
  17. image = new QImage(path);
  18.  
  19. emit freshSignal();
  20.  
  21. }
  22.  
  23. void MainWindow::freshSlot()
  24.  
  25. {
  26.  
  27. label->setPixmap(QPixmap::fromImage(*image));
  28.  
  29. label->resize(image->size());
  30.  
  31. }
  32.  
  33. void MainWindow::editDialogSlot()
  34.  
  35. {
  36.  
  37. editDialog->show();
  38.  
  39. }
  40.  
  41. void MainWindow::rectChangeSlot(QPoint startPoint,QPoint endPoint,QColor color)
  42.  
  43. {
  44.  
  45. // Qt 打开的 bmp、jpg 图像格式为 Format_RGB32,在内存中的顺序为 B G R 0
  46.  
  47. // 打开的 png 图像的格式为 Format_ARGB32,在内存中的顺序为 B G R A
  48.  
  49. unsigned char *scrdata = image->bits();
  50.  
  51. int width = image->width();
  52.  
  53. int height = image->height();
  54.  
  55. int bytesPerLine = image->bytesPerLine();//图像每行字节对齐
  56.  
  57. unsigned char *dstdata = new unsigned char[bytesPerLine*height];//存储处理后的数据
  58.  
  59. int r = color.red();
  60.  
  61. int g = color.green();
  62.  
  63. int b = color.blue();
  64.  
  65. for(int i=;i<height;i++)
  66.  
  67. for(int j=;j<width;j++)
  68.  
  69. {
  70.  
  71. if((i>=startPoint.x())&&i<endPoint.x()&&
  72.  
  73. (j>=startPoint.y())&&j<endPoint.y())
  74.  
  75. {
  76.  
  77. dstdata[i*bytesPerLine+j*] = b;
  78.  
  79. dstdata[i*bytesPerLine+j*+]= g;
  80.  
  81. dstdata[i*bytesPerLine+j*+]= r;
  82.  
  83. }
  84.  
  85. else{
  86.  
  87. dstdata[i*bytesPerLine+j*] = scrdata[];
  88.  
  89. dstdata[i*bytesPerLine+j*+]= scrdata[];
  90.  
  91. dstdata[i*bytesPerLine+j*+]= scrdata[];
  92.  
  93. }
  94.  
  95. scrdata+=;
  96.  
  97. }
  98.  
  99. image= new QImage(dstdata,width,height,bytesPerLine,QImage::Format_RGB32);
  100.  
  101. emit freshSignal();
  102.  
  103. }

5.连接信号与槽

在MainWindow的实现函数中进行连接:

  1. connect(openAction,SIGNAL(triggered()),this,SLOT(openFileSlot()));
  2.  
  3. connect(this,SIGNAL(freshSignal()),this,SLOT(freshSlot()));
  4.  
  5. connect(rectAction,SIGNAL(triggered()),this,SLOT(editDialogSlot()));

这样,MainWindow 的实现就基本完成

(二)编辑对话框

1.创建编辑对话框类

编辑对话框类需要自己创建,步骤:右键项目文件夹->添加新文件->选择C++类

->选择基类为QWidget->命名为EditDialog->完成。这样工程就会自动添加两个新的文件

,编辑对话框创建完成。

2.头文件

在 EditDialog 的头文件中加入头文件(Qt中使用一个类,就要引用这个类的头文件):

  1. #include <QLabel>
  2.  
  3. #include <QGridLayout>
  4.  
  5. #include <QPushButton>
  6.  
  7. #include <QLineEdit>
  8.  
  9. #include <QPoint>

3.布局

在 EditDialog 的定义中加入

  1. public:
  2.  
  3. QGridLayout *layout;
  4.  
  5. QLabel *startLabel;
  6.  
  7. QLabel *endLabel;
  8.  
  9. QLineEdit *x1Text;
  10.  
  11. QLineEdit *y1Text;
  12.  
  13. QLineEdit *x2Text;
  14.  
  15. QLineEdit *y2Text;
  16.  
  17. QLabel *rLabel;
  18.  
  19. QLabel *gLabel;
  20.  
  21. QLabel *bLabel;
  22.  
  23. QLineEdit *rText;
  24.  
  25. QLineEdit *gText;
  26.  
  27. QLineEdit *bText;
  28.  
  29. QPushButton *okButton;

然后在 EditDialog 的构造函数中加入

  1. layout = new QGridLayout(this);
  2.  
  3. startLabel = new QLabel("start",this);
  4.  
  5. endLabel = new QLabel("end",this);
  6.  
  7. x1Text = new QLineEdit("",this);
  8.  
  9. y1Text = new QLineEdit("",this);
  10.  
  11. x2Text = new QLineEdit("",this);
  12.  
  13. y2Text = new QLineEdit("",this);
  14.  
  15. rLabel = new QLabel("R:",this);
  16.  
  17. gLabel = new QLabel("G:",this);
  18.  
  19. bLabel = new QLabel("B:",this);
  20.  
  21. rText = new QLineEdit("",this);
  22.  
  23. gText = new QLineEdit("",this);
  24.  
  25. bText = new QLineEdit("",this);
  26.  
  27. okButton = new QPushButton("OK",this);
  28.  
  29. layout->addWidget(startLabel,,,,); // 添加布局
  30.  
  31. layout->addWidget(x1Text,,,,);
  32.  
  33. layout->addWidget(y1Text,,,,);
  34.  
  35. layout->addWidget(endLabel,,,,);
  36.  
  37. layout->addWidget(x2Text,,,,);
  38.  
  39. layout->addWidget(y2Text,,,,);
  40.  
  41. layout->addWidget(rLabel,,,,);
  42.  
  43. layout->addWidget(gLabel,,,,);
  44.  
  45. layout->addWidget(bLabel,,,,);
  46.  
  47. layout->addWidget(rText,,,,);
  48.  
  49. layout->addWidget(gText,,,,);
  50.  
  51. layout->addWidget(bText,,,,);
  52.  
  53. layout->addWidget(okButton,,,,);

这样 EditDialog 的布局完成,效果如下

4.信号

在 EditDialog 的定义中加入如下信号,该信号用于向 MainWindow 返回需要涂色的矩形起点和终点,并告诉 MainWIndow 执行涂色操作。

  1. signals:
  2.  
  3. void resultSignal(QPoint,QPoint,QColor);

5.槽函数

在 EditDialog 的定义中加入如下函数

  1. public slots:
  2.  
  3. void okButtonSlot(); // 处理案件操作

槽函数的实现:

  1. void EditDialog::okButtonSlot()
  2.  
  3. {
  4.  
  5. int x1 = x1Text->text().toInt();
  6.  
  7. int y1 = y1Text->text().toInt();
  8.  
  9. int x2 = x2Text->text().toInt();
  10.  
  11. int y2 = y2Text->text().toInt();
  12.  
  13. int r = rText->text().toInt();
  14.  
  15. int g = gText->text().toInt();
  16.  
  17. int b = bText->text().toInt();
  18.  
  19. QPoint startPoint = QPoint(x1,y1);
  20.  
  21. QPoint endPoint = QPoint(x2,y2);
  22.  
  23. QColor color = QColor(r,g,b);
  24.  
  25. emit resultSignal(startPoint,endPoint,color);
  26.  
  27. this->hide();
  28.  
  29. }

6.连接信号与槽

在 EditDialog 的构造函数中加入

  1. connect(okButton,SIGNAL(clicked()),this,SLOT(okButtonSlot()));

(三)主窗口与编辑对话框的连接

1.在 MainWindow 的头文件中引用头文件

  1. #include "editdialog.h"

2.在 MainWindow 的定义中加入

  1. EditDialog *editDialog;

3.在 MainWindow 的构造函数中加入

  1. editDialog = new EditDialog();

4.在 MainWIndow 的构造函数中加入

  1. 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的图像矩形区域改色的更多相关文章

  1. 基础的基于QT的图像查看程序

    代码来自<QT5.9c++开发指南>,因为实现了图片的遍历显示,对于将来编写ImageShop一类的图像程序来说将非常有用(这个程序目前存在一定问题,在研究过程中进行解决) 一.基本功能 ...

  2. 基于Qt的图像采集系统

    硬件 Point Gray Camera 型号:FL3-U3-13S2C-CS 参数 Sony IMX035 CMOS, 1/3", 3.63 µm Rolling Shutter 1328 ...

  3. opencv2 使用鼠标绘制矩形并截取和保存矩形区域图像

    前言 好长时间没写博文了,今天偷偷懒写篇关于opencv2中鼠标响应操作的文章. 鼠标操作属于用户接口设计,以前一直使用Qt来做,但是如果只需要简单的鼠标,键盘操作,直接调用opencv库的函数也未尝 ...

  4. 在OpenCV中利用鼠标绘制矩形和截取图像的矩形区域

    这是两个相关的程序,前者是后者的基础.实际上前一个程序也是在前面博文的基础上做的修改,请参考<在OpenCV中利用鼠标绘制直线> .下面贴出代码. 程序之一,在OpenCV中利用鼠标绘制矩 ...

  5. 基于Qt实现的截图小程序

    在最近做的行人检测项目中,由于需要训练分类器,而分类器的训练又需要有一个一定长宽的样本.为了方便样本的采集,因此实现了这样的一个截图程序.该程序的主要功能是加载视频到程序中,程序可以对视频进行播放.暂 ...

  6. Win32 GDI 非矩形区域剪裁,双缓冲技术

    传统的Win32通过GDI提供图形显示的功能,包括了基本的绘图功能,如画线.方块.椭圆等等,高级功能包括了多边形和Bezier的绘制.这样app就不用关心那些图形学的细节了,有点类似于UNIX上的X- ...

  7. Java基于opencv实现图像数字识别(四)—图像降噪

    Java基于opencv实现图像数字识别(四)-图像降噪 我们每一步的工作都是基于前一步的,我们先把我们前面的几个函数封装成一个工具类,以后我们所有的函数都基于这个工具类 这个工具类呢,就一个成员变量 ...

  8. 玩转Android Camera开发(四):预览界面四周暗中间亮,仅仅拍摄矩形区域图片(附完整源代码)

    杂家前文曾写过一篇关于仅仅拍摄特定区域图片的demo.仅仅是比較简陋.在坐标的换算上不是非常严谨,并且没有完毕预览界面四周暗中间亮的效果,深以为憾.今天把这个补齐了. 在上代码之前首先交代下,这里面存 ...

  9. HT for Web基于HTML5的图像操作(二)

    上篇介绍了HT for Web采用HTML5 Canvas的getImageData和setImageData函数,通过颜色乘积实现的染色效果,本文将再次介绍另一种更为高效的实现方式,当然要实现的功能 ...

随机推荐

  1. 项目中gulp使用发生的错误及解决

    在项目开发中,执行gulp css来生成合成的css文件时,报如下错误 Error: Cannot find module 'browserslist' 解决方法: npm install brows ...

  2. 8.bwapp亲测xxe漏洞

    这几天在学习XXE漏洞,这里用靶机bwapp来练习一下这个漏洞,重在学习 xxe漏洞主要针对webservice危险的引用的外部实体并且未对外部实体进行敏感字符的过滤, 从而可以造成命令执行,目录遍历 ...

  3. Flask 入门(第一篇)

    1. 认识 Flask Flask 是一个微型 Web 框架,依赖于 jinjia2 模板系统和 Werkzeug WSGI(本质为 Socket 服务端) 服务,默认情况不支持数据库抽象层.表单验证 ...

  4. Ajax原生请求及Json基础

    1.基本结构 <script type="text/javascript"> // 创建XMLHttpRequest对象 var request = new XMLHt ...

  5. CF70D Professor's task(动态凸包)

    题面 两种操作: 1 往点集S中添加一个点(x,y); 2 询问(x,y)是否在点集S的凸包中. 数据保证至少有一个2操作, 保证刚开始会给出三个1操作, 且这三个操作中的点不共线. 题解 动态凸包板 ...

  6. POJ1027 The Same Game

    题目来源:http://poj.org/problem?id=1027 题目大意: 题目说的就是现在蛮流行的手机小游戏popstar,求用贪心方法能得到多少分. 小球有三种颜色:R/G/B.横向.纵向 ...

  7. 如何顺畅使用sourcetree可视化工具

    http://www.360doc.com/content/17/0711/10/11253639_670493403.shtml sourcetree软件下载 下载地址:https://www.so ...

  8. Java中只有按值传递,没有按引用传递!(两种参数情况下都是值传递)

    今天,我在一本面试书上看到了关于java的一个参数传递的问题: 写道 java中对象作为参数传递给一个方法,到底是值传递,还是引用传递? 我毫无疑问的回答:“引用传递!”,并且还觉得自己对java的这 ...

  9. #define 只是字符替换

    可以使用 #define MAX 100 int main (int argc, char *argv[]) { printf("MAX is %d\n", MAX); ; } g ...

  10. 利用Python进行数据分析 2017 第二版 项目代码

    最近在学习<利用Python进行数据分析>,找到了github项目的地址, 英文版本,中文版本 (非常感谢翻译中文的作者). mark一下,方便后边学习查找.