嗯,这个QImage的问题研究好久了,有段时间没用,忘了,已经被两次问到了,突然有点解释不清楚,我汗颜,觉得有必要重新总结下了,不然无颜对自己了。

图像的数据是以字节为单位保存的,每一行的字节数必须是4的整数倍,不足的补0。

(因为我们使用的是32操作系统,因此数据是按照32位对齐的,所以每行的字节数必须是4的整数倍也就是说每行的数据位必须是32位的整数倍。)这里是按照我的理解的,貌似错了,修正一下,最近在看数据对齐,这段话先忽略了,没有删掉,是因为,想留个足迹,等我找到合适的答案再贴上来。不过,图像的数据确实是按32位对齐的。

如果不是整数倍,则根据公式: W = ( w * bitcount +  )/ * ;

注:  w是图像的宽度,bitcount是图像的位深,即32、24等, 计算得到的W是程序中图像每行的字节数。

这里讲述QImage的32、、8位图。

图像格式:QImage::Format_RGB32 ,QImage::Format_RGB888,QImage::Format_Indexed8。

构造图像:

    ()、QImage myImage1 = QImage(filename);  根据文件名打开图像,如果图像本身是32、24位的,程序中图像是32位的,如果图像本身是8位、1位的,程序中对应为8位、1位。

   ()、QImage myImage2 = QImage(width, height, QImage::Format_…); 根据图像宽高来构造一幅图像,程序会自动根据图像格式对齐图像数据。

操作图像:按照()的方式构造图像,在Debug下,如果不给图像myImage2初值,图像不是黑的, 但release下,则构造好的图像默认为黑色。

好了,现在我们需要对图像数据操作,32位图像无疑是最简单的,因为它数据是对齐的。用width表示图像宽度,height表示图像高度。

首先熟悉几个函数:

a、uchar* bits();       可以获取图像的首地址

b、int  byteCount();  图像的总字节数 

c、int  bytesPerLine(); 图像每行字节数

