一、基于Qt的图像矩形区域改色

Qt环境下图像的打开和涂色

一、设计目标

能够在 Qt QtCreator 环境下打开常用图像格式文件,诸如 bmpjpgpng 图像等,然后将他们转化为 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=0;i<height;i++)

        for(int j=0;j<width;j++)

        {

            if((i>=startPoint.x())&&i<endPoint.x()&&

                    (j>=startPoint.y())&&j<endPoint.y())

            {

                dstdata[i*bytesPerLine+j*4]  = b;

                dstdata[i*bytesPerLine+j*4+1]= g;

                dstdata[i*bytesPerLine+j*4+2]= r;

            }

            else{

                dstdata[i*bytesPerLine+j*4]  = scrdata[0];

                dstdata[i*bytesPerLine+j*4+1]= scrdata[1];

                dstdata[i*bytesPerLine+j*4+2]= scrdata[2];

            }

            scrdata+=4;

        }

    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("0",this);

    y1Text = new QLineEdit("0",this);

    x2Text = new QLineEdit("100",this);

    y2Text = new QLineEdit("100",this);

    rLabel = new QLabel("R:",this);

    gLabel = new QLabel("G:",this);

    bLabel = new QLabel("B:",this);

    rText = new QLineEdit("0",this);

    gText = new QLineEdit("0",this);

    bText = new QLineEdit("0",this);

    okButton = new QPushButton("OK",this);

 

    layout->addWidget(startLabel,0,0,1,1); // 添加布局

    layout->addWidget(x1Text,0,1,1,1);

    layout->addWidget(y1Text,0,2,1,1);

    layout->addWidget(endLabel,1,0,1,1);

    layout->addWidget(x2Text,1,1,1,1);

    layout->addWidget(y2Text,1,2,1,1);

    layout->addWidget(rLabel,2,0,1,1);

    layout->addWidget(gLabel,3,0,1,1);

    layout->addWidget(bLabel,4,0,1,1);

    layout->addWidget(rText,2,1,1,1);

    layout->addWidget(gText,3,1,1,1);

    layout->addWidget(bText,4,1,1,1);

    layout->addWidget(okButton,2,2,1,1);

这样 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

如果上述教程或代码中有任何错误,欢迎批评和指证。

猜你喜欢

转载自www.cnblogs.com/akakakkk/p/8534644.html
今日推荐