点击上方蓝字关注我们
Qt提供了四个类用于处理图像数据:QImage、QPixmap、QBitmap、QPicture。一般利用QImage、QPxmap类实现图像的加载显示,使用其类中的方法可以实现图像的基本操作(缩放、旋转)。QBitmap是一个继承于QPixmap的简单类,用于显示单色图片。在界面中通常使用QLabel控件来显示图像,QLabel的setPixmap()函数用于设置显示图像或者使用QPainter画出图像。
1、QPixmap主要是用于绘图,针对屏幕显示而最佳化设计,QImage主要是为图像I/O、图片访问和像素修改而设计的,当图片小的情况下,直接用QPixmap进行加载,一般图片大的情况下,用QImage进行加载,然后转QPixmap绘制。
2、QPixmap依赖于所在的平台的绘图引擎,例如反锯齿等一些效果在不同的平台上可能会有不同的显示效果,QImage使用Qt自身的绘图引擎,可在不同平台上具有相同的显示效果。所以QPixmap绘图依赖于硬件,QImage独立于硬件。
3、由于QImage是独立于硬件的,也是一种QPaintDevice,因此我们可以在另一个线程中对其进行绘制,而不需要在GUI线程中处理,使用这一方式可以很大幅度提高UI响应速度。
参考Qt的帮助文档,可查看当前QT支持的图片类型,或者可以通过QImageReader::supportedImageFormats() QImageWriter::supportedImageFormats()函数进行获取。
以上介绍4个类之间的继承关系如下图:
本章节前面小节先介绍图片数据加载与显示相关知识,后面小节再介绍图形的绘制部分。
9.1 使用QPxmap类加载图片 QPixmap是专门为绘图而生,当需要绘制图片时就需要使用QPixmap类。QPixmap可以很容易使用QLabel或QAbstractButton的子类(QPushButton和QToolButton等)将图片在显示在屏幕上。本小节主要介绍QPixmap相关函数使用方法。
1. 构造QPixmap
QPixmap(int width, int height)
QPixmap(const QSize &size)
QPixmap(const QString &fileName, const char *format = Q_NULLPTR, Qt::ImageConversionFlags flags = Qt::AutoColor)
QPixmap(const char * const[] xpm)
QPixmap(const QPixmap &pixmap) //复制构造函数
|
QPixmap的构造函数不仅可以传入图片的文件名称,也支持传入图片的尺寸创建一个图片。形参中的format属性用于指定当前加载文件的格式,一般情况下QPixmap会根据文件的后缀进行识别,该属性使用默认值即可。一般支持显示的format格式有BMP、GIF、JPG、JPEG、PNG、TIFF、PBM、PGM、PPM、XBM、XPM等。
使用QPixmap加载图片并显示示例:
#include <QApplication>
#include <QLabel>
#include <QHBoxLayout>
#include <QWidget>
#include <QPixmap>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QPixmap pixmap1("E:/1.png"); //加载图片
QPixmap pixmap2(100,100); //构造100*100的画布
pixmap2.fill(QColor(255,0,255)); //构建的颜色
QLabel *label1 = new QLabel;
QLabel *label2 = new QLabel;
label1->setPixmap(pixmap1);
label2->setPixmap(pixmap2);
//水平布局
QHBoxLayout *layout=new QHBoxLayout;
layout->addWidget(label1);
layout->addWidget(label2);
QWidget *widget =new QWidget;
widget->setLayout(layout);
widget->show();
return a.exec();
}
|
显示效果:
图9-1-1 使用QPixmap显示图片效果
2. 加载图片方法
加载图片可以通过QPixmap的构造函数传入,也可以通过QPixmap类提供的load函数进行加载或者通过loadFromData函数进行加载。相关函数原型如下:
(1)bool QPixmap::load
(const QString &fileName, const char *format = Q_NULLPTR, Qt::ImageConversionFlags flags = Qt::AutoColor
(2)bool QPixmap::loadFromData
(const uchar *data, uint len, const char *format = Q_NULLPTR, Qt::ImageConversionFlags flags = Qt::AutoColor)
(3)bool QPixmap::loadFromData
(const QByteArray &data, const char *format = Q_NULLPTR, Qt::ImageConversionFlags flags = Qt::AutoColor)
|
其中load函数用于加载本地的图片文件,loadFromData函数是根据内存中的图像数据进行导入,而图像的数据可以是从本地磁盘上读入的文件。比如:读入一张BMP格式的文件到QByteArray对象中,再调用loadFromData函数,那么loadFromData函数就会根据QByteArray中数据进行解析,分析图像的格式等。
加载二进制格式数据示例:
#include <QApplication>
#include <QLabel>
#include <QHBoxLayout>
#include <QWidget>
#include <QPixmap>
#include <QFile>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QFile file("E:/1.png");
file.open(QIODevice::ReadOnly);
QByteArray array=file.readAll(); //读取文件数据
file.close();
QPixmap pixmap1;
QPixmap pixmap2;
pixmap1.loadFromData(array); //加载二进制数据
pixmap2.load("E:/1.png"); //加载文件数据
QLabel *label1 = new QLabel;
QLabel *label2 = new QLabel;
label1->setPixmap(pixmap1);
label2->setPixmap(pixmap2);
//水平布局
QHBoxLayout *layout=new QHBoxLayout;
layout->addWidget(label1);
layout->addWidget(label2);
QWidget *widget =new QWidget;
widget->setLayout(layout);
widget->show();
return a.exec();
}
|
效果图如下:
图9-1-2 QPixmap加载二进制数据显示
3. 获取图片基本信息
图片基本信息包括图片尺寸、颜色位数等。相关函数函数原型如下:
int QPixmap::height() const
int QPixmap::width() const
QSize QPixmap::size() const
QRect QPixmap::rect() const
int QPixmap::depth() const
|
其中height()和width()函数获取图片的高度与宽度,size()函数获取图片的尺寸,相当于同时获取了宽度和高度。rect()函数获取当前图片的矩形尺寸,包含图片的宽度、高度和显示的位置。depth()函数用于获取当前图片的颜色位数。
4. 保存图片
Qpixmap支持将当前显示的图片数据保存为文件,也支持将图片数据保存为QIODevice类型。
bool save(const QString &fileName, const char *format = Q_NULLPTR, int quality = -1) const
bool save(QIODevice *device, const char *format = Q_NULLPTR, int quality = -1) const
|
保存图片示例:
#include <QApplication>
#include <QLabel>
#include <QHBoxLayout>
#include <QWidget>
#include <QPixmap>
#include <QFile>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QFile file;
file.setFileName("E:/image/3.bmp");
QPixmap pixmap;
pixmap.load("E:/image/1.png","PNG"); //加载文件数据
pixmap.save("E:/image/2.jpg","JPG"); //保存为jpg格式的图片文件
pixmap.save(&file,"BMP"); //保存为bmp格式的数据
file.close();
return 0;
}
|
运行效果图如下:
图9-1-3 保存图片运行效果
5. 图片放大与缩放
QPixmap支持将当前加载的图片按照指定的宽度和高度创建成一个副本返回。相关函数原型如下:
(1)
QPixmap QPixmap::scaled(int width, int height, Qt::AspectRatioMode aspectRatioMode = Qt::IgnoreAspectRatio, Qt::TransformationMode transformMode = Qt::FastTransformation) const
(2)
QPixmap QPixmap::scaledToHeight(int height, Qt::TransformationMode mode = Qt::FastTransformation) const
(3)
QPixmap QPixmap::scaledToWidth(int width, Qt::TransformationMode mode = Qt::FastTransformation) const
|
Scaled函数支持传入高度和宽度参数,如果想保持高度或者宽度不变只是改变其中一种尺寸,可以使用scaledToHeight函数和scaledToWidth函数。
缩放示例:
#include <QApplication>
#include <QLabel>
#include <QHBoxLayout>
#include <QWidget>
#include <QPixmap>
#include <QFile>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QPixmap pixmap1;
QPixmap pixmap2;
QPixmap pixmap3;
QPixmap pixmap4;
pixmap1.load("E:/1.png"); //加载图文件数据
pixmap2=pixmap1.scaled(100,100); //比例
pixmap3=pixmap1.scaled(80,80);
pixmap4=pixmap1.scaled(40,40);
QLabel *label1 = new QLabel;
QLabel *label2 = new QLabel;
QLabel *label3 = new QLabel;
QLabel *label4 = new QLabel;
label1->setPixmap(pixmap1);
label2->setPixmap(pixmap2);
label3->setPixmap(pixmap3);
label4->setPixmap(pixmap4);
//水平布局
QHBoxLayout *layout=new QHBoxLayout;
layout->addWidget(label1);
layout->addWidget(label2);
layout->addWidget(label3);
layout->addWidget(label4);
QWidget *widget =new QWidget;
widget->setLayout(layout);
widget->show();
return a.exec();
return 0;
}
|
运行效果如下:
图 9-1-4 图片缩放效果
6. QPixmap与QImage格式转换
QImage QPixmap::toImage() const
bool convertFromImage(const QImage &img, Qt::ImageConversionFlags flags = Qt::AutoColor);
static QPixmap fromImage(const QImage &image, Qt::ImageConversionFlags flags = Qt::AutoColor);
|
toImage()函数用于将Qpixmap格式数据转为QImage格式返回。
convertFromImage函数用于加载QImage类型的数据。
fromImage函数是一个静态函数,也是用于加载QImage类型的数据,并使用Qpixmap格式返回。
7. 快速拷贝图片
Qpixmap支持截取当前加载图片上的某一个区域返回QPixmap对象。类似于指定区域截图的效果。
QPixmap QPixmap::copy(int x, int y, int width, int height) const
QPixmap::copy(const QRect & rectangle = QRect()) const
|
9.2 使用QImage类加载图片 QImage类提供了一个硬件无关的图像表示方法,可以直接访问图像的像素和用于画图设备。如果要对图像进行操作,就需要使用QImage类,最终显示在标签上还得利用QPixmap类。下面将介绍常用的成员函数使用方法。
下面将介绍QImage使用方法。
1. 构造QImage
(1)QImage(int width, int height, Format format)
(2)QImage(uchar *data, int width, int height, int bytesPerLine, Format format, QImageCleanupFunction cleanupFunction = Q_NULLPTR, void *cleanupInfo = Q_NULLPTR)
(3)QImage(uchar *data, int width, int height, Format format, QImageCleanupFunction cleanupFunction = Q_NULLPTR, void *cleanupInfo = Q_NULLPTR)
(4)QImage(const QString &fileName, const char *format = Q_NULLPTR)
|
通过以上4个构造函数的形参中看出,QImage类支持加载文件名称,也支持加载二进制图像数据。第2个构造函数支持加载原始的RGB数据。Format格式枚举值如下表所示:
颜色格式枚举值
| 描述
| QImage::Format_Invalid
| 图像无效
| QImage::Format_Mono
| 存储使用1位每像素的图像,字节填充最重要位第一
| QImage::Format_MonoLSB
| 存储使用1位每像素的图像,字节填充不显著位第一
| QImage::Format_Indexed8
| 图像存储使用8位指标转化成Colormap
| QImage::Format_RGB32
| 存储使用32位RGB格式的图像(0xffrrggbb)
| QImage::Format_ARGB32
| 存储使用32为ARGB格式的图像(0xaarrggbb)
| QImage::Format_ARGB32_Premultiplied
| 图像存储使用32位ARGB格式
| QImage::Format_RGB16
| 图像存储使用5-6-5 16位RGB格式
| QImage::Format_ARGB8565_Premultiplied
| 图像存储使用24位ARGB格式8-5-6-5
| QImage::Format_RGB666
| 图像存储使用6-6-6 24位RGB格式,未使用的最重要的位总是为零
| QImage::Format_ARGB6666_Premultiplied
| 图像存储使用24位ARGB格式6-6-6-6
| QImage::Format_RGB555
| 图像存储使用16位RGB格式(5-5-5
| QImage::Format_ARGB8555_Premultiplied
| 图像存储使用24位ARGB格式8-5-5-5
| QImage::Format_RGB888
| 图像存储使用8-8-8 24位RGB格式
| QImage::Format_RGB444
| 图像存储使用16位RGB格式(4-4-4)未使用的位始终为零
| QImage::Format_ARGB4444_Premultiplied
| 图像存储使用16位ARGB格式4-4-4-4
| QImage::Format_RGBX8888
| 图像存储使用32位字节命令RGB(x)格式8-8-8-8
| QImage::Format_RGBA8888
| 存储使用32位字节命令RGBA格式(8-8-8-8)的的图像
| QImage::Format_RGBA8888_Premultiplied
| 图像存储使用32位字节命令RGBA格式8-8-8-8
| QImage::Format_BGR30
| 存储使用32位BGR格式(x-10-10-10)的的图像
| QImage::Format_A2BGR30_Premultiplied
| 图像存储使用32位abgr格式2-10-10-10
| QImage::Format_RGB30
| 存储使用32位RGB格式(x-10-10-10)的的图像
| QImage::Format_A2RGB30_Premultiplied
| 图像存储使用2-10-10-10 32位自左乘ARGB格式
| QImage::Format_Alpha8
| 该图像是使用一个8位的阿尔法格式存储
| QImage::Format_Grayscale8
| 图像是使用一个8位灰度格式存储
|
加载图片显示示例:
#include <QImage>
#include <QApplication>
#include <QLabel>
#include <QHBoxLayout>
#include <QWidget>
#include <QPixmap>
#include <QFile>
#include <QBitmap>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QImage image("E:/1.png"); //加载图片
qDebug()<<image.format();
QPixmap pixmap=QPixmap::fromImage(image); //转换格式
QLabel *label = new QLabel;
label->setPixmap(pixmap);
//水平布局
QHBoxLayout *layout=new QHBoxLayout;
layout->addWidget(label);
QWidget *widget =new QWidget;
widget->setLayout(layout);
widget->show();
return a.exec();
}
|
效果图如下:
图9-2-1 QImage加载图片示例
2. QImage加载图像数据
除了通过构造函数加载图像参数,也可以通过以下4个函数进行加载。
bool load(const QString &fileName, const char *format = Q_NULLPTR)
bool load(QIODevice *device, const char *format)
bool loadFromData(const uchar *data, int len, const char *format = Q_NULLPTR)
bool loadFromData(const QByteArray &data, const char *format = Q_NULLPTR)
|
前两个load函数可以直接加载文件和QIODevice类型数据,后两个loadFromData函数用于加载缓冲区中的图片数据。
加载缓存区图像数据示例:
#include <QImage>
#include <QApplication>
#include <QLabel>
#include <QHBoxLayout>
#include <QWidget>
#include <QPixmap>
#include <QFile>
#include <QBitmap>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QFile file("E:/2.jpg");
file.open(QIODevice::ReadOnly);
QByteArray array=file.readAll();
file.close();
QImage image; //加载图片
image.loadFromData(array,"JPG"); //直接加载缓冲区数据
QPixmap pixmap=QPixmap::fromImage(image); //转换格式
QLabel *label = new QLabel;
label->setPixmap(pixmap
//水平布局
QHBoxLayout *layout=new QHBoxLayout;
layout->addWidget(label)
QWidget *widget =new QWidget;
widget->setLayout(layout);
widget->show();
return a.exec();
}
|
3. 保存图像数据到文件相关函数接口
bool QImage::save(const QString & fileName, const char * format = 0, int quality = -1) const
bool QImage::save(QIODevice * device, const char * format = 0, int quality = -1) const
|
示例代码可以参考9.1 QPxmap章节对应的save函数。
4. 关于图片的放大与缩小相关函数
QImage QImage::scaledToWidth(int width, Qt::TransformationMode mode = Qt::FastTransformation) const
QImage QImage::scaledToHeight(int height, Qt::TransformationMode mode = Qt::FastTransformation) const
QImage QImage::scaled(int width, int height, Qt::AspectRatioMode aspectRatioMode = Qt::IgnoreAspectRatio, Qt::TransformationMode transformMode = Qt::FastTransformation) cons
|
示例代码可以参考9.1 QPxmap章节对应的scaled函数。
5. 获取图像相关信息
int QImage::byteCount() const
| 获取图像像素数据部分总字节数
| int QImage::bytesPerLine() const
| 获取图像一行的像素字节数
| int QImage::height() const
| 获取图像高度
| int QImage::width() const
| 获取图像宽度
| bool QImage::isNull() const
| 判断当前加载的图像是否有效
| Format QImage::format() const
| 获取当前加载图像的格式
| int QImage::depth() const
| 获取图像颜色深度。支持的深度是1、8、16、24、32。
|
6. 将图像填充为指定的颜色值
void QImage::fill(uint pixelValue)
void QImage::fill(Qt::GlobalColor color)
void QImage::fill(const QColor &color)
|
示例:
QImage image;
image.load("D:/1.png");
image.fill(Qt::red); //将图片填充为红色
|
7. RGB颜色通道转换
QImage QImage::rgbSwapped() const
|
将RGB格式转为BGR格式。将所有像素的红色和蓝色分量值交换位置。
8. 设置与读取颜色值相关函数
QRgb QImage::color(int i) const
| 获取颜色表中指定索引位置的颜色值
| QRgb QImage::pixel(int x, int y) const
| 获取指定坐标位置的颜色值
| void QImage::setPixel(int x, int y, uint index_or_rgb)
| 设置指定位置的颜色值
| uchar *QImage::scanLine(int i)
| 获取第i行的像素数据首地址
| uchar *QImage::bits()
| 获取像素数据首地址。相当于scanLine(0)
|
下面编写一个示例代码,使用QImag函数实现将像素颜色从一张图片中读取出来,得到颜色值,再将颜色值用setPixel函数写入另一个空的QImage对象中,设置空的QImage对象像素格式为QImage::Format_ARGB32。
代码如下:
#include <QImage>
#include <QApplication>
#include <QLabel>
#include <QHBoxLayout>
#include <QWidget>
#include <QPixmap>
#include <QFile>
#include <QBitmap>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QLabel *label = new QLabel;
QLabel *labe2 = new QLabel;
QImage image_old("E:/1.png");
label->setPixmap(QPixmap::fromImage(image_old));//原图
QImage image_new(image_old.size(), QImage::Format_ARGB32); //构造新的像素图
image_new.fill(QColor(0,0,0,0)); //清除为透明色
QRgb rgb;
//读取颜色值并写入
for(int row = 0; row < image_old.height(); ++row){
for(int col = 0; col < image_old.width(); ++col){
rgb = image_old.pixel(row, col);
image_new.setPixel(row, col, rgb);
}
}
labe2->setPixmap(QPixmap::fromImage(image_new));
//水平布局
QHBoxLayout *layout=new QHBoxLayout;
layout->addWidget(label);
layout->addWidget(labe2);
QWidget *widget =new QWidget;
widget->setLayout(layout);
widget->show();
return a.exec();
}
|
图9-2-2 复制图片后显示效果
技术合作与咨询
QQ:1126626497 关注我长按二维码可识别微信号:xl1126626497
---------------------------------------------------------------------------------------------------------------------- 我们尊重原创,也注重分享,文章来源于微信公众号:DS小龙哥 嵌入式技术资讯,建议关注公众号查看原文。如若侵权请联系qter@qter.org。 ----------------------------------------------------------------------------------------------------------------------
|