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

  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. 【linux-command not find解决方法 】

    在linux下我们经常输入某些命令时经常出现提示说:command not find 首先 当出现 command not find时肯定是环境变量的问题,所以得修改环境变量.下面我也引用一下其他牛人 ...

  2. 使用Log4j2,打包后提示ERROR StatusLogger Log4j2 could not find a logging implementation.

    从Log4j切换到Log4j2,没有打包之前日志输出正常,但是打包后总是提示下面内容: 错误一: ERROR StatusLogger Log4j2 could not find a logging ...

  3. 《OD学spark》20160925 Spark Core

    一.引言 Spark内存计算框架 中国Spark技术峰会 十二场演讲 大数据改变世界,Spark改变大数据 大数据: 以Hadoop 2.x为主的生态系统框架(MapReduce并行计算框架) 存储数 ...

  4. ajax跨域问题解决方案(jsonp,cors)

    跨域 跨域有三个条件,满足任何一个条件就是跨域 1:服务器端口不一致 2:协议不一致 3:域名不一致 解决方案: 1.jsonp 在远程服务器上设法动态的把数据装进js格式的文本代码段中,供客户端调用 ...

  5. 60个DevOps开源工具,你在用哪些?

    你喜欢免费的东西吗?获得开发者社区支持的自动化,开源的工具是大家梦寐以求的.这里列举了 60 多款最棒的开源工具,可以帮助你很好的实行 DevOps. 一.开发工具 版本控制&协作开发 1.版 ...

  6. java.lang.ClassCastException: java.util.ArrayList cannot be cast to com.github.pagehelper.Page

    出现这个错误,首先看配置mybatis-config.xml中的<plugins> <plugin interceptor="com.github.pagehelper.P ...

  7. E 聪明的“KK”

    Description 非洲某国展馆的设计灵感源于富有传奇色彩的沙漠中陡然起伏的沙丘,体现出本国不断变换和绚丽多彩的自然风光与城市风貌.展馆由五部分组成,馆内影院播放名为<一眨眼的瞬间>的 ...

  8. idea dao使用@Mapper注解 业务类使用@Autowired 注入dao 爆红问题

    实际项目跑起来无影响,但是看起来不太爽. 可以在dao类添加org.springframework.stereotype.Repository 注解 或者可以在service类中使用 javax.an ...

  9. CF24D Broken robot 后效性DP

    这题咕了好久..... 设$f[i][j]$表示从$(i,j)$到最后一行的期望步数: 则有 $ f[i][1]=\frac{1}{3}(f[i][1]+f[i][2]+f[i+1][1])+1$ $ ...

  10. 才知道 Windows Live Writer Source Code plugin for SyntaxHighlighter 更新到2.0了

    这是我用 Windows Live Writer 发布的第一篇文章! 在官方网站看到 Windows Live Writer Source Code plugin for SyntaxHighligh ...