Qt——图像处理与绘制

1.设备无关图像类------QImage

  • 独立于具体硬件的图像类
  • 主要用于读写图像文件,针对IO访问而设计
  • 能够直接在像素级对图像进行处理,内置简易图像处理相关算法

2.设备相关图像类------QPixmap

  • 依赖于具体硬件的图像类,最大限度利用硬件加速,增强图像显示效果
  • 主要用于绘图,针对屏幕显示而设计
  • 显示效果依赖于所在平台的绘图引擎(不可移植)
  • 屏幕截图、窗口截图、组件截图

3.Qt图像类都继承自QPaintDevice,QPainter能够直接在图像上绘制图形,QImage和QPixmap能够相互转换

示例1:

复制代码
#include <QtCore/QCoreApplication>
#include <QImage>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QImage img;
    if(img.load("test.png"))
    {
        img =img.scaled(QSize(img.width() / 2, img.height() / 2)); // 将大小缩小一半
        for(int i=0; i<img.width(); i++)
        {
            for(int j=0; j<img.height(); j++)
            {
                QRgb rgb = img.pixel(i, j);
                int r = qRed(rgb);
                int g = qGreen(rgb);
                int b = qBlue(rgb);
                int gray = (r + g + b) / 3;
                img.setPixel(i, j, qRgb(gray, gray, gray));
            }
        }
        img.save("new.png");
    }
    
    return QCoreApplication::exec();
}

示例二:

Widget.h

复制代码
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QPushButton>
#include <QPixmap>

class Widget : public QWidget
{
    Q_OBJECT

    QPushButton m_loadBtn;
    QPushButton m_grabBtn;
    QPixmap m_pmap;

protected slots:
    void onLoadBtnClicked();
    void onGrabBtnClicked();

protected:
    void paintEvent(QPaintEvent *);

public:
    explicit Widget(QWidget *parent = nullptr);
    ~Widget() override;
};
#endif // WIDGET_H

Widget.cpp

复制代码
#include "Widget.h"
#include <QFileDialog>
#include <QImage>
#include <QMessageBox>
#include <QPainter>
#include <QApplication>
#include <QDesktopWidget>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    m_loadBtn.setParent(this);
    m_loadBtn.move(10, 10);
    m_loadBtn.resize(70, 30);
    m_loadBtn.setText("Load");

    m_grabBtn.setParent(this);
    m_grabBtn.move(90, 10);
    m_grabBtn.resize(70, 30);
    m_grabBtn.setText("Grab");

    resize(500, 350);

    connect(&m_loadBtn, SIGNAL(clicked()), this, SLOT(onLoadBtnClicked()));
    connect(&m_grabBtn, SIGNAL(clicked()), this, SLOT(onGrabBtnClicked()));
}

void Widget::onLoadBtnClicked()
{
    QFileDialog fd(this);

    fd.setAcceptMode(QFileDialog::AcceptOpen); //设置对话框模式为打开
    fd.setFileMode(QFileDialog::ExistingFile); //只能选择已存在的单个文件

    if( fd.exec() == QFileDialog::Accepted )
    {
        QImage img;
        // 拿到选中的文件路径,调用load加载图片,加载成功返回true
        if( img.load(fd.selectedFiles()[0]) )
        {
            // QImage 转 QPixmap,存入类成员变量 m_pmap
            m_pmap = QPixmap::fromImage(img);
            // 触发窗口重绘,自动调用 paintEvent 绘制图片
            update();
        }
        else
        {
            QMessageBox(QMessageBox::Critical, "Error", "Invalid image file!").exec();
        }
    }
}
void Widget::onGrabBtnClicked()
{
    // QApplication::desktop() 获取桌面对象
    // winId() 获取桌面窗口系统ID
    // grabWindow(窗口ID) 截取该窗口画面,得到QPixmap赋值给m_pmap
    m_pmap = QPixmap::grabWindow(QApplication::desktop()->winId());

    update();
}

// 窗口绘图事件:窗口刷新、resize、update()触发时自动执行
void Widget::paintEvent(QPaintEvent *)
{
    QPainter painter;

    if( !m_pmap.isNull() )
    {
        painter.begin(this);
        
        // drawPixmap(x,y,宽,高,图片):从窗口左上角(0,0)开始,把图片拉伸铺满整个窗口
        painter.drawPixmap(0, 0, width(), height(), m_pmap);
        painter.end();
    }
}

Widget::~Widget() = default;