Qt提供了四个类来处理图像数据:QImage, QPixmap, QBitmap和QPicture
-QImage是为I/O和直接像素访问和操作而设计和优化的,
-QPixmap是为屏幕上显示图像而设计和优化的
-QBitmap只是一个继承QPixmap的便利类
-QPicture类是一个绘制设备,用于记录和回放QPainter操作
QPicture的理解
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
QPicture picture;
QPainter painter;
painter.begin(&picture); // paint in picture
painter.drawEllipse(10,20, 80,70); // draw an ellipse
painter.end(); // painting done
picture.save("drawing.pic"); // save picture
}
void Widget::paintEvent(QPaintEvent *)
{
QPicture pic;
pic.load("drawing.pic");
QPainter p;
p.begin(this); // paint in current widget
p.drawPicture(0, 0, pic); // draw the pic at (0,0)
p.end();
}
设备无关图像类 - QImage
-独立于具体硬件的图像类 ,主要用于读写图像文件,针对IO访问而设计 ,能够直接在像素级对图像进行处理
-读取图像文件,直接进行像素级操作 ,内置简易图像处理相关算法
-加载图像的三种方式:带参构造函数,load函数,fromData函数
设备相关图像类 - QPixmap
-依赖于具体硬件的图像类 ,主要是用于绘图,针对屏幕显示而设计 ,显示效果依赖于所在平台的绘制引擎(不可移植)
-最大限度利用硬件(显卡)加速,增强图像显示效果。屏幕截图,窗口截图,组件截图,...
◆ grabWindow() 用于对屏幕图像进行抓取
◆ grabWidget() 用于对当前程序中的组件外观图像进行抓取
适用场合
-Qlmage适用于直接进行图像处理的场合 ,QPixmap适用于在界面上显示图像的场合
-QPixmap能够对Qlmage图像进行转换 ,QPainter能够直接在图像对象上进行绘图
-Qt图像类都继承自QPaintDevice ,QPainter能够直接在图像上绘制图形
QImage像素操作
存储在QImage中的每个像素都用一个整数表示。整数的大小取决于格式
8位图像使用8位索引存储在一个颜色表中,即每个像素有一个字节。颜色表是一个QVector<QRgb>, QRgb 相当于一个unsigned int,包含格式为0xAARRGGBB
32位图像没有颜色表;相反,每个像素包含一个QRgb值,包含alpha通道、红、绿、蓝通道。通过这些通道能够确定一个像素的各种颜色。默认的alpha通道是ff,即不透明
// 32bit
QImage image(3, 3, QImage::Format_RGB32); // 图像使用32位RGB格式存储
QRgb value;
value = qRgb(189, 149, 39); // 0xffbd9527, ff代表不透明
image.setPixel(1, 1, value);
value = qRgb(122, 163, 39); // 0xff7aa327
image.setPixel(0, 1, value);
image.setPixel(1, 0, value);
value = qRgb(237, 187, 51); // 0xffedba31
image.setPixel(2, 1, value);
// 8bit
QImage image(3, 3, QImage::Format_Indexed8); // 图像使用8位索引存储到一个颜色映射中
QRgb value;
value = qRgb(122, 163, 39); // 0xff7aa327
image.setColor(0, value);
value = qRgb(237, 187, 51); // 0xffedba31
image.setColor(1, value);
value = qRgb(189, 149, 39); // 0xffbd9527
image.setColor(2, value);
image.setPixel(0, 1, 0);
image.setPixel(1, 0, 0);
image.setPixel(1, 1, 2);
image.setPixel(2, 1, 1);
图像处理
Qt中的QColor类同时支持多种颜色表示方式
- RGB: 以红,绿,蓝为基准的三色模型
- HSV: 以色调,饱和度,明度为基准的六角锥体模型
- CMYK: 以天蓝,品红,黄色,黑为基准的全彩印刷色彩模型
颜色通常按照RGB(红、绿、蓝)来指定,但是也可以按照HSV和CMYK来指定
QColor构造函数根据RGB值创建颜色。可以使用toHsv()和toCmyk()函数 得到HSV或CMYK创建的QColor
-想提高图片的亮度,可以增高红绿蓝通道的颜色,偏白效果
-想提高图片的灰度,可以综合红绿蓝通道的颜色,偏白效果
-想提高图片的暖色,可以增高红色和绿色,偏黄效果
-想提高图片的冷色,可以增高蓝色
-可以用RGB构建QColor,再转换为HSV创建的QColor,再提高各个参数
重置图像大小并灰度化 main.cpp
#include <QtCore/QCoreApplication>
#include <QImage>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QImage img;
if( img.load("test.jpg") ) // 也可以直接QImage构造函数中传参加载
{
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); // 该函数开销很大; 如果考虑性能,建议使用scanLine()一次读取整行像素值
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.jpg");
}
return a.exec();
}
屏幕截图 Widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QtGui/QWidget>
#include <QPushButton>
#include <QPixmap>
class Widget : public QWidget
{
Q_OBJECT
QPushButton m_loadBtn;
QPushButton m_grabBtn;
QPixmap m_pmap; // 支持隐式共享
private slots:
void onLoadBtnClicked();
void onGrabBtnClicked();
protected:
void paintEvent(QPaintEvent *);
public:
Widget(QWidget *parent = 0);
~Widget();
};
#endif // WIDGET_H
Widget.cpp
#include "Widget.h"
#include <QPainter>
#include <QFileDialog>
#include <QImage>
#include <QMessageBox>
#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;
if( img.load(fd.selectedFiles()[0]) )
{
m_pmap = QPixmap::fromImage(img);
update();
}
else
{
QMessageBox(QMessageBox::Critical, "Error", "Invalid image file!").exec();
}
}
}
void Widget::onGrabBtnClicked()
{
m_pmap = QPixmap::grabWindow(QApplication::desktop()->winId());
update();
}
void Widget::paintEvent(QPaintEvent *)
{
QPainter painter;
if( !m_pmap.isNull() )
{
painter.begin(this);
painter.drawPixmap(0, 0, width(), height(), m_pmap);
painter.end();
}
}
Widget::~Widget()
{
}