、QImage::Format_RGB32,存入格式为B,G,R,A 对应 ,,,

    QImage::Format_RGB888,存入格式为R, G, B 对应 ,,

    QImage::Format_Indexed8,需要设定颜色表,QVector<QRgb>

    灰度图像颜色表设定:

    QVector<QRgb>  colorTable;

    for(int k=;k<;++k)
{ colorTable.push_back( qRgb(k,k,k) ); } 、QImage image32 = QImage(width, height, QImage::Format_32); QImage image24 = QImage(width, height, QImage::Format_24); QImage image8 = QImage(width, height, QImage::Format_8); image8.setColorTable(colorTable); 、需要取每个像素处理,采用指针取值,行扫的方式: int lineNum_32 = ; //行数 int pixelsub_32 = ; //像素下标 uchar* imagebits_32 = image32.bits(); //获取图像首地址,32位图 uchar* imagebits24 = image24.bits(); uchar* imagebits8 = image8.bits(); for(int i=; i<height; ++i) { //按照通常的理解,我们会如下处理,取每行 lineNum_32 = i * width * ; //对于任意图像,这句没有问题 // lineNum_24 = i * width * 3; //??当width不是4的整数倍时,这句取不到每行开头 // lineNum_8 = i * width; //??当width不是4的整数倍时,这句取不到每行开头 for(int j=; j<width; ++j) { int r_32 = imagebits_32[ lineNum_32 + j * + ]; int g_32 = imagebits_32[ lineNum_32 + j * + ]; int b_32 = imagebits_32[ lineNum _32 + j * ]; // int r_24 = imagebits_24[ lineNum_24 + j * 3]; //注意区别32位的图 // int g_24 = imagebits_24[ lineNum_24 + j *3 + 1]; // int b_24 = imagebits_24[ lineNum_24 + j * 3 + 2]; // int gray_8 = imagebits_8[ lineNum_8 + j]; …… //自己的操作 } } //??出问题了,因为实际的图像数据并不是以width为真实宽度的,解决,有两种方法: 第一种方法:自己计算实际的宽度 修改为: // 获取每行的字节数 int W_32 = ( width * + )/ * ; //注意这里没有四舍五入,所以不要随意换算 int W_24 = ( width * + )/ * ; int W_8 = ( width * + )/ * ; //也可以使用QT函数来获取,功能和上面一样 { int W_32 = image32.bytesPerLine(); int W_24 = image24.bytesPerLine(); int W_8 = image8.bytesPerLine(); } for(int i=; i<height; ++i) { //现在可以按照通常的理解,取每行 lineNum_32 = i * W_32; //注意,这里不再需要乘倍数了(4, 3等) // lineNum_24 = i * W_24; // lineNum_8 = i * W_8; for(int j=; j<width; ++j) { //这里的操作同上面的一样 } } 第二种方法:采用scanLine(int)来获取每行的首地址, for(int i=; i<height; ++i) { imagebits_32 = image32.scanLine(i); imagebits_24 = image24.scanLine(i); imagebits_8 = image8.scanLine(i); for(int j=; j<width; ++j) { int r_32 = imagebits_32[ j * + ]; int g_32 = imagebits_32[ j * + ]; int b_32 = imagebits_32[ j * ]; // int r_24 = imagebits_24[ j * 3]; // int g_24 = imagebits_24[ j *3 + 1]; // int b_24 = imagebits_24[ j * 3 + 2]; // int gray_8 = imagebits_8[ j ]; …… //自己的操作 } } OK,上述两种方法的索引就不会出现图像数据偏移的问题 、大家注意到QImage的这个构造函数了吧,QImage::QImage ( uchar * data, int width, int height, Format format ) 嗯,这个函数就是从uchar* 的数据来构造图像,一般我们都可能先将图像数据存在uchar*中, uchar* data32 = new uchar[ width * height * ]; uchar* data24 = new uchar[ width * height * ]; uchar* data8 = new uchar[ width * height]; 从data32构造图像,不会有任何问题,但是当width不是4的整数倍时,你就不可能从data24和data8构造出自己想要的数据,程序会挂掉的,因为这两个数组的数据量根本不够一幅图(还记得数据补齐不)。 解决办法: 你需要首先计算出,你的图像的真实数据量(字节数), 可以根据QImage.byteCount()函数来获取图像的字节数,当然,你也可以自己计算,计算公式 byteCount = height * W; 这里的W就是每行的字节数,上面已经讲过了它的计算方法。 然后,你可以由QByteArray来获取转换的指针数据: 如:你的图像数据放在数组 uchar* srcData; 中 QByteArray imageByteArray = QByteArray( (const char*)srcData, byteCount ); uchar* transData = (unsigned char*)imageByteArray.data(); QImage desImage = QImage(transData, width, height, QImage::Format_…); 嗯,经过上述转换后,transData中将是补齐数据的数组,由此构造的图像不会有任何问题。 好了,终于总结完了,有很多小的问题,我不想写了,应该够用了,如果有具体其他问题,大家再仔细想想,肯定能解决的,哈哈

