Qt QImage加载内存数据后绘制

如果我在内存中生成了一个包含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_ARGB3232bit的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列表(待更新....)

 

如有不足,欢迎拍砖。如需转载,请注明来源。

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
QT QImage加载图片可以通过以下步骤完成。首先,创建一个QImage对象和一个QLabel对象,然后使用load()函数加载图片文件。可以通过右击工程的图片获取图片路径。接下来,使用setPixmap()函数将QImage对象转换为QPixmap对象,并将其设置为QLabel的显示内容。还可以使用setGeometry()函数设置QLabel相对于父类的位置。最后,使用show()函数显示QLabel。 另外,可以使用QImageReader的方法读取图片。首先设置QImageReader的属性,例如setDecideFormatFromContent()设置是否根据内容自动确定图片格式,setScaledSize()设置图片的大小。然后使用setFileName()函数设置图片的路径。如果可以读取图片,使用read()函数读取图片,并通过QPainter的drawPixmap()函数绘制图片。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [一种QImage加载大图片的解决方案](https://download.csdn.net/download/fregry10/10685883)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [【QT】添加图片资源并使用QImage加载图片显示](https://blog.csdn.net/weixin_43894927/article/details/107177957)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [Qt加载大图片(图片较大无法正常加载,显示空白处理方法)](https://blog.csdn.net/fhakfs/article/details/124500642)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值