如果我在内存中生成了一个包含RGBA各分量的颜色二维数组ColorArray,要怎样通过QImage把这些数据显示出来呢?
①QImage需要加载这些数据
//1、 通过QImage的构造函数
QImage(const uchar *data, int width, int height, Format format, QImageCleanupFunction cleanupFunction = Q_NULLPTR,
void *cleanupInfo = Q_NULLPTR);
//其中data是指向颜色数据(32bit)的指针,width表示一行有多少个像素,height表示一列有多少个像素,format表示图像格式(QImage
//提供了多种格式)。QImage在析构时并不会删除data。如果提供了cleanupFunction和cleanupInfo,那么当QImage的图像数据不再被使用时,
//会调用cleanupFunction清除cleanupInfo所指向的内存。
//通过静态函数 QImage::fromData 还没尝试过
②内存中ColorArray的格式需要和QImage的数据格式一致。
存在QImage中的每一个像素都是以整型integer来表示的。这个integer的size以及每个byte的意义,与QImage的格式有关 。QImage支持的颜色数据格式有很多种,比如QImage::Format_RGB16、QImage::Format_RGBA8888、QImage::Format_ARGB32等等。
格式类型 | 不同点 |
QImage::Format_ARGB32 | 32bit的ARGB,按32bit整型去访问,始终是0xAARRGGBB。如果按字节来读取(也就是存储方式相关),在不同的系统上,读取的顺序不同。如果在大端big_endian架构上,按字节会被读取为0xAA、0xRR、0xGG、0xBB;在小端little_endian架构上,按字节会被读取为0xBB、0xGG、0xRR、0xAA。 可以记作,Byte存储方式顺序不定,4-Byte读取的数值固定。 |
QImage::Format_RGBA8888 | 每一个32bit中,RGBA各分量的顺序是有序的。如果按字节来读取,那么会依次读取字节0xRR、0xGG、0xBB、0xAA。那么,在大端big_endian上,这个32bits会被表示为0xRRGGBBAA,在小端little_endian上,会被表示为0xAABBGGRR。 可以记作,Byte存储方式顺序固定,4-Byte读取的数值不定。 |
从上面的表格中可以看出,对于一块ColorArray,如果用不同的QImage::Fromat,可能会产生不同的图像。
我们的问题是,如果用这块buffer,直接套用QImage(ColorArray,width,height, format)的构造函数,如何生成一个QImage::Format_RGBA8888的QImage?
在大端big_endian结构上,QImage::Format_RGBA8888对应的byte顺序是 0xRR、0xGG、0xBB、0xAA,所以我们在buffer中赋值时,应依给每个Byte字节幅值RR、GG、BB、AA。或者使用如下结构体直接给32bits赋值。
typedef struct
{
U8 red;
U8 green;
U8 blue;
U8 alpha;
} Color;
/*
注意,使用这种结构计算出RGBA的各分量后,形成了一块显示内存区域ColorArray.
对于这块ColorArray, QImage是直接以int*指针来访问的。通常情况下,这没有问题。
但是,如果还要对基于这块ColorArray的QImage进行一次缩放(QImage::scales(...)),则容易出现问题。
因为,进行一次缩放,涉及对ColorArray的遍历,会用int*的指针进行访问,但是,由于ColorArray是用
Color对象构造的,ColorArray并不一定存放在与int对齐的地址上,因此,用int*指针访问会导致“段错误”。
那么,如何避免这种情况呢?有这么2个思路:
1.将ColorArray拷贝到一个int类型的数组上ColorArrayInt,QImage用ColorArrayInt构造
2.typedef union{Color color; int colorInt}ColorUnion;通过构造联合体,确保Color是与int类型对齐的。
无论对于大端还是小端系统,无论是栈上还是堆上,Color::red的地址都小于Color::alpha;相应的,int32 temp[4]中,
temp[0]的地址小于temp[4]的地址。
但是,在大端系统中,int32类型变量的第一个byte对应高8位数据,int32类型变量的地4个字节,对应低8未数据;
在小端系统中,int32类型变量的第一个byte,对应低8位数据,int32类型变量的地4个字节,对应高8未数据。
大端和小端的概念,仅在于变量类型内部如何安排byte,但是变量和变量之间,还是按照通常的顺序排布。
*/
附件:
QImage::Format列表(待更新....)
如有不足,欢迎拍砖。如需转载,请注明来源。