QImage使用scanLine直接对图片的颜色数据进行操作

2021年07月15日 158点热度 1人点赞 0条评论

简介

在对QImage进行渲染的时候,有两种方式。一种是使用qpainter,把QImage作为一个画布构造一个QPainter,这样就可以使用QPainter的绘图函数在QImage对象上进行一些操作。还有一种方法是直接对QImage的数据及进行操作。

首先要了解QImage储存图像数据的方式,Qimage::Format给出了很多中数据存储的方式,

官方文档https://doc.qt.io/qt-5/qimage.html#Format-enum

这里以Format_ARGB32为例,我们知道图片都是以一个一个像素点构成的,Qimage的存储方式是将每个点的像素颜色使用32位的数据,按照ARGB的顺序来存储的(0x(AARRGGBB)),如0xff00ff00可以表示绿色。

那么知道了对象存储图像数据的方式,接下来只需要依次修改每一个像素点的颜色就可以对QImage对象进行渲染了。Uchar* Qimage::scanLine(int i)这个函数提供了直接访问QImage对象内部的像素点的方法,通过传入的扫面行号,返回一个数据的指针,这个指针指向第一个像素的第一个字节的数据。

效果实现

先实现对图片的操作

QImage image(QSize(800, 400),QImage::Format_ARGB32);
unsigned char* line = image->scanLine(200);
    for (int i = 0; i < 800;i++)
    {
        unsigned int rgb = qRgba(255, 0, 0,255);
        unsigned char* c = (unsigned char*)(&rgb);
        unsigned char a = *(c);
        unsigned char r = *(c + 1);
        unsigned char g = *(c + 2);
        unsigned char b = *(c + 3);
        
        *line = a;
        line++;
        *line = r;
        line++;
        *line = g;
        line++;
        *line = b;
        line++;
            }

然后将图片显示到窗口上,就可以看到这样的效果

因为这里只对一根像素线进行了操作,所以这里看到的是一根红色的线。

补充

实际上这里有一个小错误,就是在获取argb值得顺序的时候,我直接按照直觉从左到右的获取的,只要调试一下a,r,g,b四个变量的值,就能发现端倪,他们的顺序被过来了。我后来想了半天才明白,我取值的时候是从低位地址取的,但是赋值的时候确实从左到右,先从高位开始的,那么顺序当然是反的。那么这里结果却是正确的,是因为给imag对象的数据赋值的时候顺序也是反的,所以负负得正。

所以我们如果需要自己填入rgb的颜色数据,而不是从qrgb转换,那么我们的代码需要这样写,才能得到跟上面一样的结果。

    unsigned char* line = image->scanLine(200);
    for (int i = 0; i < 800;i++)
    {
        unsigned char a = 0xff;
        unsigned char r = 0xff;
        unsigned char g = 0x00;
        unsigned char b = 0x00;
        
        *line = b;
        line++;
        *line = g;
        line++;
        *line = r;
        line++;
        *line = a;
        line++;
}

 

大脸猫

半个C++程序员。

文章评论