目录
其他文章:
QT - 图像处理 ( 2 ) - Qt 中 update() 和 repaint() 的区别
https://blog.csdn.net/LearnLHC/article/details/96180892
QT - 图像处理 ( 3 ) - QTransform 概述
https://blog.csdn.net/LearnLHC/article/details/96431877
QT - 图像处理 ( 4 ) - QTransform 之 坐标变换矩阵
https://blog.csdn.net/LearnLHC/article/details/96449625
QT - 图像处理 ( 5 ) - QPainterPath、QPolygonF 绘制中空图形( 环、三角板)
https://blog.csdn.net/LearnLHC/article/details/96494611
QT - 图像处理 ( 6 ) - QPainter 对 QPixmap 图像拼接、覆盖、写文字
https://blog.csdn.net/LearnLHC/article/details/96862256
QT - 图像处理 ( 7 ) - 生成透明色图片
https://blog.csdn.net/LearnLHC/article/details/96867622
0、前言
这篇文章主要阐述了如何使用Qt在像素级别上对图像进行操作,并实现了一些图像效果,这些效果主要有:灰度,模糊,锐化,添加相框,金属质感,改变图像饱和度,亮度还有白平衡。
scanLine 返回某一行数据,转换为QRgb指针可进行直接有效的像素存取操作。
一、QImage、QPixmap、QPicture区别
简介:
QBitmap:存储单色的图像,比如遮罩
QPicture:在存储QPainter的一些操作指令
QPixmap:后台显示的图像,在屏幕上绘制图像最快的方法,不过坏处就是无法访问和修改像素
QImage:提供了与硬件无关的图像表示,在IO操作中有很快的速度,并且给出了访问像素的接口
区别:
1. QPixmap主要是用于绘图,针对屏幕显示而最佳化设计,QImage主要是为图像I/O、图片访问和像素修改而设计的
2. QPixmap依赖于所在的平台的绘图引擎,故例如反锯齿等一些效果在不同的平台上可能会有不同的显示效果,QImage使用Qt自身的绘图引擎,可在不同平台上具有相同的显示效果
3. 目前的Qt会把QPixmap都存储在graphics memory中,QImage是存储在客户端的,是独立于硬件的。在 X11, Mac 以及 Symbian平台上,QPixmap 是存储在服务器端,而QImage则是存储在客户端,在Windows平台上,QPixmap和QImage都是存储在客户端,并不使用任何的GDI资源
4. 由于QImage是独立于硬件的,也是一种QPaintDevice,因此我们可以在另一个线程中对其进行绘制,而不需要在GUI线程中处理,使用这一方式可以很大幅度提高UI响应速度
5. QImage可通过setPixpel()和pixel()等方法直接存取指定的像素
6. QBitmap是QPixmap的一个子类,主要用于显示单色位图。用于制作游标QCursor或笔刷QBrush等
二、图形处理
1. 处理大的图片
如果你是要处理大的图片,比如摄像头拍摄的照片,这种情况最好是将原图缩小之后作为预览图显示在屏幕上,将图像加载进QImage或者QPixmap,然后调整大小:
QImage image("sample.png");
image = image.scaled(width, height);
使用QImageReader来读取和缩放图片,然后再加载进QImage中。QImageReader无法将一张图片加载进QPixmap中去,但是可以使用静态方法 QPixmap::fromImage(QImage img)从QImage中加载进QPixmap。这个方法非常快,并且不需要加载大图的内存开销:
QImageReader imgReader("sample.png");
imgReader.setScaledSize(QSize(width, height));
QImage * image;
imgReader.read(image);
2. 彩色图转换成灰度图
每一张图片都是由像素点组成,每一个像素都有三个通道:红,绿,蓝,还有一个alpha通道来保存透明度(JPEG格式的图片不支持透明)。每个通道的值是0-255,三个通道都是0的话,表示黑色,都是255表示白色。这篇文章中我们用RGB来表示一种颜色,也就是三个通道的值。
相比于一个像素一个像素地读取,uchar * QImage::scanLine(int i)可以一次读取整行的像素值,会更加高效,下面的例子就是按行读取的例子,也是我们将要讲的第一个例子,转灰度图
QImage * MainWindow::greyScale(QImage * origin)
{
QImage * newImage = new QImage(origin->width(), origin->height(), QImage::Format_ARGB32);
QRgb * line;
for(int y = 0; y<newImage->height(); y++)
{
QRgb * line = (QRgb *)origin->scanLine(y);
for(int x = 0; x<newImage->width(); x++)
{
// 灰度 - 取R,G,B值为三者的算数平均数;
int average = (qRed(line[x]) + qGreen(line[x]) + qRed(line[x]))/3;
newImage->setPixel(x,y, qRgb(average, average, average));
}
}
return newImage;
}
灰度
我们要学习的第一个技术就是将彩色图转换成灰度图,我们首先要明白的一点就是,其实标准的灰度图就是每个像素点的三个通道的值一样或者近似,我们的策略就是将每个像素的每个通道的值都调成一样,