QImage 图像格式小结 Format_RGB32
原文链接
嗯,这个QImage的问题研究好久了,有段时间没用,忘了,已经被两次问到了,突然有点解释不清楚,我汗颜,觉得有必要重新总结下了,不然无颜对自己了。
图像的数据是以字节为单位保存的,每一行的字节数必须是4的整数倍,不足的补0。
(因为我们使用的是32操作系统,因此数据是按照32位对齐的,所以每行的字节数必须是4的整数倍也就是说每行的数据位必须是32位的整数倍。)这里是按照我的理解的,貌似错了,修正一下,最近在看数据对齐,这段话先忽略了,没有删掉,是因为,想留个足迹,等我找到合适的答案再贴上来。不过,图像的数据确实是按32位对齐的。
如果不是整数倍,则根据公式: W = ( w * bitcount + 31 )/32 * 4;
注: w是图像的宽度,bitcount是图像的位深,即32、24等, 计算得到的W是程序中图像每行的字节数。
这里讲述QImage的32、24、8位图。
图像格式:QImage::Format_RGB32 ,QImage::Format_RGB888,QImage::Format_Indexed8。
构造图像:
(1)、QImage myImage1 = QImage(filename); 根据文件名打开图像,如果图像本身是32、24位的,程序中图像是32位的,如果图像本身是8位、1位的,程序中对应为8位、1位。
(2)、QImage myImage2 = QImage(width, height, QImage::Format_…); 根据图像宽高来构造一幅图像,程序会自动根据图像格式对齐图像数据。
操作图像:按照(2)的方式构造图像,在Debug下,如果不给图像myImage2初值,图像不是黑的, 但release下,则构造好的图像默认为黑色。
好了,现在我们需要对图像数据操作,32位图像无疑是最简单的,因为它数据是对齐的。用width表示图像宽度,height表示图像高度。
首先熟悉几个函数:
a、uchar* bits(); 可以获取图像的首地址
b、int byteCount(); 图像的总字节数
c、int bytesPerLine(); 图像每行字节数
1、QImage::Format_RGB32,存入格式为B,G,R,A 对应 0,1,2,3
QImage::Format_RGB888,存入格式为R, G, B 对应 0,1,2QImage::Format_Indexed8,需要设定颜色表,QVector<QRgb>灰度图像颜色表设定:QVector<QRgb> colorTable;for(int k=0;k<256;++k)
{colorTable.push_back( qRgb(k,k,k) );}
2、QImage p_w_picpath32 = QImage(width, height, QImage::Format_32);
QImage p_w_picpath24 = QImage(width, height, QImage::Format_24);QImage p_w_picpath8 = QImage(width, height, QImage::Format_8);p_w_picpath8.setColorTable(colorTable);
3、需要取每个像素处理,采用指针取值,行扫的方式:
int lineNum_32 = 0; //行数int pixelsub_32 = 0; //像素下标uchar* p_w_picpathbits_32 = p_w_picpath32.bits(); //获取图像首地址,32位图uchar* p_w_picpathbits24 = p_w_picpath24.bits();uchar* p_w_picpathbits8 = p_w_picpath8.bits();for(int i=0; i<height; ++i){ //按照通常的理解,我们会如下处理,取每行lineNum_32 = i * width * 4; //对于任意图像,这句没有问题// lineNum_24 = i * width * 3; //??当width不是4的整数倍时,这句取不到每行开头// lineNum_8 = i * width; //??当width不是4的整数倍时,这句取不到每行开头for(int j=0; j<width; ++j){int r_32 = p_w_picpathbits_32[ lineNum_32 + j * 4 + 2]; int g_32 = p_w_picpathbits_32[ lineNum_32 + j * 4 + 1];int b_32 = p_w_picpathbits_32[ lineNum _32 + j * 4];// int r_24 = p_w_picpathbits_24[ lineNum_24 + j * 3]; //注意区别32位的图// int g_24 = p_w_picpathbits_24[ lineNum_24 + j *3 + 1];// int b_24 = p_w_picpathbits_24[ lineNum_24 + j * 3 + 2];// int gray_8 = p_w_picpathbits_8[ lineNum_8 + j];……//自己的操作}}
//??出问题了,因为实际的图像数据并不是以width为真实宽度的,解决,有两种方法:
第一种方法:自己计算实际的宽度
修改为:
// 获取每行的字节数
int W_32 = ( width * 32 + 31 )/32 * 4; //注意这里没有四舍五入,所以不要随意换算
int W_24 = ( width * 24 + 31 )/32 * 4;
int W_8 = ( width * 8 + 31)/32 * 4;
//也可以使用QT函数来获取,功能和上面一样
{
int W_32 = p_w_picpath32.bytesPerLine();int W_24 = p_w_picpath24.bytesPerLine();int W_8 = p_w_picpath8.bytesPerLine();
}
for(int i=0; i<height; ++i)
{
//现在可以按照通常的理解,取每行lineNum_32 = i * W_32; //注意,这里不再需要乘倍数了(4, 3等)// lineNum_24 = i * W_24; // lineNum_8 = i * W_8; for(int j=0; j<width; ++j){//这里的操作同上面的一样}
}
第二种方法:采用scanLine(int)来获取每行的首地址,
for(int i=0; i<height; ++i)
{
p_w_picpathbits_32 = p_w_picpath32.scanLine(i);p_w_picpathbits_24 = p_w_picpath24.scanLine(i);p_w_picpathbits_8 = p_w_picpath8.scanLine(i);for(int j=0; j<width; ++j){int r_32 = p_w_picpathbits_32[ j * 4 + 2]; int g_32 = p_w_picpathbits_32[ j * 4 + 1];int b_32 = p_w_picpathbits_32[ j * 4];// int r_24 = p_w_picpathbits_24[ j * 3]; // int g_24 = p_w_picpathbits_24[ j *3 + 1];// int b_24 = p_w_picpathbits_24[ j * 3 + 2];// int gray_8 = p_w_picpathbits_8[ j ];……//自己的操作}
}
OK,上述两种方法的索引就不会出现图像数据偏移的问题
4、大家注意到QImage的这个构造函数了吧,QImage::QImage ( uchar * data, int width, int height, Format format )
嗯,这个函数就是从uchar* 的数据来构造图像,一般我们都可能先将图像数据存在uchar*中,uchar* data32 = new uchar[ width * height * 4]; uchar* data24 = new uchar[ width * height * 3];uchar* data8 = new uchar[ width * height];从data32构造图像,不会有任何问题,但是当width不是4的整数倍时,你就不可能从data24和data8构造出自己想要的数据,程序会挂掉的,因为这两个数组的数据量根本不够一幅图(还记得数据补齐不)。
解决办法:
你需要首先计算出,你的图像的真实数据量(字节数), 可以根据QImage.byteCount()函数来获取图像的字节数,当然,你也可以自己计算,计算公式 byteCount = height * W; 这里的W就是每行的字节数,上面已经讲过了它的计算方法。
然后,你可以由QByteArray来获取转换的指针数据:
如:你的图像数据放在数组 uchar* srcData; 中
QByteArray p_w_picpathByteArray = QByteArray( (const char*)srcData, byteCount );
uchar* transData = (unsigned char*)p_w_picpathByteArray.data();
QImage desImage = QImage(transData, width, height, QImage::Format_…);
嗯,经过上述转换后,transData中将是补齐数据的数组,由此构造的图像不会有任何问题。
好了,终于总结完了,有很多小的问题,我不想写了,应该够用了,如果有具体其他问题,大家再仔细想想,肯定能解决的,哈哈
QImage 图像格式小结 Format_RGB32相关推荐
- QImage 图像格式小结,QImage::Format
文章转载自: https://blog.51cto.com/tracey2076/539690 嗯,这个QImage的问题研究好久了,有段时间没用,忘了,已经被两次问到了,突然有点解释不清楚,我汗颜, ...
- QImage图像格式解读
enum QImage::Format QImage::Format_Invalid 图像无效 QImage::Format_Mono 存储使用1位每像素的图像,字节填充最重要位第一 QImage:: ...
- Qt之QImage类
文章目录 QT--QImage类 QImage获取图像的数据信息 QImage图像格式转换 由RGB格式转换为BGR格式 将彩色图转换为灰度图 图像保存 QImage图像显示在QLabel上 QPix ...
- Linux环境中对海康威视工业相机SDK进行二次开发(QT+CMake+Opencv+海康SDK)
关于在Windows环境中对海康威视工业相机SDK进行二次开发的话,可以参考这两篇博客. 海康威视工业相机SDK二次开发(VS+Opencv+QT+海康SDK+C++)(一) 海康威视工业相机SDK二 ...
- [视觉实战案例]Qt下BYTE、QImage、HObject、Mat等图像格式的转换和图像显示方法
文章目录 一.图像格式间相互转换 1.BYTE转QImage.HObject和Mat 2.QImage.HObject和Mat的相互转换 二.图像显示方法 1.QLabel显示QPixmap图像 2. ...
- QImage/cv::Mat/HObject的图像格式互相转换,4字节对齐
QImage/cv::Mat互相转换 QImage ImgChange::cvMat2QImage(const Mat &mat) // Mat 改成 QImage {if (mat.type ...
- QImage与OpenCV中的MAT图像格式转换
1.Mat转换为QImage QImage Mat2QImage(const Mat& mat) { Mat rgb; cvtColor(mat, rgb, CV_BGR2RGB); ...
- Qt QImage像素格式小结
- QT中使用GDAL多线程读取遥感图像到QImage
GDAL 是一个很强大的可以读取很多格式 的带有GIS信息的栅格型图像.前阵子项目中需要读取遥感图像,并显示到QT界面,由于遥感图像一般很大,所以采取新开一个读图线程的方式来读取,防止界面假死.下面是 ...
最新文章
- freecodecamp_常见技术支持问题– freeCodeCamp常见问题解答
- Cent OS 6.4安装mysql
- python科学计算三剑客_1-python数据分析-数据分析介绍、数据分析三剑客之NumPy
- UE4 Packaging and Cooking Games
- java 事务嵌套_解惑 spring 嵌套事务
- Spring MVC (mvc框架)
- 六.用户.群组和权限
- 3.7 钱包、帐户、token、智能合约、action、权限、权重和阀值之间关系
- 佳能g2810打印机扫描怎么用_佳能g2810怎么自动清洗
- python处理nc气象数据_气象数据处理——nc文件
- Javascript使用模板字符串,find,findIndex,some,every查找数据以及map,filter过滤数据,reduce求和或平均值
- 中华文本库c语言题答案,大学计算机基础试题题库及答案(精编).doc
- react-native打包失败: Expiring daemon because jvm heap space is exhausted
- uboot研读笔记 | 13 - uboot编译构建Makefile分析研读(2016.03版本)
- 用python画玫瑰花
- vue-cli4引入Element Plus 插件
- IN 与 DISTINCT
- cloudera manager报错解决方案
- Unity 动画系统:Animator
- 2022年计算机软件水平考试信息系统项目管理(高级)练习题及答案
热门文章
- 【实验】实验课总结2 实验一
- vi复制粘贴(转贴+自己总结)
- 遗传算法 商旅问题 c++ GA tsp
- kafka消息存储机制和原理
- Unity Steam_VR 开发工具插件 VRTK自带案例分析(第一部分)
- win10系统ipv6服务器地址,Win10关闭iPv6地址方法
- 浅谈mysql 平衡二叉树理解_浅析二分查找,二叉树,平衡二叉树,B树,B+树
- mysql火焰图_Linux 性能分析利器 -火焰图 flame graph
- php eclipse xampp,PHP版eclipse配置xampp
- el-dialog内的el-table实现自适应高度