(转) QImage总结的更多相关文章

  1. 关于QImage提取单色通道方法(vector)

    转载请标明处: 作者:微微苏荷 本文地址:关于QImage提取单色通道方法(vector) 近日,用QT和mxnet结合做一个图像识别的demo.遇到需要把图片从QImage转为vector单色分离的 ...

  2. Mat转换为QImage

    请留意: opencv为3.0.0版本,Qt为4.8.4版本 #include"image1.h" #include<QApplication> #include< ...

  3. QImage::drawRect 和 fillRect在处理大面积区域时代价高昂

    项目需要生成一张掩码图, 出于操作pixel方便的考虑采用QImage(mono), 但在实现一个类似于 cvZero的操作时发现在图片面积较大时效率很低, 提醒一下 ps: 后来是改变策略, 用偏移 ...

  4. 关于 QImage::Format_Mono

    QImage::Format_Mono 为通常所讲的位图模式, QT中本提供了 QBitmap 来作为位图相关的应用, 但其最大弊端在于无法操作图片中 pixel 本身或说相关方法太过繁琐. Mono ...

  5. 悲惨记忆。。QImage之 pixel() && setPixel()参数不要给反了。。。

    QImage repairImg(width, height, QImage::Format_Mono); ; row < height; row++) { // uchar* ucRow = ...

  6. Convert between cv::Mat and QImage 两种图片类转换

    在使用Qt和OpenCV混合编程时,我们有时需要在两种图片类cv::Mat和QImage之间进行转换,下面的代码参考了网上这个帖子: //##### cv::Mat ---> QImage ## ...

  7. QImage 图像格式小结

    原地址:http://tracey2076.blog.51cto.com/1623739/539690 嗯,这个QImage的问题研究好久了,有段时间没用,忘了,已经被两次问到了,突然有点解释不清楚, ...

  8. QImage Color Convert to Gray 转为灰度图

    在Qt中,我们有时需要把QImage类的彩色图片转为灰度图,一开始我想的是用QImage的成员函数convertToFormat(),但是试了好多参数,返现转化的图片都有问题,不是我们想要的灰度图,如 ...

  9. IplImage 与 QImage 相互转换

    在使用Qt和OpenCV编程时,对于它们各自的图像类QImage和IplImage难以避免的需要互相之间的转换,下面我们就来看它们的相互转换. 1. QImage 转换为 IplImage IplIm ...

  10. 将Mat类型转换成QImage类型

    ui 头文件 #ifndef DIALOG_H #define DIALOG_H #include <QDialog> #include<opencv2/highgui/highgu ...

随机推荐

  1. 几种主流浏览器内置http抓包工具软件使用方法

    对于学习网站的人或者相关编程人员,经常需要用到http抓包工具来跟踪网页,但主流抓包软件如httpwatch.httpanalyzerstdv都是收费的,破解版往往也不稳定.实际上现在很多浏览器都内置 ...

  2. ios在项目中打开word文档、ppt等总结

    最近在项目开发中遇到下载附件文档预览需求,在这里总结一下我的实现方法,本文最后会附带我写的demo下载地址 这里我总结了三种实现方法(1)用webView预览(2)通过UIDocumentIntera ...

  3. C# 图形普通处理,resize ,水印..

    网站中,对用户图片上传处理是很有必要的.对于一些常用的处理,对图片各种形式的压缩,各种形式的水印. 1.裁剪正方形头像方法 /// <summary> /// 正方型裁剪 /// 以图片中 ...

  4. Angular React 和 Vue的比较

    Angular(1&2),React,Vue对比 一 数据流 数据绑定 Angular 使用双向绑定即:界面的操作能实时反映到数据,数据的变更能实时展现到界面. 实现原理: $scope变量中 ...

  5. swift 中Value Type VS Class Type

    ios 中Value Type 和 Class Type 有哪些异同点,这个问题是在微信的公共帐号中看到的,觉得挺有意思,这里梳理一下. 1.swift 中为什么要设置值类型? 值类型在参数传递.赋值 ...

  6. iOS参考工具和资源

    图片: Glyphish(图标资源) 资源: SwiftGuide:这份指南汇集了Swift语言主流学习资源,并以开发者的视角整理编排. 27款iOS开源库,让你的开发溜到飞起 创业者的新春礼包—优秀 ...

  7. Error pulling origin: error: Your local changes to the following files would be overwritten by merge

    Git在pull时,出现这种错误的时候,可能很多人进进行stash,相关stash的请看:Error pulling origin: error: Your local changes to the ...

  8. html 页面太长滚动时,固定页面菜单标签,或者导航标签的位置,fixed/stickUp the position

    有时你曾经需要把页面上的某些东西当页面太长发滚动的时候保留置顶位置显示,或许你有别的实现方式,我这个仅供参考, 源代码: /*global $, jQuery, alert*/ (function ( ...

  9. nginx trouble shooting

    除去配置语法失误.逻辑失误 nginx中的大部分问题都是前端到后端联通性 curl 域名没反应 cyr@test:/etc/nginx/sites-enabled$ curl test.hehe.ex ...

  10. C++编程技巧(长期更新)

    1.数组使用 int* p = new int[5](); // 数组新建并全部初始化为0 等价于: int* p; p = new int[5](); int* q = new int[5];    ...